diff --git a/services/distributeddataservice/service/test/udmf_run_time_store_test.cpp b/services/distributeddataservice/service/test/udmf_run_time_store_test.cpp index 486cd352932453c5d171085c490643b291f1201f..26cb6b97e8cb1a09f8980f26dd65add9e5a7a77e 100644 --- a/services/distributeddataservice/service/test/udmf_run_time_store_test.cpp +++ b/services/distributeddataservice/service/test/udmf_run_time_store_test.cpp @@ -719,5 +719,33 @@ HWTEST_F(UdmfRunTimeStoreTest, GetRuntime002, TestSize.Level1) auto status = store->GetRuntime(key, outRuntime); EXPECT_EQ(status, E_NOT_FOUND); } + +/** +* @tc.name: MarkWhenCorrupted001 +* @tc.desc: Normal testcase of MarkWhenCorrupted +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfRunTimeStoreTest, MarkWhenCorrupted001, TestSize.Level1) +{ + DistributedDB::DBStatus status = DistributedDB::DBStatus::OK; + auto store = std::make_shared(STORE_ID); + store->MarkWhenCorrupted(status); + EXPECT_FALSE(store->isCorrupted); +} + +/** +* @tc.name: MarkWhenCorrupted001 +* @tc.desc: Normal testcase of MarkWhenCorrupted +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfRunTimeStoreTest, MarkWhenCorrupted002, TestSize.Level1) +{ + DistributedDB::DBStatus status = DistributedDB::DBStatus::INVALID_PASSWD_OR_CORRUPTED_DB; + auto store = std::make_shared(STORE_ID); + store->MarkWhenCorrupted(status); + EXPECT_TRUE(store->isCorrupted); +} }; // namespace DistributedDataTest }; // namespace OHOS::Test \ No newline at end of file diff --git a/services/distributeddataservice/service/test/udmf_service_impl_test.cpp b/services/distributeddataservice/service/test/udmf_service_impl_test.cpp index bcb18a86406b7702f270ea8105c8d3d591010cec..f76f1d0b5ee83196df04993d8320305d40feb01e 100644 --- a/services/distributeddataservice/service/test/udmf_service_impl_test.cpp +++ b/services/distributeddataservice/service/test/udmf_service_impl_test.cpp @@ -13,6 +13,7 @@ * limitations under the License. */ +#include "error_code.h" #define LOG_TAG "UdmfServiceImplTest" #include "udmf_service_impl.h" #include "accesstoken_kit.h" @@ -431,5 +432,39 @@ HWTEST_F(UdmfServiceImplTest, IsValidInput004, TestSize.Level1) bool result = impl.IsValidInput(query, unifiedData, key); EXPECT_FALSE(result); } + +/** + * @tc.name: CloseStoreWhenCorrupted001 + * @tc.desc: Normal test of CloseStoreWhenCorrupted + * @tc.type: FUNC + */ +HWTEST_F(UdmfServiceImplTest, CloseStoreWhenCorrupted001, TestSize.Level1) +{ + std::string intention = "drag"; + StoreCache::GetInstance().CloseStores(); + auto store = StoreCache::GetInstance().GetStore(intention); + EXPECT_EQ(StoreCache::GetInstance().stores_.Size(), 1); + Status status = UDMF::E_OK; + UdmfServiceImpl impl; + impl.CloseStoreWhenCorrupted(intention, status); + EXPECT_EQ(StoreCache::GetInstance().stores_.Size(), 1); +} + +/** + * @tc.name: CloseStoreWhenCorrupted002 + * @tc.desc: Abnormal test of CloseStoreWhenCorrupted + * @tc.type: FUNC + */ +HWTEST_F(UdmfServiceImplTest, CloseStoreWhenCorrupted002, TestSize.Level1) +{ + std::string intention = "drag"; + StoreCache::GetInstance().CloseStores(); + auto store = StoreCache::GetInstance().GetStore(intention); + EXPECT_EQ(StoreCache::GetInstance().stores_.Size(), 1); + Status status = UDMF::E_DB_CORRUPTED; + UdmfServiceImpl impl; + impl.CloseStoreWhenCorrupted(intention, status); + EXPECT_EQ(StoreCache::GetInstance().stores_.Size(), 0); +} }; // namespace DistributedDataTest }; // namespace OHOS::Test diff --git a/services/distributeddataservice/service/udmf/store/runtime_store.cpp b/services/distributeddataservice/service/udmf/store/runtime_store.cpp index d13e1adec59091eef37cf2d6d2b077895a07dc57..866449f744325752300ba9044abcf7a17abf3cef 100644 --- a/services/distributeddataservice/service/udmf/store/runtime_store.cpp +++ b/services/distributeddataservice/service/udmf/store/runtime_store.cpp @@ -60,7 +60,7 @@ Status RuntimeStore::PutLocal(const std::string &key, const std::string &value) auto status = kvStore_->PutLocal(keyBytes, valueBytes); if (status != DBStatus::OK) { ZLOGE("KvStore PutLocal failed, status: %{public}d.", status); - return E_DB_ERROR; + return MarkWhenCorrupted(status); } return E_OK; } @@ -73,7 +73,7 @@ Status RuntimeStore::GetLocal(const std::string &key, std::string &value) DBStatus status = kvStore_->GetLocal(keyBytes, valueBytes); if (status != DBStatus::OK && status != DBStatus::NOT_FOUND) { ZLOGE("GetLocal entry failed, key: %{public}s.", key.c_str()); - return E_DB_ERROR; + return MarkWhenCorrupted(status); } if (valueBytes.empty()) { ZLOGW("GetLocal entry is empty, key: %{public}s", key.c_str()); @@ -91,7 +91,7 @@ Status RuntimeStore::DeleteLocal(const std::string &key) DBStatus status = kvStore_->DeleteLocal(keyBytes); if (status != DBStatus::OK && status != DBStatus::NOT_FOUND) { ZLOGE("DeleteLocal failed, key: %{public}s.", key.c_str()); - return E_DB_ERROR; + return MarkWhenCorrupted(status); } return E_OK; } @@ -115,9 +115,10 @@ Status RuntimeStore::Get(const std::string &key, UnifiedData &unifiedData) { UpdateTime(); std::vector entries; - if (GetEntries(UnifiedKey(key).GetKeyCommonPrefix(), entries) != E_OK) { + auto status = GetEntries(UnifiedKey(key).GetKeyCommonPrefix(), entries); + if (status != E_OK) { ZLOGE("GetEntries failed, dataPrefix: %{public}s.", key.c_str()); - return E_DB_ERROR; + return status; } if (entries.empty()) { ZLOGW("entries is empty, dataPrefix: %{public}s", key.c_str()); @@ -173,9 +174,10 @@ Status RuntimeStore::GetSummary(UnifiedKey &key, Summary &summary) ZLOGW("Get stored summary failed, key: %{public}s, status:%{public}d", summaryKey.c_str(), res); UnifiedData unifiedData; auto udKey = key.GetUnifiedKey(); - if (Get(udKey, unifiedData) != E_OK) { + auto status = Get(udKey, unifiedData); + if (status != E_OK) { ZLOGE("Get unified data failed, key: %{public}s", udKey.c_str()); - return E_DB_ERROR; + return status; } UDDetails details {}; if (PreProcessUtils::GetDetailsFromUData(unifiedData, details)) { @@ -204,7 +206,7 @@ Status RuntimeStore::PutRuntime(const std::string &key, const Runtime &runtime) auto res = kvStore_->Put({key.begin(), key.end()}, value); if (res != OK) { ZLOGE("Put failed, key:%{public}s, status:%{public}d", key.c_str(), res); - return E_DB_ERROR; + return MarkWhenCorrupted(res); } return E_OK; } @@ -220,7 +222,7 @@ Status RuntimeStore::GetRuntime(const std::string &key, Runtime &runtime) } if (res != OK || value.empty()) { ZLOGE("Get failed, key: %{public}s, status:%{public}d", key.c_str(), res); - return E_DB_ERROR; + return MarkWhenCorrupted(res); } auto status = DataHandler::UnmarshalEntries(value, runtime, TAG::TAG_RUNTIME); if (status != E_OK) { @@ -233,14 +235,16 @@ Status RuntimeStore::GetRuntime(const std::string &key, Runtime &runtime) Status RuntimeStore::Update(const UnifiedData &unifiedData) { std::string key = unifiedData.GetRuntime()->key.key; - if (Delete(UnifiedKey(key).GetKeyCommonPrefix()) != E_OK) { + auto status = Delete(UnifiedKey(key).GetKeyCommonPrefix()); + if (status != E_OK) { UpdateTime(); ZLOGE("Delete unified data failed, dataPrefix: %{public}s.", key.c_str()); - return E_DB_ERROR; + return status; } - if (Put(unifiedData) != E_OK) { + status = Put(unifiedData); + if (status != E_OK) { ZLOGE("Update unified data failed, dataPrefix: %{public}s.", key.c_str()); - return E_DB_ERROR; + return status; } return E_OK; } @@ -248,9 +252,10 @@ Status RuntimeStore::Update(const UnifiedData &unifiedData) Status RuntimeStore::Delete(const std::string &key) { std::vector entries; - if (GetEntries(key, entries) != E_OK) { + auto status = GetEntries(key, entries); + if (status != E_OK) { ZLOGE("GetEntries failed, dataPrefix: %{public}s.", key.c_str()); - return E_DB_ERROR; + return status; } if (entries.empty()) { ZLOGD("entries is empty."); @@ -382,7 +387,7 @@ Status RuntimeStore::GetBatchData(const std::string &dataPrefix, std::vector(status)); + if (delegateManager_->DeleteKvStore(storeId_) != DBStatus::OK) { + ZLOGE("DeleteKvStore fail, status: %{public}d.", static_cast(status)); + } + return false; + } if (status != DBStatus::OK) { ZLOGE("GetKvStore fail, status: %{public}d.", static_cast(status)); return false; @@ -447,6 +459,13 @@ bool RuntimeStore::Init() if (retStatus != DBStatus::OK) { ZLOGE("CloseKvStore fail, status: %{public}d.", static_cast(retStatus)); } + if (isCorrupted) { + ZLOGI("start to delete runtime kvStore."); + retStatus = delegateManager_->DeleteKvStore(storeId_); + if (retStatus != DBStatus::OK) { + ZLOGE("DeleteKvStore fail, status: %{public}d.", static_cast(retStatus)); + } + } }; kvStore_ = std::shared_ptr(delegate, release); uint32_t pragmData = 16 * 1024 * 1024; @@ -554,7 +573,7 @@ Status RuntimeStore::GetEntries(const std::string &dataPrefix, std::vectorGetEntries(dbQuery, entries); if (status != DBStatus::OK && status != DBStatus::NOT_FOUND) { ZLOGE("KvStore getEntries failed, status: %{public}d.", static_cast(status)); - return E_DB_ERROR; + return MarkWhenCorrupted(status); } return E_OK; } @@ -564,7 +583,7 @@ Status RuntimeStore::PutEntries(const std::vector &entries) DBStatus status = kvStore_->PutBatch(entries); if (status != DBStatus::OK) { ZLOGE("putBatch failed, status: %{public}d.", status); - return E_DB_ERROR; + return MarkWhenCorrupted(status); } return E_OK; } @@ -574,10 +593,19 @@ Status RuntimeStore::DeleteEntries(const std::vector &keys) DBStatus status = kvStore_->DeleteBatch(keys); if (status != DBStatus::OK) { ZLOGE("deleteBatch failed, status: %{public}d.", status); - return E_DB_ERROR; + return MarkWhenCorrupted(status); } return E_OK; } +Status RuntimeStore::MarkWhenCorrupted(DistributedDB::DBStatus status) +{ + if (status == INVALID_PASSWD_OR_CORRUPTED_DB) { + ZLOGE("Kv database corrupted"); + isCorrupted = true; + return E_DB_CORRUPTED; + } + return E_DB_ERROR; +} } // namespace UDMF } // namespace OHOS \ No newline at end of file diff --git a/services/distributeddataservice/service/udmf/store/runtime_store.h b/services/distributeddataservice/service/udmf/store/runtime_store.h index ef9c37e36c0789a10dc25fa7b7d9bb6ff698651c..04700ea4aaa06fc4cc23480aa4b351099be303ef 100644 --- a/services/distributeddataservice/service/udmf/store/runtime_store.h +++ b/services/distributeddataservice/service/udmf/store/runtime_store.h @@ -65,6 +65,9 @@ private: void NotifySyncProcss(const DevSyncProcessMap &processMap, ProcessCallback callback, const DevNameMap &deviceNameMap); Status PutSummary(const UnifiedData &data, std::vector &entries); + Status MarkWhenCorrupted(DistributedDB::DBStatus status); + bool isCorrupted = false; + }; } // namespace UDMF } // namespace OHOS diff --git a/services/distributeddataservice/service/udmf/store/store_cache.cpp b/services/distributeddataservice/service/udmf/store/store_cache.cpp index 545b549a17b0145ca1a1957ba92ce5c7986594c9..73104baac94696b5b8fde363f270b0053655d3be 100644 --- a/services/distributeddataservice/service/udmf/store/store_cache.cpp +++ b/services/distributeddataservice/service/udmf/store/store_cache.cpp @@ -12,6 +12,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include +#include +#include #define LOG_TAG "StoreCache" #include "store_cache.h" @@ -38,7 +41,6 @@ std::shared_ptr StoreCache::GetStore(std::string intention) } std::string key = intention; key.append(std::to_string(foregroundUserId)); - stores_.Compute(key, [&store, intention](const auto &key, std::shared_ptr &storePtr) -> bool { if (storePtr != nullptr) { store = storePtr; @@ -56,7 +58,7 @@ std::shared_ptr StoreCache::GetStore(std::string intention) } return false; }); - + std::unique_lock lock(taskMutex_); if (taskId_ == ExecutorPool::INVALID_TASK_ID && executorPool_ != nullptr) { taskId_ = executorPool_->Schedule(std::chrono::minutes(INTERVAL), std::bind(&StoreCache::GarbageCollect, this)); @@ -94,6 +96,19 @@ void StoreCache::CloseStores() stores_.Clear(); } +void StoreCache::RemoveStore(std::string intention) +{ + ZLOGI("RemoveStore, intention:%{public}s", intention.c_str()); + int foregroundUserId = 0; + if (!DistributedData::AccountDelegate::GetInstance()->QueryForegroundUserId(foregroundUserId)) { + ZLOGE("QueryForegroundUserId failed."); + return; + } + std::string key = intention; + key.append(std::to_string(foregroundUserId)); + stores_.Erase(key); +} + bool StoreCache::IsValidIntention(const std::string &intention) { return UnifiedDataUtils::GetIntentionByString(intention) != UD_INTENTION_BUTT; diff --git a/services/distributeddataservice/service/udmf/store/store_cache.h b/services/distributeddataservice/service/udmf/store/store_cache.h index 5d3918d2d0bd44121b6e8f7618eade4103ff3358..9c25d82540c40de4e07116ab4402e42bd8af5465 100644 --- a/services/distributeddataservice/service/udmf/store/store_cache.h +++ b/services/distributeddataservice/service/udmf/store/store_cache.h @@ -19,6 +19,7 @@ #include "concurrent_map.h" #include "executor_pool.h" #include "store.h" +#include namespace OHOS { namespace UDMF { @@ -28,6 +29,7 @@ public: static StoreCache &GetInstance(); void SetThreadPool(std::shared_ptr executors); void CloseStores(); + void RemoveStore(std::string intention); private: StoreCache() {} diff --git a/services/distributeddataservice/service/udmf/udmf_service_impl.cpp b/services/distributeddataservice/service/udmf/udmf_service_impl.cpp index a3ea7ce7ed82c0f2bd1b2bb1adb1994d7014eca3..eaf6c96f2e1f1e2d4a0a079d928db74dd895a287 100644 --- a/services/distributeddataservice/service/udmf/udmf_service_impl.cpp +++ b/services/distributeddataservice/service/udmf/udmf_service_impl.cpp @@ -13,6 +13,7 @@ * limitations under the License. */ +#include "error_code.h" #define LOG_TAG "UdmfServiceImpl" #include "udmf_service_impl.h" @@ -155,9 +156,10 @@ int32_t UdmfServiceImpl::SaveData(CustomOption &option, UnifiedData &unifiedData ZLOGE("Get store failed:%{public}s", intention.c_str()); return E_DB_ERROR; } - - if (store->Put(unifiedData) != E_OK) { - ZLOGE("Put unified data failed:%{public}s", intention.c_str()); + auto status = store->Put(unifiedData); + if (status != E_OK) { + ZLOGE("Put unified data failed:%{public}s, status:%{public}d", intention.c_str(), status); + CloseStoreWhenCorrupted(intention, status); return E_DB_ERROR; } key = unifiedData.GetRuntime()->key.GetUnifiedKey(); @@ -223,6 +225,7 @@ int32_t UdmfServiceImpl::RetrieveData(const QueryOption &query, UnifiedData &uni int32_t res = store->Get(query.key, unifiedData); if (res != E_OK) { ZLOGE("Get data failed,res:%{public}d,key:%{public}s", res, query.key.c_str()); + CloseStoreWhenCorrupted(key.intention, static_cast(res)); return res; } @@ -420,6 +423,7 @@ int32_t UdmfServiceImpl::UpdateData(const QueryOption &query, UnifiedData &unifi int32_t res = store->Get(query.key, data); if (res != E_OK) { ZLOGE("Get data failed:%{public}s", key.intention.c_str()); + CloseStoreWhenCorrupted(key.intention, static_cast(res)); return res; } if (data.IsEmpty()) { @@ -437,8 +441,10 @@ int32_t UdmfServiceImpl::UpdateData(const QueryOption &query, UnifiedData &unifi runtime->lastModifiedTime = PreProcessUtils::GetTimestamp(); unifiedData.SetRuntime(*runtime); PreProcessUtils::SetRecordUid(unifiedData); - if (store->Update(unifiedData) != E_OK) { + res = store->Update(unifiedData); + if (res != E_OK) { ZLOGE("Unified data update failed:%{public}s", key.intention.c_str()); + CloseStoreWhenCorrupted(key.intention, static_cast(res)); return E_DB_ERROR; } return E_OK; @@ -485,8 +491,10 @@ int32_t UdmfServiceImpl::DeleteData(const QueryOption &query, std::vectorDeleteBatch(deleteKeys) != E_OK) { + status = store->DeleteBatch(deleteKeys); + if (status != E_OK) { ZLOGE("Remove data failed."); + CloseStoreWhenCorrupted(key.intention, static_cast(status)); return E_DB_ERROR; } return E_OK; @@ -506,9 +514,10 @@ int32_t UdmfServiceImpl::GetSummary(const QueryOption &query, Summary &summary) ZLOGE("Get store failed:%{public}s", key.intention.c_str()); return E_DB_ERROR; } - - if (store->GetSummary(key, summary) != E_OK) { + auto status = store->GetSummary(key, summary); + if (status != E_OK) { ZLOGE("Store get summary failed:%{public}s", key.intention.c_str()); + CloseStoreWhenCorrupted(key.intention, status); return E_DB_ERROR; } return E_OK; @@ -553,14 +562,17 @@ int32_t UdmfServiceImpl::AddPrivilege(const QueryOption &query, Privilege &privi } if (res != E_OK) { ZLOGE("Get runtime failed, res:%{public}d, key:%{public}s.", res, query.key.c_str()); + CloseStoreWhenCorrupted(key.intention, res); return res; } runtime.privileges.emplace_back(privilege); res = store->PutRuntime(query.key, runtime); if (res != E_OK) { ZLOGE("Update runtime failed, res:%{public}d, key:%{public}s", res, query.key.c_str()); + CloseStoreWhenCorrupted(key.intention, res); + return E_DB_ERROR; } - return res; + return E_OK; } int32_t UdmfServiceImpl::Sync(const QueryOption &query, const std::vector &devices) @@ -670,6 +682,7 @@ int32_t UdmfServiceImpl::IsRemoteData(const QueryOption &query, bool &result) auto res = store->GetRuntime(query.key, runtime); if (res != E_OK) { ZLOGE("Get runtime failed, res:%{public}d, key:%{public}s.", res, query.key.c_str()); + CloseStoreWhenCorrupted(key.intention, res); return E_DB_ERROR; } @@ -706,9 +719,10 @@ int32_t UdmfServiceImpl::SetAppShareOption(const std::string &intention, int32_t ZLOGE("SetAppShareOption failed,shareOption already set:%{public}s", shareOptionTmp.c_str()); return E_SETTINGS_EXISTED; } - - if (store->PutLocal(std::to_string(accessTokenIDEx), ShareOptionsUtil::GetEnumStr(shareOption)) != E_OK) { - ZLOGE("Store get unifiedData failed:%{public}d", shareOption); + auto status = store->PutLocal(std::to_string(accessTokenIDEx), ShareOptionsUtil::GetEnumStr(shareOption)); + if (status != E_OK) { + ZLOGE("Store get unifiedData failed:%{public}d", status); + CloseStoreWhenCorrupted(intention, status); return E_DB_ERROR; } return E_OK; @@ -730,6 +744,7 @@ int32_t UdmfServiceImpl::GetAppShareOption(const std::string &intention, int32_t int32_t ret = store->GetLocal(std::to_string(accessTokenIDEx), appShareOption); if (ret != E_OK) { ZLOGW("GetLocal failed:%{public}s", intention.c_str()); + CloseStoreWhenCorrupted(intention, static_cast(ret)); return ret; } ZLOGI("GetLocal ok intention:%{public}s,appShareOption:%{public}s", intention.c_str(), appShareOption.c_str()); @@ -757,8 +772,10 @@ int32_t UdmfServiceImpl::RemoveAppShareOption(const std::string &intention) } UnifiedData unifiedData; - if (store->DeleteLocal(std::to_string(accessTokenIDEx)) != E_OK) { - ZLOGE("Store DeleteLocal failed:%{public}s", intention.c_str()); + auto status = store->DeleteLocal(std::to_string(accessTokenIDEx)); + if (status != E_OK) { + ZLOGE("Store DeleteLocal failed:%{public}s, status:%{public}d", intention.c_str(), status); + CloseStoreWhenCorrupted(intention, status); return E_DB_ERROR; } return E_OK; @@ -804,8 +821,10 @@ int32_t UdmfServiceImpl::QueryDataCommon( ZLOGE("Get store failed:%{public}s", intention.c_str()); return E_DB_ERROR; } - if (store->GetBatchData(dataPrefix, dataSet) != E_OK) { - ZLOGE("Get dataSet failed, dataPrefix: %{public}s.", dataPrefix.c_str()); + auto status = store->GetBatchData(dataPrefix, dataSet); + if (status != E_OK) { + ZLOGE("Get dataSet failed, dataPrefix: %{public}s, status:%{public}d.", dataPrefix.c_str(), status); + CloseStoreWhenCorrupted(intention, status); return E_DB_ERROR; } return E_OK; @@ -1090,8 +1109,10 @@ int32_t UdmfServiceImpl::SetDelayInfo(const DataLoadInfo &dataLoadInfo, sptrPutSummary(udkey, summary) != E_OK) { - ZLOGE("Put summary failed:%{public}s", key.c_str()); + auto status = store->PutSummary(udkey, summary); + if (status != E_OK) { + ZLOGE("Put summary failed:%{public}s, status:%{public}d", key.c_str(), status); + CloseStoreWhenCorrupted(UD_INTENTION_MAP.at(UD_INTENTION_DRAG), status); return E_DB_ERROR; } return E_OK; @@ -1194,5 +1215,13 @@ bool UdmfServiceImpl::IsValidInput(const QueryOption &query, UnifiedData &unifie } return true; } + +void UdmfServiceImpl::CloseStoreWhenCorrupted(const std::string &intention, Status status) +{ + if (status == E_DB_CORRUPTED) { + ZLOGE("Kv database corrupted, start to remove store"); + StoreCache::GetInstance().RemoveStore(intention); + } +} } // namespace UDMF } // namespace OHOS \ No newline at end of file diff --git a/services/distributeddataservice/service/udmf/udmf_service_impl.h b/services/distributeddataservice/service/udmf/udmf_service_impl.h index 8f366463f115a91d92db2235973f50bd04c25a0c..ee7cc6ab6eae9e9428c909ecc0da8b1f0289f70b 100644 --- a/services/distributeddataservice/service/udmf/udmf_service_impl.h +++ b/services/distributeddataservice/service/udmf/udmf_service_impl.h @@ -80,6 +80,7 @@ private: std::string FindIntentionMap(const Intention &queryintention); bool IsValidOptionsNonDrag(UnifiedKey &key, const std::string &intention); bool IsValidInput(const QueryOption &query, UnifiedData &unifiedData, UnifiedKey &key); + void CloseStoreWhenCorrupted(const std::string &intention, Status status); class Factory { public: Factory();