diff --git a/data_object/frameworks/innerkitsimpl/include/communicator/softbus_adapter.h b/data_object/frameworks/innerkitsimpl/include/communicator/softbus_adapter.h index bb3961e5e5b5abae9bde64b2ce9f79560b582603..94b229169d0ee495b48114b5b9356fc8e2e2139a 100644 --- a/data_object/frameworks/innerkitsimpl/include/communicator/softbus_adapter.h +++ b/data_object/frameworks/innerkitsimpl/include/communicator/softbus_adapter.h @@ -96,6 +96,7 @@ private: void DoSend(); int GetSocket(const PipeInfo &pipeInfo, const DeviceId &deviceId); int CreateClientSocket(const PipeInfo &pipeInfo, const DeviceId &deviceId); + std::string GetSocketName(const std::string &socketName); mutable std::mutex networkMutex_{}; mutable std::map networkId2Uuid_{}; DeviceInfo localInfo_{}; @@ -115,6 +116,9 @@ private: ConcurrentMap peerSocketInfos_; ISocketListener clientListener_{}; ISocketListener serverListener_{}; + std::string appId_; + bool isSystemApp_ = false; + std::mutex bundleInfoMutex_{}; }; class AppDataListenerWrap { diff --git a/data_object/frameworks/innerkitsimpl/src/communicator/softbus_adapter_standard.cpp b/data_object/frameworks/innerkitsimpl/src/communicator/softbus_adapter_standard.cpp index 6aa7762062bda2c0c9b0ae05932d5e4f669eae36..0e8c87117d51c1431a92ee6635d0fda8876bae4c 100644 --- a/data_object/frameworks/innerkitsimpl/src/communicator/softbus_adapter_standard.cpp +++ b/data_object/frameworks/innerkitsimpl/src/communicator/softbus_adapter_standard.cpp @@ -410,38 +410,56 @@ int SoftBusAdapter::GetSocket(const PipeInfo &pipeInfo, const DeviceId &deviceId return socketId; } -static std::string GetSelfAppId() +// AppId is used only for socket verification. The created socket name does not contain appId. +std::string SoftBusAdapter::GetSocketName(const std::string &socketName) { + std::lock_guard lock(bundleInfoMutex_); + if (isSystemApp_) { + return socketName; + } + if (!appId_.empty()) { + return socketName + '-' + appId_; + } sptr saManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); if (saManager == nullptr) { LOG_ERROR("Get system ability manager failed"); - return ""; + return socketName; } sptr remoteObject = saManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID); if (remoteObject == nullptr) { LOG_ERROR("Get system ability failed"); - return ""; + return socketName; } sptr bundleManager = iface_cast(remoteObject); if (bundleManager == nullptr) { LOG_ERROR("Get bundle manager failed"); - return ""; + return socketName; } AppExecFwk::BundleInfo bundleInfo; auto status = bundleManager->GetBundleInfoForSelf( + static_cast(AppExecFwk::GetBundleInfoFlag::GET_BUNDLE_INFO_WITH_APPLICATION) | static_cast(AppExecFwk::GetBundleInfoFlag::GET_BUNDLE_INFO_WITH_SIGNATURE_INFO), bundleInfo); if (status != 0) { LOG_ERROR("Get bundle info failed, status: %{public}d", status); - return ""; + return socketName; + } + if (bundleInfo.applicationInfo.isSystemApp) { + isSystemApp_ = true; + LOG_INFO("System app does not require appId, bundleName: %{public}s", bundleInfo.name.c_str()); + return socketName; + } + if (bundleInfo.appId.empty()) { + LOG_ERROR("Get appId empty, bundleName: %{public}s", bundleInfo.name.c_str()); + return socketName; } - return bundleInfo.appId; + appId_ = bundleInfo.appId; + return socketName + '-' + appId_; } int SoftBusAdapter::CreateClientSocket(const PipeInfo &pipeInfo, const DeviceId &deviceId) { SocketInfo socketInfo; - // AppId is used only for socket verification. The created socket name does not contain appId. - std::string socketNameAndAppId = pipeInfo.pipeId + '-' + GetSelfAppId(); + std::string socketNameAndAppId = GetSocketName(pipeInfo.pipeId); socketInfo.name = socketNameAndAppId.data(); socketInfo.peerName = const_cast(pipeInfo.pipeId.c_str()); std::string networkId = ToNodeID(deviceId.deviceId); @@ -514,8 +532,7 @@ bool SoftBusAdapter::IsSameStartedOnPeer( int SoftBusAdapter::CreateSessionServerAdapter(const std::string &sessionName) { SocketInfo socketInfo; - // AppId is used only for socket verification. The created socket name does not contain appId. - std::string socketNameAndAppId = sessionName + '-' + GetSelfAppId(); + std::string socketNameAndAppId = GetSocketName(sessionName); socketInfo.name = socketNameAndAppId.data(); socketInfo.pkgName = const_cast(PKG_NAME); socketServer_ = Socket(socketInfo); diff --git a/data_object/frameworks/jskitsimpl/include/common/napi_queue.h b/data_object/frameworks/jskitsimpl/include/common/napi_queue.h index a4c5d37a8442bcc8210503a79609f8a6928fa954..11495f7c2d8c29e0b188992e9fec5be0e76a7511 100644 --- a/data_object/frameworks/jskitsimpl/include/common/napi_queue.h +++ b/data_object/frameworks/jskitsimpl/include/common/napi_queue.h @@ -54,7 +54,6 @@ struct ContextBase { private: napi_deferred deferred = nullptr; - napi_async_work work = nullptr; napi_ref callbackRef = nullptr; napi_ref selfRef = nullptr; @@ -87,7 +86,7 @@ private: class NapiQueue { public: - static napi_value AsyncWork(napi_env env, std::shared_ptr ctxt, const std::string &name, + static napi_value AsyncWork(napi_env env, std::shared_ptr contextBase, const std::string &name, NapiAsyncExecute execute = NapiAsyncExecute(), NapiAsyncComplete complete = NapiAsyncComplete()); static void SetBusinessError(napi_env env, napi_value *businessError, std::shared_ptr error); @@ -98,6 +97,13 @@ private: RESULT_DATA = 1, RESULT_ALL = 2 }; + struct AsyncContext { + std::shared_ptr ctxt; + NapiAsyncExecute execute = nullptr; + NapiAsyncComplete complete = nullptr; + napi_deferred deferred = nullptr; + napi_async_work work = nullptr; + }; static void GenerateOutput(ContextBase *ctxt); }; } // namespace OHOS::ObjectStore diff --git a/data_object/frameworks/jskitsimpl/src/common/napi_queue.cpp b/data_object/frameworks/jskitsimpl/src/common/napi_queue.cpp index b5d330d369e5e46edec355341a41e67ade7ae9cd..fad2f4fdd95cb004b9adeb4ee7661f0fea72d7ca 100644 --- a/data_object/frameworks/jskitsimpl/src/common/napi_queue.cpp +++ b/data_object/frameworks/jskitsimpl/src/common/napi_queue.cpp @@ -23,12 +23,6 @@ ContextBase::~ContextBase() { LOG_DEBUG("no memory leak after callback or promise[resolved/rejected]"); if (env != nullptr) { - if (work != nullptr) { - napi_delete_async_work(env, work); - } - if (callbackRef != nullptr) { - napi_delete_reference(env, callbackRef); - } napi_delete_reference(env, selfRef); env = nullptr; } @@ -71,50 +65,52 @@ void ContextBase::GetCbInfo(napi_env envi, napi_callback_info info, NapiCbInfoPa } } -napi_value NapiQueue::AsyncWork(napi_env env, std::shared_ptr ctxt, const std::string& name, +napi_value NapiQueue::AsyncWork(napi_env env, std::shared_ptr contextBase, const std::string &name, NapiAsyncExecute execute, NapiAsyncComplete complete) { - LOG_DEBUG("name=%{public}s", name.c_str()); - + AsyncContext *aCtx = new (std::nothrow) AsyncContext; + if (aCtx == nullptr) { + LOG_ERROR("create aysnc context failed"); + return nullptr; + } + aCtx->ctxt = std::move(contextBase); + aCtx->execute = std::move(execute); + aCtx->complete = std::move(complete); + auto ctxt = aCtx->ctxt; napi_value promise = nullptr; if (ctxt->callbackRef == nullptr) { napi_create_promise(ctxt->env, &ctxt->deferred, &promise); - LOG_DEBUG("create deferred promise"); } else { napi_get_undefined(ctxt->env, &promise); } - napi_value resource = nullptr; napi_create_string_utf8(ctxt->env, name.c_str(), NAPI_AUTO_LENGTH, &resource); - napi_create_async_work( - ctxt->env, nullptr, resource, - [](napi_env env, void* data) { + napi_create_async_work(ctxt->env, nullptr, resource, + [](napi_env env, void *data) { NOT_MATCH_RETURN_VOID(data != nullptr); - auto ctxt = reinterpret_cast(data); - LOG_DEBUG("napi_async_execute_callback ctxt->status=%{public}d", ctxt->status); - if (ctxt->execute && ctxt->status == napi_ok) { - ctxt->execute(); + auto actxt = reinterpret_cast(data); + if (actxt->execute && actxt->ctxt->status == napi_ok) { + actxt->execute(); } }, - [](napi_env env, napi_status status, void* data) { + [](napi_env env, napi_status status, void *data) { NOT_MATCH_RETURN_VOID(data != nullptr); - auto ctxt = reinterpret_cast(data); - LOG_DEBUG("napi_async_complete_callback status=%{public}d, ctxt->status=%{public}d", status, ctxt->status); - if ((status != napi_ok) && (ctxt->status == napi_ok)) { - ctxt->status = status; + auto actxt = reinterpret_cast(data); + if ((status != napi_ok) && (actxt->ctxt->status == napi_ok)) { + actxt->ctxt->status = status; } - if ((ctxt->complete) && (status == napi_ok) && (ctxt->status == napi_ok)) { - ctxt->complete(ctxt->output); + if ((actxt->complete) && (status == napi_ok) && (actxt->ctxt->status == napi_ok)) { + actxt->complete(actxt->ctxt->output); } - GenerateOutput(ctxt); - }, - reinterpret_cast(ctxt.get()), &ctxt->work); - ctxt->execute = std::move(execute); - ctxt->complete = std::move(complete); - ctxt->hold = ctxt; // save crossing-thread ctxt. - auto status = napi_queue_async_work_with_qos(ctxt->env, ctxt->work, napi_qos_user_initiated); + GenerateOutput(actxt->ctxt.get()); + napi_delete_reference(env, actxt->ctxt->callbackRef); + napi_delete_async_work(env, actxt->work); + delete actxt; + }, reinterpret_cast(aCtx), &aCtx->work); + auto status = napi_queue_async_work(ctxt->env, aCtx->work); if (status != napi_ok) { - napi_get_undefined(ctxt->env, &promise); + napi_get_undefined(env, &promise); + delete aCtx; } return promise; } diff --git a/data_object/frameworks/jskitsimpl/src/common/object_error.cpp b/data_object/frameworks/jskitsimpl/src/common/object_error.cpp index 12347fd0d2022895f9fcc68068e56742e2591120..bcbbd913da41bf04b448eca1b6b61866786659d1 100644 --- a/data_object/frameworks/jskitsimpl/src/common/object_error.cpp +++ b/data_object/frameworks/jskitsimpl/src/common/object_error.cpp @@ -50,7 +50,7 @@ int DatabaseError::GetCode() std::string DatabaseError::GetMessage() { - return "create table failed"; + return "Failed to create the in-memory database."; } int PermissionError::GetCode() diff --git a/data_object/frameworks/jskitsimpl/test/unittest/src/ObjectStoreJsunitV9.test.js b/data_object/frameworks/jskitsimpl/test/unittest/src/ObjectStoreJsunitV9.test.js index cd2395d8bd9d0a42c09cecbca56d4c896196d2d3..06e33872d33d923bc10aa821106ad1daba286b28 100644 --- a/data_object/frameworks/jskitsimpl/test/unittest/src/ObjectStoreJsunitV9.test.js +++ b/data_object/frameworks/jskitsimpl/test/unittest/src/ObjectStoreJsunitV9.test.js @@ -162,7 +162,7 @@ describe('objectStoreTest', function () { console.info(TAG + "setSessionId test"); }).catch((error) => { expect(error.code == 15400001).assertEqual(true); - expect(error.message == "create table failed").assertEqual(true); + expect(error.message == "Failed to create the in-memory database.").assertEqual(true); }); console.log(TAG + "************* V9testsetSessionId002 end *************"); g_object.setSessionId((error, data) => { diff --git a/data_share/frameworks/js/napi/dataShare/src/napi_datashare_helper.cpp b/data_share/frameworks/js/napi/dataShare/src/napi_datashare_helper.cpp index 9e6c535795affb34b248a0414159134620ecb5be..52947282ad858e9e6193492dd118cad7d3a4dc79 100644 --- a/data_share/frameworks/js/napi/dataShare/src/napi_datashare_helper.cpp +++ b/data_share/frameworks/js/napi/dataShare/src/napi_datashare_helper.cpp @@ -16,7 +16,6 @@ #include "napi_datashare_helper.h" #include "data_proxy_observer_stub.h" -#include "datashare_errno.h" #include "datashare_helper.h" #include "datashare_log.h" #include "datashare_predicates_proxy.h" diff --git a/data_share/frameworks/native/consumer/src/datashare_helper.cpp b/data_share/frameworks/native/consumer/src/datashare_helper.cpp index 6e3ad68d16e2e9ddf023cbac4e4c43ee93c4bee8..8db2dcba7da710d1c6ec0235d1e8870f35bd34cf 100644 --- a/data_share/frameworks/native/consumer/src/datashare_helper.cpp +++ b/data_share/frameworks/native/consumer/src/datashare_helper.cpp @@ -178,6 +178,11 @@ int DataShareHelper::GetSilentProxyStatus(const std::string &uri) std::shared_ptr DataShareHelper::CreateExtHelper(Uri &uri, const sptr &token, const int waitTime) { + if (uri.GetQuery().find("appIndex=") != std::string::npos) { + LOG_ERROR("ExtHelper do not support appIndex. Uri:%{public}s", + DataShareStringUtils::Anonymous(uri.ToString()).c_str()); + return nullptr; + } sptr connection = new (std::nothrow) DataShareConnection(uri, token, waitTime); if (connection == nullptr) { LOG_ERROR("Create DataShareConnection failed."); diff --git a/data_share/frameworks/native/provider/include/datashare_uv_queue.h b/data_share/frameworks/native/provider/include/datashare_uv_queue.h index ee7d41c55d6828f1d21ab075acc0d278afc15ceb..b122a1586cad46a1f17468edad0f5218a479a692 100644 --- a/data_share/frameworks/native/provider/include/datashare_uv_queue.h +++ b/data_share/frameworks/native/provider/include/datashare_uv_queue.h @@ -47,7 +47,7 @@ private: bool done; std::condition_variable condition; std::mutex mutex; - std::atomic count; + std::atomic_int32_t count; }; static void LambdaForWork(uv_work_t* work, int uvstatus); diff --git a/data_share/test/native/unittest/mediadatashare_test/src/errorcode_test.cpp b/data_share/test/native/unittest/mediadatashare_test/src/errorcode_test.cpp index fa0fcb94d9a7356e6fd922b50f71bd8fe6bbe608..9b8841b20c60a00856e4d50417af0e074fbc9d8a 100644 --- a/data_share/test/native/unittest/mediadatashare_test/src/errorcode_test.cpp +++ b/data_share/test/native/unittest/mediadatashare_test/src/errorcode_test.cpp @@ -29,13 +29,6 @@ namespace DataShare { using namespace testing::ext; using namespace OHOS::Security::AccessToken; constexpr int STORAGE_MANAGER_MANAGER_ID = 5003; -//std::string DATA_SHARE_URI = "datashare:///com.acts.errorcodetest"; -//std::string SLIENT_ACCESS_URI = "datashare:///com.acts.errorcodetest/entry/DB00/TBL00?Proxy=true"; -//std::string TBL_STU_NAME = "name"; -//std::string TBL_STU_AGE = "age"; -//std::shared_ptr g_slientAccessHelper; -//std::shared_ptr dataShareHelper; - class ErrorCodeTest : public testing::Test { public: static void SetUpTestCase(void); diff --git a/datamgr_service/services/distributeddataservice/app/src/kvstore_meta_manager.cpp b/datamgr_service/services/distributeddataservice/app/src/kvstore_meta_manager.cpp index 8cf32c404ce5a873d8d46a182b5ea9f24b368d3c..96705c439b08539e25ea36ffce315d9d6a467ca9 100644 --- a/datamgr_service/services/distributeddataservice/app/src/kvstore_meta_manager.cpp +++ b/datamgr_service/services/distributeddataservice/app/src/kvstore_meta_manager.cpp @@ -244,6 +244,11 @@ KvStoreMetaManager::NbDelegate KvStoreMetaManager::GetMetaKvStore() auto backup = [executors = executors_, queue = std::make_shared>(MAX_TASK_COUNT), fullName]( const auto &store) -> int32_t { auto result = queue->PushNoWait([fullName](const auto &store) -> int32_t { + auto dbStatus = store->CheckIntegrity(); + if (dbStatus != DistributedDB::DBStatus::OK) { + ZLOGE("meta store check integrity fail, dbStatus:%{public}d", dbStatus); + return dbStatus; + } return store->Export(fullName, {}, true); }); if (!result) { @@ -285,11 +290,17 @@ KvStoreMetaManager::NbDelegate KvStoreMetaManager::CreateMetaKvStore() if (dbStatusTmp == DistributedDB::DBStatus::INVALID_PASSWD_OR_CORRUPTED_DB) { ZLOGE("meta data corrupted!"); option.isNeedRmCorruptedDb = true; + auto fullName = GetBackupPath(); delegateManager_.GetKvStore(Bootstrap::GetInstance().GetMetaDBName(), option, - [&delegate, &dbStatusTmp](DistributedDB::DBStatus dbStatus, + [&delegate, &dbStatusTmp, &fullName](DistributedDB::DBStatus dbStatus, DistributedDB::KvStoreNbDelegate *nbDelegate) { delegate = nbDelegate; dbStatusTmp = dbStatus; + if (dbStatusTmp == DistributedDB::DBStatus::OK && delegate != nullptr) { + ZLOGI("start import meta data"); + DistributedDB::CipherPassword password; + delegate->Import(fullName, password, true); + } }); } diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/asset_loader.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/asset_loader.cpp index af4b0c626d27ce2ebc11cdb00b18cfd1093fa8f2..fdaf28e3e90f6c95897ddd95969a2f89301ae4ea 100644 --- a/datamgr_service/services/distributeddataservice/framework/cloud/asset_loader.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/asset_loader.cpp @@ -21,6 +21,12 @@ int32_t AssetLoader::Download( return E_NOT_SUPPORT; } +void AssetLoader::Download(const std::string &tableName, std::vector &assetsRecords) +{ + (void)assetsRecords; + return; +} + int32_t AssetLoader::RemoveLocalAssets( const std::string &tableName, const std::string &gid, const Value &prefix, VBucket &assets) { diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/asset_loader.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/asset_loader.h index 15a6b5156a150dcce52940c09bc93d4e82822714..80126aa769d0c6cf530b09c093d046ff6ad93b81 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/asset_loader.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/asset_loader.h @@ -21,9 +21,11 @@ namespace OHOS::DistributedData { class API_EXPORT AssetLoader { public: + using AssetsRecord = DistributedData::AssetRecord; virtual ~AssetLoader() = default; virtual int32_t Download( const std::string &tableName, const std::string &gid, const Value &prefix, VBucket &assets); + virtual void Download(const std::string &tableName, std::vector &assetsRecords); virtual int32_t RemoveLocalAssets( const std::string &tableName, const std::string &gid, const Value &prefix, VBucket &assets); virtual int32_t Cancel(); diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_report.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_report.h index 5b1a19e8e98bc63e5d77fc6cf97f62cbbe0ff82f..7b075a3ab403f32fa5a7b2ac13e94d1d1a2499ce 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_report.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_report.h @@ -23,6 +23,7 @@ namespace OHOS::DistributedData { class API_EXPORT CloudReport { public: using ReportParam = DistributedData::ReportParam; + virtual ~CloudReport() = default; API_EXPORT static CloudReport *GetInstance(); API_EXPORT static bool RegisterCloudReportInstance(CloudReport *instance); virtual std::string GetPrepareTraceId(int32_t userId); diff --git a/datamgr_service/services/distributeddataservice/framework/include/metadata/store_meta_data_local.h b/datamgr_service/services/distributeddataservice/framework/include/metadata/store_meta_data_local.h index 301810c77ac25080524e35964f2cfde0c56393b2..2ac940d25f7806ba966d245ceb8bc6af3a9e6d29 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/metadata/store_meta_data_local.h +++ b/datamgr_service/services/distributeddataservice/framework/include/metadata/store_meta_data_local.h @@ -31,6 +31,19 @@ struct API_EXPORT PolicyValue final : public Serializable { API_EXPORT bool Marshal(json &node) const override; API_EXPORT bool Unmarshal(const json &node) override; }; + +struct API_EXPORT PromiseInfo final : public Serializable { + // User authorization can access the tokenIds of the database + std::vector tokenIds = {}; + // User authorization can access the uids of the database + std::vector uids = {}; + std::vector permissionNames = {}; + API_EXPORT PromiseInfo() = default; + API_EXPORT ~PromiseInfo() = default; + API_EXPORT bool Marshal(json &node) const override; + API_EXPORT bool Unmarshal(const json &node) override; +}; + struct API_EXPORT StoreMetaDataLocal final : public Serializable { bool isAutoSync = false; bool isBackup = false; @@ -40,6 +53,7 @@ struct API_EXPORT StoreMetaDataLocal final : public Serializable { std::string dataDir = ""; std::string schema = ""; std::vector policies {}; + PromiseInfo promiseInfo; API_EXPORT StoreMetaDataLocal(); API_EXPORT ~StoreMetaDataLocal(); diff --git a/datamgr_service/services/distributeddataservice/framework/include/metadata/version_meta_data.h b/datamgr_service/services/distributeddataservice/framework/include/metadata/version_meta_data.h index 11aead0418d2a8a9775ef9dea9dea30617551356..75b64a1dd29c5e032934c8251a7cb7a9a436e4ae 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/metadata/version_meta_data.h +++ b/datamgr_service/services/distributeddataservice/framework/include/metadata/version_meta_data.h @@ -20,7 +20,7 @@ namespace OHOS::DistributedData { class API_EXPORT VersionMetaData final : public Serializable { public: - static constexpr int32_t CURRENT_VERSION = 3; + static constexpr int32_t CURRENT_VERSION = 4; static constexpr int32_t INVALID_VERSION = -1; int32_t version = INVALID_VERSION; diff --git a/datamgr_service/services/distributeddataservice/framework/include/store/general_store.h b/datamgr_service/services/distributeddataservice/framework/include/store/general_store.h index da35babc8e6cbb61903b00b06a9723344aaa1233..ddc987ad189997d2c9ee89ff2b30e36af24e4d37 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/store/general_store.h +++ b/datamgr_service/services/distributeddataservice/framework/include/store/general_store.h @@ -172,6 +172,8 @@ public: virtual int32_t MergeMigratedData(const std::string &tableName, VBuckets &&values) = 0; + virtual int32_t CleanTrackerData(const std::string &tableName, int64_t cursor) = 0; + virtual std::vector GetWaterVersion(const std::string &deviceId) = 0; virtual void SetEqualIdentifier(const std::string &appId, const std::string &storeId) {}; diff --git a/datamgr_service/services/distributeddataservice/framework/include/store/general_value.h b/datamgr_service/services/distributeddataservice/framework/include/store/general_value.h index a0b22bd0bca627d5d5e924b0c2488fbf84e5e457..f25f36ab87f9ab7428377270fdfbafd3e7ae23c4 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/store/general_value.h +++ b/datamgr_service/services/distributeddataservice/framework/include/store/general_value.h @@ -129,6 +129,12 @@ inline constexpr size_t TYPE_INDEX = Traits::variant_index_of_v; inline constexpr size_t TYPE_MAX = Traits::variant_size_of_v; +struct AssetRecord { + std::string gid; + Value prefix; + VBucket assets; +}; + enum class QueryOperation : uint32_t { ILLEGAL = 0, IN = 1, diff --git a/datamgr_service/services/distributeddataservice/framework/metadata/store_meta_data_local.cpp b/datamgr_service/services/distributeddataservice/framework/metadata/store_meta_data_local.cpp index dcff9a4ca058aa780dc234c15e0118338896588e..28a040b54b0c1d5526c53b4bbe1ae13ee79c45eb 100644 --- a/datamgr_service/services/distributeddataservice/framework/metadata/store_meta_data_local.cpp +++ b/datamgr_service/services/distributeddataservice/framework/metadata/store_meta_data_local.cpp @@ -58,6 +58,22 @@ PolicyValue StoreMetaDataLocal::GetPolicy(uint32_t type) return PolicyValue(); } +bool PromiseInfo::Marshal(json &node) const +{ + SetValue(node[GET_NAME(tokenIds)], tokenIds); + SetValue(node[GET_NAME(uids)], uids); + SetValue(node[GET_NAME(permissionNames)], permissionNames); + return true; +} + +bool PromiseInfo::Unmarshal(const json &node) +{ + GetValue(node, GET_NAME(tokenIds), tokenIds); + GetValue(node, GET_NAME(uids), uids); + GetValue(node, GET_NAME(permissionNames), permissionNames); + return true; +} + bool StoreMetaDataLocal::Marshal(json &node) const { SetValue(node[GET_NAME(isAutoSync)], isAutoSync); @@ -68,6 +84,7 @@ bool StoreMetaDataLocal::Marshal(json &node) const SetValue(node[GET_NAME(schema)], schema); SetValue(node[GET_NAME(policies)], policies); SetValue(node[GET_NAME(isPublic)], isPublic); + SetValue(node[GET_NAME(promiseInfo)], promiseInfo); return true; } @@ -81,6 +98,7 @@ bool StoreMetaDataLocal::Unmarshal(const json &node) GetValue(node, GET_NAME(schema), schema); GetValue(node, GET_NAME(policies), policies); GetValue(node, GET_NAME(isPublic), isPublic); + GetValue(node, GET_NAME(promiseInfo), promiseInfo); return true; } diff --git a/datamgr_service/services/distributeddataservice/service/data_share/common/scheduler_manager.cpp b/datamgr_service/services/distributeddataservice/service/data_share/common/scheduler_manager.cpp index cce99c945ba0145d5e84a2061ef0194e51684148..e02fec3b05182860bf7d1e712b5bdb061416df5f 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/common/scheduler_manager.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/common/scheduler_manager.cpp @@ -178,11 +178,6 @@ void SchedulerManager::ExecuteSchedulerSQL(const std::string &rdbDir, const int3 count); return; } - errCode = resultSet->GoToFirstRow(); - if (errCode != E_OK) { - ZLOGE("GoToFirstRow error, %{public}s, %{public}" PRId64 ", %{public}s, errCode is %{public}d", - DistributedData::Anonymous::Change(key.uri).c_str(), key.subscriberId, key.bundleName.c_str(), errCode); - } } void SchedulerManager::GenRemindTimerFuncParams( diff --git a/datamgr_service/services/distributeddataservice/service/data_share/common/uri_utils.cpp b/datamgr_service/services/distributeddataservice/service/data_share/common/uri_utils.cpp index 26447121a82615ea7304cef1f41d75bec5b845f9..fef9de081466554b192a71c783f7bd6693c47480 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/common/uri_utils.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/common/uri_utils.cpp @@ -62,6 +62,21 @@ bool URIUtils::GetBundleNameFromProxyURI(const std::string &uri, std::string &bu return true; } +bool URIUtils::GetAppIndexFromProxyURI(const std::string &uri, int32_t &appIndex) +{ + auto queryParams = URIUtils::GetQueryParams(uri); + if (!queryParams[APP_INDEX].empty()) { + auto [success, data] = URIUtils::Strtoul(queryParams[APP_INDEX]); + if (!success) { + appIndex = -1; + ZLOGE("appIndex is invalid! appIndex: %{public}s", queryParams[APP_INDEX].c_str()); + return false; + } + appIndex = static_cast(data); + } + return true; +} + void URIUtils::FormatUri(std::string &uri) { auto pos = uri.find_last_of('?'); diff --git a/datamgr_service/services/distributeddataservice/service/data_share/common/uri_utils.h b/datamgr_service/services/distributeddataservice/service/data_share/common/uri_utils.h index ffd4286c3ea7732968b9459b1ba8e0f0b591a679..77ebfdc9e0d7f73329c99da65a719c2b415db119 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/common/uri_utils.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/common/uri_utils.h @@ -39,6 +39,7 @@ class URIUtils { public: static bool GetInfoFromURI(const std::string &uri, UriInfo &uriInfo); static bool GetBundleNameFromProxyURI(const std::string &uri, std::string &bundleName); + static bool GetAppIndexFromProxyURI(const std::string &uri, int32_t &appIndex); static bool IsDataProxyURI(const std::string &uri); static void FormatUri(std::string &uri); static UriConfig GetUriConfig(const std::string &uri); @@ -50,6 +51,7 @@ public: static constexpr const char *PARAM_URI_SEPARATOR = ":///"; static constexpr const char *SCHEME_SEPARATOR = "://"; static constexpr const char *URI_SEPARATOR = "/"; + static constexpr const char *APP_INDEX = "appIndex"; // for Application Clone static constexpr int DATA_PROXY_SCHEMA_LEN = sizeof(DATA_PROXY_SCHEMA) - 1; static constexpr uint32_t PARAM_URI_SEPARATOR_LEN = 4; diff --git a/datamgr_service/services/distributeddataservice/service/data_share/data_provider_config.cpp b/datamgr_service/services/distributeddataservice/service/data_share/data_provider_config.cpp index 4b8aca96517d5038f4dda9da90644941c1c2cf42..3689b802ff8aa4ad783c3b26695d4ac0f5560a4b 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/data_provider_config.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/data_provider_config.cpp @@ -33,7 +33,7 @@ DataProviderConfig::DataProviderConfig(const std::string &uri, uint32_t callerTo { providerInfo_.uri = uri; providerInfo_.currentUserId = DistributedKv::AccountDelegate::GetInstance()->GetUserByToken(callerTokenId); - LoadConfigCommonStrategy::GetAppIndexFromProxyURI(providerInfo_.uri, providerInfo_.appIndex); + URIUtils::GetAppIndexFromProxyURI(providerInfo_.uri, providerInfo_.appIndex); if (providerInfo_.currentUserId == 0) { LoadConfigCommonStrategy::GetInfoFromProxyURI(providerInfo_.uri, providerInfo_.currentUserId, callerTokenId, providerInfo_.bundleName); diff --git a/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_impl.cpp b/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_impl.cpp index f36d3800de6c17372f9d43890e36718cecd0a053..fe13493f619444c415431d4ed5c118c71109ec97 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_impl.cpp @@ -42,6 +42,7 @@ #include "ipc_skeleton.h" #include "iservice_registry.h" #include "log_print.h" +#include "common/uri_utils.h" #include "metadata/auto_launch_meta_data.h" #include "metadata/meta_data_manager.h" #include "matching_skills.h" @@ -843,7 +844,12 @@ int32_t DataShareServiceImpl::GetSilentProxyStatus(const std::string &uri, bool return E_OK; } std::string calledBundleName = uriInfo.bundleName; - uint32_t calledTokenId = Security::AccessToken::AccessTokenKit::GetHapTokenID(currentUserId, calledBundleName, 0); + int32_t appIndex = 0; + if (!URIUtils::GetAppIndexFromProxyURI(uri, appIndex)) { + return E_APPINDEX_INVALID; + } + uint32_t calledTokenId = Security::AccessToken::AccessTokenKit::GetHapTokenID( + currentUserId, calledBundleName, appIndex); if (calledTokenId == 0) { calledTokenId = Security::AccessToken::AccessTokenKit::GetHapTokenID(0, calledBundleName, 0); } diff --git a/datamgr_service/services/distributeddataservice/service/data_share/strategies/general/load_config_common_strategy.cpp b/datamgr_service/services/distributeddataservice/service/data_share/strategies/general/load_config_common_strategy.cpp index 80cf59a7d33106ef1ca637cda015c0865968ae98..f0ce98ceca2dc383076b6726044bb0e0c8aa7e5c 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/strategies/general/load_config_common_strategy.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/strategies/general/load_config_common_strategy.cpp @@ -26,14 +26,13 @@ namespace OHOS::DataShare { constexpr const char USER_PARAM[] = "user"; constexpr const char TOKEN_ID_PARAM[] = "srcToken"; constexpr const char DST_BUNDLE_NAME_PARAM[] = "dstBundleName"; -constexpr const char APP_INDEX[] = "appIndex"; // for Application Clone bool LoadConfigCommonStrategy::operator()(std::shared_ptr context) { if (context->callerTokenId == 0) { context->callerTokenId = IPCSkeleton::GetCallingTokenID(); } context->currentUserId = DistributedKv::AccountDelegate::GetInstance()->GetUserByToken(context->callerTokenId); - if (!GetAppIndexFromProxyURI(context->uri, context->appIndex)) { + if (!URIUtils::GetAppIndexFromProxyURI(context->uri, context->appIndex)) { return false; } // sa, userId is in uri, caller token id is from first caller tokenId @@ -77,19 +76,4 @@ bool LoadConfigCommonStrategy::GetInfoFromProxyURI( } return true; } - -bool LoadConfigCommonStrategy::GetAppIndexFromProxyURI(const std::string &uri, int32_t &appIndex) -{ - auto queryParams = URIUtils::GetQueryParams(uri); - if (!queryParams[APP_INDEX].empty()) { - auto [success, data] = URIUtils::Strtoul(queryParams[APP_INDEX]); - if (!success) { - appIndex = -1; - ZLOGE("appIndex is invalid! appIndex: %{public}s", queryParams[APP_INDEX].c_str()); - return false; - } - appIndex = data; - } - return true; -} } // namespace OHOS::DataShare \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/data_share/strategies/general/load_config_common_strategy.h b/datamgr_service/services/distributeddataservice/service/data_share/strategies/general/load_config_common_strategy.h index 5b633a15cf1064b1376d8ea4b9b6651c8f293289..cf6ddfcbdb1caaafa4ee8f6416e590bb48cf33f8 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/strategies/general/load_config_common_strategy.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/strategies/general/load_config_common_strategy.h @@ -23,7 +23,6 @@ public: bool operator()(std::shared_ptr context) override; static bool GetInfoFromProxyURI( const std::string &uri, int32_t &user, uint32_t &callerTokenId, std::string &calledBundleName); - static bool GetAppIndexFromProxyURI(const std::string &uri, int32_t &appIndex); }; } // namespace OHOS::DataShare #endif // DATASHARESERVICE_LOAD_CONFIG_COMMON_STRAGETY_H diff --git a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_exporter.cpp b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_exporter.cpp index f31c14d1d69ae5d1b00d25727504048a14d2e61a..8f62255c93024da29a23400f798937605a34e6e5 100644 --- a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_exporter.cpp +++ b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_exporter.cpp @@ -34,14 +34,20 @@ void KVDBExporter::Exporter(const StoreMetaData &meta, const std::string &backup auto dbOption = KVDBGeneralStore::GetDBOption(meta, dbPassword); manager.GetKvStore(meta.storeId, dbOption, [&manager, &backupPath, &dbPassword, &result] - (DistributedDB::DBStatus dbstatus, DistributedDB::KvStoreNbDelegate *delegate) { + (DistributedDB::DBStatus dbStatus, DistributedDB::KvStoreNbDelegate *delegate) { if (delegate == nullptr) { ZLOGE("Auto backup delegate is null"); result = false; return; } - dbstatus = delegate->Export(backupPath, dbPassword); - result = (dbstatus == DistributedDB::DBStatus::OK) ? true : false; + dbStatus = delegate->CheckIntegrity(); + if (dbStatus != DistributedDB::DBStatus::OK) { + ZLOGE("CheckIntegrity fail, dbStatus:%{public}d, backupPath:%{public}s", dbStatus, backupPath.c_str()); + result = false; + return; + } + dbStatus = delegate->Export(backupPath, dbPassword); + result = (dbStatus == DistributedDB::DBStatus::OK) ? true : false; manager.CloseKvStore(delegate); }); std::string message; diff --git a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_general_store.cpp b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_general_store.cpp index 308938dbfb50373d628440c21c81cbbf9ec54ff8..ab5ab9a0cd1e4ebfb9b8f3e83e186f815b7ae59e 100644 --- a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_general_store.cpp +++ b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_general_store.cpp @@ -332,6 +332,11 @@ int32_t KVDBGeneralStore::MergeMigratedData(const std::string &tableName, VBucke return GeneralError::E_NOT_SUPPORT; } +int32_t KVDBGeneralStore::CleanTrackerData(const std::string &tableName, int64_t cursor) +{ + return GeneralError::E_NOT_SUPPORT; +} + KVDBGeneralStore::DBSyncCallback KVDBGeneralStore::GetDBSyncCompleteCB(DetailAsync async) { if (!async) { diff --git a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_general_store.h b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_general_store.h index 6bb4ddc7bbc012874db9801f3089765a1ec42de0..8caa063bf02316050d5096b9a745f9b87ddaace1 100644 --- a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_general_store.h +++ b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_general_store.h @@ -71,6 +71,7 @@ public: int32_t Release() override; int32_t BindSnapshots(std::shared_ptr>> bindAssets) override; int32_t MergeMigratedData(const std::string &tableName, VBuckets &&values) override; + int32_t CleanTrackerData(const std::string &tableName, int64_t cursor) override; std::vector GetWaterVersion(const std::string &deviceId) override; void SetEqualIdentifier(const std::string &appId, const std::string &storeId) override; void SetConfig(const StoreConfig &storeConfig) override; diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_asset_loader.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_asset_loader.cpp index 96f5416cf27333c1577f1fbfff34befa1aca0a0b..62a1262eab7716f1683c79793d78024d92fd8207 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_asset_loader.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_asset_loader.cpp @@ -16,9 +16,12 @@ #define LOG_TAG "RdbAssetLoader" #include "rdb_asset_loader.h" +#include + #include "error/general_error.h" #include "log_print.h" #include "rdb_cloud.h" +#include "store/general_value.h" #include "value_proxy.h" using namespace DistributedDB; @@ -44,6 +47,75 @@ DBStatus RdbAssetLoader::Download(const std::string &tableName, const std::strin : CLOUD_RECORD_EXIST_CONFLICT; } +void RdbAssetLoader::BatchDownload(const std::string &tableName, std::vector &downloadAssets) +{ + std::vector assetsRecords = Convert(std::move(downloadAssets)); + std::set skipAssets; + std::set deleteAssets; + PostEvent(skipAssets, assetsRecords, DistributedData::AssetEvent::DOWNLOAD, deleteAssets); + assetLoader_->Download(tableName, assetsRecords); + PostEvent(skipAssets, assetsRecords, DistributedData::AssetEvent::DOWNLOAD_FINISHED, deleteAssets); + downloadAssets = Convert(std::move(assetsRecords)); +} + +std::vector RdbAssetLoader::Convert(std::vector &&downloadAssets) +{ + std::vector assetsRecords; + for (auto &assetRecord : downloadAssets) { + AssetsRecord assetsRecord; + assetsRecord.gid = std::move(assetRecord.gid); + DistributedDB::Type prefixTemp = assetRecord.prefix; + assetsRecord.prefix = ValueProxy::Convert(std::move(prefixTemp)); + assetsRecord.assets = ValueProxy::Convert(std::move(assetRecord.assets)); + assetsRecords.emplace_back(std::move(assetsRecord)); + } + return assetsRecords; +} + +void RdbAssetLoader::UpdateStatus(AssetRecord &assetRecord, const VBucket &assets) +{ + for (const auto &[key, value] : assets) { + auto downloadAssets = std::get_if(&value); + if (downloadAssets == nullptr) { + continue; + } + for (const auto &asset : *downloadAssets) { + if (assetRecord.status == DBStatus::OK) { + assetRecord.status = ConvertStatus(static_cast(asset.status)); + return; + } + } + } +} + +std::vector RdbAssetLoader::Convert(std::vector &&assetsRecords) +{ + std::vector assetRecords; + for (auto &assetsRecord : assetsRecords) { + AssetRecord assetRecord{ + .gid = std::move(assetsRecord.gid), + }; + UpdateStatus(assetRecord, assetsRecord.assets); + assetRecord.assets = ValueProxy::Convert(std::move(assetsRecord.assets)); + assetRecords.emplace_back(std::move(assetRecord)); + } + return assetRecords; +} + +DBStatus RdbAssetLoader::ConvertStatus(AssetStatus error) +{ + switch (error) { + case AssetStatus::STATUS_NORMAL: + return DBStatus::OK; + case AssetStatus::STATUS_DOWNLOADING: + return DBStatus::OK; + default: + ZLOGE("error:0x%{public}x", error); + break; + } + return DBStatus::CLOUD_ERROR; +} + DBStatus RdbAssetLoader::RemoveLocalAssets(const std::vector &assets) { DistributedData::VBucket deleteAssets = ValueProxy::Convert(std::map{{ "", assets }}); @@ -51,6 +123,20 @@ DBStatus RdbAssetLoader::RemoveLocalAssets(const std::vector &assets) return RdbCloud::ConvertStatus(static_cast(error)); } +void RdbAssetLoader::PostEvent(std::set &skipAssets, std::vector &assetsRecords, + DistributedData::AssetEvent eventId, std::set &deleteAssets) +{ + for (auto &assetsRecord : assetsRecords) { + for (auto &asset : assetsRecord.assets) { + auto *downLoadAssets = Traits::get_if(&asset.second); + if (downLoadAssets == nullptr) { + return; + } + PostEvent(eventId, *downLoadAssets, skipAssets, deleteAssets); + } + } +} + void RdbAssetLoader::PostEvent(std::set& skipAssets, std::map& assets, DistributedData::AssetEvent eventId, std::set& deleteAssets) { diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_asset_loader.h b/datamgr_service/services/distributeddataservice/service/rdb/rdb_asset_loader.h index 5c24452365e3de3d7d3a21dfd4c724a2cc89fce9..a8a90d914aa8b5ac9a8415d951997cb271914aea 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_asset_loader.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_asset_loader.h @@ -29,23 +29,37 @@ public: using Asset = DistributedDB::Asset; using DBStatus = DistributedDB::DBStatus; using BindAssets = DistributedData::BindAssets; + using AssetsRecord = DistributedData::AssetRecord; + using AssetStatus = DistributedData::Asset::Status; + using GeneralError = DistributedData::GeneralError; + using VBucket = DistributedData::VBucket; - explicit RdbAssetLoader(std::shared_ptr cloudAssetLoader, BindAssets* bindAssets); + explicit RdbAssetLoader(std::shared_ptr cloudAssetLoader, BindAssets *bindAssets); ~RdbAssetLoader() = default; DBStatus Download(const std::string &tableName, const std::string &gid, const Type &prefix, std::map> &assets) override; + void BatchDownload(const std::string &tableName, std::vector &downloadAssets) override; + DBStatus RemoveLocalAssets(const std::vector &assets) override; private: + static std::vector Convert(std::vector &&assetsRecords); + static std::vector Convert(std::vector &&assetRecords); + static DBStatus ConvertStatus(AssetStatus error); + static void UpdateStatus(AssetRecord &assetRecord, const VBucket &assets); + + void PostEvent(std::set &skipAssets, std::map &assets, + DistributedData::AssetEvent eventId, std::set &deleteAssets); + void PostEvent(std::set &skipAssets, std::vector &assetsRecords, + DistributedData::AssetEvent eventId, std::set &deleteAssets); + void PostEvent(DistributedData::AssetEvent eventId, DistributedData::Assets &assets, + std::set &skipAssets, std::set &deleteAssets); + std::shared_ptr assetLoader_; - BindAssets* snapshots_; - void PostEvent(std::set& skipAssets, std::map& assets, - DistributedData::AssetEvent eventId, std::set& deleteAssets); - void PostEvent(DistributedData::AssetEvent eventId, DistributedData::Assets& assets, - std::set& skipAssets, std::set& deleteAssets); + BindAssets *snapshots_; }; } // namespace OHOS::DistributedRdb #endif // OHOS_DISTRIBUTED_DATA_DATAMGR_SERVICE_RDB_ASSET_LOADER_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.cpp index c326a86d3f3a279349ab110c519255596414505e..3a5cf6ca25ae54d35858d01de1a9ec61059b7dec 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.cpp @@ -470,7 +470,8 @@ std::pair> RdbGeneralStore::Query(const std::st ZLOGE("RemoteQuery: devices size error! size:%{public}zu", rdbQuery->GetDevices().size()); return { GeneralError::E_ERROR, nullptr }; } - return { GeneralError::E_OK, RemoteQuery(*rdbQuery->GetDevices().begin(), rdbQuery->GetRemoteCondition()) }; + auto cursor = RemoteQuery(*rdbQuery->GetDevices().begin(), rdbQuery->GetRemoteCondition()); + return { cursor != nullptr ? GeneralError::E_OK : GeneralError::E_ERROR, cursor}; } return { GeneralError::E_ERROR, nullptr }; } @@ -488,6 +489,19 @@ int32_t RdbGeneralStore::MergeMigratedData(const std::string &tableName, VBucket return status == DistributedDB::OK ? GeneralError::E_OK : GeneralError::E_ERROR; } +int32_t RdbGeneralStore::CleanTrackerData(const std::string &tableName, int64_t cursor) +{ + std::shared_lock lock(rwMutex_); + if (delegate_ == nullptr) { + ZLOGE("Database already closed! database:%{public}s, table:%{public}s", + Anonymous::Change(storeInfo_.storeName).c_str(), Anonymous::Change(tableName).c_str()); + return GeneralError::E_ERROR; + } + + auto status = delegate_->CleanTrackerData(tableName, cursor); + return status == DistributedDB::OK ? GeneralError::E_OK : GeneralError::E_ERROR; +} + int32_t RdbGeneralStore::Sync(const Devices &devices, GenQuery &query, DetailAsync async, SyncParam &syncParam) { DistributedDB::Query dbQuery; diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.h b/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.h index b61d01c6609cb9fc4f6ad7735d2803e581ea32a3..dcb38ab14cb5be758c514d5bcaf393c8ffd202be 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.h @@ -84,6 +84,7 @@ public: int32_t Release() override; int32_t BindSnapshots(std::shared_ptr>> bindAssets) override; int32_t MergeMigratedData(const std::string &tableName, VBuckets&& values) override; + int32_t CleanTrackerData(const std::string &tableName, int64_t cursor) override; std::vector GetWaterVersion(const std::string &deviceId) override; std::pair LockCloudDB() override; int32_t UnLockCloudDB() override; diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp index eeb4d3795d6ee6cd9b758d79f0ce39aafe26c272..17d05d287ed0eebdef9d2b9b7c56b2628bc46dea 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp @@ -39,6 +39,7 @@ #include "metadata/meta_data_manager.h" #include "metadata/store_debug_info.h" #include "metadata/store_meta_data.h" +#include "metadata/store_meta_data_local.h" #include "rdb_general_store.h" #include "rdb_notifier_proxy.h" #include "rdb_query.h" @@ -51,6 +52,7 @@ #include "utils/constant.h" #include "utils/converter.h" #include "xcollie.h" +#include "permit_delegate.h" using OHOS::DistributedData::Anonymous; using OHOS::DistributedData::CheckerManager; using OHOS::DistributedData::MetaDataManager; @@ -209,6 +211,7 @@ int32_t RdbServiceImpl::OnAppExit(pid_t uid, pid_t pid, uint32_t tokenId, const } AutoCache::GetInstance().Enable(tokenId); } + heartbeatTaskIds_.Erase(pid); return E_OK; } @@ -787,6 +790,7 @@ int32_t RdbServiceImpl::AfterOpen(const RdbSyncerParam ¶m) } SaveDebugInfo(meta, param); + SavePromiseInfo(meta, param); AppIDMetaData appIdMeta; appIdMeta.bundleName = meta.bundleName; @@ -1097,7 +1101,7 @@ bool RdbServiceImpl::IsPostImmediately(const int32_t callingPid, const RdbNotify heartbeatTaskIds_.Compute(callingPid, [this, &postImmediately, &rdbNotifyConfig, &storeInfo, &eventInfo, &storeName](const int32_t &key, std::map &tasks) { auto iter = tasks.find(storeName); - ExecutorPool::TaskId taskId; + ExecutorPool::TaskId taskId = ExecutorPool::INVALID_TASK_ID; if (iter != tasks.end()) { taskId = iter->second; } @@ -1302,4 +1306,57 @@ int32_t RdbServiceImpl::SaveDebugInfo(const StoreMetaData &metaData, const RdbSy MetaDataManager::GetInstance().SaveMeta(metaData.GetDebugInfoKey(), debugMeta, true); return RDB_OK; } + +int32_t RdbServiceImpl::SavePromiseInfo(const StoreMetaData &metaData, const RdbSyncerParam ¶m) +{ + if (param.tokenIds_.empty() && param.uids_.empty()) { + return RDB_OK; + } + StoreMetaDataLocal localMeta; + localMeta.promiseInfo.tokenIds = param.tokenIds_; + localMeta.promiseInfo.uids = param.uids_; + localMeta.promiseInfo.permissionNames = param.permissionNames_; + MetaDataManager::GetInstance().SaveMeta(metaData.GetKeyLocal(), localMeta, true); + return RDB_OK; +} + +int32_t RdbServiceImpl::VerifyPromiseInfo(const RdbSyncerParam ¶m) +{ + XCollie xcollie(__FUNCTION__, HiviewDFX::XCOLLIE_FLAG_LOG | HiviewDFX::XCOLLIE_FLAG_RECOVERY); + auto meta = GetStoreMetaData(param); + auto tokenId = IPCSkeleton::GetCallingTokenID(); + auto uid = IPCSkeleton::GetCallingUid(); + meta.user = param.user_; + StoreMetaDataLocal localMeta; + auto isCreated = MetaDataManager::GetInstance().LoadMeta(meta.GetKeyLocal(), localMeta, true); + if (!isCreated) { + ZLOGE("Store not exist. bundleName:%{public}s, storeName:%{public}s", meta.bundleName.c_str(), + meta.storeId.c_str()); + return RDB_ERROR; + } + ATokenTypeEnum type = AccessTokenKit::GetTokenType(tokenId); + if (type == ATokenTypeEnum::TOKEN_NATIVE) { + auto tokenIdRet = + std::find(localMeta.promiseInfo.tokenIds.begin(), localMeta.promiseInfo.tokenIds.end(), tokenId); + auto uidRet = std::find(localMeta.promiseInfo.uids.begin(), localMeta.promiseInfo.uids.end(), uid); + bool isPromise = std::any_of(localMeta.promiseInfo.permissionNames.begin(), + localMeta.promiseInfo.permissionNames.end(), [tokenId](const std::string &permissionName) { + return PermitDelegate::VerifyPermission(permissionName, tokenId); + }); + if (tokenIdRet == localMeta.promiseInfo.tokenIds.end() && uidRet == localMeta.promiseInfo.uids.end() && + !isPromise) { + return RDB_ERROR; + } + } + if (type == ATokenTypeEnum::TOKEN_HAP) { + for (const auto& permissionName : localMeta.promiseInfo.permissionNames) { + if (PermitDelegate::VerifyPermission(permissionName, tokenId)) { + return RDB_OK; + } + } + ZLOGE("Permission denied! tokenId:0x%{public}x", tokenId); + return RDB_ERROR; + } + return RDB_OK; +} } // namespace OHOS::DistributedRdb \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h index 4b7312b6f6666e0a78851c03f66af57122ef3cfe..b49d448efd11186f487e6d558acf776a03b7d4ff 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h @@ -105,6 +105,8 @@ public: int32_t GetDebugInfo(const RdbSyncerParam ¶m, std::map &debugInfo) override; + int32_t VerifyPromiseInfo(const RdbSyncerParam ¶m) override; + private: using Watchers = DistributedData::AutoCache::Watchers; using StaticActs = DistributedData::StaticActs; @@ -202,6 +204,8 @@ private: int32_t SaveDebugInfo(const StoreMetaData &metaData, const RdbSyncerParam ¶m); + int32_t SavePromiseInfo(const StoreMetaData &metaData, const RdbSyncerParam ¶m); + int32_t PostSearchEvent(int32_t evtId, const RdbSyncerParam& param, DistributedData::SetSearchableEvent::EventInfo &eventInfo); diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.cpp index 6f6d0cf40f2d1f9556fa961bbc375739bf70e4f9..d30125b91792f1463bcf049ee9e89ac9ab68bc09 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.cpp @@ -438,4 +438,20 @@ int32_t RdbServiceStub::OnGetDebugInfo(MessageParcel &data, MessageParcel &reply } return RDB_OK; } + +int32_t RdbServiceStub::OnVerifyPromiseInfo(MessageParcel &data, MessageParcel &reply) +{ + RdbSyncerParam param; + if (!ITypesUtil::Unmarshal(data, param)) { + ZLOGE("Unmarshal bundleName_:%{public}s storeName_:%{public}s", param.bundleName_.c_str(), + Anonymous::Change(param.storeName_).c_str()); + return IPC_STUB_INVALID_DATA_ERR; + } + auto status = VerifyPromiseInfo(param); + if (!ITypesUtil::Marshal(reply, status)) { + ZLOGE("Marshal status:0x%{public}x", status); + return IPC_STUB_WRITE_PARCEL_ERR; + } + return RDB_OK; +} } // namespace OHOS::DistributedRdb diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.h b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.h index eb506e8550e6dfe0f5519eecbb76959d2245b19a..9164eb0a1ab0fe273a8a3aca5bf86e14c8eff8e0 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.h @@ -76,6 +76,8 @@ private: int32_t OnGetDebugInfo(MessageParcel& data, MessageParcel& reply); + int32_t OnVerifyPromiseInfo(MessageParcel& data, MessageParcel& reply); + using RequestHandle = int (RdbServiceStub::*)(MessageParcel &, MessageParcel &); static constexpr RequestHandle HANDLERS[static_cast(RdbServiceCode::RDB_SERVICE_CMD_MAX)] = { [static_cast(RdbServiceCode::RDB_SERVICE_CMD_OBTAIN_TABLE)] = @@ -108,7 +110,9 @@ private: &RdbServiceStub::OnLockCloudContainer, [static_cast(RdbServiceCode::RDB_SERVICE_CMD_UNLOCK_CLOUD_CONTAINER)] = &RdbServiceStub::OnUnlockCloudContainer, - [static_cast(RdbServiceCode::RDB_SERVICE_CMD_GET_DEBUG_INFO)] = &RdbServiceStub::OnGetDebugInfo + [static_cast(RdbServiceCode::RDB_SERVICE_CMD_GET_DEBUG_INFO)] = &RdbServiceStub::OnGetDebugInfo, + [static_cast(RdbServiceCode::RDB_SERVICE_CMD_VERIFY_PROMISE_INFO)] = + &RdbServiceStub::OnVerifyPromiseInfo }; }; } // namespace OHOS::DistributedRdb diff --git a/datamgr_service/services/distributeddataservice/service/test/cloud_data_test.cpp b/datamgr_service/services/distributeddataservice/service/test/cloud_data_test.cpp index b576ac0e302bea84ab15826fa8310b7e7cd9fdbf..7f54d05f07325ceabde2daab925f9d8d48f87bcf 100644 --- a/datamgr_service/services/distributeddataservice/service/test/cloud_data_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/cloud_data_test.cpp @@ -22,6 +22,7 @@ #include "checker_mock.h" #include "cloud/change_event.h" #include "cloud/cloud_event.h" +#include "cloud/cloud_report.h" #include "cloud/cloud_server.h" #include "cloud/cloud_share_event.h" #include "cloud/make_query_event.h" @@ -46,6 +47,7 @@ #include "rdb_service_impl.h" #include "rdb_types.h" #include "store/auto_cache.h" +#include "store/general_value.h" #include "store/store_info.h" #include "token_setproc.h" @@ -1982,5 +1984,23 @@ HWTEST_F(CloudDataTest, DoSubscribe, TestSize.Level0) status = cloudServiceImpl_->DoSubscribe(user); EXPECT_FALSE(status); } + +/** +* @tc.name: Report +* @tc.desc: Test Report. +* @tc.type: FUNC +* @tc.require: + */ +HWTEST_F(CloudDataTest, Report, TestSize.Level0) +{ + auto cloudReport = std::make_shared(); + auto prepareTraceId = cloudReport->GetPrepareTraceId(100); + EXPECT_EQ(prepareTraceId, ""); + auto requestTraceId = cloudReport->GetRequestTraceId(100); + EXPECT_EQ(requestTraceId, ""); + ReportParam reportParam{ 100, TEST_CLOUD_BUNDLE }; + auto ret = cloudReport->Report(reportParam); + EXPECT_TRUE(ret); +} } // namespace DistributedDataTest } // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/db_store_mock.cpp b/datamgr_service/services/distributeddataservice/service/test/mock/db_store_mock.cpp index 6466dd56c42129bffb3b4fd0e1e969b3384638a8..7b6b52b78160c6f1a6819fe00674476c54e66cdb 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/db_store_mock.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/mock/db_store_mock.cpp @@ -167,7 +167,8 @@ DBStatus DBStoreMock::Export(const std::string &filePath, const CipherPassword & return NOT_SUPPORT; } -DBStatus DBStoreMock::Import(const std::string &filePath, const CipherPassword &passwd) +DBStatus DBStoreMock::Import(const std::string &filePath, const CipherPassword &passwd, + bool isNeedIntegrityCheck) { return NOT_SUPPORT; } @@ -384,6 +385,11 @@ DBStatus DBStoreMock::Sync(const DeviceSyncOption &option, const DeviceSyncProce DBStatus DBStoreMock::CancelSync(uint32_t syncId) { return NOT_SUPPORT; +} + +KvStoreNbDelegate::DatabaseStatus DBStoreMock::GetDatabaseStatus() const +{ + return KvStoreNbDelegate::DatabaseStatus(); }; } // namespace DistributedData } // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/db_store_mock.h b/datamgr_service/services/distributeddataservice/service/test/mock/db_store_mock.h index d4f2c2aef400bc0bce75adbde441b59287b2e8e4..454e5d5ff9866c97ef9e5364d8996a5a65ff6b8c 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/db_store_mock.h +++ b/datamgr_service/services/distributeddataservice/service/test/mock/db_store_mock.h @@ -78,7 +78,8 @@ public: DBStatus SetConflictNotifier(int conflictType, const KvStoreNbConflictNotifier ¬ifier) override; DBStatus Rekey(const CipherPassword &password) override; DBStatus Export(const std::string &filePath, const CipherPassword &passwd, bool force) override; - DBStatus Import(const std::string &filePath, const CipherPassword &passwd) override; + DBStatus Import(const std::string &filePath, const CipherPassword &passwd, + bool isNeedIntegrityCheck = false) override; DBStatus StartTransaction() override; DBStatus Commit() override; DBStatus Rollback() override; @@ -116,6 +117,7 @@ public: DBStatus GetDeviceEntries(const std::string &device, std::vector &entries) const override; DBStatus Sync(const DeviceSyncOption &option, const DeviceSyncProcessCallback &onProcess) override; DBStatus CancelSync(uint32_t syncId) override; + DatabaseStatus GetDatabaseStatus() const override; private: static const uint32_t DEFAULT_SIZE = 0; DBStatus Get(ConcurrentMap &store, const Key &key, Value &value) const; diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/general_store_mock.cpp b/datamgr_service/services/distributeddataservice/service/test/mock/general_store_mock.cpp index 62c31e848204bd918da1424ead595d2b71bf9a1a..90e945f57448f76057398cf5715bc6d772630ee7 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/general_store_mock.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/mock/general_store_mock.cpp @@ -47,8 +47,8 @@ int32_t GeneralStoreMock::SetDistributedTables( return 0; } -int32_t GeneralStoreMock::SetTrackerTable(const std::string &tableName, const std::set &trackerColNames, - const std::string &extendColName, bool isForceUpgrade) +int32_t GeneralStoreMock::SetTrackerTable(const std::string &tableName, + const std::set &trackerColNames, const std::string &extendColName, bool isForceUpgrade) { return 0; } @@ -139,6 +139,11 @@ int32_t GeneralStoreMock::MergeMigratedData(const std::string &tableName, VBucke return 0; } +int32_t GeneralStoreMock::CleanTrackerData(const std::string &tableName, int64_t cursor) +{ + return 0; +} + std::pair> GeneralStoreMock::Query(const std::string &table, const std::string &sql, Values &&args) { diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/general_store_mock.h b/datamgr_service/services/distributeddataservice/service/test/mock/general_store_mock.h index 86f2c4ca0ab0d1afbb7df0819b50062fba32e2ad..401417b8bdd8bb61a936f3335012576bfb87f11b 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/general_store_mock.h +++ b/datamgr_service/services/distributeddataservice/service/test/mock/general_store_mock.h @@ -41,7 +41,7 @@ public: int32_t SetDistributedTables( const std::vector &tables, int32_t type, const std::vector &references) override; int32_t SetTrackerTable(const std::string &tableName, const std::set &trackerColNames, - const std::string &extendColName, bool isForceUpgrade) override; + const std::string &extendColName, bool isForceUpgrade = false) override; int32_t Insert(const std::string &table, VBuckets &&values) override; int32_t Update(const std::string &table, const std::string &setSql, Values &&values, const std::string &whereSql, Values &&conditions) override; @@ -62,6 +62,7 @@ public: int32_t Release() override; int32_t BindSnapshots(std::shared_ptr>> bindAssets) override; int32_t MergeMigratedData(const std::string &tableName, VBuckets &&values) override; + int32_t CleanTrackerData(const std::string &tableName, int64_t cursor) override; std::vector GetWaterVersion(const std::string &deviceId) override; void SetExecutor(std::shared_ptr executor) override; void MakeCursor(const std::map &entry); diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/kv_store_nb_delegate_mock.cpp b/datamgr_service/services/distributeddataservice/service/test/mock/kv_store_nb_delegate_mock.cpp index 9ab67e8b11ad2f55070ba9a73efda7bdb106abef..d37fc737609a308ccd3af28a68622f0a25daef4a 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/kv_store_nb_delegate_mock.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/mock/kv_store_nb_delegate_mock.cpp @@ -153,7 +153,8 @@ DBStatus KvStoreNbDelegateMock::Export(const std::string &filePath, return DBStatus::OK; } -DBStatus KvStoreNbDelegateMock::Import(const std::string &filePath, const CipherPassword &passwd) +DBStatus KvStoreNbDelegateMock::Import(const std::string &filePath, const CipherPassword &passwd, + bool isNeedIntegrityCheck) { return DBStatus::OK; } @@ -331,4 +332,9 @@ DBStatus KvStoreNbDelegateMock::CancelSync(uint32_t syncId) { return DBStatus::OK; } + +KvStoreNbDelegate::DatabaseStatus KvStoreNbDelegateMock::GetDatabaseStatus() const +{ + return {}; +} } // namespace DistributedDB \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/kv_store_nb_delegate_mock.h b/datamgr_service/services/distributeddataservice/service/test/mock/kv_store_nb_delegate_mock.h index a7483b7a5d9c5fbaba3043551c31ef4a06e911f7..7f3d77c8d184b2d02877307072caf3024eff713e 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/kv_store_nb_delegate_mock.h +++ b/datamgr_service/services/distributeddataservice/service/test/mock/kv_store_nb_delegate_mock.h @@ -66,7 +66,7 @@ public: const KvStoreNbConflictNotifier ¬ifier); DBStatus Rekey(const CipherPassword &password); DBStatus Export(const std::string &filePath, const CipherPassword &passwd, bool force = false); - DBStatus Import(const std::string &filePath, const CipherPassword &passwd); + DBStatus Import(const std::string &filePath, const CipherPassword &passwd, bool isNeedIntegrityCheck = false); DBStatus StartTransaction(); DBStatus Commit(); DBStatus Rollback(); @@ -106,6 +106,7 @@ public: DBStatus GetDeviceEntries(const std::string &device, std::vector &entries) const; DBStatus Sync(const DeviceSyncOption &option, const DeviceSyncProcessCallback &onProcess); DBStatus CancelSync(uint32_t syncId); + DatabaseStatus GetDatabaseStatus() const; }; } // namespace DistributedDB #endif // KV_STORE_NB_DELEGATE_H_MOCK \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/rdb_asset_loader_test.cpp b/datamgr_service/services/distributeddataservice/service/test/rdb_asset_loader_test.cpp index 165a766ae74270f188961c5d97f4bf55d5eb43ef..b4c02ebd809cd87ae50fbc82871f3c0b6803920a 100644 --- a/datamgr_service/services/distributeddataservice/service/test/rdb_asset_loader_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/rdb_asset_loader_test.cpp @@ -29,6 +29,7 @@ using namespace testing::ext; using namespace OHOS::DistributedRdb; using namespace OHOS::DistributedData; using Type = DistributedDB::Type; +using AssetsRecord = DistributedData::AssetRecord; const DistributedDB::Asset g_rdbAsset = { .version = 1, .name = "Phone", .assetId = "0", @@ -92,6 +93,74 @@ HWTEST_F(RdbAssetLoaderTest, Download, TestSize.Level0) EXPECT_EQ(result, DistributedDB::DBStatus::OK); } +/** +* @tc.name: BatchDownload +* @tc.desc: RdbAssetLoader batch download test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(RdbAssetLoaderTest, BatchDownload, TestSize.Level0) +{ + BindAssets bindAssets; + auto cloudAssetLoader = std::make_shared(); + DistributedRdb::RdbAssetLoader rdbAssetLoader(cloudAssetLoader, &bindAssets); + std::string tableName = "testTable"; + Type prefix; + std::map assets; + assets["asset1"].push_back(g_rdbAsset); + std::vector assetRecords; + DistributedDB::IAssetLoader::AssetRecord assetRecord { .gid = "gid", .prefix = prefix, .assets = assets }; + assetRecords.emplace_back(assetRecord); + rdbAssetLoader.BatchDownload(tableName, assetRecords); + ASSERT_TRUE(!assetRecords.empty()); + EXPECT_EQ(assetRecords[0].status, DistributedDB::DBStatus::OK); +} + +/** +* @tc.name: Convert001 +* @tc.desc: Convert test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(RdbAssetLoaderTest, Convert001, TestSize.Level0) +{ + BindAssets bindAssets; + auto cloudAssetLoader = std::make_shared(); + DistributedRdb::RdbAssetLoader rdbAssetLoader(cloudAssetLoader, &bindAssets); + Type prefix; + std::map assets; + assets["asset1"].push_back(g_rdbAsset); + std::vector assetRecords; + DistributedDB::IAssetLoader::AssetRecord assetRecord { .gid = "gid", .prefix = prefix, .assets = assets }; + assetRecords.emplace_back(assetRecord); + assetRecords.emplace_back(assetRecord); + auto assetsRecords = rdbAssetLoader.Convert(std::move(assetRecords)); + EXPECT_TRUE(!assetsRecords.empty()); +} + +/** +* @tc.name: Convert002 +* @tc.desc: Convert test. +* @tc.type: FUNC +* @tc.require: +* @tc.author: +*/ +HWTEST_F(RdbAssetLoaderTest, Convert002, TestSize.Level0) +{ + BindAssets bindAssets; + auto cloudAssetLoader = std::make_shared(); + DistributedRdb::RdbAssetLoader rdbAssetLoader(cloudAssetLoader, &bindAssets); + Value prefix; + VBucket assets; + std::vector assetsRecords; + AssetRecord assetsRecord { .gid = "gid", .prefix = prefix, .assets = assets }; + assetsRecords.emplace_back(assetsRecord); + auto assetRecords = rdbAssetLoader.Convert(std::move(assetsRecords)); + EXPECT_TRUE(!assetRecords.empty()); +} + /** * @tc.name: RemoveLocalAssets * @tc.desc: RdbAssetLoader RemoveLocalAssets test. diff --git a/datamgr_service/services/distributeddataservice/service/test/rdb_cloud_test.cpp b/datamgr_service/services/distributeddataservice/service/test/rdb_cloud_test.cpp index 3000a5d68259e7e963f24039fe29975a010324e9..cdfa288e99f448d32c028c1fc224a80f71abf5ef 100644 --- a/datamgr_service/services/distributeddataservice/service/test/rdb_cloud_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/rdb_cloud_test.cpp @@ -74,6 +74,8 @@ HWTEST_F(RdbCloudTest, RdbCloudTest002, TestSize.Level1) RdbCloud rdbCloud(cloudDB, &bindAssets); std::string tableName = "testTable"; rdbCloud.Lock(); + std::string traceId = "id"; + rdbCloud.SetPrepareTraceId(traceId); auto result = rdbCloud.BatchInsert(tableName, std::move(g_DBVBucket), g_DBVBucket); EXPECT_EQ(result, DBStatus::CLOUD_ERROR); DBVBucket extends = { diff --git a/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_impl.cpp b/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_impl.cpp index 939453cfd0c30e3af904976363aa48d0a5f9e1b9..cb0f376212bb9b79e6c53da43e56f0cef94a8c50 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_impl.cpp @@ -81,6 +81,7 @@ int32_t UdmfServiceImpl::SetData(CustomOption &option, UnifiedData &unifiedData, ZLOGD("start"); int32_t res = E_OK; UdmfBehaviourMsg msg; + std::string types; auto find = UD_INTENTION_MAP.find(option.intention); msg.channel = find == UD_INTENTION_MAP.end() ? "invalid" : find->second; msg.operation = "insert"; @@ -94,7 +95,13 @@ int32_t UdmfServiceImpl::SetData(CustomOption &option, UnifiedData &unifiedData, } auto errFind = ERROR_MAP.find(res); msg.result = errFind == ERROR_MAP.end() ? "E_ERROR" : errFind->second; - msg.dataType = unifiedData.GetTypes(); + + for (const auto &record : unifiedData.GetRecords()) { + for (const auto &type : record->GetUtdIds()) { + types.append("-").append(type); + } + } + msg.dataType = types; msg.dataSize = unifiedData.GetSize(); Reporter::GetInstance()->BehaviourReporter()->UDMFReport(msg); return res; @@ -158,6 +165,7 @@ int32_t UdmfServiceImpl::GetData(const QueryOption &query, UnifiedData &unifiedD ZLOGD("start"); int32_t res = E_OK; UdmfBehaviourMsg msg; + std::string types; auto find = UD_INTENTION_MAP.find(query.intention); msg.channel = find == UD_INTENTION_MAP.end() ? "invalid" : find->second; msg.operation = "insert"; @@ -171,7 +179,12 @@ int32_t UdmfServiceImpl::GetData(const QueryOption &query, UnifiedData &unifiedD } auto errFind = ERROR_MAP.find(res); msg.result = errFind == ERROR_MAP.end() ? "E_ERROR" : errFind->second; - msg.dataType = unifiedData.GetTypes(); + for (const auto &record : unifiedData.GetRecords()) { + for (const auto &type : record->GetUtdIds()) { + types.append("-").append(type); + } + } + msg.dataType = types; msg.dataSize = unifiedData.GetSize(); Reporter::GetInstance()->BehaviourReporter()->UDMFReport(msg); return res; diff --git a/interface_sdk/api/@ohos.data.relationalStore.d.ts b/interface_sdk/api/@ohos.data.relationalStore.d.ts index cbaa8eaa77bf366beda638f938888858c70da7e3..c4baa32240cad8658ae4c5ea265f0cbf842e5114 100644 --- a/interface_sdk/api/@ohos.data.relationalStore.d.ts +++ b/interface_sdk/api/@ohos.data.relationalStore.d.ts @@ -1472,6 +1472,7 @@ declare namespace relationalStore { /** * The type of transaction. * + * @type { TransactionType } * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 14 */ @@ -5717,8 +5718,6 @@ declare namespace relationalStore { * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform * @since 12 - * @deprecated since 14 - * @useinstead ohos.data.relationalStore.RdbStore.createTransaction */ beginTransaction(): void; @@ -5792,8 +5791,6 @@ declare namespace relationalStore { * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform * @since 12 - * @deprecated since 14 - * @useinstead ohos.data.relationalStore.Transaction.commit */ commit(): void; @@ -5867,8 +5864,6 @@ declare namespace relationalStore { * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform * @since 12 - * @deprecated since 14 - * @useinstead ohos.data.relationalStore.Transaction.rollback */ rollBack(): void; @@ -7253,7 +7248,7 @@ declare namespace relationalStore { /** * create a transaction instance and begin. * - * @param { TransactionOptions } The option for creating transactions. + * @param { TransactionOptions } options - The option for creating transactions. * @returns { Promise } The {@link Transaction} object if the operation is successful. * @throws { BusinessError } 14800000 - Inner error. * @throws { BusinessError } 14800011 - Database corrupted. @@ -7284,6 +7279,7 @@ declare namespace relationalStore { /** * commit the transaction. * + * @returns { Promise } Promise used to return the result. * @throws { BusinessError } 14800000 - Inner error. * @throws { BusinessError } 14800011 - Database corrupted. * @throws { BusinessError } 14800014 - Already closed. @@ -7302,6 +7298,7 @@ declare namespace relationalStore { /** * rollback the transaction. * + * @returns { Promise } Promise used to return the result. * @throws { BusinessError } 14800000 - Inner error. * @throws { BusinessError } 14800011 - Database corrupted. * @throws { BusinessError } 14800014 - Already closed. @@ -7596,7 +7593,7 @@ declare namespace relationalStore { * Queries data in the database based on SQL statement. * * @param { string } sql - Indicates the SQL statement to execute. - * @param { Array } bindArgs - Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. + * @param { Array } args - Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. * @returns { Promise } The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. @@ -7614,13 +7611,13 @@ declare namespace relationalStore { * @crossplatform * @since 14 */ - querySql(sql: string, bindArgs?: Array): Promise; + querySql(sql: string, args?: Array): Promise; /** * Queries data in the database based on SQL statement with sync interface. * * @param { string } sql - Indicates the SQL statement to execute. - * @param { Array } bindArgs - Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. + * @param { Array } args - Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. * @returns { ResultSet } The {@link ResultSet} object if the operation is successful. * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; *
2. Incorrect parameter types. @@ -7638,7 +7635,7 @@ declare namespace relationalStore { * @crossplatform * @since 14 */ - querySqlSync(sql: string, bindArgs?: Array): ResultSet; + querySqlSync(sql: string, args?: Array): ResultSet; /** * Executes a SQL statement that contains specified parameters and returns a value of ValueType. diff --git a/kv_store/bundle.json b/kv_store/bundle.json index b938a590d50878dccd6ea0e3fcd37df3ab0bd9b8..b69686167551c89728a1b0237fcbf497e4a9d6e1 100644 --- a/kv_store/bundle.json +++ b/kv_store/bundle.json @@ -54,7 +54,6 @@ "libuv", "openssl", "sqlite", - "zlib", "googletest" ], "kernel_special": {}, @@ -77,7 +76,8 @@ "napi", "safwk", "samgr", - "file_api" + "file_api", + "zlib" ] }, "build": { diff --git a/kv_store/frameworks/cj/src/distributed_kv_store_impl.cpp b/kv_store/frameworks/cj/src/distributed_kv_store_impl.cpp index ba1b762523244fe7d651c5d6ad35500ddbb475c7..2b311299d35eb4132550e0fe27c61fd4419b7a58 100644 --- a/kv_store/frameworks/cj/src/distributed_kv_store_impl.cpp +++ b/kv_store/frameworks/cj/src/distributed_kv_store_impl.cpp @@ -48,6 +48,7 @@ static int32_t ConvertCJErrCode(Status status) // 15100002 return CJ_ERROR_STORE_META_CHANGED; case CRYPT_ERROR: + case DATA_CORRUPTED: // 15100003 return CJ_ERROR_CRYPT_ERROR; case NOT_FOUND: @@ -220,7 +221,7 @@ uint64_t CJKVManager::GetKVStore(const char* cStoreId, const CJOptions cjOptions options.hapName = param_->hapName; std::shared_ptr kvStore; Status status = kvDataManager_.GetSingleKvStore(options, appId, storeId, kvStore); - if (status == CRYPT_ERROR) { + if (status == DATA_CORRUPTED) { options.rebuild = true; status = kvDataManager_.GetSingleKvStore(options, appId, storeId, kvStore); LOGE("Data has corrupted, rebuild db"); diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/include/backup_manager.h b/kv_store/frameworks/innerkitsimpl/kvdb/include/backup_manager.h index 9a9251d3c15e3e933c38365cedb2e5af34b67131..281db55f594732d9d2f85a20203d4f7433195af6 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/include/backup_manager.h +++ b/kv_store/frameworks/innerkitsimpl/kvdb/include/backup_manager.h @@ -28,6 +28,12 @@ class BackupManager { public: using DBStore = DistributedDB::KvStoreNbDelegate; using DBPassword = DistributedKv::SecurityManager::DBPassword; + struct BackupInfo { + std::string name; + std::string baseDir; + std::string appId; + std::string storeId; + }; struct ResidueInfo { size_t tmpBackupSize; size_t tmpKeySize; @@ -46,10 +52,8 @@ public: static BackupManager &GetInstance(); void Init(const std::string &baseDir); void Prepare(const std::string &path, const std::string &storeId); - Status Backup(const std::string &name, const std::string &baseDir, - const std::string &storeId, std::shared_ptr dbStore); - Status Restore(const std::string &name, const std::string &baseDir, - const std::string &appId, const std::string &storeId, std::shared_ptr dbStore); + Status Backup(const BackupInfo &info, std::shared_ptr dbStore); + Status Restore(const BackupInfo &info, std::shared_ptr dbStore, bool isCheckIntegrity); Status DeleteBackup(std::map &deleteList, const std::string &baseDir, const std::string &storeId); private: diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/include/security_manager.h b/kv_store/frameworks/innerkitsimpl/kvdb/include/security_manager.h index 49e8c3cbfcd13ed887f84addfd6b080b5e155dd6..22b56ea3da380ef37393ad01eb5588600c22e3f7 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/include/security_manager.h +++ b/kv_store/frameworks/innerkitsimpl/kvdb/include/security_manager.h @@ -49,6 +49,32 @@ public: } }; + class KeyFiles { + public: + KeyFiles(const std::string &name, const std::string &path, bool openFile = true); + ~KeyFiles(); + const std::string &GetKeyFilePath(); + int32_t Lock(); + int32_t UnLock(); + int32_t DestroyLock(); + private: + int32_t FileLock(int32_t lockType); + int32_t lockFd_ = -1; + std::string keyPath_; + std::string lockFile_; + }; + + class KeyFilesAutoLock { + public: + explicit KeyFilesAutoLock(KeyFiles& keyFiles); + ~KeyFilesAutoLock(); + KeyFilesAutoLock(const KeyFilesAutoLock&) = delete; + KeyFilesAutoLock& operator=(const KeyFilesAutoLock&) = delete; + int32_t UnLockAndDestroy(); + private: + KeyFiles& keyFiles_; + }; + static SecurityManager &GetInstance(); DBPassword GetDBPassword(const std::string &name, const std::string &path, bool needCreate = false); bool SaveDBPassword(const std::string &name, const std::string &path, const DistributedDB::CipherPassword &key); @@ -58,6 +84,10 @@ private: static constexpr const char *ROOT_KEY_ALIAS = "distributeddb_client_root_key"; static constexpr const char *HKS_BLOB_TYPE_NONCE = "Z5s0Bo571KoqwIi6"; static constexpr const char *HKS_BLOB_TYPE_AAD = "distributeddata_client"; + static constexpr const char *SUFFIX_KEY = ".key"; + static constexpr const char *SUFFIX_KEY_LOCK = ".key_lock"; + static constexpr const char *KEY_DIR = "/key"; + static constexpr const char *SLASH = "/"; static constexpr int KEY_SIZE = 32; static constexpr int HOURS_PER_YEAR = (24 * 365); diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/include/single_store_impl.h b/kv_store/frameworks/innerkitsimpl/kvdb/include/single_store_impl.h index 2d7a0f2c5cfa5aca355d8adc9dd316f47e7d5ffd..a6468c9a0c11434b4d6d904bd283029232f2dcca 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/include/single_store_impl.h +++ b/kv_store/frameworks/innerkitsimpl/kvdb/include/single_store_impl.h @@ -116,6 +116,7 @@ private: (std::chrono::steady_clock::now() + std::chrono::milliseconds(offset)).time_since_epoch()) .count(); } + static constexpr int32_t INTEGRITY_CHECK_API_VERSION = 14; static constexpr uint32_t NOTIFY_INTERVAL = 200; // ms static constexpr size_t MAX_VALUE_LENGTH = 4 * 1024 * 1024; static constexpr size_t MAX_OBSERVER_SIZE = 8; @@ -134,6 +135,7 @@ private: void Register(); void ReportDBCorruptedFault(Status status) const; + int32_t apiVersion_ = -1; bool isApplication_ = false; bool autoSync_ = false; bool cloudAutoSync_ = false; diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/include/store_util.h b/kv_store/frameworks/innerkitsimpl/kvdb/include/store_util.h index 4b93e8162a237fdaaa4fb0de91d22879c9e65c06..20a24ac1cacf84d245775077517183c1c2715033 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/include/store_util.h +++ b/kv_store/frameworks/innerkitsimpl/kvdb/include/store_util.h @@ -52,6 +52,7 @@ public: static bool RemoveRWXForOthers(const std::string &path); private: static std::atomic sequenceId_; + static std::map statusMap_; }; } // namespace OHOS::DistributedKv #endif // OHOS_DISTRIBUTED_DATA_FRAMEWORKS_KVDB_STORE_UTIL_H diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/src/backup_manager.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/src/backup_manager.cpp index 46e3047828459e6a2a95a4220454450650f58f92..33bd523526e0d9842ba9a3445b166ffb16cb89c1 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/src/backup_manager.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/src/backup_manager.cpp @@ -106,20 +106,20 @@ void BackupManager::CleanTmpData(const std::string &name) StoreUtil::Remove(tmpName); } -Status BackupManager::Backup( - const std::string &name, const std::string &baseDir, const std::string &storeId, std::shared_ptr dbStore) +Status BackupManager::Backup(const BackupInfo &info, std::shared_ptr dbStore) { if (dbStore == nullptr) { return ALREADY_CLOSED; } - if (name.size() == 0 || baseDir.size() == 0 || storeId.size() == 0 || name == AUTO_BACKUP_NAME) { + if (info.name.size() == 0 || info.baseDir.size() == 0 || info.storeId.size() == 0 || + info.name == AUTO_BACKUP_NAME) { return INVALID_ARGUMENT; } - std::string topPath = baseDir + BACKUP_TOP_PATH; - std::string storePath = topPath + "/" + storeId; - std::string backupFullName = storePath + "/" + name + BACKUP_POSTFIX; - std::string keyName = BACKUP_KEY_PREFIX + storeId + "_" + name; - std::string keyFullName = baseDir + KEY_PATH + "/" + keyName + BACKUP_KEY_POSTFIX; + std::string topPath = info.baseDir + BACKUP_TOP_PATH; + std::string storePath = topPath + "/" + info.storeId; + std::string backupFullName = storePath + "/" + info.name + BACKUP_POSTFIX; + std::string keyName = BACKUP_KEY_PREFIX + info.storeId + "_" + info.name; + std::string keyFullName = info.baseDir + KEY_PATH + "/" + keyName + BACKUP_KEY_POSTFIX; bool isCreate = !StoreUtil::IsFileExist(backupFullName); if ((StoreUtil::GetFiles(storePath).size() >= MAX_BACKUP_NUM) && isCreate) { @@ -128,7 +128,7 @@ Status BackupManager::Backup( (void)StoreUtil::InitPath(topPath); (void)StoreUtil::InitPath(storePath); KeepData(backupFullName, isCreate); - auto dbPassword = SecurityManager::GetInstance().GetDBPassword(storeId, baseDir); + auto dbPassword = SecurityManager::GetInstance().GetDBPassword(info.storeId, info.baseDir); if (dbPassword.IsValid()) { KeepData(keyFullName, isCreate); } @@ -137,7 +137,7 @@ Status BackupManager::Backup( auto status = StoreUtil::ConvertStatus(dbStatus); if (status == SUCCESS) { if (dbPassword.IsValid()) { - SecurityManager::GetInstance().SaveDBPassword(keyName, baseDir, dbPassword.password); + SecurityManager::GetInstance().SaveDBPassword(keyName, info.baseDir, dbPassword.password); CleanTmpData(keyFullName); } CleanTmpData(backupFullName); @@ -173,21 +173,20 @@ StoreUtil::FileInfo BackupManager::GetBackupFileInfo( return backupFile; } -Status BackupManager::Restore(const std::string &name, const std::string &baseDir, const std::string &appId, - const std::string &storeId, std::shared_ptr dbStore) +Status BackupManager::Restore(const BackupInfo &info, std::shared_ptr dbStore, bool isCheckIntegrity) { if (dbStore == nullptr) { return ALREADY_CLOSED; } - if (storeId.size() == 0 || baseDir.size() == 0) { + if (info.storeId.size() == 0 || info.baseDir.size() == 0) { return INVALID_ARGUMENT; } - auto backupFile = GetBackupFileInfo(name, baseDir, storeId); + auto backupFile = GetBackupFileInfo(info.name, info.baseDir, info.storeId); if (backupFile.name.size() == 0) { return INVALID_ARGUMENT; } - auto fullName = baseDir + BACKUP_TOP_PATH + "/" + storeId + "/" + backupFile.name; - auto password = GetRestorePassword(backupFile.name, baseDir, appId, storeId).password; + auto fullName = info.baseDir + BACKUP_TOP_PATH + "/" + info.storeId + "/" + backupFile.name; + auto password = GetRestorePassword(backupFile.name, info.baseDir, info.appId, info.storeId).password; auto dbStatus = dbStore->Import(fullName, password); auto status = StoreUtil::ConvertStatus(dbStatus); return status; diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/src/security_manager.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/src/security_manager.cpp index 4201c2a2b7e1454fe8c7aa901ef80f7918361f0f..b1195c2889de414f53f93156a1f65d17899d0f40 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/src/security_manager.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/src/security_manager.cpp @@ -16,8 +16,10 @@ #include "security_manager.h" #include +#include #include #include +#include #include #include "file_ex.h" @@ -71,6 +73,8 @@ SecurityManager::DBPassword SecurityManager::GetDBPassword(const std::string &na const std::string &path, bool needCreate) { DBPassword dbPassword; + KeyFiles keyFiles(name, path); + KeyFilesAutoLock fileLock(keyFiles); auto secKey = LoadKeyFromFile(name, path, dbPassword.isKeyOutdated); std::vector key{}; @@ -95,6 +99,8 @@ SecurityManager::DBPassword SecurityManager::GetDBPassword(const std::string &na bool SecurityManager::SaveDBPassword(const std::string &name, const std::string &path, const DistributedDB::CipherPassword &key) { + KeyFiles keyFiles(name, path); + KeyFilesAutoLock fileLock(keyFiles); std::vector pwd(key.GetData(), key.GetData() + key.GetSize()); auto result = SaveKeyToFile(name, path, pwd); pwd.assign(pwd.size(), 0); @@ -103,8 +109,11 @@ bool SecurityManager::SaveDBPassword(const std::string &name, const std::string void SecurityManager::DelDBPassword(const std::string &name, const std::string &path) { - auto keyPath = path + "/key/" + name + ".key"; + KeyFiles keyFiles(name, path); + KeyFilesAutoLock fileLock(keyFiles); + auto keyPath = keyFiles.GetKeyFilePath(); StoreUtil::Remove(keyPath); + fileLock.UnLockAndDestroy(); } std::vector SecurityManager::Random(int32_t len) @@ -121,11 +130,11 @@ std::vector SecurityManager::Random(int32_t len) std::vector SecurityManager::LoadKeyFromFile(const std::string &name, const std::string &path, bool &isOutdated) { - auto keyPath = path + "/key/" + name + ".key"; + auto keyPath = path + KEY_DIR + SLASH + name + SUFFIX_KEY; if (!FileExists(keyPath)) { return {}; } - StoreUtil::RemoveRWXForOthers(path + "/key"); + StoreUtil::RemoveRWXForOthers(path + KEY_DIR); std::vector content; auto loaded = LoadBufferFromFile(keyPath, content); @@ -159,7 +168,7 @@ bool SecurityManager::SaveKeyToFile(const std::string &name, const std::string & return false; } auto secretKey = Encrypt(key); - auto keyPath = path + "/key"; + auto keyPath = path + KEY_DIR; StoreUtil::InitPath(keyPath); std::vector content; auto time = std::chrono::system_clock::to_time_t(std::chrono::system_clock::system_clock::now()); @@ -167,7 +176,7 @@ bool SecurityManager::SaveKeyToFile(const std::string &name, const std::string & content.push_back(char((sizeof(time_t) / sizeof(uint8_t)) + KEY_SIZE)); content.insert(content.end(), date.begin(), date.end()); content.insert(content.end(), secretKey.begin(), secretKey.end()); - auto keyFullPath = keyPath + "/" + name + ".key"; + auto keyFullPath = keyPath + SLASH + name + SUFFIX_KEY; auto ret = SaveBufferToFile(keyFullPath, content); if (access(keyFullPath.c_str(), F_OK) == 0) { StoreUtil::RemoveRWXForOthers(keyFullPath); @@ -367,4 +376,83 @@ bool SecurityManager::IsKeyOutdated(const std::vector &date) return ((createTime + std::chrono::hours(HOURS_PER_YEAR)) < std::chrono::system_clock::now()); } +SecurityManager::KeyFiles::KeyFiles(const std::string &name, const std::string &path, bool openFile) +{ + keyPath_ = path + KEY_DIR + SLASH + name + SUFFIX_KEY; + lockFile_ = path + KEY_DIR + SLASH + name + SUFFIX_KEY_LOCK; + StoreUtil::InitPath(path + KEY_DIR); + if (!openFile) { + return; + } + lockFd_ = open(lockFile_.c_str(), O_RDONLY | O_CREAT, S_IRWXU | S_IRWXG); + if (lockFd_ < 0) { + ZLOGE("Open failed, errno:%{public}d, path:%{public}s", errno, StoreUtil::Anonymous(lockFile_).c_str()); + } +} + +SecurityManager::KeyFiles::~KeyFiles() +{ + if (lockFd_ < 0) { + return; + } + close(lockFd_); + lockFd_ = -1; +} + +const std::string &SecurityManager::KeyFiles::GetKeyFilePath() +{ + return keyPath_; +} + +int32_t SecurityManager::KeyFiles::Lock() +{ + return FileLock(LOCK_EX); +} + +int32_t SecurityManager::KeyFiles::UnLock() +{ + return FileLock(LOCK_UN); +} + +int32_t SecurityManager::KeyFiles::DestroyLock() +{ + if (lockFd_ > 0) { + close(lockFd_); + lockFd_ = -1; + } + StoreUtil::Remove(lockFile_); + return Status::SUCCESS; +} + +int32_t SecurityManager::KeyFiles::FileLock(int32_t lockType) +{ + if (lockFd_ < 0) { + return Status::INVALID_ARGUMENT; + } + int32_t errCode = 0; + do { + errCode = flock(lockFd_, lockType); + } while (errCode < 0 && errno == EINTR); + if (errCode < 0) { + ZLOGE("flock failed, type:%{public}d, errno:%{public}d, path:%{public}s", lockType, errno, + StoreUtil::Anonymous(lockFile_).c_str()); + return Status::ERROR; + } + return Status::SUCCESS; +} + +SecurityManager::KeyFilesAutoLock::KeyFilesAutoLock(KeyFiles& keyFiles) : keyFiles_(keyFiles) +{ + keyFiles_.Lock(); +} + +SecurityManager::KeyFilesAutoLock::~KeyFilesAutoLock() +{ + keyFiles_.UnLock(); +} +int32_t SecurityManager::KeyFilesAutoLock::UnLockAndDestroy() +{ + keyFiles_.UnLock(); + return keyFiles_.DestroyLock(); +} } // namespace OHOS::DistributedKv diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/src/single_store_impl.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/src/single_store_impl.cpp index 682f13e4585c7bc8837d22b1570ceada63b73e81..b5f12015493977bb36848673751df90a458d0897 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/src/single_store_impl.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/src/single_store_impl.cpp @@ -57,6 +57,13 @@ SingleStoreImpl::SingleStoreImpl( uint32_t tokenId = IPCSkeleton::GetSelfTokenID(); if (AccessTokenKit::GetTokenTypeFlag(tokenId) == TOKEN_HAP) { isApplication_ = true; + HapTokenInfo hapTokenInfo; + auto ret = AccessTokenKit::GetHapTokenInfo(tokenId, hapTokenInfo); + if (ret == 0) { + apiVersion_ = hapTokenInfo.apiVersion; + } else { + ZLOGE("GetHapTokenInfo fail, tokenId:%{public}d, ret:%{public}d", tokenId, ret); + } } } @@ -755,7 +762,15 @@ int32_t SingleStoreImpl::Close(bool isForce) Status SingleStoreImpl::Backup(const std::string &file, const std::string &baseDir) { DdsTrace trace(std::string(LOG_TAG "::") + std::string(__FUNCTION__)); - auto status = BackupManager::GetInstance().Backup(file, baseDir, storeId_, dbStore_); + if (isApplication_ && (apiVersion_ >= INTEGRITY_CHECK_API_VERSION)) { + auto dbStatus = dbStore_->CheckIntegrity(); + if (dbStatus != DistributedDB::DBStatus::OK) { + ZLOGE("CheckIntegrity fail, dbStatus:%{public}d", dbStatus); + return StoreUtil::ConvertStatus(dbStatus); + } + } + BackupManager::BackupInfo info = { .name = file, .baseDir = baseDir, .storeId = storeId_ }; + auto status = BackupManager::GetInstance().Backup(info, dbStore_); if (status != SUCCESS) { ZLOGE("status:0x%{public}x storeId:%{public}s backup:%{public}s ", status, StoreUtil::Anonymous(storeId_).c_str(), file.c_str()); @@ -770,7 +785,12 @@ Status SingleStoreImpl::Restore(const std::string &file, const std::string &base if (service != nullptr) { service->Close({ appId_ }, { storeId_ }); } - auto status = BackupManager::GetInstance().Restore(file, baseDir, appId_, storeId_, dbStore_); + bool isCheckIntegrity = false; + if (isApplication_ && (apiVersion_ >= INTEGRITY_CHECK_API_VERSION)) { + isCheckIntegrity = true; + } + BackupManager::BackupInfo info = { .name = file, .baseDir = baseDir, .appId = appId_, .storeId = storeId_ }; + auto status = BackupManager::GetInstance().Restore(info, dbStore_, isCheckIntegrity); if (status != SUCCESS) { ZLOGE("status:0x%{public}x storeId:%{public}s backup:%{public}s ", status, StoreUtil::Anonymous(storeId_).c_str(), file.c_str()); @@ -1088,7 +1108,7 @@ bool SingleStoreImpl::IsRebuild() void SingleStoreImpl::ReportDBCorruptedFault(Status status) const { - if (status == CRYPT_ERROR) { + if (status == DATA_CORRUPTED) { Options options = { .encrypt = encrypt_, .autoSync = autoSync_, .securityLevel = securityLevel_, .area = area_, .hapName = hapName_ }; KvStoreTuple tuple = { .appId = appId_, .storeId = storeId_ }; diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/src/store_factory.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/src/store_factory.cpp index daa0e51ae7b0191bf7d23e5cc5f0b08560507151..344c2a1fc7b20b6ed607c79ce4ea6365f1909afe 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/src/store_factory.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/src/store_factory.cpp @@ -103,11 +103,7 @@ std::shared_ptr StoreFactory::GetOrOpenStore(const AppId &appId, const Convertor &convertor = *(convertors_[options.kvStoreType]); kvStore = std::make_shared(dbStore, appId, options, convertor); }); - if (dbStatus == DBStatus::INVALID_PASSWD_OR_CORRUPTED_DB) { - status = DATA_CORRUPTED; - } else { - status = StoreUtil::ConvertStatus(dbStatus); - } + status = StoreUtil::ConvertStatus(dbStatus); if (kvStore == nullptr) { ZLOGE("failed! status:%{public}d appId:%{public}s storeId:%{public}s path:%{public}s", dbStatus, appId.appId.c_str(), StoreUtil::Anonymous(storeId.storeId).c_str(), path.c_str()); diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/src/store_manager.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/src/store_manager.cpp index e4e65af27a75a1d6d1ed453a4a39fcc7515f57af..4a7e48578e71c3ee9d238456c640da75840a42e7 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/src/store_manager.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/src/store_manager.cpp @@ -52,16 +52,14 @@ std::shared_ptr StoreManager::GetKVStore(const AppId &appId, cons } bool isCreate = false; auto kvStore = StoreFactory::GetInstance().GetOrOpenStore(appId, storeId, options, status, isCreate); + if (status == DATA_CORRUPTED && options.encrypt && GetSecretKeyFromService(appId, storeId, path) == SUCCESS) { + kvStore = StoreFactory::GetInstance().GetOrOpenStore(appId, storeId, options, status, isCreate); + } if (status == DATA_CORRUPTED) { - if (options.encrypt && GetSecretKeyFromService(appId, storeId, path) == SUCCESS) { - kvStore = StoreFactory::GetInstance().GetOrOpenStore(appId, storeId, options, status, isCreate); - } else { - ZLOGW("database is corrupt, storeId:%{public}s", StoreUtil::Anonymous(storeId.storeId).c_str()); - KvStoreTuple tuple = { .appId = appId.appId, .storeId = storeId.storeId }; - auto repoterDir = KVDBFaultHiViewReporter::GetDBPath(path, storeId.storeId); - KVDBFaultHiViewReporter::ReportKVDBCorruptedFault(options, status, errno, tuple, repoterDir); - status = CRYPT_ERROR; - } + ZLOGW("database is corrupt, storeId:%{public}s", StoreUtil::Anonymous(storeId.storeId).c_str()); + KvStoreTuple tuple = { .appId = appId.appId, .storeId = storeId.storeId }; + auto repoterDir = KVDBFaultHiViewReporter::GetDBPath(path, storeId.storeId); + KVDBFaultHiViewReporter::ReportKVDBCorruptedFault(options, status, errno, tuple, repoterDir); } if (kvStore != nullptr && status == SUCCESS && kvStore->IsRebuild()) { ZLOGI("rebuild store success, storeId:%{public}s", StoreUtil::Anonymous(storeId.storeId).c_str()); diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/src/store_util.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/src/store_util.cpp index 0b9672372c7be92613e11200e3d918b36f246fbc..9f49528669465b2467b61e327afe9bdeaf08b100 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/src/store_util.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/src/store_util.cpp @@ -31,6 +31,31 @@ constexpr const char *REPLACE_CHAIN = "***"; constexpr const char *DEFAULT_ANONYMOUS = "******"; constexpr int32_t SERVICE_GID = 3012; std::atomic StoreUtil::sequenceId_ = 0; +using DBStatus = DistributedDB::DBStatus; +std::map StoreUtil::statusMap_ = { + { DBStatus::BUSY, Status::DB_ERROR }, + { DBStatus::DB_ERROR, Status::DB_ERROR }, + { DBStatus::OK, Status::SUCCESS }, + { DBStatus::INVALID_ARGS, Status::INVALID_ARGUMENT }, + { DBStatus::NOT_FOUND, Status::NOT_FOUND }, + { DBStatus::INVALID_VALUE_FIELDS, Status::INVALID_VALUE_FIELDS }, + { DBStatus::INVALID_FIELD_TYPE, Status::INVALID_FIELD_TYPE }, + { DBStatus::CONSTRAIN_VIOLATION, Status::CONSTRAIN_VIOLATION }, + { DBStatus::INVALID_FORMAT, Status::INVALID_FORMAT }, + { DBStatus::INVALID_QUERY_FORMAT, Status::INVALID_QUERY_FORMAT }, + { DBStatus::INVALID_QUERY_FIELD, Status::INVALID_QUERY_FIELD }, + { DBStatus::NOT_SUPPORT, Status::NOT_SUPPORT }, + { DBStatus::TIME_OUT, Status::TIME_OUT }, + { DBStatus::OVER_MAX_LIMITS, Status::OVER_MAX_LIMITS }, + { DBStatus::INVALID_PASSWD_OR_CORRUPTED_DB, Status::DATA_CORRUPTED }, + { DBStatus::SCHEMA_MISMATCH, Status::SCHEMA_MISMATCH }, + { DBStatus::INVALID_SCHEMA, Status::INVALID_SCHEMA }, + { DBStatus::EKEYREVOKED_ERROR, Status::SECURITY_LEVEL_ERROR }, + { DBStatus::SECURITY_OPTION_CHECK_ERROR, Status::SECURITY_LEVEL_ERROR }, + { DBStatus::LOG_OVER_LIMITS, Status::WAL_OVER_LIMITS }, + { DBStatus::SQLITE_CANT_OPEN, Status::DB_CANT_OPEN } +}; + StoreUtil::DBSecurity StoreUtil::GetDBSecurity(int32_t secLevel) { if (secLevel < SecurityLevel::NO_LABEL || secLevel > SecurityLevel::S4) { @@ -119,51 +144,14 @@ uint32_t StoreUtil::Anonymous(const void *ptr) Status StoreUtil::ConvertStatus(DBStatus status) { - switch (status) { - case DBStatus::BUSY: // fallthrough - case DBStatus::DB_ERROR: - return Status::DB_ERROR; - case DBStatus::OK: - return Status::SUCCESS; - case DBStatus::INVALID_ARGS: - return Status::INVALID_ARGUMENT; - case DBStatus::NOT_FOUND: - return Status::NOT_FOUND; - case DBStatus::INVALID_VALUE_FIELDS: - return Status::INVALID_VALUE_FIELDS; - case DBStatus::INVALID_FIELD_TYPE: - return Status::INVALID_FIELD_TYPE; - case DBStatus::CONSTRAIN_VIOLATION: - return Status::CONSTRAIN_VIOLATION; - case DBStatus::INVALID_FORMAT: - return Status::INVALID_FORMAT; - case DBStatus::INVALID_QUERY_FORMAT: - return Status::INVALID_QUERY_FORMAT; - case DBStatus::INVALID_QUERY_FIELD: - return Status::INVALID_QUERY_FIELD; - case DBStatus::NOT_SUPPORT: - return Status::NOT_SUPPORT; - case DBStatus::TIME_OUT: - return Status::TIME_OUT; - case DBStatus::OVER_MAX_LIMITS: - return Status::OVER_MAX_LIMITS; - case DBStatus::INVALID_PASSWD_OR_CORRUPTED_DB: - return Status::CRYPT_ERROR; - case DBStatus::SCHEMA_MISMATCH: - return Status::SCHEMA_MISMATCH; - case DBStatus::INVALID_SCHEMA: - return Status::INVALID_SCHEMA; - case DBStatus::EKEYREVOKED_ERROR: // fallthrough - case DBStatus::SECURITY_OPTION_CHECK_ERROR: - return Status::SECURITY_LEVEL_ERROR; - case DBStatus::LOG_OVER_LIMITS: - return Status::WAL_OVER_LIMITS; - default: - ZLOGE("unknown db error:0x%{public}x", status); - break; + auto iter = statusMap_.find(status); + if (iter == statusMap_.end()) { + ZLOGE("unknown db error:0x%{public}x", status); + return Status::ERROR; } - return Status::ERROR; + return iter->second; } + bool StoreUtil::InitPath(const std::string &path) { umask(DEFAULT_UMASK); diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/test/BUILD.gn b/kv_store/frameworks/innerkitsimpl/kvdb/test/BUILD.gn index a39cb3ec808e6e85f1e0c3e1b675886fb3c0f2a1..40adf8a4c2e429348720e243c1a2729703c1ae25 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/test/BUILD.gn +++ b/kv_store/frameworks/innerkitsimpl/kvdb/test/BUILD.gn @@ -136,6 +136,11 @@ ohos_unittest("SingleStoreImplTest") { "samgr:samgr_proxy", ] + cflags = [ + "-Dprivate=public", + "-Dprotected=public", + ] + deps = [ ":kvdb_src_file", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/:distributeddb", @@ -229,11 +234,6 @@ ohos_unittest("DevManagerMockTest") { configs = [ ":module_private_config" ] - cflags = [ - "-Dprivate=public", - "-Dprotected=public", - ] - external_deps = [ "c_utils:utils", "device_manager:devicemanagersdk", @@ -300,6 +300,29 @@ ohos_unittest("StoreFactoryTest") { ] } +ohos_unittest("SecurityManagerTest") { + module_out_path = module_output_path + + sources = [ "security_manager_test.cpp" ] + + configs = [ ":module_private_config" ] + + external_deps = [ + "c_utils:utils", + "hilog:libhilog", + "huks:libhukssdk", + "ipc:ipc_single", + "safwk:system_ability_fwk", + "samgr:samgr_proxy", + ] + + deps = [ + ":kvdb_src_file", + "../../../libs/distributeddb/:distributeddb", + "//third_party/googletest:gtest", + ] +} + ############################################################################### group("unittest") { testonly = true @@ -314,5 +337,9 @@ group("unittest") { ":StoreFactoryTest", ":StoreUtilTest", ] + + if (!use_libfuzzer) { + deps += [ ":SecurityManagerTest" ] + } } ############################################################################### diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/test/device_manager_mock.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/test/device_manager_mock.cpp index 18c735a8f785a4856aeb5016fc1410f803a479c2..321d5eb9074dc0544cbfe9b514391acd974befe4 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/test/device_manager_mock.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/test/device_manager_mock.cpp @@ -69,7 +69,11 @@ int32_t DeviceManager::GetLocalDeviceInfo(const std::string &pkgName, DmDeviceIn return DM_OK; } else { testDemo = 0; - deviceInfo.networkId[0] = 'a'; + DmDeviceInfo info; + info.networkId[0] = '1'; + info.networkId[1] = '1'; + DmDeviceInfo& infos = info; + deviceInfo = infos; return DM_OK; } } diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/test/device_manager_mock.h b/kv_store/frameworks/innerkitsimpl/kvdb/test/device_manager_mock.h index 229b28c79916d9f41ccc7fbe1c7bd566807a480f..52ac6aa05ac1d4fb6194a91ace62a642aef0a172 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/test/device_manager_mock.h +++ b/kv_store/frameworks/innerkitsimpl/kvdb/test/device_manager_mock.h @@ -30,7 +30,6 @@ namespace OHOS { namespace DistributedHardware { class DeviceManager { public: - int32_t testDemo = 0; static DeviceManager &GetInstance(); virtual int32_t InitDeviceManager(const std::string &pkgName, std::shared_ptr dmInitCallback); @@ -59,12 +58,9 @@ public: virtual int32_t GetEncryptedUuidByNetworkId(const std::string &pkgName, const std::string &networkId, std::string &uuid); private: + int32_t testDemo = 0; DeviceManager() = default; - ~DeviceManager() = default; - DeviceManager(const DeviceManager &) = delete; - DeviceManager &operator=(const DeviceManager &) = delete; - DeviceManager(DeviceManager &&) = delete; - DeviceManager &operator=(DeviceManager &&) = delete; + virtual ~DeviceManager() = default; }; } // namespace DistributedHardware } // namespace OHOS diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/test/security_manager_test.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/test/security_manager_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8d3222522d6f9624a21487776b50e3d45b27da9d --- /dev/null +++ b/kv_store/frameworks/innerkitsimpl/kvdb/test/security_manager_test.cpp @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "block_data.h" +#include "security_manager.h" +#include "store_util.h" +#include "log_print.h" + +namespace OHOS::Test { +using namespace testing::ext; +using namespace OHOS::DistributedKv; +class SecurityManagerTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void SecurityManagerTest::SetUpTestCase(void) +{} + +void SecurityManagerTest::TearDownTestCase(void) +{} + +void SecurityManagerTest::SetUp(void) +{} + +void SecurityManagerTest::TearDown(void) +{} + +/** +* @tc.name: DBPasswordTest +* @tc.desc: Test DBPassword function +* @tc.type: FUNC +*/ +HWTEST_F(SecurityManagerTest, DBPasswordTest, TestSize.Level1) +{ + SecurityManager::DBPassword passwd; + EXPECT_FALSE(passwd.IsValid()); + std::vector key = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + }; + passwd.SetValue(key.data(), key.size()); + EXPECT_TRUE(passwd.IsValid()); + EXPECT_EQ(passwd.GetSize(), 32); + auto newKey = passwd.GetData(); + EXPECT_EQ(newKey[0], 0x00); + passwd.Clear(); + EXPECT_FALSE(passwd.IsValid()); +} + +/** +* @tc.name: KeyFilesMultiLockTest +* @tc.desc: Test KeyFiles function +* @tc.type: FUNC +*/ +HWTEST_F(SecurityManagerTest, KeyFilesMultiLockTest, TestSize.Level1) +{ + std::string dbPath = "/data/service/el1/public/database/SecurityManagerTest"; + std::string dbName = "test1"; + StoreUtil::InitPath(dbPath); + SecurityManager::KeyFiles keyFiles(dbName, dbPath); + auto keyPath = keyFiles.GetKeyFilePath(); + EXPECT_EQ(keyPath, "/data/service/el1/public/database/SecurityManagerTest/key/test1.key"); + auto ret = keyFiles.Lock(); + EXPECT_EQ(ret, Status::SUCCESS); + ret = keyFiles.Lock(); + EXPECT_EQ(ret, Status::SUCCESS); + ret = keyFiles.UnLock(); + EXPECT_EQ(ret, Status::SUCCESS); + ret = keyFiles.UnLock(); + EXPECT_EQ(ret, Status::SUCCESS); +} + +/** +* @tc.name: KeyFilesTest +* @tc.desc: Test KeyFiles function +* @tc.type: FUNC +*/ +HWTEST_F(SecurityManagerTest, KeyFilesTest, TestSize.Level1) +{ + std::string dbPath = "/data/service/el1/public/database/SecurityManagerTest"; + std::string dbName = "test2"; + StoreUtil::InitPath(dbPath); + SecurityManager::KeyFiles keyFiles(dbName, dbPath); + auto keyPath = keyFiles.GetKeyFilePath(); + EXPECT_EQ(keyPath, "/data/service/el1/public/database/SecurityManagerTest/key/test2.key"); + keyFiles.Lock(); + auto blockResult = std::make_shared>(1, false); + std::thread thread([dbPath, dbName, blockResult]() { + SecurityManager::KeyFiles keyFiles(dbName, dbPath); + keyFiles.Lock(); + keyFiles.UnLock(); + blockResult->SetValue(true); + }); + auto beforeUnlock = blockResult->GetValue(); + EXPECT_FALSE(beforeUnlock); + blockResult->Clear(); + keyFiles.UnLock(); + auto afterUnlock = blockResult->GetValue(); + EXPECT_TRUE(afterUnlock); + thread.join(); +} + +/** +* @tc.name: KeyFilesAutoLockTest +* @tc.desc: Test KeyFilesAutoLock function +* @tc.type: FUNC +*/ +HWTEST_F(SecurityManagerTest, KeyFilesAutoLockTest, TestSize.Level1) +{ + std::string dbPath = "/data/service/el1/public/database/SecurityManagerTest"; + std::string dbName = "test3"; + StoreUtil::InitPath(dbPath); + SecurityManager::KeyFiles keyFiles(dbName, dbPath); + auto blockResult = std::make_shared>(1, false); + { + SecurityManager::KeyFilesAutoLock fileLock(keyFiles); + std::thread thread([dbPath, dbName, blockResult]() { + SecurityManager::KeyFiles keyFiles(dbName, dbPath); + SecurityManager::KeyFilesAutoLock fileLock(keyFiles); + blockResult->SetValue(true); + }); + EXPECT_FALSE(blockResult->GetValue()); + blockResult->Clear(); + thread.detach(); + } + EXPECT_TRUE(blockResult->GetValue()); +} +} \ No newline at end of file diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/test/single_store_impl_test.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/test/single_store_impl_test.cpp index 11e349a9245bdbcbc7f82078812147eeaae020a4..247bff5e6ee2e1599351547885c5e6646fee52e5 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/test/single_store_impl_test.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/test/single_store_impl_test.cpp @@ -24,8 +24,17 @@ #include "store_manager.h" #include "sys/stat.h" #include "types.h" +#include "single_store_impl.h" +#include "store_factory.h" +#include "dm_device_info.h" +#include "device_manager.h" + using namespace testing::ext; using namespace OHOS::DistributedKv; +using DBStatus = DistributedDB::DBStatus; +using DBStore = DistributedDB::KvStoreNbDelegate; +using SyncCallback = KvStoreSyncCallback; +using DevInfo = OHOS::DistributedHardware::DmDeviceInfo; namespace OHOS::Test { std::vector Random(int32_t len) @@ -65,6 +74,7 @@ public: void TearDown(); std::shared_ptr CreateKVStore(std::string storeIdTest, KvStoreType type, bool encrypt, bool backup); + std::shared_ptr CreateKVStore(bool autosync = false); std::shared_ptr kvStore_; static constexpr int MAX_RESULTSET_SIZE = 8; }; @@ -123,6 +133,37 @@ std::shared_ptr SingleStoreImplTest::CreateKVStore(std::string st return StoreManager::GetInstance().GetKVStore(appId, storeId, options, status); } +std::shared_ptr SingleStoreImplTest::CreateKVStore(bool autosync) +{ + AppId appId = { "SingleStoreImplTest" }; + StoreId storeId = { "DestructorTest" }; + std::shared_ptr kvStore; + Options options; + options.kvStoreType = SINGLE_VERSION; + options.securityLevel = S2; + options.area = EL1; + options.autoSync = autosync; + options.baseDir = "/data/service/el1/public/database/SingleStoreImplTest"; + StoreFactory storeFactory; + auto dbManager = storeFactory.GetDBManager(options.baseDir, appId); + auto dbPassword = + SecurityManager::GetInstance().GetDBPassword(storeId.storeId, options.baseDir, options.encrypt); + DBStatus dbStatus = DBStatus::DB_ERROR; + dbManager->GetKvStore(storeId, storeFactory.GetDBOption(options, dbPassword), + [&dbManager, &kvStore, &appId, &dbStatus, &options, &storeFactory](auto status, auto *store) { + dbStatus = status; + if (store == nullptr) { + return; + } + auto release = [dbManager](auto *store) { dbManager->CloseKvStore(store); }; + auto dbStore = std::shared_ptr(store, release); + storeFactory.SetDbConfig(dbStore); + const Convertor &convertor = *(storeFactory.convertors_[options.kvStoreType]); + kvStore = std::make_shared(dbStore, appId, options, convertor); + }); + return kvStore; +} + /** * @tc.name: GetStoreId * @tc.desc: get the store id of the kv store @@ -223,6 +264,45 @@ HWTEST_F(SingleStoreImplTest, PutBatch, TestSize.Level0) ASSERT_EQ(status, SUCCESS); } +/** + * @tc.name: GetStoreId + * @tc.desc: test IsRebuild + * @tc.type: FUNC + */ +HWTEST_F(SingleStoreImplTest, IsRebuild, TestSize.Level0) +{ + ASSERT_NE(kvStore_, nullptr); + auto status = kvStore_->IsRebuild(); + ASSERT_EQ(status, false); +} + +/** + * @tc.name: PutBatch001 + * @tc.desc: entry.value.Size() > MAX_VALUE_LENGTH + * @tc.type: FUNC + */ +HWTEST_F(SingleStoreImplTest, PutBatch001, TestSize.Level1) +{ + ASSERT_NE(kvStore_, nullptr); + size_t totalLength = SingleStoreImpl::MAX_VALUE_LENGTH + 1; // create an out-of-limit large number + char fillChar = 'a'; + std::string longString(totalLength, fillChar); + std::vector entries; + Entry entry; + entry.key = "PutBatch001_test"; + entry.value = longString; + entries.push_back(entry); + auto status = kvStore_->PutBatch(entries); + ASSERT_EQ(status, INVALID_ARGUMENT); + entries.clear(); + Entry entrys; + entrys.key = ""; + entrys.value = "PutBatch001_test_value"; + entries.push_back(entrys); + status = kvStore_->PutBatch(entries); + ASSERT_EQ(status, INVALID_ARGUMENT); +} + /** * @tc.name: Delete * @tc.desc: delete the value of the key @@ -412,6 +492,22 @@ HWTEST_F(SingleStoreImplTest, SubscribeKvStore002, TestSize.Level0) ASSERT_EQ(status, OVER_MAX_LIMITS); } +/** + * @tc.name: SubscribeKvStore003 + * @tc.desc: isClientSync_ + * @tc.type: FUNC + */ +HWTEST_F(SingleStoreImplTest, SubscribeKvStore003, TestSize.Level0) +{ + auto observer = std::make_shared(); + std::shared_ptr kvStore; + kvStore = CreateKVStore(); + ASSERT_NE(kvStore, nullptr); + kvStore->isClientSync_ = true; + auto status = kvStore->SubscribeKvStore(SUBSCRIBE_TYPE_LOCAL, observer); + ASSERT_EQ(status, SUCCESS); +} + /** * @tc.name: UnsubscribeKvStore * @tc.desc: unsubscribe @@ -722,6 +818,20 @@ HWTEST_F(SingleStoreImplTest, CloseResultSet, TestSize.Level0) ASSERT_EQ(outputTmp->GetEntry(entry), ALREADY_CLOSED); } +/** + * @tc.name: CloseResultSet001 + * @tc.desc: output = nullptr; + * @tc.type: FUNC + */ +HWTEST_F(SingleStoreImplTest, CloseResultSet001, TestSize.Level0) +{ + ASSERT_NE(kvStore_, nullptr); + std::shared_ptr output; + output = nullptr; + auto status = kvStore_->CloseResultSet(output); + ASSERT_EQ(status, INVALID_ARGUMENT); +} + /** * @tc.name: ResultSetMaxSizeTest * @tc.desc: test if kv supports 8 resultSets at the same time @@ -1795,4 +1905,128 @@ HWTEST_F(SingleStoreImplTest, SetConfig, TestSize.Level0) storeConfig.cloudConfig.enableCloud = true; ASSERT_EQ(kvStore->SetConfig(storeConfig), Status::SUCCESS); } + +/** + * @tc.name: GetDeviceEntries001 + * @tc.desc: + * @tc.type: FUNC + */ +HWTEST_F(SingleStoreImplTest, GetDeviceEntries001, TestSize.Level1) +{ + std::string PKG_NAME_EX = "_distributed_data"; + std::shared_ptr kvStore; + kvStore = CreateKVStore(); + ASSERT_NE(kvStore, nullptr); + std::vector output; + std::string device = DevManager::GetInstance().GetUnEncryptedUuid(); + std::string devices = "GetDeviceEntriestest"; + auto status = kvStore->GetDeviceEntries("", output); + ASSERT_EQ(status, INVALID_ARGUMENT); + status = kvStore->GetDeviceEntries(device, output); + ASSERT_EQ(status, SUCCESS); + DevInfo devinfo; + std::string PKG_NAME = std::to_string(getpid()) + PKG_NAME_EX; + DistributedHardware::DeviceManager::GetInstance().GetLocalDeviceInfo(PKG_NAME, devinfo); + ASSERT_NE(std::string(devinfo.deviceId), ""); + status = kvStore->GetDeviceEntries(std::string(devinfo.deviceId), output); + ASSERT_EQ(status, SUCCESS); +} + +/** + * @tc.name: DoSync001 + * @tc.desc: observer = nullptr + * @tc.type: FUNC + */ +HWTEST_F(SingleStoreImplTest, DoSync001, TestSize.Level1) +{ + std::shared_ptr kvStore; + kvStore = CreateKVStore(); + EXPECT_NE(kvStore, nullptr) << "kvStorePtr is null."; + std::string deviceId = "no_exist_device_id"; + std::vector deviceIds = { deviceId }; + uint32_t allowedDelayMs = 200; + kvStore->isClientSync_ = false; + auto syncStatus = kvStore->Sync(deviceIds, SyncMode::PUSH, allowedDelayMs); + EXPECT_EQ(syncStatus, Status::SUCCESS) << "sync device should return success"; + kvStore->isClientSync_ = true; + kvStore->syncObserver_ = nullptr; + syncStatus = kvStore->Sync(deviceIds, SyncMode::PUSH, allowedDelayMs); + EXPECT_EQ(syncStatus, Status::SUCCESS) << "sync device should return success"; +} + +/** + * @tc.name: SetCapabilityEnabled001 + * @tc.desc: enabled + * @tc.type: FUNC + */ +HWTEST_F(SingleStoreImplTest, SetCapabilityEnabled001, TestSize.Level1) +{ + ASSERT_NE(kvStore_, nullptr); + auto status = kvStore_->SetCapabilityEnabled(true); + ASSERT_EQ(status, SUCCESS); + status = kvStore_->SetCapabilityEnabled(false); + ASSERT_EQ(status, SUCCESS); +} + +/** + * @tc.name: DoClientSync001 + * @tc.desc: observer = nullptr + * @tc.type: FUNC + */ +HWTEST_F(SingleStoreImplTest, DoClientSync001, TestSize.Level1) +{ + std::shared_ptr kvStore; + kvStore = CreateKVStore(); + ASSERT_NE(kvStore, nullptr); + KVDBService::SyncInfo syncInfo; + syncInfo.mode = SyncMode::PULL; + syncInfo.seqId = 10; // syncInfo seqId + syncInfo.devices = { "networkId" }; + std::shared_ptr observer; + observer = nullptr; + auto status = kvStore->DoClientSync(syncInfo, observer); + ASSERT_EQ(status, DB_ERROR); +} + +/** + * @tc.name: DoNotifyChange001 + * @tc.desc: called within timeout + * @tc.type: FUNC + */ +HWTEST_F(SingleStoreImplTest, DoNotifyChange001, TestSize.Level1) +{ + std::shared_ptr kvStore; + kvStore = CreateKVStore(); + EXPECT_NE(kvStore, nullptr) << "kvStorePtr is null."; + auto status = kvStore->Put({ "Put Test" }, { "Put Value" }); + ASSERT_EQ(kvStore->notifyExpiredTime_, 0); + kvStore->cloudAutoSync_ = true; + status = kvStore->Put({ "Put Test" }, { "Put Value" }); + ASSERT_EQ(status, SUCCESS); + auto notifyExpiredTime = kvStore->notifyExpiredTime_; + ASSERT_NE(notifyExpiredTime, 0); + status = kvStore->Put({ "Put Test1" }, { "Put Value1" }); + ASSERT_EQ(status, SUCCESS); + ASSERT_EQ(notifyExpiredTime, kvStore->notifyExpiredTime_); + sleep(1); + status = kvStore->Put({ "Put Test2" }, { "Put Value2" }); + ASSERT_EQ(status, SUCCESS); + ASSERT_NE(notifyExpiredTime, kvStore->notifyExpiredTime_); +} + +/** + * @tc.name: DoAutoSync001 + * @tc.desc: observer = nullptr + * @tc.type: FUNC + */ +HWTEST_F(SingleStoreImplTest, DoAutoSync001, TestSize.Level1) +{ + std::shared_ptr kvStore; + kvStore = CreateKVStore(true); + ASSERT_NE(kvStore, nullptr); + kvStore->isApplication_ = true; + auto status = kvStore->Put({ "Put Test" }, { "Put Value" }); + ASSERT_EQ(status, SUCCESS); + ASSERT_EQ(!kvStore->autoSync_ || !kvStore->isApplication_, false); +} } // namespace OHOS::Test \ No newline at end of file diff --git a/kv_store/frameworks/jskitsimpl/distributedkvstore/include/js_kv_manager.h b/kv_store/frameworks/jskitsimpl/distributedkvstore/include/js_kv_manager.h index 645a98eeb1bae95d35ed870473392d5c3aff8187..b5d4b7b8076219b13180c56b2f0cc7479a2334b9 100644 --- a/kv_store/frameworks/jskitsimpl/distributedkvstore/include/js_kv_manager.h +++ b/kv_store/frameworks/jskitsimpl/distributedkvstore/include/js_kv_manager.h @@ -27,6 +27,7 @@ struct ContextParam { std::string hapName = ""; int32_t area = DistributedKv::Area::EL1; bool isSystemApp = false; + int32_t apiVersion = 9; }; class JsKVManager { public: @@ -62,6 +63,7 @@ private: std::shared_ptr uvQueue_; std::shared_ptr param_; static constexpr int MAX_APP_ID_LEN = 256; + static constexpr int API_14_VERSION = 14; }; } // namespace OHOS::DistributedKVStore #endif // OHOS_KV_MANAGER_H diff --git a/kv_store/frameworks/jskitsimpl/distributedkvstore/include/js_util.h b/kv_store/frameworks/jskitsimpl/distributedkvstore/include/js_util.h index 137bc07555e544348854448501856f9c77f7226f..59874055fa70bb55b6cbf7f7e26a9933d1f45f4a 100644 --- a/kv_store/frameworks/jskitsimpl/distributedkvstore/include/js_util.h +++ b/kv_store/frameworks/jskitsimpl/distributedkvstore/include/js_util.h @@ -218,6 +218,8 @@ public: static bool IsNull(napi_env env, napi_value value); + static int32_t GetApiVersion(napi_env, napi_value value); + private: enum { /* std::map to js::tuple */ @@ -229,6 +231,8 @@ private: static std::pair GetInnerValue( napi_env env, napi_value in, const std::string& prop, bool optional); static constexpr int MAX_STORE_ID_LEN = 128; + static constexpr int API_VERSION_MOD = 100; + static constexpr int DEFAULT_API_VERSION = 9; }; } // namespace OHOS::DistributedKVStore #endif // OHOS_JS_UTIL_H diff --git a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_error_utils.cpp b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_error_utils.cpp index 6718c6e51c5334d86efbeb6f765a4f5493c34046..1b0bef814797bace9c0ae1e00337d4272a3c05ae 100644 --- a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_error_utils.cpp +++ b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_error_utils.cpp @@ -29,10 +29,12 @@ static constexpr JsErrorCode JS_ERROR_CODE_MSGS[] = { { Status::NOT_FOUND, 15100004, "Not found." }, { Status::STORE_META_CHANGED, 15100002, "Open existed database with changed options." }, { Status::PERMISSION_DENIED, 202, "Permission denied" }, - { Status::CRYPT_ERROR, 15100003, "Database corrupted." }, + { Status::CRYPT_ERROR, 15100006, "Unable to open the database." }, { Status::OVER_MAX_LIMITS, 15100001, "Over max limits." }, { Status::ALREADY_CLOSED, 15100005, "Database or result set already closed." }, - { Status::WAL_OVER_LIMITS, 14800047, "the WAL file size exceeds the default limit."} + { Status::DATA_CORRUPTED, 15100003, "Database corrupted" }, + { Status::WAL_OVER_LIMITS, 14800047, "the WAL file size exceeds the default limit."}, + { Status::DB_CANT_OPEN, 15100006, "Unable to open the database." } }; const std::optional GetJsErrorCode(int32_t errorCode) diff --git a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_kv_manager.cpp b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_kv_manager.cpp index 58d745115c6732170d67d5162ce35e28e9e1019e..2b0941c2f4146c4e02ce3ccc8456791de34ed4ec 100644 --- a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_kv_manager.cpp +++ b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_kv_manager.cpp @@ -146,12 +146,14 @@ napi_value JsKVManager::GetKVStore(napi_env env, napi_callback_info info) ZLOGD("Options area:%{public}d dir:%{public}s", ctxt->options.area, ctxt->options.baseDir.c_str()); std::shared_ptr kvStore; Status status = kvm->kvDataManager_.GetSingleKvStore(ctxt->options, appId, storeId, kvStore); - if (status == CRYPT_ERROR) { + if (status == DATA_CORRUPTED) { ctxt->options.rebuild = true; status = kvm->kvDataManager_.GetSingleKvStore(ctxt->options, appId, storeId, kvStore); ZLOGE("Data has corrupted, rebuild db"); } - + if (status == CRYPT_ERROR && kvm->param_->apiVersion < API_14_VERSION) { + status = DATA_CORRUPTED; + } ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ? napi_ok : napi_generic_failure; ctxt->kvStore->SetKvStorePtr(kvStore); diff --git a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_util.cpp b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_util.cpp index ee6ea4dd7e1d1429a975f67f048dcd30b6aade4f..9087b7a21c3dca46dbfd08405a99155d68c1e349 100644 --- a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_util.cpp +++ b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_util.cpp @@ -1285,6 +1285,7 @@ JSUtil::StatusMsg JSUtil::GetValue(napi_env env, napi_value in, ContextParam &pa if (appInfo != nullptr) { statusMsg = GetNamedProperty(env, appInfo, "systemApp", param.isSystemApp); ASSERT(statusMsg.status == napi_ok, "get appInfo failed", napi_invalid_arg); + param.apiVersion = GetApiVersion(env, in); } return napi_ok; } @@ -1304,6 +1305,21 @@ bool JSUtil::IsNull(napi_env env, napi_value value) return false; } +int32_t JSUtil::GetApiVersion(napi_env env, napi_value value) +{ + auto context = AbilityRuntime::GetStageModeContext(env, value); + if (context == nullptr) { + ZLOGW("get context fail."); + return DEFAULT_API_VERSION; + } + auto appInfo = context->GetApplicationInfo(); + if (appInfo == nullptr) { + ZLOGW("get app info fail."); + return DEFAULT_API_VERSION; + } + return appInfo->apiTargetVersion % API_VERSION_MOD; +} + std::pair JSUtil::GetInnerValue( napi_env env, napi_value in, const std::string& prop, bool optional) { diff --git a/kv_store/frameworks/libs/CMakeLists.txt b/kv_store/frameworks/libs/CMakeLists.txt index b4125edadeac8b76aa23a4740849af8557c5dacb..ae863153d211f1ce3bdce9f2b8f0b5280a7555cc 100644 --- a/kv_store/frameworks/libs/CMakeLists.txt +++ b/kv_store/frameworks/libs/CMakeLists.txt @@ -6,7 +6,7 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdata-sections -fPIC -fpic -ffunction-s set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wl,--no-as-needed -ldl") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wformat=0 -Wattributes") set(MOCK_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../../mock) -add_definitions(-DUSE_HARMONY_SQLITE -DUSING_HILOG_LOGGER -DOMIT_FLATBUFFER -DEVLOOP_TIMER_ONLY) #-DOMIT_JSON +add_definitions(-DUSE_HARMONY_SQLITE -DUSING_HILOG_LOGGER -DOMIT_FLATBUFFER -DOMIT_MULTI_VER -DEVLOOP_TIMER_ONLY) #-DOMIT_JSON add_definitions(-DUSING_DB_JSON_EXTRACT_AUTOMATICALLY -DSQLITE_ENABLE_JSON1 -DRELATIONAL_STORE -DOMIT_ZLIB) add_definitions(-DWINDOWS_PLATFORM -DSQLITE_HAS_CODEC -DJSONCPP_USE_BUILDER -DEKEYREVOKED=128 -DSQLITE_ENABLE_DROPTABLE_CALLBACK) add_definitions(-Dfseeko64=fseeko) diff --git a/kv_store/frameworks/libs/distributeddb/BUILD.gn b/kv_store/frameworks/libs/distributeddb/BUILD.gn index b619cf6a46b1ca1b02282316ccbb1c28011ee610..80f2fba30ae6e4969771c43282cad7476f08de21 100644 --- a/kv_store/frameworks/libs/distributeddb/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/BUILD.gn @@ -112,13 +112,13 @@ ohos_shared_library("distributeddb") { "hilog:libhilog", "hisysevent:libhisysevent", "hitrace:hitrace_meter", + "zlib:shared_libz", ] public_external_deps = [ "jsoncpp:jsoncpp", "openssl:libcrypto_shared", "sqlite:sqlite", - "zlib:shared_libz", ] subsystem_name = "distributeddatamgr" diff --git a/kv_store/frameworks/libs/distributeddb/common/include/cloud/cloud_db_constant.h b/kv_store/frameworks/libs/distributeddb/common/include/cloud/cloud_db_constant.h index c20e5a7fb06dfad811613ec9984985acca614f4c..9ee39239948eb4f2204b28f813a2fbda1c4706fa 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/cloud/cloud_db_constant.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/cloud/cloud_db_constant.h @@ -79,15 +79,15 @@ public: // cloud data timestamp is utc ms precision // used for 100ns to ms when handle cloud data timestamp - static constexpr uint32_t TEN_THOUSAND = 10000; - static constexpr int64_t CLOUD_DEFAULT_TIMEOUT = -1; - static constexpr uint32_t ONE_SECOND = 1000 * TEN_THOUSAND; // 1000ms + static constexpr const uint32_t TEN_THOUSAND = 10000; + static constexpr const int64_t CLOUD_DEFAULT_TIMEOUT = -1; + static constexpr const uint32_t ONE_SECOND = 1000 * TEN_THOUSAND; // 1000ms - static constexpr int32_t MAX_UPLOAD_BATCH_COUNT = 2000; - static constexpr int32_t MIN_UPLOAD_BATCH_COUNT = 1; - static constexpr int32_t MAX_UPLOAD_SIZE = 128 * 1024 * 1024; // 128M - static constexpr int32_t MIN_UPLOAD_SIZE = 1024; // 1024Bytes - static constexpr int32_t MIN_RETRY_CONFLICT_COUNTS = -1; // unlimited + static constexpr const int32_t MAX_UPLOAD_BATCH_COUNT = 2000; + static constexpr const int32_t MIN_UPLOAD_BATCH_COUNT = 1; + static constexpr const int32_t MAX_UPLOAD_SIZE = 128 * 1024 * 1024; // 128M + static constexpr const int32_t MIN_UPLOAD_SIZE = 1024; // 1024Bytes + static constexpr const int32_t MIN_RETRY_CONFLICT_COUNTS = -1; // unlimited }; } // namespace DistributedDB #endif // CLOUD_DB_CONSTANT_H \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/common/include/db_common.h b/kv_store/frameworks/libs/distributeddb/common/include/db_common.h index 134ce2fe91c26bca5c2e577773688ec16f80e127..89a9f3080567d10deb7add1bf0951e8b2ab9d6f6 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/db_common.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/db_common.h @@ -119,6 +119,8 @@ public: static bool IsRecordError(const VBucket &record); + static bool IsRecordFailed(const VBucket &record, DBStatus status); + static bool IsIntTypeRecordError(const VBucket &record); static bool IsRecordIgnored(const VBucket &record); @@ -151,7 +153,7 @@ public: static std::string GetCursorKey(const std::string &tableName); - static bool ConvertToUInt(const std::string &str, uint64_t &value); + static bool ConvertToUInt64(const std::string &str, uint64_t &value); static void RemoveDuplicateAssetsData(std::vector &assets); private: diff --git a/kv_store/frameworks/libs/distributeddb/common/include/db_constant.h b/kv_store/frameworks/libs/distributeddb/common/include/db_constant.h index 67ef145fa7c02cea9965d4264ef7fbfc2dbb17e9..1d37bbf3c2f7591deff2f2f5d87506d8422f3568 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/db_constant.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/db_constant.h @@ -21,45 +21,45 @@ namespace DistributedDB { class DBConstant { public: - static constexpr size_t MAX_KEY_SIZE = 1024; - static constexpr size_t MAX_VALUE_SIZE = 4194304; - static constexpr size_t MAX_BATCH_SIZE = 128; - static constexpr size_t MAX_DEV_LENGTH = 128; - static constexpr size_t MAX_TRANSACTION_KEY_VALUE_LENS = 512 * 1024 * 1024; // 512M + static constexpr const size_t MAX_KEY_SIZE = 1024; + static constexpr const size_t MAX_VALUE_SIZE = 4194304; + static constexpr const size_t MAX_BATCH_SIZE = 128; + static constexpr const size_t MAX_DEV_LENGTH = 128; + static constexpr const size_t MAX_TRANSACTION_KEY_VALUE_LENS = 512 * 1024 * 1024; // 512M - static constexpr size_t MAX_DATA_DIR_LENGTH = 512; + static constexpr const size_t MAX_DATA_DIR_LENGTH = 512; - static constexpr size_t MAX_INKEYS_SIZE = 128; - static constexpr size_t MAX_SQL_ARGS_COUNT = 100; - static constexpr size_t MAX_IN_COUNT = 100; + static constexpr const size_t MAX_INKEYS_SIZE = 128; + static constexpr const size_t MAX_SQL_ARGS_COUNT = 100; + static constexpr const size_t MAX_IN_COUNT = 100; - static constexpr int DB_TYPE_LOCAL = 1; - static constexpr int DB_TYPE_MULTI_VER = 2; - static constexpr int DB_TYPE_SINGLE_VER = 3; + static constexpr const int DB_TYPE_LOCAL = 1; + static constexpr const int DB_TYPE_MULTI_VER = 2; + static constexpr const int DB_TYPE_SINGLE_VER = 3; - static constexpr int QUEUED_SYNC_LIMIT_DEFAULT = 32; - static constexpr int QUEUED_SYNC_LIMIT_MIN = 1; - static constexpr int QUEUED_SYNC_LIMIT_MAX = 4096; + static constexpr const int QUEUED_SYNC_LIMIT_DEFAULT = 32; + static constexpr const int QUEUED_SYNC_LIMIT_MIN = 1; + static constexpr const int QUEUED_SYNC_LIMIT_MAX = 4096; - static constexpr int MAX_DEVICES_SIZE = 100; - static constexpr int MAX_COMMIT_SIZE = 1000000; - static constexpr int MAX_ENTRIES_SIZE = 1000000; + static constexpr const int MAX_DEVICES_SIZE = 100; + static constexpr const int MAX_COMMIT_SIZE = 1000000; + static constexpr const int MAX_ENTRIES_SIZE = 1000000; - static constexpr uint32_t MAX_COLUMN = 32767; + static constexpr const uint32_t MAX_COLUMN = 32767; - static constexpr int MAX_REMOTEDATA_SIZE = 4194304; // 4M. + static constexpr const int MAX_REMOTEDATA_SIZE = 4194304; // 4M. - static constexpr int DEFAULT_ITER_TIMES = 5000; + static constexpr const int DEFAULT_ITER_TIMES = 5000; // In querySync, when getting query data finished, // if the block size reach the half of max block size, will get deleted data next; // if the block size not reach the half of max block size, will not get deleted data. - static constexpr float QUERY_SYNC_THRESHOLD = 0.50; + static constexpr const float QUERY_SYNC_THRESHOLD = 0.50; - static constexpr uint64_t MAX_USER_ID_LENGTH = 128; - static constexpr uint64_t MAX_APP_ID_LENGTH = 128; - static constexpr uint64_t MAX_STORE_ID_LENGTH = 128; - static constexpr uint64_t MAX_SUB_USER_LENGTH = 128; + static constexpr const uint64_t MAX_USER_ID_LENGTH = 128; + static constexpr const uint64_t MAX_APP_ID_LENGTH = 128; + static constexpr const uint64_t MAX_STORE_ID_LENGTH = 128; + static constexpr const uint64_t MAX_SUB_USER_LENGTH = 128; static const std::string MULTI_SUB_DIR; static const std::string SINGLE_SUB_DIR; @@ -121,35 +121,36 @@ public: static constexpr const char *QUERY_SYNC_PREFIX_KEY = "querySync"; static constexpr const char *DELETE_SYNC_PREFIX_KEY = "deleteSync"; - static const size_t MAX_NORMAL_PACK_ITEM_SIZE = 4000; - static const size_t MAX_HPMODE_PACK_ITEM_SIZE = 2000; // slide window mode to reduce last ack transfer time + static constexpr const size_t MAX_NORMAL_PACK_ITEM_SIZE = 4000; + // slide window mode to reduce last ack transfer time + static constexpr const size_t MAX_HPMODE_PACK_ITEM_SIZE = 2000; - static constexpr uint32_t MIN_MTU_SIZE = 1024; // 1KB - static constexpr uint32_t MAX_MTU_SIZE = 5242880; // 5MB + static constexpr const uint32_t MIN_MTU_SIZE = 1024; // 1KB + static constexpr const uint32_t MAX_MTU_SIZE = 5242880; // 5MB - static constexpr uint32_t MIN_TIMEOUT = 5000; // 5s - static constexpr uint32_t MAX_TIMEOUT = 60000; // 60s - static constexpr uint32_t MAX_SYNC_TIMEOUT = 300000; // 300s - static constexpr int INFINITE_WAIT = -1; // -1 is infinite waiting + static constexpr const uint32_t MIN_TIMEOUT = 5000; // 5s + static constexpr const uint32_t MAX_TIMEOUT = 60000; // 60s + static constexpr const uint32_t MAX_SYNC_TIMEOUT = 300000; // 300s + static constexpr const int INFINITE_WAIT = -1; // -1 is infinite waiting - static constexpr uint8_t DEFAULT_COMPTRESS_RATE = 100; + static constexpr const uint8_t DEFAULT_COMPTRESS_RATE = 100; - static constexpr size_t MAX_SYNC_BLOCK_SIZE = 31457280; // 30MB + static constexpr const size_t MAX_SYNC_BLOCK_SIZE = 31457280; // 30MB - static constexpr int DOUBLE_PRECISION = 15; - static constexpr int MAX_DISTRIBUTED_TABLE_COUNT = 32; + static constexpr const int DOUBLE_PRECISION = 15; + static constexpr const int MAX_DISTRIBUTED_TABLE_COUNT = 32; - static constexpr uint64_t MAX_LOG_SIZE_HIGH = 0x400000000ULL; // 16GB - static constexpr uint64_t MAX_LOG_SIZE_LOW = 0x400000ULL; // 4MB - static constexpr uint64_t MAX_LOG_SIZE_DEFAULT = 0x40000000ULL; // 1GB + static constexpr const uint64_t MAX_LOG_SIZE_HIGH = 0x400000000ULL; // 16GB + static constexpr const uint64_t MAX_LOG_SIZE_LOW = 0x400000ULL; // 4MB + static constexpr const uint64_t MAX_LOG_SIZE_DEFAULT = 0x40000000ULL; // 1GB - static constexpr int DEF_LIFE_CYCLE_TIME = 60000; // 60S + static constexpr const int DEF_LIFE_CYCLE_TIME = 60000; // 60S - static constexpr int RELATIONAL_LOG_TABLE_FIELD_NUM = 7; // field num is relational distributed log table + static constexpr const int RELATIONAL_LOG_TABLE_FIELD_NUM = 7; // field num is relational distributed log table - static constexpr uint64_t IGNORE_CONNECTION_ID = 0; + static constexpr const uint64_t IGNORE_CONNECTION_ID = 0; // Soft limit of a connection observer count. - static constexpr int MAX_OBSERVER_COUNT = 8; + static constexpr const int MAX_OBSERVER_COUNT = 8; // For relational static const std::string SYSTEM_TABLE_PREFIX; @@ -170,25 +171,30 @@ public: static constexpr const char *REMOTE_DEVICE_SCHEMA_KEY_PREFIX = "remote_device_schema_"; - static constexpr uint32_t MAX_CONDITION_KEY_LEN = 128; - static constexpr uint32_t MAX_CONDITION_VALUE_LEN = 128; - static constexpr uint32_t MAX_CONDITION_COUNT = 32; + static constexpr const uint32_t MAX_CONDITION_KEY_LEN = 128; + static constexpr const uint32_t MAX_CONDITION_VALUE_LEN = 128; + static constexpr const uint32_t MAX_CONDITION_COUNT = 32; - static constexpr uint32_t REMOTE_QUERY_MAX_SQL_LEN = 1000000U; + static constexpr const uint32_t REMOTE_QUERY_MAX_SQL_LEN = 1000000U; - static constexpr int HASH_KEY_SIZE = 32; // size of SHA256_DIGEST_LENGTH + static constexpr const int HASH_KEY_SIZE = 32; // size of SHA256_DIGEST_LENGTH static constexpr const char *TABLE_IS_DROPPED = "table_is_dropped_"; static constexpr const char *SQLITE_INNER_ROWID = "_rowid_"; - static constexpr int32_t DEFAULT_ROW_ID = -1; - static constexpr int STR_TO_LL_BY_DEVALUE = 10; + static constexpr const int32_t DEFAULT_ROW_ID = -1; + static constexpr const int STR_TO_LL_BY_DEVALUE = 10; // key in meta_data static constexpr const char *LOCALTIME_OFFSET_KEY = "localTimeOffset"; - static constexpr uint64_t OBSERVER_CHANGES_MASK = 0XF00; + static constexpr const uint64_t OBSERVER_CHANGES_MASK = 0XF00; static constexpr const char *STORAGE_TYPE_LONG = "long"; + + static constexpr const char *KV_SYNC_TABLE_NAME = "sync_data"; + static constexpr const char *KV_LOCAL_TABLE_NAME = "local_data"; + + static constexpr uint64_t INVALID_CURSOR = UINT64_MAX; }; } // namespace DistributedDB #endif // DISTRIBUTEDDB_CONSTANT_H diff --git a/kv_store/frameworks/libs/distributeddb/common/include/db_errno.h b/kv_store/frameworks/libs/distributeddb/common/include/db_errno.h index e8f136de1b27f999e435ea6dbefeab2a8d50b393..805da445d9d2f1826ece986229b8b8950148b7d9 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/db_errno.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/db_errno.h @@ -17,166 +17,174 @@ #define DISTRIBUTEDDB_ERRNO_H namespace DistributedDB { -constexpr int E_OK = 0; -constexpr int E_BASE = 1000; // different from the other errno. -constexpr int E_NOT_SUPPORT = (E_BASE + 1); // not support currently. -constexpr int E_INVALID_DB = (E_BASE + 2); // invalid db or connection. -constexpr int E_NOT_FOUND = (E_BASE + 3); // not found the resource. -constexpr int E_BUSY = (E_BASE + 4); // the db is busy -constexpr int E_UNEXPECTED_DATA = (E_BASE + 5); // Data does not match expectation. -constexpr int E_STALE = (E_BASE + 6); // Resource has been stopped, killed or destroyed. -constexpr int E_INVALID_ARGS = (E_BASE + 7); // the input args is invalid. -constexpr int E_REGISTER_OBSERVER = (E_BASE + 8); // error in register observer related function. -constexpr int E_TRANSACT_STATE = (E_BASE + 9); // transaction state error. -constexpr int E_SECUREC_ERROR = (E_BASE + 10); // security interface returns error -constexpr int E_OUT_OF_MEMORY = (E_BASE + 11); // out of memory -constexpr int E_NOT_PERMIT = (E_BASE + 12); // operation is not permitted -constexpr int E_ALREADY_REGISTER = (E_BASE + 13); // function or handle already registered and not allowed replace -constexpr int E_ALREADY_ALLOC = (E_BASE + 14); // Object had already been allocated -constexpr int E_ALREADY_RELEASE = (E_BASE + 15); // Object had already been released -constexpr int E_CONTAINER_FULL = (E_BASE + 16); // container full -constexpr int E_CONTAINER_EMPTY = (E_BASE + 17); // container empty -constexpr int E_CONTAINER_FULL_TO_NOTFULL = (E_BASE + 18); // container status changed from full to not full -constexpr int E_CONTAINER_NOTEMPTY_TO_EMPTY = (E_BASE + 19); // container status changed from full to not full -constexpr int E_WAIT_RETRY = (E_BASE + 20); // wait and retry later -constexpr int E_PARSE_FAIL = (E_BASE + 21); // parse packet or frame fail -constexpr int E_TIMEOUT = (E_BASE + 22); // time out -constexpr int E_SERIALIZE_ERROR = (E_BASE + 23); // serialize error -constexpr int E_DESERIALIZE_ERROR = (E_BASE + 24); // deserialize error -constexpr int E_NOT_REGISTER = (E_BASE + 25); // handler or function not registered -constexpr int E_LENGTH_ERROR = (E_BASE + 26); // error relative to length -constexpr int E_UNFINISHED = (E_BASE + 27); // get sync data unfinished. -constexpr int E_FINISHED = (E_BASE + 28); // get sync data finished. -constexpr int E_INVALID_MESSAGE_ID = (E_BASE + 29); // invalid messageId error -constexpr int E_MESSAGE_ID_ERROR = (E_BASE + 30); // messageId is not expected -constexpr int E_MESSAGE_TYPE_ERROR = (E_BASE + 31); // messageType is not expected -constexpr int E_PERIPHERAL_INTERFACE_FAIL = (E_BASE + 32); // peripheral interface fail -constexpr int E_NOT_INIT = (E_BASE + 33); // module may not init -constexpr int E_MAX_LIMITS = (E_BASE + 34); // over max limits. -constexpr int E_INVALID_CONNECTION = (E_BASE + 35); // invalid db connection. -constexpr int E_NO_SUCH_ENTRY = (E_BASE + 36); // invalid db connection. -constexpr int E_INTERNAL_ERROR = (E_BASE + 37); // an error due to code logic that is a bug -constexpr int E_CONTAINER_ONLY_DELAY_TASK = (E_BASE + 38); // only delay task left in the container -constexpr int E_SUM_CALCULATE_FAIL = (E_BASE + 39); // only delay task left in the container -constexpr int E_SUM_MISMATCH = (E_BASE + 40); // check sum mismatch -constexpr int E_OUT_OF_DATE = (E_BASE + 41); // things is out of date -constexpr int E_OBJ_IS_KILLED = (E_BASE + 42); // the refObject has been killed. -constexpr int E_SYSTEM_API_FAIL = (E_BASE + 43); // call the system api failed -constexpr int E_INVALID_DATA = (E_BASE + 44); // invalid data -constexpr int E_OUT_OF_IDS = (E_BASE + 45); // out of ids. -constexpr int E_SEND_DATA = (E_BASE + 46); // need send data -constexpr int E_NEED_TIMER = (E_BASE + 47); // timer is still need -constexpr int E_NO_NEED_TIMER = (E_BASE + 48); // timer no longer need -constexpr int E_COMBINE_FAIL = (E_BASE + 49); // fail in combining a frame -constexpr int E_END_TIMER = (E_BASE + 50); // timer no longer needed -constexpr int E_CALC_HASH = (E_BASE + 51); // calc hash error -constexpr int E_REMOVE_FILE = (E_BASE + 52); // remove file failed -constexpr int E_STATE_MACHINE_ERROR = (E_BASE + 53); // sync state machine error -constexpr int E_NO_DATA_SEND = (E_BASE + 54); // no data to send -constexpr int E_RECV_FINISHED = (E_BASE + 55); // recv finished -constexpr int E_NEED_PULL_REPONSE = (E_BASE + 56); // need to response pull request -constexpr int E_NO_SYNC_TASK = (E_BASE + 57); // no sync task to do -constexpr int E_INVALID_PASSWD_OR_CORRUPTED_DB = (E_BASE + 58); // invalid password or corrupted database. -constexpr int E_RESULT_SET_STATUS_INVALID = (E_BASE + 59); // status of result set is invalid. -constexpr int E_RESULT_SET_EMPTY = (E_BASE + 60); // the result set is empty. -constexpr int E_UPGRADE_FAILED = (E_BASE + 61); // the upgrade failed. -constexpr int E_INVALID_FILE = (E_BASE + 62); // import invalid file. -constexpr int E_INVALID_PATH = (E_BASE + 63); // the path is invalid. -constexpr int E_EMPTY_PATH = (E_BASE + 64); // the path is empty. -constexpr int E_TASK_BREAK_OFF = (E_BASE + 65); // task quit due to normal break off or error happen -constexpr int E_INCORRECT_DATA = (E_BASE + 66); // data in the database is incorrect -constexpr int E_NO_RESOURCE_FOR_USE = (E_BASE + 67); // no resource such as dbhandle for use -constexpr int E_LAST_SYNC_FRAME = (E_BASE + 68); // this frame is the last frame for this sync -constexpr int E_VERSION_NOT_SUPPORT = (E_BASE + 69); // version not support in any layer -constexpr int E_FRAME_TYPE_NOT_SUPPORT = (E_BASE + 70); // frame type not support -constexpr int E_INVALID_TIME = (E_BASE + 71); // the time is invalid -constexpr int E_INVALID_VERSION = (E_BASE + 72); // sqlite storage version is invalid -constexpr int E_SCHEMA_NOTEXIST = (E_BASE + 73); // schema does not exist -constexpr int E_INVALID_SCHEMA = (E_BASE + 74); // the schema is invalid -constexpr int E_SCHEMA_MISMATCH = (E_BASE + 75); // the schema is mismatch -constexpr int E_INVALID_FORMAT = (E_BASE + 76); // the value is invalid json or mismatch with the schema. -constexpr int E_READ_ONLY = (E_BASE + 77); // only have the read permission. -constexpr int E_NEED_ABILITY_SYNC = (E_BASE + 78); // ability sync has not done -constexpr int E_WAIT_NEXT_MESSAGE = (E_BASE + 79); // need remote device send a next message. -constexpr int E_LOCAL_DELETED = (E_BASE + 80); // local data is deleted by the unpublish. -constexpr int E_LOCAL_DEFEAT = (E_BASE + 81); // local data defeat the sync data while unpublish. -constexpr int E_LOCAL_COVERED = (E_BASE + 82); // local data is covered by the sync data while unpublish. -constexpr int E_INVALID_QUERY_FORMAT = (E_BASE + 83); // query format is not valid. -constexpr int E_INVALID_QUERY_FIELD = (E_BASE + 84); // query field is not valid. -constexpr int E_ALREADY_OPENED = (E_BASE + 85); // the database is already opened. -constexpr int E_ALREADY_SET = (E_BASE + 86); // already set. -constexpr int E_SAVE_DATA_NOTIFY = (E_BASE + 87); // notify remote device to keep alive, don't timeout -constexpr int E_RE_SEND_DATA = (E_BASE + 88); // need re send data -constexpr int E_EKEYREVOKED = (E_BASE + 89); // the EKEYREVOKED error -constexpr int E_SECURITY_OPTION_CHECK_ERROR = (E_BASE + 90); // remote device's SecurityOption not equal to local -constexpr int E_SYSTEM_API_ADAPTER_CALL_FAILED = (E_BASE + 91); // Adapter call failed -constexpr int E_NOT_NEED_DELETE_MSG = (E_BASE + 92); // not need delete msg, will be delete by sliding window receiver -constexpr int E_SLIDING_WINDOW_SENDER_ERR = (E_BASE + 93); // sliding window sender err -constexpr int E_SLIDING_WINDOW_RECEIVER_INVALID_MSG = (E_BASE + 94); // sliding window receiver invalid msg -constexpr int E_IGNORE_DATA = (E_BASE + 95); // ignore the data changed by other devices and ignore the same data. -constexpr int E_FORBID_CACHEDB = (E_BASE + 96); // such after rekey can not check passwd due to file control. -constexpr int E_INTERCEPT_DATA_FAIL = (E_BASE + 97); // Intercept push data failed. -constexpr int E_INVALID_COMPRESS_ALGO = (E_BASE + 98); // The algo is defined, but there's no implement for the algo. -constexpr int E_LOG_OVER_LIMITS = (E_BASE + 99); // The log file size is over the limits. -constexpr int E_MODE_MISMATCH = (E_BASE + 100); // dual sync mode mismatch -constexpr int E_NO_NEED_ACTIVE = (E_BASE + 101); // no need to active sync mode -constexpr int E_REMOTE_OVER_SIZE = (E_BASE + 102); // for remote query, over MAX_REMOTEDATA_SIZE -constexpr int E_NONEXISTENT = (E_BASE + 103); // for result set, nonexistent index -constexpr int E_TYPE_MISMATCH = (E_BASE + 104); // for result set, mismatch type -constexpr int E_DENIED_SQL = (E_BASE + 105); // denied sql, not permit to execute -constexpr int E_USER_CHANGE = (E_BASE + 106); // user change -constexpr int E_CONSTRAINT = (E_BASE + 107); // sql failed with constraint -constexpr int E_CLOUD_ERROR = (E_BASE + 108); // cloud error -constexpr int E_QUERY_END = (E_BASE + 110); // Indicates that query function has queried last data from cloud -constexpr int E_DB_CLOSED = (E_BASE + 111); // db is closed -constexpr int E_NOT_SET = (E_BASE + 112); // asset loader is not set -constexpr int E_CLOUD_NETWORK_ERROR = (E_BASE + 113); // network error in cloud -constexpr int E_CLOUD_SYNC_UNSET = (E_BASE + 114); // not set sync option in cloud -constexpr int E_CLOUD_FULL_RECORDS = (E_BASE + 115); // cloud's record is full -constexpr int E_CLOUD_LOCK_ERROR = (E_BASE + 116); // cloud failed to get sync lock -constexpr int E_CLOUD_ASSET_SPACE_INSUFFICIENT = (E_BASE + 117); // cloud failed to download asset -constexpr int E_CLOUD_INVALID_ASSET = (E_BASE + 118); // the asset is invalid -constexpr int E_TASK_PAUSED = (E_BASE + 119); // the task was paused, don't finished it -constexpr int E_CLOUD_VERSION_CONFLICT = (E_BASE + 120); // cloud failed to update version -constexpr int E_CLOUD_RECORD_EXIST_CONFLICT = (E_BASE + 121); // record conflict when upload/download -constexpr int E_REMOVE_ASSETS_FAILED = (E_BASE + 122); // remove local assets failed -constexpr int E_ABILITY_SYNC_FINISHED = (E_BASE + 123); // add at 108 version, use for machine check ability sync finish -constexpr int E_NEED_TIME_SYNC = (E_BASE + 124); // time sync has not done -constexpr int E_CLOUD_GID_MISMATCH = (E_BASE + 125); // cloud gid cannot match in db -constexpr int E_WITH_INVENTORY_DATA = (E_BASE + 126); // inventory data exists when setTracker for the first time -constexpr int E_WAIT_COMPENSATED_SYNC = (E_BASE + 127); // need to do compensated sync -constexpr int E_CLOUD_SYNC_TASK_MERGED = (E_BASE + 128); // sync task is merged -constexpr int E_SQLITE_CANT_OPEN = (E_BASE + 129); // the sqlite cannot open +constexpr const int E_OK = 0; +constexpr const int E_BASE = 1000; // different from the other errno. +constexpr const int E_NOT_SUPPORT = (E_BASE + 1); // not support currently. +constexpr const int E_INVALID_DB = (E_BASE + 2); // invalid db or connection. +constexpr const int E_NOT_FOUND = (E_BASE + 3); // not found the resource. +constexpr const int E_BUSY = (E_BASE + 4); // the db is busy +constexpr const int E_UNEXPECTED_DATA = (E_BASE + 5); // Data does not match expectation. +constexpr const int E_STALE = (E_BASE + 6); // Resource has been stopped, killed or destroyed. +constexpr const int E_INVALID_ARGS = (E_BASE + 7); // the input args is invalid. +constexpr const int E_REGISTER_OBSERVER = (E_BASE + 8); // error in register observer related function. +constexpr const int E_TRANSACT_STATE = (E_BASE + 9); // transaction state error. +constexpr const int E_SECUREC_ERROR = (E_BASE + 10); // security interface returns error +constexpr const int E_OUT_OF_MEMORY = (E_BASE + 11); // out of memory +constexpr const int E_NOT_PERMIT = (E_BASE + 12); // operation is not permitted +// function or handle already registered and not allowed replace +constexpr const int E_ALREADY_REGISTER = (E_BASE + 13); +constexpr const int E_ALREADY_ALLOC = (E_BASE + 14); // Object had already been allocated +constexpr const int E_ALREADY_RELEASE = (E_BASE + 15); // Object had already been released +constexpr const int E_CONTAINER_FULL = (E_BASE + 16); // container full +constexpr const int E_CONTAINER_EMPTY = (E_BASE + 17); // container empty +constexpr const int E_CONTAINER_FULL_TO_NOTFULL = (E_BASE + 18); // container status changed from full to not full +constexpr const int E_CONTAINER_NOTEMPTY_TO_EMPTY = (E_BASE + 19); // container status changed from full to not full +constexpr const int E_WAIT_RETRY = (E_BASE + 20); // wait and retry later +constexpr const int E_PARSE_FAIL = (E_BASE + 21); // parse packet or frame fail +constexpr const int E_TIMEOUT = (E_BASE + 22); // time out +constexpr const int E_SERIALIZE_ERROR = (E_BASE + 23); // serialize error +constexpr const int E_DESERIALIZE_ERROR = (E_BASE + 24); // deserialize error +constexpr const int E_NOT_REGISTER = (E_BASE + 25); // handler or function not registered +constexpr const int E_LENGTH_ERROR = (E_BASE + 26); // error relative to length +constexpr const int E_UNFINISHED = (E_BASE + 27); // get sync data unfinished. +constexpr const int E_FINISHED = (E_BASE + 28); // get sync data finished. +constexpr const int E_INVALID_MESSAGE_ID = (E_BASE + 29); // invalid messageId error +constexpr const int E_MESSAGE_ID_ERROR = (E_BASE + 30); // messageId is not expected +constexpr const int E_MESSAGE_TYPE_ERROR = (E_BASE + 31); // messageType is not expected +constexpr const int E_PERIPHERAL_INTERFACE_FAIL = (E_BASE + 32); // peripheral interface fail +constexpr const int E_NOT_INIT = (E_BASE + 33); // module may not init +constexpr const int E_MAX_LIMITS = (E_BASE + 34); // over max limits. +constexpr const int E_INVALID_CONNECTION = (E_BASE + 35); // invalid db connection. +constexpr const int E_NO_SUCH_ENTRY = (E_BASE + 36); // invalid db connection. +constexpr const int E_INTERNAL_ERROR = (E_BASE + 37); // an error due to code logic that is a bug +constexpr const int E_CONTAINER_ONLY_DELAY_TASK = (E_BASE + 38); // only delay task left in the container +constexpr const int E_SUM_CALCULATE_FAIL = (E_BASE + 39); // only delay task left in the container +constexpr const int E_SUM_MISMATCH = (E_BASE + 40); // check sum mismatch +constexpr const int E_OUT_OF_DATE = (E_BASE + 41); // things is out of date +constexpr const int E_OBJ_IS_KILLED = (E_BASE + 42); // the refObject has been killed. +constexpr const int E_SYSTEM_API_FAIL = (E_BASE + 43); // call the system api failed +constexpr const int E_INVALID_DATA = (E_BASE + 44); // invalid data +constexpr const int E_OUT_OF_IDS = (E_BASE + 45); // out of ids. +constexpr const int E_SEND_DATA = (E_BASE + 46); // need send data +constexpr const int E_NEED_TIMER = (E_BASE + 47); // timer is still need +constexpr const int E_NO_NEED_TIMER = (E_BASE + 48); // timer no longer need +constexpr const int E_COMBINE_FAIL = (E_BASE + 49); // fail in combining a frame +constexpr const int E_END_TIMER = (E_BASE + 50); // timer no longer needed +constexpr const int E_CALC_HASH = (E_BASE + 51); // calc hash error +constexpr const int E_REMOVE_FILE = (E_BASE + 52); // remove file failed +constexpr const int E_STATE_MACHINE_ERROR = (E_BASE + 53); // sync state machine error +constexpr const int E_NO_DATA_SEND = (E_BASE + 54); // no data to send +constexpr const int E_RECV_FINISHED = (E_BASE + 55); // recv finished +constexpr const int E_NEED_PULL_REPONSE = (E_BASE + 56); // need to response pull request +constexpr const int E_NO_SYNC_TASK = (E_BASE + 57); // no sync task to do +constexpr const int E_INVALID_PASSWD_OR_CORRUPTED_DB = (E_BASE + 58); // invalid password or corrupted database. +constexpr const int E_RESULT_SET_STATUS_INVALID = (E_BASE + 59); // status of result set is invalid. +constexpr const int E_RESULT_SET_EMPTY = (E_BASE + 60); // the result set is empty. +constexpr const int E_UPGRADE_FAILED = (E_BASE + 61); // the upgrade failed. +constexpr const int E_INVALID_FILE = (E_BASE + 62); // import invalid file. +constexpr const int E_INVALID_PATH = (E_BASE + 63); // the path is invalid. +constexpr const int E_EMPTY_PATH = (E_BASE + 64); // the path is empty. +constexpr const int E_TASK_BREAK_OFF = (E_BASE + 65); // task quit due to normal break off or error happen +constexpr const int E_INCORRECT_DATA = (E_BASE + 66); // data in the database is incorrect +constexpr const int E_NO_RESOURCE_FOR_USE = (E_BASE + 67); // no resource such as dbhandle for use +constexpr const int E_LAST_SYNC_FRAME = (E_BASE + 68); // this frame is the last frame for this sync +constexpr const int E_VERSION_NOT_SUPPORT = (E_BASE + 69); // version not support in any layer +constexpr const int E_FRAME_TYPE_NOT_SUPPORT = (E_BASE + 70); // frame type not support +constexpr const int E_INVALID_TIME = (E_BASE + 71); // the time is invalid +constexpr const int E_INVALID_VERSION = (E_BASE + 72); // sqlite storage version is invalid +constexpr const int E_SCHEMA_NOTEXIST = (E_BASE + 73); // schema does not exist +constexpr const int E_INVALID_SCHEMA = (E_BASE + 74); // the schema is invalid +constexpr const int E_SCHEMA_MISMATCH = (E_BASE + 75); // the schema is mismatch +constexpr const int E_INVALID_FORMAT = (E_BASE + 76); // the value is invalid json or mismatch with the schema. +constexpr const int E_READ_ONLY = (E_BASE + 77); // only have the read permission. +constexpr const int E_NEED_ABILITY_SYNC = (E_BASE + 78); // ability sync has not done +constexpr const int E_WAIT_NEXT_MESSAGE = (E_BASE + 79); // need remote device send a next message. +constexpr const int E_LOCAL_DELETED = (E_BASE + 80); // local data is deleted by the unpublish. +constexpr const int E_LOCAL_DEFEAT = (E_BASE + 81); // local data defeat the sync data while unpublish. +constexpr const int E_LOCAL_COVERED = (E_BASE + 82); // local data is covered by the sync data while unpublish. +constexpr const int E_INVALID_QUERY_FORMAT = (E_BASE + 83); // query format is not valid. +constexpr const int E_INVALID_QUERY_FIELD = (E_BASE + 84); // query field is not valid. +constexpr const int E_ALREADY_OPENED = (E_BASE + 85); // the database is already opened. +constexpr const int E_ALREADY_SET = (E_BASE + 86); // already set. +constexpr const int E_SAVE_DATA_NOTIFY = (E_BASE + 87); // notify remote device to keep alive, don't timeout +constexpr const int E_RE_SEND_DATA = (E_BASE + 88); // need re send data +constexpr const int E_EKEYREVOKED = (E_BASE + 89); // the EKEYREVOKED error +constexpr const int E_SECURITY_OPTION_CHECK_ERROR = (E_BASE + 90); // remote device's SecurityOption not equal to local +constexpr const int E_SYSTEM_API_ADAPTER_CALL_FAILED = (E_BASE + 91); // Adapter call failed +// not need delete msg, will be delete by sliding window receiver +constexpr const int E_NOT_NEED_DELETE_MSG = (E_BASE + 92); +constexpr const int E_SLIDING_WINDOW_SENDER_ERR = (E_BASE + 93); // sliding window sender err +constexpr const int E_SLIDING_WINDOW_RECEIVER_INVALID_MSG = (E_BASE + 94); // sliding window receiver invalid msg +constexpr const int E_IGNORE_DATA = (E_BASE + 95); // ignore the data changed by other devices and ignore the same data. +constexpr const int E_FORBID_CACHEDB = (E_BASE + 96); // such after rekey can not check passwd due to file control. +constexpr const int E_INTERCEPT_DATA_FAIL = (E_BASE + 97); // Intercept push data failed. +// The algo is defined, but there's no implement for the algo. +constexpr const int E_INVALID_COMPRESS_ALGO = (E_BASE + 98); +constexpr const int E_LOG_OVER_LIMITS = (E_BASE + 99); // The log file size is over the limits. +constexpr const int E_MODE_MISMATCH = (E_BASE + 100); // dual sync mode mismatch +constexpr const int E_NO_NEED_ACTIVE = (E_BASE + 101); // no need to active sync mode +constexpr const int E_REMOTE_OVER_SIZE = (E_BASE + 102); // for remote query, over MAX_REMOTEDATA_SIZE +constexpr const int E_NONEXISTENT = (E_BASE + 103); // for result set, nonexistent index +constexpr const int E_TYPE_MISMATCH = (E_BASE + 104); // for result set, mismatch type +constexpr const int E_DENIED_SQL = (E_BASE + 105); // denied sql, not permit to execute +constexpr const int E_USER_CHANGE = (E_BASE + 106); // user change +constexpr const int E_CONSTRAINT = (E_BASE + 107); // sql failed with constraint +constexpr const int E_CLOUD_ERROR = (E_BASE + 108); // cloud error +constexpr const int E_QUERY_END = (E_BASE + 110); // Indicates that query function has queried last data from cloud +constexpr const int E_DB_CLOSED = (E_BASE + 111); // db is closed +constexpr const int E_NOT_SET = (E_BASE + 112); // asset loader is not set +constexpr const int E_CLOUD_NETWORK_ERROR = (E_BASE + 113); // network error in cloud +constexpr const int E_CLOUD_SYNC_UNSET = (E_BASE + 114); // not set sync option in cloud +constexpr const int E_CLOUD_FULL_RECORDS = (E_BASE + 115); // cloud's record is full +constexpr const int E_CLOUD_LOCK_ERROR = (E_BASE + 116); // cloud failed to get sync lock +constexpr const int E_CLOUD_ASSET_SPACE_INSUFFICIENT = (E_BASE + 117); // cloud failed to download asset +constexpr const int E_CLOUD_INVALID_ASSET = (E_BASE + 118); // the asset is invalid +constexpr const int E_TASK_PAUSED = (E_BASE + 119); // the task was paused, don't finished it +constexpr const int E_CLOUD_VERSION_CONFLICT = (E_BASE + 120); // cloud failed to update version +constexpr const int E_CLOUD_RECORD_EXIST_CONFLICT = (E_BASE + 121); // record conflict when upload/download +constexpr const int E_REMOVE_ASSETS_FAILED = (E_BASE + 122); // remove local assets failed +// add at 108 version, use for machine check ability sync finish +constexpr const int E_ABILITY_SYNC_FINISHED = (E_BASE + 123); +constexpr const int E_NEED_TIME_SYNC = (E_BASE + 124); // time sync has not done +constexpr const int E_CLOUD_GID_MISMATCH = (E_BASE + 125); // cloud gid cannot match in db +constexpr const int E_WITH_INVENTORY_DATA = (E_BASE + 126); // inventory data exists when setTracker for the first time +constexpr const int E_WAIT_COMPENSATED_SYNC = (E_BASE + 127); // need to do compensated sync +constexpr const int E_CLOUD_SYNC_TASK_MERGED = (E_BASE + 128); // sync task is merged +constexpr const int E_SQLITE_CANT_OPEN = (E_BASE + 129); // the sqlite cannot open. // Num 150+ is reserved for schema related errno, since it may be added regularly -constexpr int E_JSON_PARSE_FAIL = (E_BASE + 150); // Parse json fail in grammatical level -constexpr int E_JSON_INSERT_PATH_EXIST = (E_BASE + 151); // Path already exist before insert -constexpr int E_JSON_INSERT_PATH_CONFLICT = (E_BASE + 152); // Nearest path ends with type not object -constexpr int E_JSON_DELETE_PATH_NOT_FOUND = (E_BASE + 153); // Path to delete not found -constexpr int E_SCHEMA_PARSE_FAIL = (E_BASE + 160); // Parse schema fail in content level -constexpr int E_SCHEMA_EQUAL_EXACTLY = (E_BASE + 161); // Two schemas are exactly the same -constexpr int E_SCHEMA_UNEQUAL_COMPATIBLE = (E_BASE + 162); // New schema contain different index -constexpr int E_SCHEMA_UNEQUAL_COMPATIBLE_UPGRADE = (E_BASE + 163); // New schema contain more field(index may differ) -constexpr int E_SCHEMA_UNEQUAL_INCOMPATIBLE = (E_BASE + 164); // New schema contain more field or index -constexpr int E_SCHEMA_VIOLATE_VALUE = (E_BASE + 165); // New schema violate values already exist in dbFile -constexpr int E_FLATBUFFER_VERIFY_FAIL = (E_BASE + 170); // Verify flatbuffer content(schema or value) fail. -constexpr int E_VALUE_MATCH = (E_BASE + 180); // Value match schema(strict or compatible) without amend -constexpr int E_VALUE_MATCH_AMENDED = (E_BASE + 181); // Value match schema(strict or compatible) with amend -constexpr int E_VALUE_MISMATCH_FEILD_COUNT = (E_BASE + 182); // Value mismatch schema in field count -constexpr int E_VALUE_MISMATCH_FEILD_TYPE = (E_BASE + 183); // Value mismatch schema in field type -constexpr int E_VALUE_MISMATCH_CONSTRAINT = (E_BASE + 184); // Value mismatch schema in constraint -constexpr int E_VALUE_MISMATCH_OTHER_REASON = (E_BASE + 185); // Value mismatch schema in other reason -constexpr int E_RELATIONAL_TABLE_EQUAL = (E_BASE + 186); // In table is same -constexpr int E_RELATIONAL_TABLE_COMPATIBLE = (E_BASE + 187); // In table is compatible -constexpr int E_RELATIONAL_TABLE_COMPATIBLE_UPGRADE = (E_BASE + 188); // In table has more fields with default value -constexpr int E_RELATIONAL_TABLE_INCOMPATIBLE = (E_BASE + 189); // In table is incompatible -constexpr int E_REBUILD_DATABASE = (E_BASE + 190); // database is rebuilt +constexpr const int E_JSON_PARSE_FAIL = (E_BASE + 150); // Parse json fail in grammatical level +constexpr const int E_JSON_INSERT_PATH_EXIST = (E_BASE + 151); // Path already exist before insert +constexpr const int E_JSON_INSERT_PATH_CONFLICT = (E_BASE + 152); // Nearest path ends with type not object +constexpr const int E_JSON_DELETE_PATH_NOT_FOUND = (E_BASE + 153); // Path to delete not found +constexpr const int E_SCHEMA_PARSE_FAIL = (E_BASE + 160); // Parse schema fail in content level +constexpr const int E_SCHEMA_EQUAL_EXACTLY = (E_BASE + 161); // Two schemas are exactly the same +constexpr const int E_SCHEMA_UNEQUAL_COMPATIBLE = (E_BASE + 162); // New schema contain different index +// New schema contain more field(index may differ) +constexpr const int E_SCHEMA_UNEQUAL_COMPATIBLE_UPGRADE = (E_BASE + 163); +constexpr const int E_SCHEMA_UNEQUAL_INCOMPATIBLE = (E_BASE + 164); // New schema contain more field or index +constexpr const int E_SCHEMA_VIOLATE_VALUE = (E_BASE + 165); // New schema violate values already exist in dbFile +constexpr const int E_FLATBUFFER_VERIFY_FAIL = (E_BASE + 170); // Verify flatbuffer content(schema or value) fail. +constexpr const int E_VALUE_MATCH = (E_BASE + 180); // Value match schema(strict or compatible) without amend +constexpr const int E_VALUE_MATCH_AMENDED = (E_BASE + 181); // Value match schema(strict or compatible) with amend +constexpr const int E_VALUE_MISMATCH_FEILD_COUNT = (E_BASE + 182); // Value mismatch schema in field count +constexpr const int E_VALUE_MISMATCH_FEILD_TYPE = (E_BASE + 183); // Value mismatch schema in field type +constexpr const int E_VALUE_MISMATCH_CONSTRAINT = (E_BASE + 184); // Value mismatch schema in constraint +constexpr const int E_VALUE_MISMATCH_OTHER_REASON = (E_BASE + 185); // Value mismatch schema in other reason +constexpr const int E_RELATIONAL_TABLE_EQUAL = (E_BASE + 186); // In table is same +constexpr const int E_RELATIONAL_TABLE_COMPATIBLE = (E_BASE + 187); // In table is compatible +// In table has more fields with default value +constexpr const int E_RELATIONAL_TABLE_COMPATIBLE_UPGRADE = (E_BASE + 188); +constexpr const int E_RELATIONAL_TABLE_INCOMPATIBLE = (E_BASE + 189); // In table is incompatible +constexpr const int E_REBUILD_DATABASE = (E_BASE + 190); // database is rebuilt // Num 200+ is reserved for fixed value errno, which should not be changed between time // Message with errorNo of Feedback-type is generated by CommunicatorAggregator without data part(No deserial if exist) -constexpr int E_FEEDBACK_UNKNOWN_MESSAGE = (E_BASE + 200); // Unknown message feedback from remote device -constexpr int E_FEEDBACK_COMMUNICATOR_NOT_FOUND = (E_BASE + 201); // Communicator not found feedback from remote device -constexpr int E_DISTRIBUTED_SCHEMA_NOT_FOUND = (E_BASE + 202); // Schema was not found in relational distributed tables -constexpr int E_DISTRIBUTED_SCHEMA_CHANGED = (E_BASE + 203); // Schema has change when do sync -constexpr int E_TABLE_REFERENCE_CHANGED = (E_BASE + 204); // table reference is changed +constexpr const int E_FEEDBACK_UNKNOWN_MESSAGE = (E_BASE + 200); // Unknown message feedback from remote device +// Communicator not found feedback from remote device +constexpr const int E_FEEDBACK_COMMUNICATOR_NOT_FOUND = (E_BASE + 201); +// Schema was not found in relational distributed tables +constexpr const int E_DISTRIBUTED_SCHEMA_NOT_FOUND = (E_BASE + 202); +constexpr const int E_DISTRIBUTED_SCHEMA_CHANGED = (E_BASE + 203); // Schema has change when do sync +constexpr const int E_TABLE_REFERENCE_CHANGED = (E_BASE + 204); // table reference is changed } // namespace DistributedDB #endif // DISTRIBUTEDDB_ERRNO_H diff --git a/kv_store/frameworks/libs/distributeddb/common/include/relational/relational_schema_object.h b/kv_store/frameworks/libs/distributeddb/common/include/relational/relational_schema_object.h index 934b986fb8a2f86f52c03fea0eb27129c4d02de5..0014ffdbd556b6ac20d1a915c37e5bcc91aaae93 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/relational/relational_schema_object.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/relational/relational_schema_object.h @@ -104,6 +104,7 @@ private: int ParseCheckTrackerTableName(const JsonObject &inJsonObject, TrackerTable &resultTable); int ParseCheckTrackerExtendName(const JsonObject &inJsonObject, TrackerTable &resultTable); int ParseCheckTrackerName(const JsonObject &inJsonObject, TrackerTable &resultTable); + int ParseCheckTrackerAction(const JsonObject &inJsonObject, TrackerTable &resultTable); void GenerateReachableRef(); void GenerateTableInfoReferenced(); void RefreshReachableRef(const TableReferenceProperty &referenceProperty); diff --git a/kv_store/frameworks/libs/distributeddb/common/include/relational/tracker_table.h b/kv_store/frameworks/libs/distributeddb/common/include/relational/tracker_table.h index 65d12d595e9ca3f8a233ed4b22b63e86e9f1e951..df376ab2cc6bbecaa6af5cba66c4517a6c08f9a7 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/relational/tracker_table.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/relational/tracker_table.h @@ -54,11 +54,13 @@ public: bool IsEmpty() const; bool IsChanging(const TrackerSchema &schema); int ReBuildTempTrigger(sqlite3 *db, TriggerMode::TriggerModeEnum mode, const AfterBuildAction &action); + void SetTrackerAction(bool isTrackerAction); private: std::string tableName_; std::string extendColName_; std::set trackerColNames_; + bool isTrackerAction_ = false; }; } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/common/include/runtime_context.h b/kv_store/frameworks/libs/distributeddb/common/include/runtime_context.h index e67596c252e1bf4fb509afc033b901e0bfa327bd..e0a9851421a391efac29abf89d76263a21034034 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/runtime_context.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/runtime_context.h @@ -199,6 +199,9 @@ public: virtual bool IsTimeTickMonitorValid() const = 0; virtual bool IsTimeChanged() const = 0; virtual void SetTimeChanged(bool timeChange) = 0; + + virtual bool IsBatchDownloadAssets() const = 0; + virtual void SetBatchDownloadAssets(bool isBatchDownload) = 0; protected: RuntimeContext() = default; virtual ~RuntimeContext() {} diff --git a/kv_store/frameworks/libs/distributeddb/common/include/version.h b/kv_store/frameworks/libs/distributeddb/common/include/version.h index 89632fe05eb577c3cf5bf027c93b30e3240e41c0..df8f0a016898fd2bcb47ec11a4e8652a873e9f92 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/version.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/version.h @@ -31,55 +31,56 @@ namespace DistributedDB { // submodule C, if we simply change version of C to 102 then version of A is still 105, but if we change version of C // to 106 then version of A is now 106, so we can know that something had changed for module A. constexpr const char *SOFTWARE_VERSION_STRING = "1.1.5"; // DistributedDB current version string. -constexpr uint32_t SOFTWARE_VERSION_BASE = 100; // Software version base value, do not change it -constexpr uint32_t SOFTWARE_VERSION_RELEASE_1_0 = SOFTWARE_VERSION_BASE + 1; // 1 for first released version -constexpr uint32_t SOFTWARE_VERSION_RELEASE_2_0 = SOFTWARE_VERSION_BASE + 2; // 2 for second released version -constexpr uint32_t SOFTWARE_VERSION_RELEASE_3_0 = SOFTWARE_VERSION_BASE + 3; // 3 for third released version -constexpr uint32_t SOFTWARE_VERSION_RELEASE_4_0 = SOFTWARE_VERSION_BASE + 4; // 4 for fourth released version -constexpr uint32_t SOFTWARE_VERSION_RELEASE_5_0 = SOFTWARE_VERSION_BASE + 5; // 5 for fifth released version -constexpr uint32_t SOFTWARE_VERSION_RELEASE_6_0 = SOFTWARE_VERSION_BASE + 6; // 6 for sixth released version +constexpr const uint32_t SOFTWARE_VERSION_BASE = 100; // Software version base value, do not change it +constexpr const uint32_t SOFTWARE_VERSION_RELEASE_1_0 = SOFTWARE_VERSION_BASE + 1; // 1 for first released version +constexpr const uint32_t SOFTWARE_VERSION_RELEASE_2_0 = SOFTWARE_VERSION_BASE + 2; // 2 for second released version +constexpr const uint32_t SOFTWARE_VERSION_RELEASE_3_0 = SOFTWARE_VERSION_BASE + 3; // 3 for third released version +constexpr const uint32_t SOFTWARE_VERSION_RELEASE_4_0 = SOFTWARE_VERSION_BASE + 4; // 4 for fourth released version +constexpr const uint32_t SOFTWARE_VERSION_RELEASE_5_0 = SOFTWARE_VERSION_BASE + 5; // 5 for fifth released version +constexpr const uint32_t SOFTWARE_VERSION_RELEASE_6_0 = SOFTWARE_VERSION_BASE + 6; // 6 for sixth released version // check both device has security label at 107 -constexpr uint32_t SOFTWARE_VERSION_RELEASE_7_0 = SOFTWARE_VERSION_BASE + 7; // 7 for seventh released version +constexpr const uint32_t SOFTWARE_VERSION_RELEASE_7_0 = SOFTWARE_VERSION_BASE + 7; // 7 for seventh released version // kv ability sync with 2 packet at 108 -constexpr uint32_t SOFTWARE_VERSION_RELEASE_8_0 = SOFTWARE_VERSION_BASE + 8; // 8 for eighth released version +constexpr const uint32_t SOFTWARE_VERSION_RELEASE_8_0 = SOFTWARE_VERSION_BASE + 8; // 8 for eighth released version // 109 version add field in request packet // add schema version in ability request // add schema version, system time offset, sender local time offset in data request -constexpr uint32_t SOFTWARE_VERSION_RELEASE_9_0 = SOFTWARE_VERSION_BASE + 9; // 9 for ninth released version +constexpr const uint32_t SOFTWARE_VERSION_RELEASE_9_0 = SOFTWARE_VERSION_BASE + 9; // 9 for ninth released version // 110 version add totalDataCount field in DataRequestPkt -constexpr uint32_t SOFTWARE_VERSION_RELEASE_10_0 = SOFTWARE_VERSION_BASE + 10; -constexpr uint32_t SOFTWARE_VERSION_EARLIEST = SOFTWARE_VERSION_RELEASE_1_0; -constexpr uint32_t SOFTWARE_VERSION_CURRENT = SOFTWARE_VERSION_RELEASE_10_0; -constexpr int VERSION_INVALID = INT32_MAX; +constexpr const uint32_t SOFTWARE_VERSION_RELEASE_10_0 = SOFTWARE_VERSION_BASE + 10; // 10 for tenth released version +constexpr const uint32_t SOFTWARE_VERSION_EARLIEST = SOFTWARE_VERSION_RELEASE_1_0; +constexpr const uint32_t SOFTWARE_VERSION_CURRENT = SOFTWARE_VERSION_RELEASE_10_0; +constexpr const int VERSION_INVALID = INT32_MAX; // Storage Related Version // LocalNaturalStore Related Version -constexpr int LOCAL_STORE_VERSION_CURRENT = SOFTWARE_VERSION_RELEASE_1_0; +constexpr const int LOCAL_STORE_VERSION_CURRENT = SOFTWARE_VERSION_RELEASE_1_0; // SingleVerNaturalStore Related Version -constexpr int SINGLE_VER_STORE_VERSION_V1 = SOFTWARE_VERSION_RELEASE_1_0; -constexpr int SINGLE_VER_STORE_VERSION_V2 = SOFTWARE_VERSION_RELEASE_2_0; -constexpr int SINGLE_VER_STORE_VERSION_V3 = SOFTWARE_VERSION_RELEASE_3_0; +constexpr const int SINGLE_VER_STORE_VERSION_V1 = SOFTWARE_VERSION_RELEASE_1_0; +constexpr const int SINGLE_VER_STORE_VERSION_V2 = SOFTWARE_VERSION_RELEASE_2_0; +constexpr const int SINGLE_VER_STORE_VERSION_V3 = SOFTWARE_VERSION_RELEASE_3_0; // 104 add modify time and create time into sync_data -constexpr int SINGLE_VER_STORE_VERSION_V4 = SOFTWARE_VERSION_RELEASE_4_0; -constexpr int SINGLE_VER_STORE_VERSION_CURRENT = SINGLE_VER_STORE_VERSION_V4; +constexpr const int SINGLE_VER_STORE_VERSION_V4 = SOFTWARE_VERSION_RELEASE_4_0; +constexpr const int SINGLE_VER_STORE_VERSION_CURRENT = SINGLE_VER_STORE_VERSION_V4; // MultiVerNaturalStore Related Version -constexpr uint32_t VERSION_FILE_VERSION_CURRENT = 1; -constexpr uint32_t MULTI_VER_STORE_VERSION_CURRENT = SOFTWARE_VERSION_RELEASE_1_0; -constexpr int MULTI_VER_COMMIT_STORAGE_VERSION_CURRENT = SOFTWARE_VERSION_RELEASE_1_0; -constexpr int MULTI_VER_DATA_STORAGE_VERSION_CURRENT = SOFTWARE_VERSION_RELEASE_1_0; -constexpr int MULTI_VER_METADATA_STORAGE_VERSION_CURRENT = SOFTWARE_VERSION_RELEASE_1_0; -constexpr int MULTI_VER_VALUESLICE_STORAGE_VERSION_CURRENT = SOFTWARE_VERSION_RELEASE_1_0; +constexpr const uint32_t VERSION_FILE_VERSION_CURRENT = 1; +constexpr const uint32_t MULTI_VER_STORE_VERSION_CURRENT = SOFTWARE_VERSION_RELEASE_1_0; +constexpr const int MULTI_VER_COMMIT_STORAGE_VERSION_CURRENT = SOFTWARE_VERSION_RELEASE_1_0; +constexpr const int MULTI_VER_DATA_STORAGE_VERSION_CURRENT = SOFTWARE_VERSION_RELEASE_1_0; +constexpr const int MULTI_VER_METADATA_STORAGE_VERSION_CURRENT = SOFTWARE_VERSION_RELEASE_1_0; +constexpr const int MULTI_VER_VALUESLICE_STORAGE_VERSION_CURRENT = SOFTWARE_VERSION_RELEASE_1_0; // Syncer Related Version -constexpr int TIME_SYNC_VERSION_V1 = SOFTWARE_VERSION_RELEASE_1_0; // time sync proctol added in version 101. -constexpr int ABILITY_SYNC_VERSION_V1 = SOFTWARE_VERSION_RELEASE_2_0; // Ability sync proctol added in version 102. -constexpr uint32_t SINGLE_VER_SYNC_PROCTOL_V1 = SOFTWARE_VERSION_RELEASE_1_0; // The 1st version num -constexpr uint32_t SINGLE_VER_SYNC_PROCTOL_V2 = SOFTWARE_VERSION_RELEASE_2_0; // The 2nd version num -constexpr uint32_t SINGLE_VER_SYNC_PROCTOL_V3 = SOFTWARE_VERSION_RELEASE_3_0; // The third version num +constexpr const int TIME_SYNC_VERSION_V1 = SOFTWARE_VERSION_RELEASE_1_0; // time sync proctol added in version 101. +// Ability sync proctol added in version 102. +constexpr const int ABILITY_SYNC_VERSION_V1 = SOFTWARE_VERSION_RELEASE_2_0; +constexpr const uint32_t SINGLE_VER_SYNC_PROCTOL_V1 = SOFTWARE_VERSION_RELEASE_1_0; // The 1st version num +constexpr const uint32_t SINGLE_VER_SYNC_PROCTOL_V2 = SOFTWARE_VERSION_RELEASE_2_0; // The 2nd version num +constexpr const uint32_t SINGLE_VER_SYNC_PROCTOL_V3 = SOFTWARE_VERSION_RELEASE_3_0; // The third version num // Local Meta Data Version -constexpr uint32_t LOCAL_META_DATA_VERSION_V1 = SOFTWARE_VERSION_RELEASE_8_0; -constexpr uint32_t LOCAL_META_DATA_VERSION_V2 = SOFTWARE_VERSION_RELEASE_9_0; +constexpr const uint32_t LOCAL_META_DATA_VERSION_V1 = SOFTWARE_VERSION_RELEASE_8_0; +constexpr const uint32_t LOCAL_META_DATA_VERSION_V2 = SOFTWARE_VERSION_RELEASE_9_0; } // namespace DistributedDB #endif // VERSION_H \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/common/src/auto_launch.cpp b/kv_store/frameworks/libs/distributeddb/common/src/auto_launch.cpp index 3a5056e2dba817750c58d9b69ef1f4cb7d67f8a1..32e6cdedc42c359935f282abc81f50ea48e11440 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/auto_launch.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/auto_launch.cpp @@ -1120,12 +1120,12 @@ int AutoLaunch::RegisterLifeCycleCallback(AutoLaunchItem &autoLaunchItem, const int errCode = E_OK; DatabaseLifeCycleNotifier notifier; if (isExt) { - notifier = [this](const std::string &identifier, const std::string &userId) { - ExtConnectionLifeCycleCallback(identifier, userId); + notifier = [this](const std::string &identifierExt, const std::string &userId) { + ExtConnectionLifeCycleCallback(identifierExt, userId); }; } else { - notifier = [this](const std::string &identifier, const std::string &userId) { - ConnectionLifeCycleCallback(identifier, userId); + notifier = [this](const std::string &identifierExt, const std::string &userId) { + ConnectionLifeCycleCallback(identifierExt, userId); }; } switch (autoLaunchItem.type) { diff --git a/kv_store/frameworks/libs/distributeddb/common/src/cloud/asset_operation_utils.cpp b/kv_store/frameworks/libs/distributeddb/common/src/cloud/asset_operation_utils.cpp index 853e33dd8990fe2703f28ad2e973af34c45aefdb..3fcfda78bbc8d36c8e980ebaddc5631569b1ee2e 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/cloud/asset_operation_utils.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/cloud/asset_operation_utils.cpp @@ -153,7 +153,8 @@ AssetOperationUtils::AssetOpType AssetOperationUtils::CheckWithDownload(bool bef if (dbAsset.name != cacheAsset.name) { continue; } - if (EraseBitMask(dbAsset.status) == AssetStatus::DOWNLOADING) { + if (EraseBitMask(dbAsset.status) == AssetStatus::DOWNLOADING || + EraseBitMask(dbAsset.status) == AssetStatus::ABNORMAL) { return AssetOpType::HANDLE; } return AssetOpType::NOT_HANDLE; diff --git a/kv_store/frameworks/libs/distributeddb/common/src/db_base64_utils.cpp b/kv_store/frameworks/libs/distributeddb/common/src/db_base64_utils.cpp index 6afb94a7481f1648250a5e161a90136d391ad12e..2d669972ff9bca18129b073279e5583d56016d15 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/db_base64_utils.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/db_base64_utils.cpp @@ -67,21 +67,21 @@ static void MakeCharFour(const std::array &cha const uint8_t table[CHAR_ARRAY_LENGTH_FOUR] = { static_cast((charArrayThree[static_cast(BASE64_ENCODE_CONSTANT::BASE64_ENCODE_INDEX0)] & static_cast(BASE64_ENCODE_CONSTANT::BASE64_ENCODE_MASK1)) >> - static_cast(BASE64_ENCODE_CONSTANT::BASE64_ENCODE_OFFSET2)), + static_cast(BASE64_ENCODE_CONSTANT::BASE64_ENCODE_OFFSET2)), static_cast(((charArrayThree[static_cast(BASE64_ENCODE_CONSTANT::BASE64_ENCODE_INDEX0)] & - static_cast(BASE64_ENCODE_CONSTANT::BASE64_ENCODE_MASK2)) + static_cast(BASE64_ENCODE_CONSTANT::BASE64_ENCODE_MASK2)) << static_cast(BASE64_ENCODE_CONSTANT::BASE64_ENCODE_OFFSET4)) + ((charArrayThree[static_cast(BASE64_ENCODE_CONSTANT::BASE64_ENCODE_INDEX1)] & - static_cast(BASE64_ENCODE_CONSTANT::BASE64_ENCODE_MASK5)) >> - static_cast(BASE64_ENCODE_CONSTANT::BASE64_ENCODE_OFFSET4))), + static_cast(BASE64_ENCODE_CONSTANT::BASE64_ENCODE_MASK5)) >> + static_cast(BASE64_ENCODE_CONSTANT::BASE64_ENCODE_OFFSET4))), static_cast(((charArrayThree[static_cast(BASE64_ENCODE_CONSTANT::BASE64_ENCODE_INDEX1)] & - static_cast(BASE64_ENCODE_CONSTANT::BASE64_ENCODE_MASK3)) + static_cast(BASE64_ENCODE_CONSTANT::BASE64_ENCODE_MASK3)) << static_cast(BASE64_ENCODE_CONSTANT::BASE64_ENCODE_OFFSET2)) + - ((charArrayThree[static_cast(BASE64_ENCODE_CONSTANT::BASE64_ENCODE_INDEX2)] & - static_cast(BASE64_ENCODE_CONSTANT::BASE64_ENCODE_MASK6)) >> + ((charArrayThree[static_cast(BASE64_ENCODE_CONSTANT::BASE64_ENCODE_INDEX2)] & + static_cast(BASE64_ENCODE_CONSTANT::BASE64_ENCODE_MASK6)) >> static_cast(BASE64_ENCODE_CONSTANT::BASE64_ENCODE_OFFSET6))), static_cast(charArrayThree[static_cast(BASE64_ENCODE_CONSTANT::BASE64_ENCODE_INDEX2)] & - static_cast(BASE64_ENCODE_CONSTANT::BASE64_ENCODE_MASK4)), + static_cast(BASE64_ENCODE_CONSTANT::BASE64_ENCODE_MASK4)), }; for (size_t index = 0; index < CHAR_ARRAY_LENGTH_FOUR; ++index) { charArrayFour[index] = table[index]; @@ -94,19 +94,19 @@ static void MakeCharTree(const std::array &char const uint8_t table[CHAR_ARRAY_LENGTH_THREE] = { static_cast((charArrayFour[static_cast(BASE64_DECODE_CONSTANT::BASE64_DECODE_INDEX0)] << static_cast(BASE64_DECODE_CONSTANT::BASE64_DECODE_OFFSET2)) + - ((charArrayFour[static_cast(BASE64_DECODE_CONSTANT::BASE64_DECODE_INDEX1)] & - static_cast(BASE64_DECODE_CONSTANT::BASE64_DECODE_MASK1)) >> + ((charArrayFour[static_cast(BASE64_DECODE_CONSTANT::BASE64_DECODE_INDEX1)] & + static_cast(BASE64_DECODE_CONSTANT::BASE64_DECODE_MASK1)) >> static_cast(BASE64_DECODE_CONSTANT::BASE64_DECODE_OFFSET4))), static_cast(((charArrayFour[static_cast(BASE64_DECODE_CONSTANT::BASE64_DECODE_INDEX1)] & - static_cast(BASE64_DECODE_CONSTANT::BASE64_DECODE_MASK2)) - << static_cast(BASE64_DECODE_CONSTANT::BASE64_DECODE_OFFSET4)) + - ((charArrayFour[static_cast(BASE64_DECODE_CONSTANT::BASE64_DECODE_INDEX2)] & - static_cast(BASE64_DECODE_CONSTANT::BASE64_DECODE_MASK3)) >> + static_cast(BASE64_DECODE_CONSTANT::BASE64_DECODE_MASK2)) + << static_cast(BASE64_DECODE_CONSTANT::BASE64_DECODE_OFFSET4)) + + ((charArrayFour[static_cast(BASE64_DECODE_CONSTANT::BASE64_DECODE_INDEX2)] & + static_cast(BASE64_DECODE_CONSTANT::BASE64_DECODE_MASK3)) >> static_cast(BASE64_DECODE_CONSTANT::BASE64_DECODE_OFFSET2))), static_cast(((charArrayFour[static_cast(BASE64_DECODE_CONSTANT::BASE64_DECODE_INDEX2)] & - static_cast(BASE64_DECODE_CONSTANT::BASE64_DECODE_MASK4)) + static_cast(BASE64_DECODE_CONSTANT::BASE64_DECODE_MASK4)) << static_cast(BASE64_DECODE_CONSTANT::BASE64_DECODE_OFFSET6)) + - charArrayFour[static_cast(BASE64_DECODE_CONSTANT::BASE64_DECODE_INDEX3)]), + charArrayFour[static_cast(BASE64_DECODE_CONSTANT::BASE64_DECODE_INDEX3)]), }; for (size_t index = 0; index < CHAR_ARRAY_LENGTH_THREE; ++index) { charArrayThree[index] = table[index]; diff --git a/kv_store/frameworks/libs/distributeddb/common/src/db_common.cpp b/kv_store/frameworks/libs/distributeddb/common/src/db_common.cpp index 5f2b11eef62497d395d047cd78db54a6d16ac5f7..03f1294ba0a2f6fe0e4efc19f9d0e9ac690bd908 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/db_common.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/db_common.cpp @@ -72,6 +72,7 @@ namespace { } static std::atomic_bool g_isGrdLoaded = false; +static std::mutex g_mutex; int DBCommon::CreateDirectory(const std::string &directory) { @@ -665,7 +666,15 @@ bool DBCommon::IsRecordIgnored(const VBucket &record) } auto status = std::get(record.at(CloudDbConstant::ERROR_FIELD)); return status == static_cast(DBStatus::CLOUD_RECORD_EXIST_CONFLICT) || - status == static_cast(DBStatus::CLOUD_VERSION_CONFLICT); + status == static_cast(DBStatus::CLOUD_VERSION_CONFLICT); +} + +bool DBCommon::IsRecordFailed(const VBucket &record, DBStatus status) +{ + if (status == OK) { + return false; + } + return DBCommon::IsRecordError(record) || !DBCommon::IsRecordSuccess(record); } bool DBCommon::IsRecordVersionConflict(const VBucket &record) @@ -760,6 +769,7 @@ uint64_t DBCommon::EraseBit(uint64_t origin, uint64_t eraseBit) void DBCommon::LoadGrdLib(void) { + std::lock_guard lock(g_mutex); static std::once_flag loadOnceFlag; std::call_once(loadOnceFlag, []() { #ifndef _WIN32 @@ -803,12 +813,25 @@ std::string DBCommon::GetCursorKey(const std::string &tableName) return DBConstant::RELATIONAL_PREFIX + "cursor_" + ToLowerCase(tableName); } -bool DBCommon::ConvertToUInt(const std::string &str, uint64_t &value) +bool DBCommon::ConvertToUInt64(const std::string &str, uint64_t &value) { auto [ptr, errCode] = std::from_chars(str.data(), str.data() + str.size(), value); return errCode == std::errc{} && ptr == str.data() + str.size(); } +bool CmpModifyTime(const std::string &preModifyTimeStr, const std::string &curModifyTimeStr) +{ + uint64_t curModifyTime = 0; + uint64_t preModifyTime = 0; + if (preModifyTimeStr.empty() || !DBCommon::ConvertToUInt64(preModifyTimeStr, preModifyTime)) { + return true; + } + if (curModifyTimeStr.empty() || !DBCommon::ConvertToUInt64(curModifyTimeStr, curModifyTime)) { + return false; + } + return curModifyTime >= preModifyTime; +} + void DBCommon::RemoveDuplicateAssetsData(std::vector &assets) { std::unordered_map indexMap; @@ -823,22 +846,19 @@ void DBCommon::RemoveDuplicateAssetsData(std::vector &assets) } size_t prevIndex = it->second; Asset &prevAsset = assets.at(prevIndex); - if (prevAsset.assetId.empty()) { + if (prevAsset.assetId.empty() && !asset.assetId.empty()) { arr[prevIndex] = 1; indexMap[asset.name] = i; continue; } - if (asset.assetId.empty()) { + if (!prevAsset.assetId.empty() && asset.assetId.empty()) { arr[i] = 1; indexMap[asset.name] = prevIndex; continue; } - uint64_t modifyTime = 0; - uint64_t prevModifyTime = 0; - if (ConvertToUInt(asset.modifyTime, modifyTime) && ConvertToUInt(prevAsset.modifyTime, prevModifyTime) && - !asset.modifyTime.empty() && !prevAsset.modifyTime.empty()) { - arr[modifyTime > prevModifyTime ? prevIndex : i] = 1; - indexMap[asset.name] = modifyTime > prevModifyTime ? i : prevIndex; + if (CmpModifyTime(prevAsset.modifyTime, asset.modifyTime)) { + arr[prevIndex] = 1; + indexMap[asset.name] = i; continue; } arr[i] = 1; diff --git a/kv_store/frameworks/libs/distributeddb/common/src/db_dfx_adapter.cpp b/kv_store/frameworks/libs/distributeddb/common/src/db_dfx_adapter.cpp index ff608c703b5974062384a875213547f5c985484b..ab56e4077866e37134f4624db43de960cdd91e06 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/db_dfx_adapter.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/db_dfx_adapter.cpp @@ -91,28 +91,28 @@ void DBDfxAdapter::ReportBehavior(const ReportTask &reportTask) .arraySize = 0}, {.name = {"FUNC"}, .t = HISYSEVENT_STRING, - .v = {.s = const_cast(ORG_PKG_NAME.c_str())}, + .v = {.s = const_cast(reportTask.funcName.c_str())}, .arraySize = 0}, {.name = {"BIZ_SCENE"}, .t = HISYSEVENT_INT32, .v = {.i32 = static_cast(reportTask.scene)}, - .arraySize = 0 }, + .arraySize = 0}, {.name = {"BIZ_STATE"}, .t = HISYSEVENT_INT32, .v = {.i32 = static_cast(reportTask.state)}, - .arraySize = 0 }, + .arraySize = 0}, {.name = {"BIZ_STAGE"}, .t = HISYSEVENT_INT32, - .v = { .i32 = static_cast(reportTask.stage)}, - .arraySize = 0 }, + .v = {.i32 = static_cast(reportTask.stage)}, + .arraySize = 0}, {.name = {"STAGE_RES"}, .t = HISYSEVENT_INT32, - .v = { .i32 = static_cast(reportTask.result)}, - .arraySize = 0 }, + .v = {.i32 = static_cast(reportTask.result)}, + .arraySize = 0}, {.name = {"ERROR_CODE"}, .t = HISYSEVENT_INT32, - .v = { .i32 = static_cast(reportTask.result)}, - .arraySize = 0 }, + .v = {.i32 = static_cast(dbDfxErrCode)}, + .arraySize = 0}, }; RuntimeContext::GetInstance()->ScheduleTask([=]() { // call hievent here diff --git a/kv_store/frameworks/libs/distributeddb/common/src/performance_analysis.cpp b/kv_store/frameworks/libs/distributeddb/common/src/performance_analysis.cpp index 6bfb9e0bfce2438de95aacbd62fa2de40247babb..6651811b5a852e21d5038e5c12fc4a6d49d3acaf 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/performance_analysis.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/performance_analysis.cpp @@ -154,8 +154,8 @@ void PerformanceAnalysis::StepTimeRecordEnd(uint32_t step) timePair.endTime = curTime; LOGD("[performance_analysis] StepTimeRecordEnd step:%" PRIu32 ", curTime:%" PRIu64, step, curTime); - if ((timePair.endTime < timePair.startTime) || (timePair.startTime == 0) - || (timePair.endTime == 0)) { // LCOV_EXCL_BR_LINE + if ((timePair.endTime < timePair.startTime) || (timePair.startTime == 0) || + (timePair.endTime == 0)) { // LCOV_EXCL_BR_LINE return; } Timestamp offset = timePair.endTime - timePair.startTime; @@ -177,8 +177,8 @@ void PerformanceAnalysis::StepTimeRecordEnd(uint32_t step) std::string PerformanceAnalysis::GetStatistics() { std::string result; - for (size_t i = 0; i < stepTimeRecordInfo_.size(); i++) { - if (stepTimeRecordInfo_[i].max != 0) { // LCOV_EXCL_BR_LINE + for (size_t i = 0; i < stepTimeRecordInfo_.size(); i++) { // LCOV_EXCL_BR_LINE + if (stepTimeRecordInfo_[i].max != 0) { result += "\nstep : " + std::to_string(i) + "\n"; result += "max: " + std::to_string(stepTimeRecordInfo_[i].max) + "\n"; result += "min: " + std::to_string(stepTimeRecordInfo_[i].min) + "\n"; diff --git a/kv_store/frameworks/libs/distributeddb/common/src/platform_specific.cpp b/kv_store/frameworks/libs/distributeddb/common/src/platform_specific.cpp index 40945cc0b03b36c5eae211858c4f4c9409c4df0b..7fe6fd38875eabed54be99b7c4e71c4b99a33206 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/platform_specific.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/platform_specific.cpp @@ -53,7 +53,7 @@ struct FileHandle { bool CheckPathExistence(const std::string &filePath) { int ret = _access(filePath.c_str(), ACCESS_MODE_EXISTENCE); - LOGI("CheckPathExistence %s error:%d", filePath.c_str(), ret); + LOGI("CheckPathExistence error:%d", ret); return (ret == 0); } @@ -71,11 +71,11 @@ int RenameFilePath(const std::string &oldFilePath, const std::string &newFilePat int RemoveFile(const std::string &filePath) { #ifdef DB_DEBUG_ENV - LOGD("---> remove db filePath: %s", filePath.c_str()); + LOGD("---> remove db"); #endif int errCode = remove(filePath.c_str()); if (errCode < 0) { - LOGE("[RemoveFile] Remove file fail %s %d err = %d", filePath.c_str(), errCode, errno); + LOGE("[RemoveFile] Remove file fail, %d err = %d", errCode, errno); return -E_SYSTEM_API_FAIL; } LOGD("Remove file successfully!"); diff --git a/kv_store/frameworks/libs/distributeddb/common/src/relational/relational_schema_object.cpp b/kv_store/frameworks/libs/distributeddb/common/src/relational/relational_schema_object.cpp index 199adeda8a456cbb4d4668c04611f7ba61408d43..1d34db8ea4bef6e249761ac0df860ffe2b934c03 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/relational/relational_schema_object.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/relational/relational_schema_object.cpp @@ -437,6 +437,10 @@ int RelationalSchemaObject::ParseCheckTrackerTable(const JsonObject &inJsonObjec if (errCode != E_OK) { // LCOV_EXCL_BR_LINE return errCode; } + errCode = ParseCheckTrackerAction(inJsonObject, table); + if (errCode != E_OK) { + return errCode; + } trackerTables_[table.GetTableName()].SetTrackerTable(table); return E_OK; } @@ -1116,5 +1120,21 @@ void RelationalSchemaObject::CalculateTableWeight(const std::set &s } } } + +int RelationalSchemaObject::ParseCheckTrackerAction(const JsonObject &inJsonObject, TrackerTable &resultTable) +{ + FieldValue fieldValue; + int errCode = GetMemberFromJsonObject(inJsonObject, "TRACKER_ACTION", FieldType::LEAF_FIELD_BOOL, + false, fieldValue); + if (errCode == E_OK) { // LCOV_EXCL_BR_LINE + resultTable.SetTrackerAction(fieldValue.boolValue); + } else if (errCode == -E_NOT_FOUND) { + fieldValue.boolValue = false; + errCode = E_OK; + } else { + LOGE("[RelationalSchema][Parse] get TRACKER_ACTION failed %d", errCode); + } + return errCode; +} } #endif \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/common/src/relational/tracker_table.cpp b/kv_store/frameworks/libs/distributeddb/common/src/relational/tracker_table.cpp index cbfb0cbbe6029a99030eac4de1c147dcc6a1b038..aaeca8b1f4d874f393cb4fefd64fd27003a2e861 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/relational/tracker_table.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/relational/tracker_table.cpp @@ -24,6 +24,7 @@ void TrackerTable::Init(const TrackerSchema &schema) tableName_ = schema.tableName; extendColName_ = schema.extendColName; trackerColNames_ = schema.trackerColNames; + isTrackerAction_ = schema.isTrackAction; } std::string TrackerTable::GetTableName() const @@ -54,8 +55,8 @@ const std::string TrackerTable::GetExtendAssignValSql(bool isDelete) const const std::string TrackerTable::GetDiffTrackerValSql() const { - if (trackerColNames_.empty()) { - return "0"; + if (trackerColNames_.empty() || isTrackerAction_) { + return isTrackerAction_ ? "1" : "0"; } std::string sql = " CASE WHEN ("; size_t index = 0; @@ -72,9 +73,12 @@ const std::string TrackerTable::GetDiffTrackerValSql() const const std::string TrackerTable::GetDiffIncCursorSql(const std::string &tableName) const { - if (trackerColNames_.empty()) { + if (IsEmpty()) { return ""; } + if (isTrackerAction_) { + return std::string(", cursor = ").append(CloudStorageUtils::GetSelectIncCursorSql(tableName)).append(" "); + } std::string sql = ", cursor = CASE WHEN ("; size_t index = 0; for (const auto &colName: trackerColNames_) { @@ -104,8 +108,13 @@ std::string TrackerTable::ToString() const for (const auto &colName: trackerColNames_) { attrStr += "\"" + colName + "\","; } - attrStr.pop_back(); - attrStr += "]}"; + if (!trackerColNames_.empty()) { + attrStr.pop_back(); + } + attrStr += "],"; + attrStr += R"("TRACKER_ACTION": )"; + attrStr += isTrackerAction_ ? SchemaConstant::KEYWORD_ATTR_VALUE_TRUE : SchemaConstant::KEYWORD_ATTR_VALUE_FALSE; + attrStr += "}"; return attrStr; } @@ -154,12 +163,18 @@ const std::string TrackerTable::GetTempInsertTriggerSql(bool incFlag) const " WHERE key = 'log_trigger_switch' AND value = 'false')\n"; sql += "BEGIN\n"; if (incFlag) { - sql += CloudStorageUtils::GetCursorIncSqlWhenAllow(tableName_) + "\n"; + sql += CloudStorageUtils::GetCursorIncSqlWhenAllow(tableName_) + "\n"; } else { - sql += CloudStorageUtils::GetCursorIncSql(tableName_) + "\n"; + sql += CloudStorageUtils::GetCursorIncSql(tableName_) + "\n"; } sql += "UPDATE " + DBConstant::RELATIONAL_PREFIX + tableName_ + "_log" + " SET "; - sql += "cursor=" + CloudStorageUtils::GetSelectIncCursorSql(tableName_) + " WHERE"; + if (incFlag) { + sql += "cursor= case when (select 1 from " + + DBConstant::RELATIONAL_PREFIX + "metadata where key='cursor_inc_flag' AND value = 'true') then " + + CloudStorageUtils::GetSelectIncCursorSql(tableName_) + " else cursor end WHERE"; + } else { + sql += "cursor=" + CloudStorageUtils::GetSelectIncCursorSql(tableName_) + " WHERE"; + } sql += " hash_key = NEW.hash_key;\n"; if (!IsEmpty()) { sql += "SELECT server_observer('" + tableName_ + "', 1);"; @@ -184,7 +199,13 @@ const std::string TrackerTable::GetTempUpdateTriggerSql(bool incFlag) const if (!IsEmpty()) { sql += "extend_field=" + GetAssignValSql() + ","; } - sql += "cursor=" + CloudStorageUtils::GetSelectIncCursorSql(tableName_) + " WHERE"; + if (incFlag) { + sql += "cursor= case when (select 1 from " + + DBConstant::RELATIONAL_PREFIX + "metadata where key='cursor_inc_flag' AND value = 'true') then " + + CloudStorageUtils::GetSelectIncCursorSql(tableName_) + " else cursor end WHERE"; + } else { + sql += "cursor=" + CloudStorageUtils::GetSelectIncCursorSql(tableName_) + " WHERE"; + } sql += " data_key = OLD." + std::string(DBConstant::SQLITE_INNER_ROWID) + ";\n"; if (!IsEmpty()) { sql += "SELECT server_observer('" + tableName_ + "', " + GetDiffTrackerValSql() + ");"; @@ -243,7 +264,7 @@ void TrackerTable::SetTrackerNames(const std::set &trackerNames) bool TrackerTable::IsEmpty() const { - return trackerColNames_.empty(); + return trackerColNames_.empty() && !isTrackerAction_; } bool TrackerTable::IsChanging(const TrackerSchema &schema) @@ -259,7 +280,7 @@ bool TrackerTable::IsChanging(const TrackerSchema &schema) return true; } } - return false; + return isTrackerAction_ != schema.isTrackAction; } int TrackerTable::ReBuildTempTrigger(sqlite3 *db, TriggerMode::TriggerModeEnum mode, const AfterBuildAction &action) @@ -303,5 +324,10 @@ int TrackerTable::ReBuildTempTrigger(sqlite3 *db, TriggerMode::TriggerModeEnum m } return errCode; } + +void TrackerTable::SetTrackerAction(bool isTrackerAction) +{ + isTrackerAction_ = isTrackerAction; +} } #endif \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/common/src/runtime_context_impl.cpp b/kv_store/frameworks/libs/distributeddb/common/src/runtime_context_impl.cpp index e4ab9353e1611508fd612ec3c92ab30ffd0812a4..10bf1f4864ee6e144dc1c5702a9a144255bcd5ed 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/runtime_context_impl.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/runtime_context_impl.cpp @@ -14,11 +14,13 @@ */ #include "runtime_context_impl.h" + +#include "communicator_aggregator.h" #include "db_common.h" -#include "db_errno.h" #include "db_dfx_adapter.h" +#include "db_errno.h" +#include "kv_store_errno.h" #include "log_print.h" -#include "communicator_aggregator.h" #include "network_adapter.h" namespace DistributedDB { @@ -38,7 +40,8 @@ RuntimeContextImpl::RuntimeContextImpl() lockStatusObserver_(nullptr), currentSessionId_(1), dbStatusAdapter_(nullptr), - subscribeRecorder_(nullptr) + subscribeRecorder_(nullptr), + isBatchDownloadAssets_(true) { } @@ -539,13 +542,10 @@ int RuntimeContextImpl::SetSecurityOption(const std::string &filePath, const Sec return errCode; } - errCode = systemApiAdapter_->SetSecurityOption(fileRealPath, option); - if (errCode != OK) { - if (errCode == NOT_SUPPORT) { - return -E_NOT_SUPPORT; - } - LOGE("SetSecurityOption failed, errCode = %d", errCode); - return -E_SYSTEM_API_ADAPTER_CALL_FAILED; + DBStatus dbErrCode = systemApiAdapter_->SetSecurityOption(fileRealPath, option); + if (dbErrCode != OK) { + LOGE("SetSecurityOption failed, errCode = %d", dbErrCode); + return TransferDBStatusToErr(dbErrCode); } return E_OK; } @@ -1226,4 +1226,14 @@ void RuntimeContextImpl::SetTimeChanged(bool timeChange) } timeTickMonitor_->SetTimeChanged(timeChange); } + +bool RuntimeContextImpl::IsBatchDownloadAssets() const +{ + return isBatchDownloadAssets_; +} + +void RuntimeContextImpl::SetBatchDownloadAssets(bool isBatchDownload) +{ + isBatchDownloadAssets_ = isBatchDownload; +} } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/common/src/runtime_context_impl.h b/kv_store/frameworks/libs/distributeddb/common/src/runtime_context_impl.h index 36d1831b3aa99cba7720d80ea47def84eab6f040..2d78683974905ee6c3597d5dea7bee8d751cbe12 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/runtime_context_impl.h +++ b/kv_store/frameworks/libs/distributeddb/common/src/runtime_context_impl.h @@ -182,6 +182,9 @@ public: bool IsTimeTickMonitorValid() const override; bool IsTimeChanged() const override; void SetTimeChanged(bool timeChange) override; + + bool IsBatchDownloadAssets() const override; + void SetBatchDownloadAssets(bool isBatchDownload) override; private: static constexpr int MAX_TP_THREADS = 10; // max threads of the task pool. static constexpr int MIN_TP_THREADS = 1; // min threads of the task pool. @@ -281,6 +284,8 @@ private: mutable std::mutex deviceTimeInfoLock_; std::map deviceTimeInfos_; std::map, bool> dbTimeChange_; + + std::atomic isBatchDownloadAssets_; }; } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/communicator/src/network_adapter.cpp b/kv_store/frameworks/libs/distributeddb/communicator/src/network_adapter.cpp index 1ff6e7615e653dbf9fd20282908cebb590ffdba3..1aaa35dafe87b0c819839eb4d374c34caea4a16e 100644 --- a/kv_store/frameworks/libs/distributeddb/communicator/src/network_adapter.cpp +++ b/kv_store/frameworks/libs/distributeddb/communicator/src/network_adapter.cpp @@ -238,7 +238,7 @@ int NetworkAdapter::SendBytes(const std::string &dstTarget, const uint8_t *bytes // Since this thread is the sending_thread of the CommunicatorAggregator, // We need an async task which bring about dependency on the lifecycle of this NetworkAdapter Object. CheckDeviceOfflineAfterSendFail(dstDevInfo); - return -E_PERIPHERAL_INTERFACE_FAIL; + return static_cast(errCode); } return E_OK; } diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/include/grd_base/grd_type_export.h b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/include/grd_base/grd_type_export.h index 506b99981be11947de5feaa156cce9121d19526a..b67478955ad11f242d5cbdbb6402a6de4cf01e17 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/include/grd_base/grd_type_export.h +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/include/grd_base/grd_type_export.h @@ -76,6 +76,10 @@ typedef struct GRD_FilterOption { GRD_KVItem end; } GRD_FilterOptionT; +typedef struct GRD_CipherInfo { + const char *hexPassword; +} GRD_CipherInfoT; + typedef struct GRD_ResultSet GRD_ResultSet; typedef struct GRD_DB GRD_DB; typedef struct GRD_KVBatch GRD_KVBatchT; diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/include/grd_api_manager.h b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/include/grd_api_manager.h index 14b5748b679efdc4623ada7a57773472c0c65c5d..7acb79c248fffae3705fcb84d8d4d1330be1e402 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/include/grd_api_manager.h +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/include/grd_api_manager.h @@ -21,9 +21,8 @@ namespace DocumentDB { typedef int32_t (*DBOpen)(const char *dbPath, const char *configStr, uint32_t flags, GRD_DB **db); typedef int32_t (*DBClose)(GRD_DB *db, uint32_t flags); -typedef int32_t (*DBBackup)(GRD_DB *db, const char *backupDbFile, uint8_t *encryptedKey, uint32_t encryptedKeyLen); -typedef int32_t (*DBRestore)(const char *dbFile, const char *backupDbFile, uint8_t *decryptedKey, - uint32_t decryptedKeyLen); +typedef int32_t (*DBBackup)(GRD_DB *db, const char *backupDbFile, GRD_CipherInfoT *cipherInfo); +typedef int32_t (*DBRestore)(const char *dbFile, const char *backupDbFile, GRD_CipherInfoT *cipherInfo); typedef int32_t (*DBFlush)(GRD_DB *db, uint32_t flags); typedef int32_t (*IndexPreload)(GRD_DB *db, const char *collectionName); typedef int32_t (*CreateCollection)(GRD_DB *db, const char *collectionName, const char *optionStr, uint32_t flags); diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/src/json_common.cpp b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/src/json_common.cpp index abdf6779ad4422d5b9384556dedeab7637dfb463..40b92e3fe6d31da203d5bd19e8d7e3cad49d5e9f 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/src/json_common.cpp +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/src/json_common.cpp @@ -129,6 +129,18 @@ bool JsonCommon::CheckJsonField(JsonObject &jsonObj) return CheckNode(jsonObj); } +static bool CheckNodeSingleCharacter(const std::string &fieldName, bool isFirstLevel, int &errCode) +{ + for (size_t i = 0; i < fieldName.size(); i++) { + if ((i == 0 && (isdigit(fieldName[i]))) || !((isalpha(fieldName[i])) || + (isdigit(fieldName[i])) || (fieldName[i] == '_') || (isFirstLevel && fieldName[i] == '.'))) { + errCode = -E_INVALID_ARGS; + return false; + } + } + return true; +} + bool JsonCommon::CheckProjectionNode(JsonObject &node, bool isFirstLevel, int &errCode) { std::queue jsonQueue; @@ -149,12 +161,8 @@ bool JsonCommon::CheckProjectionNode(JsonObject &node, bool isFirstLevel, int &e errCode = -E_INVALID_JSON_FORMAT; return false; } - for (size_t i = 0; i < fieldName.size(); i++) { - if ((i == 0 && (isdigit(fieldName[i]))) || !((isalpha(fieldName[i])) || - (isdigit(fieldName[i])) || (fieldName[i] == '_') || (isFirstLevel && fieldName[i] == '.'))) { - errCode = -E_INVALID_ARGS; - return false; - } + if (!CheckNodeSingleCharacter(fieldName, isFirstLevel, errCode)) { + return false; } if (!item.GetNext().IsNull()) { jsonQueue.push(item.GetNext()); diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/base/grd_db_api.cpp b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/base/grd_db_api.cpp index 931b070d43ef3bfdd669c9be2128b4d349a3ca0c..10d2d10a664aff87f03e5e45f0fe0468330ee2ea 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/base/grd_db_api.cpp +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/base/grd_db_api.cpp @@ -59,7 +59,8 @@ GRD_API int32_t GRD_DBBackup(GRD_DB *db, const char *backupDbFile, uint8_t *encr GLOGE("Fail to dlysm RD api symbol"); return GRD_INNER_ERR; } - return GRD_DBApiInfo.DBBackupApi(db, backupDbFile, encryptedKey, encryptedKeyLen); + GRD_CipherInfoT cipherInfo = {.hexPassword = nullptr}; + return GRD_DBApiInfo.DBBackupApi(db, backupDbFile, &cipherInfo); } GRD_API int32_t GRD_DBRestore(const char *dbFile, const char *backupDbFile, uint8_t *decryptedKey, @@ -72,7 +73,8 @@ GRD_API int32_t GRD_DBRestore(const char *dbFile, const char *backupDbFile, uint GLOGE("Fail to dlysm RD api symbol"); return GRD_INNER_ERR; } - return GRD_DBApiInfo.DBRestoreApi(dbFile, backupDbFile, decryptedKey, decryptedKeyLen); + GRD_CipherInfoT cipherInfo = {.hexPassword = nullptr}; + return GRD_DBApiInfo.DBRestoreApi(dbFile, backupDbFile, &cipherInfo); } GRD_API int32_t GRD_Flush(GRD_DB *db, uint32_t flags) diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/include/cloud/iAssetLoader.h b/kv_store/frameworks/libs/distributeddb/interfaces/include/cloud/iAssetLoader.h index 7c0ebe6beec45f4275d02ad19b2d50001ef53d42..acd16cb7dbce03c05b9739f229ce264ed6f031fe 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/include/cloud/iAssetLoader.h +++ b/kv_store/frameworks/libs/distributeddb/interfaces/include/cloud/iAssetLoader.h @@ -44,6 +44,21 @@ public: { return DBStatus::OK; } + + struct AssetRecord { + const std::string gid; + const Type prefix; + std::map assets; + DBStatus status = OK; + }; + + virtual void BatchDownload(const std::string &tableName, std::vector &downloadAssets) + { + } + + virtual void BatchRemoveLocalAssets(const std::string &tableName, std::vector &removeAssets) + { + } }; } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/include/kv_store_errno.h b/kv_store/frameworks/libs/distributeddb/interfaces/include/kv_store_errno.h index d5177782c31a9d846e8d84e2466421c09faface1..580749c33a0058600ac1cb4529aabb930e9df814 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/include/kv_store_errno.h +++ b/kv_store/frameworks/libs/distributeddb/interfaces/include/kv_store_errno.h @@ -21,5 +21,8 @@ namespace DistributedDB { // Transfer the db error code to the DBStatus. DBStatus TransferDBErrno(int err, bool isPass = false); + +// Transfer the DBStatus to db error code, return dbStatus if no matching error code +int TransferDBStatusToErr(DBStatus dbStatus); } // DistributedDB #endif // KV_STORE_ERRNO_H \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/include/kv_store_nb_delegate.h b/kv_store/frameworks/libs/distributeddb/interfaces/include/kv_store_nb_delegate.h index 616d78fc14f614f06f4e84d1c45886f146ca00fc..072a31d07e538b1d127d14fafd84672653385fdb 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/include/kv_store_nb_delegate.h +++ b/kv_store/frameworks/libs/distributeddb/interfaces/include/kv_store_nb_delegate.h @@ -60,6 +60,7 @@ public: std::string storageEngineType = SQLITE; // use gaussdb_rd as storage engine Rdconfig rdconfig; }; + struct DatabaseStatus { bool isRebuild = false; }; @@ -168,7 +169,8 @@ public: // Import the existing database files to the specified database file in the specified directory. // Warning Import may reopen database file in locked state - DB_API virtual DBStatus Import(const std::string &filePath, const CipherPassword &passwd) = 0; + DB_API virtual DBStatus Import(const std::string &filePath, const CipherPassword &passwd, + bool isNeedIntegrityCheck = false) = 0; // Start a transaction DB_API virtual DBStatus StartTransaction() = 0; @@ -203,16 +205,10 @@ public: const Query &query, bool wait) = 0; // Sync with device, provides sync count information - DB_API virtual DBStatus Sync(const DeviceSyncOption &option, const DeviceSyncProcessCallback &onProcess) - { - return OK; - }; + DB_API virtual DBStatus Sync(const DeviceSyncOption &option, const DeviceSyncProcessCallback &onProcess) = 0; // Cancel sync by syncId - DB_API virtual DBStatus CancelSync(uint32_t syncId) - { - return OK; - }; + DB_API virtual DBStatus CancelSync(uint32_t syncId) = 0; // Check the integrity of this kvStore. DB_API virtual DBStatus CheckIntegrity() const = 0; @@ -290,10 +286,7 @@ public: // If device is empty, it would return all the entries which was written by local device. DB_API virtual DBStatus GetDeviceEntries(const std::string &device, std::vector &entries) const = 0; - DB_API virtual DatabaseStatus GetDatabaseStatus() const - { - return {}; - } + DB_API virtual DatabaseStatus GetDatabaseStatus() const = 0; }; } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/include/store_types.h b/kv_store/frameworks/libs/distributeddb/interfaces/include/store_types.h index 726171df30f00ad673c9ec718e23179da6e015ab..96e9ea6609da77d01793b957434077581c4f9e35 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/include/store_types.h +++ b/kv_store/frameworks/libs/distributeddb/interfaces/include/store_types.h @@ -239,6 +239,7 @@ struct TrackerSchema { std::string extendColName; std::set trackerColNames; bool isForceUpgrade = false; + bool isTrackAction = false; }; struct TableReferenceProperty { diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_delegate_manager.cpp b/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_delegate_manager.cpp index bff7d1535f05f672ec78ab4534b939655d5c63e6..1a18a4332995b6433b4c2a837417cad8fcee0bf7 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_delegate_manager.cpp +++ b/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_delegate_manager.cpp @@ -16,28 +16,28 @@ #include "kv_store_delegate_manager.h" #include -#include #include +#include #include #include -#include "db_constant.h" -#include "platform_specific.h" -#include "log_print.h" +#include "auto_launch.h" #include "db_common.h" +#include "db_constant.h" #include "db_dfx_adapter.h" +#include "kv_store_delegate_impl.h" #include "kv_store_errno.h" +#include "kv_store_nb_delegate_impl.h" +#include "kvdb_manager.h" #include "kvdb_pragma.h" #include "kvdb_properties.h" -#include "kvdb_manager.h" -#include "kv_store_nb_delegate_impl.h" +#include "log_print.h" #include "network_adapter.h" +#include "param_check_utils.h" +#include "platform_specific.h" #include "rd_utils.h" #include "runtime_config.h" #include "runtime_context.h" -#include "param_check_utils.h" -#include "auto_launch.h" -#include "kv_store_delegate_impl.h" namespace DistributedDB { const std::string KvStoreDelegateManager::DEFAULT_PROCESS_APP_ID = "default"; @@ -573,7 +573,7 @@ DBStatus KvStoreDelegateManager::EnableKvStoreAutoLaunch(const std::string &user std::shared_ptr ptr; int errCode = AutoLaunch::GetAutoLaunchProperties(param, DBTypeInner::DB_KV, true, ptr); if (errCode != E_OK) { - LOGE("[KvStoreManager] Enable auto launch failed:%d", errCode); + LOGE("[KvStoreManager] Enable auto launch, get properties failed:%d", errCode); return TransferDBErrno(errCode); } @@ -581,7 +581,7 @@ DBStatus KvStoreDelegateManager::EnableKvStoreAutoLaunch(const std::string &user errCode = RuntimeContext::GetInstance()->EnableKvStoreAutoLaunch(*kvPtr, notifier, option); if (errCode != E_OK) { LOGE("[KvStoreManager] Enable auto launch failed:%d", errCode); - return TransferDBErrno(errCode); + return TransferDBErrno(errCode, true); } LOGI("[KvStoreManager] Enable auto launch"); return OK; diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_errno.cpp b/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_errno.cpp index b4d78bde6d27b937d0d7303c5748b499c00279a5..06ac08db62317936f16143b0fdc11d6d30a52e82 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_errno.cpp +++ b/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_errno.cpp @@ -98,4 +98,15 @@ DBStatus TransferDBErrno(int err, bool isPass) } return DB_ERROR; } + +int TransferDBStatusToErr(DBStatus dbStatus) +{ + for (const auto &item : ERRNO_MAP) { + if (item.status == dbStatus) { + return item.errCode; + } + } + + return dbStatus; +} }; diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_nb_delegate_impl.cpp b/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_nb_delegate_impl.cpp index f3f7c9f532709b6d1a84eaf4f069ba340b208660..57e32c9706dfc058f767389d7853d544327f339a 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_nb_delegate_impl.cpp +++ b/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_nb_delegate_impl.cpp @@ -532,7 +532,9 @@ DBStatus KvStoreNbDelegateImpl::RemoveDeviceData(const std::string &device) int errCode = conn_->Pragma(PRAGMA_RM_DEVICE_DATA, const_cast(static_cast(&device))); if (errCode != E_OK) { - LOGE("[KvStoreNbDelegate] Remove device data failed:%d", errCode); + LOGE("[KvStoreNbDelegate][%.3s] Remove specific device data failed:%d", storeId_.c_str(), errCode); + } else { + LOGI("[KvStoreNbDelegate][%.3s] Remove specific device data OK", storeId_.c_str()); } return TransferDBErrno(errCode); } @@ -787,7 +789,8 @@ DBStatus KvStoreNbDelegateImpl::Export(const std::string &filePath, const Cipher return TransferDBErrno(errCode); } -DBStatus KvStoreNbDelegateImpl::Import(const std::string &filePath, const CipherPassword &passwd) +DBStatus KvStoreNbDelegateImpl::Import(const std::string &filePath, const CipherPassword &passwd, + bool isNeedIntegrityCheck) { if (conn_ == nullptr) { LOGE("%s", INVALID_CONNECTION); @@ -809,7 +812,7 @@ DBStatus KvStoreNbDelegateImpl::Import(const std::string &filePath, const Cipher return INVALID_FILE; } - int errCode = conn_->Import(canonicalUrl, passwd); + int errCode = conn_->Import(canonicalUrl, passwd, isNeedIntegrityCheck); if (errCode == E_OK) { LOGI("[KvStoreNbDelegate] Import ok"); return OK; @@ -1091,7 +1094,9 @@ DBStatus KvStoreNbDelegateImpl::RemoveDeviceData() int errCode = conn_->Pragma(PRAGMA_RM_DEVICE_DATA, const_cast(static_cast(&device))); if (errCode != E_OK) { - LOGE("[KvStoreNbDelegate] Remove device data failed:%d", errCode); + LOGE("[KvStoreNbDelegate][%.3s] Remove device data failed:%d", storeId_.c_str(), errCode); + } else { + LOGI("[KvStoreNbDelegate][%.3s] Remove device data OK", storeId_.c_str()); } return TransferDBErrno(errCode); } @@ -1212,9 +1217,10 @@ DBStatus KvStoreNbDelegateImpl::RemoveDeviceData(const std::string &device, Clea } int errCode = conn_->RemoveDeviceData(device, mode); if (errCode != E_OK) { - LOGE("[KvStoreNbDelegate] remove device data res %d", errCode); + LOGE("[KvStoreNbDelegate][%.3s] Remove device data res %d", storeId_.c_str(), errCode); + } else { + LOGI("[KvStoreNbDelegate][%.3s] Remove device data OK, mode[%d]", storeId_.c_str(), static_cast(mode)); } - LOGI("[KvStoreNbDelegate] remove device data res"); return TransferDBErrno(errCode); } @@ -1226,14 +1232,16 @@ DBStatus KvStoreNbDelegateImpl::RemoveDeviceData(const std::string &device, cons return DB_ERROR; } if (user.empty() && mode != ClearMode::DEFAULT) { - LOGE("[KvStoreNbDelegate] remove device data with empty user!"); + LOGE("[KvStoreNbDelegate] Remove device data with empty user!"); return INVALID_ARGS; } int errCode = conn_->RemoveDeviceData(device, user, mode); if (errCode != E_OK) { - LOGE("[KvStoreNbDelegate] remove device data with user res %d", errCode); + LOGE("[KvStoreNbDelegate][%.3s] Remove device data with user res %d", storeId_.c_str(), errCode); + } else { + LOGI("[KvStoreNbDelegate][%.3s] Remove device data with user OK, mode[%d]", + storeId_.c_str(), static_cast(mode)); } - LOGI("[KvStoreNbDelegate] remove device data with user res"); return TransferDBErrno(errCode); } diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_nb_delegate_impl.h b/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_nb_delegate_impl.h index f166d7b37d864094621065db179fd2d358bad37e..8f897ee9c0a4de20dbce1fe7c840581c6897c861 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_nb_delegate_impl.h +++ b/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_nb_delegate_impl.h @@ -101,7 +101,8 @@ public: DBStatus Export(const std::string &filePath, const CipherPassword &passwd, bool force) override; // Import the existing database files to the specified database file in the specified directory. - DBStatus Import(const std::string &filePath, const CipherPassword &passwd) override; + DBStatus Import(const std::string &filePath, const CipherPassword &passwd, + bool isNeedIntegrityCheck = false) override; // Start a transaction DBStatus StartTransaction() override; diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_delegate_impl.cpp b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_delegate_impl.cpp index fcb68b7ec38e9e805066028baa66ee5c42ab9e4d..e592d8a167eae4dea76c8c3d48b95ce59ea278a6 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_delegate_impl.cpp +++ b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_delegate_impl.cpp @@ -78,6 +78,8 @@ int32_t RelationalStoreDelegateImpl::GetCloudSyncTaskCount() DBStatus RelationalStoreDelegateImpl::CreateDistributedTableInner(const std::string &tableName, TableSyncType type) { + LOGI("[RelationalStore Delegate] Create distributed table for [%s length[%u]], type[%d]", + DBCommon::StringMiddleMasking(tableName).c_str(), tableName.length(), static_cast(type)); if (!ParamCheckUtils::CheckRelationalTableName(tableName)) { LOGE("[RelationalStore Delegate] Invalid table name."); return INVALID_ARGS; @@ -330,6 +332,8 @@ DBStatus RelationalStoreDelegateImpl::Sync(const CloudSyncOption &option, const DBStatus RelationalStoreDelegateImpl::SetTrackerTable(const TrackerSchema &schema) { + LOGI("[RelationalStore Delegate] create tracker table for [%s length[%u]]", + DBCommon::StringMiddleMasking(schema.tableName).c_str(), schema.tableName.length()); if (conn_ == nullptr) { LOGE("[RelationalStore Delegate] Invalid connection for operation!"); return DB_ERROR; diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_sqlite_ext.cpp b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_sqlite_ext.cpp index c12cbd7ea6948de1940302457bcfdc24f5d9255f..cdcbb30aeb2b3234572618b0949677c83497ad96 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_sqlite_ext.cpp +++ b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_sqlite_ext.cpp @@ -1295,7 +1295,7 @@ int HandleDropLogicDeleteData(sqlite3 *db, const std::string &tableName, uint64_ return errCode; } sql = "DELETE FROM " + logTblName + " WHERE (flag&0x08=0x08" + - (cursor == 0 ? ");" : " AND cursor <= '" + std::to_string(cursor) + "');"); + (cursor == 0 ? ");" : " AND cursor <= '" + std::to_string(cursor) + "');"); errCode = sqlite3_exec(db, sql.c_str(), nullptr, nullptr, nullptr); if (errCode != SQLITE_OK) { LOGE("delete logic delete log failed. %d", errCode); @@ -1356,6 +1356,9 @@ void ClearTheLogAfterDropTable(sqlite3 *db, const char *tableName, const char *s if (filePath == nullptr) { return; } + LOGI("[ClearTheLogAfterDropTable] Table[%s length[%u]] of schema[%s length[%u]] has been dropped", + DBCommon::StringMiddleMasking(tableName).c_str(), strlen(tableName), + DBCommon::StringMiddleMasking(schemaName).c_str(), strlen(schemaName)); std::string fileName = std::string(filePath); Timestamp dropTimeStamp = TimeHelperManager::GetInstance()->GetTime(fileName, 0, nullptr, nullptr); std::string tableStr = std::string(tableName); @@ -1724,6 +1727,8 @@ DB_API DistributedDB::DBStatus UnregisterStoreObserver(sqlite3 *db) DB_API DistributedDB::DBStatus DropLogicDeletedData(sqlite3 *db, const std::string &tableName, uint64_t cursor) { + LOGI("Drop logic delete data from [%s length[%u]], cursor[%llu]", DBCommon::StringMiddleMasking(tableName).c_str(), + tableName.length(), cursor); std::string fileName; if (!GetDbFileName(db, fileName)) { return DistributedDB::INVALID_ARGS; diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_sync_able_storage.h b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_sync_able_storage.h index 7d30d941fd525a68380f2d8510dd66cff84b0c94..7c2f5d3ade25e3434eb6a4b7feef80f0a7d5f8fb 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_sync_able_storage.h +++ b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_sync_able_storage.h @@ -225,6 +225,12 @@ public: bool IsTableExistReferenceOrReferenceBy(const std::string &table) override; void ReleaseUploadRecord(const std::string &tableName, const CloudWaterType &type, Timestamp localMark) override; + + int GetCursor(const std::string &tableName, uint64_t &cursor) override; + + bool IsCurrentLogicDelete() const override; + + int GetLocalDataCount(const std::string &tableName, int &dataCount, int &logicDeleteDataCount) override; protected: int FillReferenceData(CloudSyncData &syncData); @@ -274,8 +280,6 @@ private: void FilterChangeDataByDetailsType(ChangedData &changedData, uint32_t type); StoreInfo GetStoreInfo() const; - bool IsCurrentLogicDelete() const; - int UpsertDataInner(SQLiteSingleVerRelationalStorageExecutor *handle, const std::string &tableName, const std::vector &records); diff --git a/kv_store/frameworks/libs/distributeddb/storage/include/cloud/cloud_storage_utils.h b/kv_store/frameworks/libs/distributeddb/storage/include/cloud/cloud_storage_utils.h index d42fe193c50c0ab09055a66a9e389fc8b0718c2a..e63e1579ac1fcd4d149b6df896286dc79660601b 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/include/cloud/cloud_storage_utils.h +++ b/kv_store/frameworks/libs/distributeddb/storage/include/cloud/cloud_storage_utils.h @@ -174,7 +174,7 @@ public: static int IdentifyCloudType(const CloudUploadRecorder &recorder, CloudSyncData &cloudSyncData, VBucket &data, VBucket &log, VBucket &flags); - static bool IsAbnormalData(const VBucket &data); + static int CheckAbnormalData(CloudSyncData &cloudSyncData, const VBucket &data, bool isInsert); static std::pair GetDataItemFromCloudData(VBucket &data); diff --git a/kv_store/frameworks/libs/distributeddb/storage/include/icloud_sync_storage_interface.h b/kv_store/frameworks/libs/distributeddb/storage/include/icloud_sync_storage_interface.h index a0036ea993ffac4a445295e9772f9d9256fa8179..b37840ec1564ff2e998964403b1d377576d100d5 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/include/icloud_sync_storage_interface.h +++ b/kv_store/frameworks/libs/distributeddb/storage/include/icloud_sync_storage_interface.h @@ -147,6 +147,7 @@ public: { return E_OK; }; + virtual int FillCloudLogAndAsset(OpType opType, const CloudSyncData &data, bool fillAsset, bool ignoreEmptyGid) = 0; virtual std::string GetIdentify() const = 0; @@ -188,7 +189,7 @@ public: } virtual int GetCompensatedSyncQuery([[gnu::unused]] std::vector &syncQuery, - std::vector &users) + [[gnu::unused]] std::vector &users) { return E_OK; } @@ -241,6 +242,19 @@ public: { return E_OK; } + + virtual int GetCursor(const std::string &tableName, uint64_t &cursor) + { + cursor = DBConstant::INVALID_CURSOR; + return E_NOT_SUPPORT; + } + + virtual bool IsCurrentLogicDelete() const + { + return false; + } + + virtual int GetLocalDataCount(const std::string &tableName, int &dataCount, int &logicDeleteDataCount) = 0; }; } diff --git a/kv_store/frameworks/libs/distributeddb/storage/include/ikvdb_connection.h b/kv_store/frameworks/libs/distributeddb/storage/include/ikvdb_connection.h index dd55180a6d4242092bbb8100b8bd8bb41ce1ba8a..ea3fda638e69eafe29334026a4c4cff543d4f423 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/include/ikvdb_connection.h +++ b/kv_store/frameworks/libs/distributeddb/storage/include/ikvdb_connection.h @@ -115,7 +115,8 @@ public: virtual int Export(const std::string &filePath, const CipherPassword &passwd) = 0; // Import the existing database files to the specified database file in the specified directory. - virtual int Import(const std::string &filePath, const CipherPassword &passwd) = 0; + virtual int Import(const std::string &filePath, const CipherPassword &passwd, + bool isNeedIntegrityCheck = false) = 0; // Get the result set virtual int GetResultSet(const IOption &option, const Key &keyPrefix, IKvDBResultSet *&resultSet) const = 0; diff --git a/kv_store/frameworks/libs/distributeddb/storage/include/kvdb_pragma.h b/kv_store/frameworks/libs/distributeddb/storage/include/kvdb_pragma.h index 922d819f24adf0d2ee46030878e348303ed4194f..5114992397d5e33f143afbf54773a9e77bcef1e6 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/include/kvdb_pragma.h +++ b/kv_store/frameworks/libs/distributeddb/storage/include/kvdb_pragma.h @@ -81,10 +81,10 @@ struct PragmaSync { PragmaSync(const DeviceSyncOption &option, const QuerySyncObject &query, const DeviceSyncProcessCallback &onProcess) : devices_(option.devices), - mode_(option.mode), - wait_(option.isWait), - isQuerySync_(option.isQuery), - onSyncProcess_(onProcess) + mode_(option.mode), + wait_(option.isWait), + isQuerySync_(option.isQuery), + onSyncProcess_(onProcess) { if (!isQuerySync_) { return; @@ -93,12 +93,12 @@ struct PragmaSync { } PragmaSync(const DeviceSyncOption &option, const DeviceSyncProcessCallback &onProcess) - :devices_(option.devices), - mode_(option.mode), - wait_(option.isWait), - isQuerySync_(false), - query_(Query::Select()), - onSyncProcess_(onProcess) + : devices_(option.devices), + mode_(option.mode), + wait_(option.isWait), + isQuerySync_(false), + query_(Query::Select()), + onSyncProcess_(onProcess) { } diff --git a/kv_store/frameworks/libs/distributeddb/storage/include/storage_proxy.h b/kv_store/frameworks/libs/distributeddb/storage/include/storage_proxy.h index add570272f8df21f7ff99b0a4488e7a080bc845c..64fd735dfb4480369f63d0e6314402e4a428beec 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/include/storage_proxy.h +++ b/kv_store/frameworks/libs/distributeddb/storage/include/storage_proxy.h @@ -97,10 +97,13 @@ public: int ReleaseContinueToken(ContinueToken &continueStmtToken); int FillCloudAssetForDownload(const std::string &tableName, VBucket &asset, bool isDownloadSuccess); + int SetLogTriggerStatus(bool status); int SetCursorIncFlag(bool flag); + int GetCursor(const std::string &tableName, uint64_t &cursor); + int FillCloudLogAndAsset(OpType opType, const CloudSyncData &data); std::string GetIdentify() const; @@ -157,6 +160,10 @@ public: SingleVerConflictResolvePolicy policy); int ReviseLocalModTime(const std::string &tableName, const std::vector &revisedData); + + bool IsCurrentLogicDelete() const; + + int GetLocalDataCount(const std::string &tableName, int &dataCount, int &logicDeleteDataCount); protected: void Init(); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/cloud/cloud_storage_utils.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/cloud/cloud_storage_utils.cpp index e78ea7c2daeb5dcca3fcfc55d7d98167fdf38f8a..fc0c08c3b748e978e966088a67848f964fa7b41c 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/cloud/cloud_storage_utils.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/cloud/cloud_storage_utils.cpp @@ -435,7 +435,9 @@ Type CloudStorageUtils::GetAssetFromAssets(Type &value) } for (Asset &asset: assets) { - if (asset.flag != static_cast(AssetOpType::DELETE)) { + uint32_t lowStatus = AssetOperationUtils::EraseBitMask(asset.status); + if ((asset.flag == static_cast(AssetOpType::DELETE) && (lowStatus == AssetStatus::ABNORMAL || + lowStatus == AssetStatus::NORMAL)) || asset.flag != static_cast(AssetOpType::DELETE)) { return std::move(asset); } } @@ -1303,14 +1305,9 @@ int CloudStorageUtils::IdentifyCloudTypeInner(CloudSyncData &cloudSyncData, VBuc cloudSyncData.delData.timestamp.push_back(*timeStamp); cloudSyncData.delData.rowid.push_back(*rowid); } else { - if (data.empty()) { - LOGE("The cloud data is empty, isInsert:%d", isInsert); - return -E_INVALID_DATA; - } - if (IsAbnormalData(data)) { - LOGW("This data is abnormal, ignore it when upload, isInsert:%d", isInsert); - cloudSyncData.ignoredCount++; - return -E_IGNORE_DATA; + int errCode = CheckAbnormalData(cloudSyncData, data, isInsert); + if (errCode != E_OK) { + return errCode; } CloudSyncBatch &opData = isInsert ? cloudSyncData.insData : cloudSyncData.updData; opData.record.push_back(data); @@ -1328,14 +1325,20 @@ int CloudStorageUtils::IdentifyCloudTypeInner(CloudSyncData &cloudSyncData, VBuc return E_OK; } -bool CloudStorageUtils::IsAbnormalData(const VBucket &data) +int CloudStorageUtils::CheckAbnormalData(CloudSyncData &cloudSyncData, const VBucket &data, bool isInsert) { + if (data.empty()) { + LOGE("The cloud data is empty, isInsert:%d", static_cast(isInsert)); + return -E_INVALID_DATA; + } + bool isDataAbnormal = false; for (const auto &item : data) { const Asset *asset = std::get_if>(&item.second); if (asset != nullptr) { if (asset->status == static_cast(AssetStatus::ABNORMAL) || (asset->status & static_cast(AssetStatus::DOWNLOAD_WITH_NULL)) != 0) { - return true; + isDataAbnormal = true; + break; } continue; } @@ -1346,11 +1349,20 @@ bool CloudStorageUtils::IsAbnormalData(const VBucket &data) for (const auto &oneAsset : *assets) { if (oneAsset.status == static_cast(AssetStatus::ABNORMAL) || (oneAsset.status & static_cast(AssetStatus::DOWNLOAD_WITH_NULL)) != 0) { - return true; + isDataAbnormal = true; + break; } } } - return false; + if (isDataAbnormal) { + std::string gid; + (void)GetValueFromVBucket(CloudDbConstant::GID_FIELD, data, gid); + LOGW("This data is abnormal, ignore it when upload, isInsert:%d, gid:%s", static_cast(isInsert), + gid.c_str()); + cloudSyncData.ignoredCount++; + return -E_IGNORE_DATA; + } + return E_OK; } std::pair CloudStorageUtils::GetDataItemFromCloudData(VBucket &data) @@ -1471,13 +1483,6 @@ std::string CloudStorageUtils::GetCursorIncSql(const std::string &tableName) DBCommon::TransferStringToHex(DBCommon::GetCursorKey(tableName)) + "';"; } -std::string CloudStorageUtils::GetCursorUpgradeSql(const std::string &tableName) -{ - return "INSERT OR REPLACE INTO " + DBCommon::GetMetaTableName() + "(key,value) VALUES (x'" + - DBCommon::TransferStringToHex(DBCommon::GetCursorKey(tableName)) + "', (SELECT CASE WHEN MAX(cursor) IS" + - " NULL THEN 0 ELSE MAX(cursor) END FROM " + DBCommon::GetLogTableName(tableName) + "));"; -} - std::string CloudStorageUtils::GetCursorIncSqlWhenAllow(const std::string &tableName) { return "UPDATE " + DBConstant::RELATIONAL_PREFIX + "metadata" + " SET value= case when (select 1 from " + @@ -1485,6 +1490,13 @@ std::string CloudStorageUtils::GetCursorIncSqlWhenAllow(const std::string &table " else value end WHERE key=x'" + DBCommon::TransferStringToHex(DBCommon::GetCursorKey(tableName)) + "';"; } +std::string CloudStorageUtils::GetCursorUpgradeSql(const std::string &tableName) +{ + return "INSERT OR REPLACE INTO " + DBCommon::GetMetaTableName() + "(key,value) VALUES (x'" + + DBCommon::TransferStringToHex(DBCommon::GetCursorKey(tableName)) + "', (SELECT CASE WHEN MAX(cursor) IS" + + " NULL THEN 0 ELSE MAX(cursor) END FROM " + DBCommon::GetLogTableName(tableName) + "));"; +} + int CloudStorageUtils::GetSyncQueryByPk(const std::string &tableName, const std::vector &data, bool isKv, QuerySyncObject &querySyncObject) { diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/cloud/schema_mgr.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/cloud/schema_mgr.cpp index 039c02eaa7e1c7972227ca6286803adf197b1ccf..6748d0049f0cf9e32eeb3cde06bd09df63fba2d0 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/cloud/schema_mgr.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/cloud/schema_mgr.cpp @@ -156,8 +156,8 @@ void SchemaMgr::SetCloudDbSchema(const DataBaseSchema &schema, RelationalSchemaO std::string tableName = table.name; TableInfo tableInfo = localSchema.GetTable(tableName); if (tableInfo.Empty()) { - msg += ("[" + DBCommon::StringMiddleMasking(tableName) + ", " + std::to_string(tableName.size()) + "]"); - missingTables++; + msg += ("[" + DBCommon::StringMiddleMasking(tableName) + ", " + std::to_string(tableName.size()) + "]"); + missingTables++; continue; } FieldInfoMap localFields = tableInfo.GetFields(); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store.cpp index 8bb6705873244627e48457042087e7d3b8050659..88eb0d8d736ec8ae991d044807e968a31afafaa0 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store.cpp @@ -311,7 +311,8 @@ int RdSingleVerNaturalStore::PreCheckRdImport(std::string &storePath) return E_OK; } -int RdSingleVerNaturalStore::Import(const std::string &filePath, const CipherPassword &passwd) +int RdSingleVerNaturalStore::Import(const std::string &filePath, const CipherPassword &passwd, + bool isNeedIntegrityCheck) { int errCode = E_OK; std::string storePath; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store.h b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store.h index 15a14e4b8e6da5efcca88df70d7931caf62a9fb6..0fbfe89685a766f755e788fa02851c9994cc46bd 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store.h @@ -18,7 +18,7 @@ #include #include "db_common.h" -#include "grd_kv_api.h" +#include "grd_kv/grd_kv_api.h" #include "kvdb_utils.h" #include "rd_single_ver_storage_engine.h" #include "rd_single_ver_storage_executor.h" @@ -78,7 +78,7 @@ public: int Export(const std::string &filePath, const CipherPassword &passwd) override; - int Import(const std::string &filePath, const CipherPassword &passwd) override; + int Import(const std::string &filePath, const CipherPassword &passwd, bool isNeedIntegrityCheck = false) override; RdSingleVerStorageExecutor *GetHandle(bool isWrite, int &errCode, OperatePerm perm = OperatePerm::NORMAL_PERM) const; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store_connection.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store_connection.cpp index 6784b71ff871d83ba1353dbea5db589bd68db64e..b3b3615d924bcfe27c2c8f5d436b3ab588ac8f3f 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store_connection.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store_connection.cpp @@ -392,7 +392,8 @@ int RdSingleVerNaturalStoreConnection::Export(const std::string &filePath, const return kvDB_->Export(filePath, passwd); } -int RdSingleVerNaturalStoreConnection::Import(const std::string &filePath, const CipherPassword &passwd) +int RdSingleVerNaturalStoreConnection::Import(const std::string &filePath, const CipherPassword &passwd, + bool isNeedIntegrityCheck) { // not support passwd if (passwd.GetSize() != 0) { @@ -405,7 +406,7 @@ int RdSingleVerNaturalStoreConnection::Import(const std::string &filePath, const if (errCode != E_OK) { return errCode; } - errCode = kvDB_->Import(filePath, passwd); + errCode = kvDB_->Import(filePath, passwd, isNeedIntegrityCheck); if ((errCode == -E_INVALID_PASSWD_OR_CORRUPTED_DB) || (errCode == -E_UNEXPECTED_DATA)) { errCode = -E_INVALID_FILE; // import damaged file or txt file, return -E_INVALID_FILE } diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store_connection.h b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store_connection.h index 5b71d1ebec0c84bcb17ba20c854101fb209ed8b8..96c1490d774600e9100f535aed9628beba3156b7 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store_connection.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store_connection.h @@ -77,7 +77,7 @@ public: int Export(const std::string &filePath, const CipherPassword &passwd) override; - int Import(const std::string &filePath, const CipherPassword &passwd) override; + int Import(const std::string &filePath, const CipherPassword &passwd, bool isNeedIntegrityCheck = false) override; // Get the result set int GetResultSet(const IOption &option, const Key &keyPrefix, IKvDBResultSet *&resultSet) const override; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_result_set.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_result_set.cpp index 7ae02aeb0851fe030511e5d7185296c3dd680f8d..17adfff96752913b02510fc262767456b442d0e7 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_result_set.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_result_set.cpp @@ -14,8 +14,8 @@ */ #include "rd_single_ver_result_set.h" #include "db_errno.h" -#include "grd_db_api.h" -#include "grd_resultset_api.h" +#include "grd_base/grd_db_api.h" +#include "grd_base/grd_resultset_api.h" #include "log_print.h" #include "rd_utils.h" #include "sqlite_single_ver_storage_executor_sql.h" diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_result_set.h b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_result_set.h index b607fe94cd938559e55d17d2b9a4a015371081e6..39d2e41e49bd92d0553b343ac5c47229e2797843 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_result_set.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_result_set.h @@ -16,7 +16,7 @@ #ifndef RD_SINGLE_VER_RESULT_SET_H #define RD_SINGLE_VER_RESULT_SET_H #include "ikvdb_result_set.h" -#include "grd_resultset_api.h" +#include "grd_base/grd_resultset_api.h" #include "rd_single_ver_natural_store.h" #include "rd_single_ver_storage_executor.h" diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_storage_engine.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_storage_engine.cpp index 737bad2b05546001a25a3a8baee2ed26f232539c..6996332e44e0456f42f766370d1192bf621e696d 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_storage_engine.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_storage_engine.cpp @@ -15,8 +15,8 @@ #include "rd_single_ver_storage_engine.h" #include "db_constant.h" -#include "grd_error.h" -#include "grd_type_export.h" +#include "grd_base/grd_error.h" +#include "grd_base/grd_type_export.h" #include "rd_single_ver_storage_executor.h" #include "rd_utils.h" #include "single_ver_utils.h" diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_storage_engine.h b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_storage_engine.h index 10335c95a5183e5e5b1b0a3a6fef45e6cc8f0672..4b7887eb9156c77dc96fbeeab16c2d37ac57d5f8 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_storage_engine.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_storage_engine.h @@ -17,7 +17,7 @@ #define RD_SINGLE_VER_STORAGE_ENGINE_H #include "db_common.h" -#include "grd_db_api.h" +#include "grd_base/grd_db_api.h" #include "param_check_utils.h" #include "platform_specific.h" #include "runtime_context.h" diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_storage_executor.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_storage_executor.cpp index 93f0b8481b7dc7a700e2b2fcb9e320d0a0ed5264..d1755e71985efe39b30311ec4ccccdc399ee1fd9 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_storage_executor.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_storage_executor.cpp @@ -18,11 +18,11 @@ #include #include "db_common.h" -#include "grd_db_api.h" -#include "grd_document_api.h" -#include "grd_error.h" -#include "grd_resultset_api.h" -#include "grd_type_export.h" +#include "grd_base/grd_db_api.h" +#include "grd_document/grd_document_api.h" +#include "grd_base/grd_error.h" +#include "grd_base/grd_resultset_api.h" +#include "grd_base/grd_type_export.h" #include "ikvdb_result_set.h" #include "rd_utils.h" #include "sqlite_single_ver_storage_executor_sql.h" diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_storage_executor.h b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_storage_executor.h index e94664217152b05723598f2cc7fd758dd9eca1c0..6290c7406cf45268124b204a7f26654ee9d04a33 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_storage_executor.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_storage_executor.h @@ -17,8 +17,8 @@ #define RD_SINGLE_VER_STORAGE_EXECUTOR_H #include "macro_utils.h" #include "db_types.h" -#include "grd_kv_api.h" -#include "grd_resultset_api.h" +#include "grd_kv/grd_kv_api.h" +#include "grd_base/grd_resultset_api.h" #include "query_object.h" #include "sqlite_utils.h" #include "sqlite_single_ver_storage_executor.h" diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_utils.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_utils.cpp index c085079129645a31fea5662e39e501a071cbd18b..c1116e9b3271e2ca54a825e9141d0d4d9aa9cc41 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_utils.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_utils.cpp @@ -301,16 +301,16 @@ bool CheckParaOption(const KvStoreNbDelegate::Option &option, { if (option.storageEngineType == SQLITE) { if ((option.rdconfig.pageSize < SQLITE_PAGE_SIZE_MIN) || - (option.rdconfig.pageSize > SQLITE_PAGE_SIZE_MAX)) { + (option.rdconfig.pageSize > SQLITE_PAGE_SIZE_MAX)) { callback(INVALID_ARGS, nullptr); - LOGE("Invalid config pagesize:%" PRIu32, option.rdconfig.pageSize); + LOGE("Invalid config pageSize:%" PRIu32, option.rdconfig.pageSize); return false; } if ((option.rdconfig.cacheSize % option.rdconfig.pageSize != 0) || ((option.rdconfig.pageSize & (option.rdconfig.pageSize - 1)) != 0) || (option.rdconfig.cacheSize / SQLITE_CACHE_SIZE_PAGE > option.rdconfig.pageSize)) { callback(INVALID_ARGS, nullptr); - LOGE("Invalid config pagesize:%" PRIu32 "and cachesize:%" PRIu32, option.rdconfig.pageSize, + LOGE("Invalid config pageSize:%" PRIu32 "and cacheSize:%" PRIu32, option.rdconfig.pageSize, option.rdconfig.cacheSize); return false; } diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_utils.h b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_utils.h index d1b660bea2e88c02f47a4041355bf1ee14b46881..4c6d36c81260af4933c2bba05bba95cc53088ea5 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_utils.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_utils.h @@ -17,13 +17,13 @@ #define RD_UTILS_H #include #include "db_errno.h" -#include "grd_db_api.h" -#include "grd_error.h" -#include "grd_kv_api.h" -#include "grd_type_export.h" +#include "grd_base/grd_db_api.h" +#include "grd_base/grd_error.h" +#include "grd_kv/grd_kv_api.h" +#include "grd_base/grd_type_export.h" #include "kv_store_nb_delegate.h" #include "sqlite_single_ver_storage_executor.h" -#include "grd_document_api.h" +#include "grd_document/grd_document_api.h" namespace DistributedDB { diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/kv/generic_kvdb.h b/kv_store/frameworks/libs/distributeddb/storage/src/kv/generic_kvdb.h index 7c32c3be4a8397b390485ab2fb6feefefb4dba4b..a34873e53bcbadbd5ca4fa5a7989365aa1b42d62 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/kv/generic_kvdb.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/kv/generic_kvdb.h @@ -85,7 +85,8 @@ public: virtual int Export(const std::string &filePath, const CipherPassword &passwd) = 0; // Import the existing database files to the specified database file in the specified directory. - virtual int Import(const std::string &filePath, const CipherPassword &passwd) = 0; + virtual int Import(const std::string &filePath, const CipherPassword &passwd, + bool isNeedIntegrityCheck = false) = 0; // Release a db connection. void ReleaseDBConnection(GenericKvDBConnection *connection); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/kv/kvdb_manager.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/kv/kvdb_manager.cpp index 595c84b11fb83afb6f049c2771964f2bcb5e2a7e..33254e3875895c73ea8cc75a819aec0d3c2450c1 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/kv/kvdb_manager.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/kv/kvdb_manager.cpp @@ -357,8 +357,8 @@ IKvDBConnection *KvDBManager::GetDatabaseConnection(const KvDBProperties &proper std::string userId = properties.GetStringProp(KvDBProperties::USER_ID, ""); std::string storeId = properties.GetStringProp(KvDBProperties::STORE_ID, ""); manager->DataBaseCorruptNotify(appId, userId, storeId); - LOGE("Database [%s] is corrupted or invalid passwd:%d", STR_MASK(DBCommon::TransferStringToHex(identifier)), - errCode); + LOGE("Database [%s] is corrupted or authentication failed:%d", + STR_MASK(DBCommon::TransferStringToHex(identifier)), errCode); } return connection; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/kv/sync_able_kvdb.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/kv/sync_able_kvdb.cpp index 3b7166e88f28dc9d1e3317d2b1189e8fa9a2a18a..fdc54ecd2de6223339b6d35c6db3bc4714a7f80f 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/kv/sync_able_kvdb.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/kv/sync_able_kvdb.cpp @@ -94,7 +94,7 @@ int SyncAbleKvDB::Sync(const ISyncer::SyncParma &parma, uint64_t connectionId) return syncer_.Sync(parma, connectionId); } -// Cancel a sync action +// Cancel a sync action. int SyncAbleKvDB::CancelSync(uint32_t syncId) { if (!started_) { @@ -305,7 +305,7 @@ void SyncAbleKvDB::ChangeUserListener() uint64_t SyncAbleKvDB::GetTimestampFromDB() { - return 0; //default is 0 + return 0; // default is 0 } // Get The current virtual timestamp diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/kv/sync_able_kvdb_connection.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/kv/sync_able_kvdb_connection.cpp index d58a7b064c6cdc3be4bcdb748c09b1ec8472b424..37d7c2d4be4e09fa18ebee46d37b3bd800d5d1af 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/kv/sync_able_kvdb_connection.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/kv/sync_able_kvdb_connection.cpp @@ -154,15 +154,13 @@ int SyncAbleKvDBConnection::PragmaSyncAction(const PragmaSync *syncParameter) syncParam.onFinalize = [this]() { DecObjRef(this); }; if (syncParameter->onComplete_) { syncParam.onComplete = [this, onComplete = syncParameter->onComplete_, wait = syncParameter->wait_]( - const std::map &statuses - ) { + const std::map &statuses) { OnSyncComplete(statuses, onComplete, wait); }; } if (syncParameter->onSyncProcess_) { syncParam.onSyncProcess = [this, onSyncProcess = syncParameter->onSyncProcess_]( - const std::map &syncRecordMap - ) { + const std::map &syncRecordMap) { OnDeviceSyncProcess(syncRecordMap, onSyncProcess); }; } @@ -187,7 +185,7 @@ int SyncAbleKvDBConnection::CancelDeviceSync(uint32_t syncId) { AutoLock lockGuard(this); if (IsKilled()) { - // if this happens, users are using a closed connection. + // If this happens, users are using a closed connection. LOGE("CancelDeviceSync on a closed connection."); return -E_STALE; } diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/multiver/multi_ver_natural_store.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/multiver/multi_ver_natural_store.cpp index 82d89e4abe82f0408aa1bdab9eecd732be6af69d..8437cc75c11d668402a375c1c46b1613844a814b 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/multiver/multi_ver_natural_store.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/multiver/multi_ver_natural_store.cpp @@ -1190,13 +1190,7 @@ int MultiVerNaturalStore::DeleteMetaDataByPrefixKey(const Key &keyPrefix) const return -E_NOT_SUPPORT; } -void MultiVerNaturalStore::SetSendDataInterceptor(const PushDataInterceptor &interceptor) -{ - (void)interceptor; - return; -} - -void MultiVerNaturalStore::SetReceiveDataInterceptor(const DataInterceptor &interceptor) +void MultiVerNaturalStore::SetDataInterceptor(const PushDataInterceptor &interceptor) { (void)interceptor; return; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/multiver/multi_ver_natural_store.h b/kv_store/frameworks/libs/distributeddb/storage/src/multiver/multi_ver_natural_store.h index 8d1adb24061dea70b6ceb03f1fbc57164a68fc5c..e2f005d941727776f77c47c2dd35108637d3bac9 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/multiver/multi_ver_natural_store.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/multiver/multi_ver_natural_store.h @@ -156,9 +156,8 @@ public: int InitStorages(const KvDBProperties &kvDBProp, bool isChangeTag = false); - void SetSendDataInterceptor(const PushDataInterceptor &interceptor) override; + void SetDataInterceptor(const PushDataInterceptor &interceptor) override; - void SetReceiveDataInterceptor(const DataInterceptor &interceptor) override; private: int CheckSubStorageVersion(const KvDBProperties &kvDBProp, bool &isSubStorageAllExist) const; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/operation/database_oper.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/operation/database_oper.cpp index 0e2b73849f1f7f002f71240357a80e64a6d5bbe9..43983472c82c2f7831abd46200f6f8614565ea81 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/operation/database_oper.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/operation/database_oper.cpp @@ -172,7 +172,7 @@ int DatabaseOper::CheckSecurityOption(const std::string &filePath, const KvDBPro } int DatabaseOper::ExecuteImport(const std::string &filePath, const CipherPassword &passwd, - const KvDBProperties &property) const + const KvDBProperties &property, bool isNeedIntegrityCheck) const { ImportFileInfo importInfo; InitImportFileInfo(importInfo, property); @@ -212,7 +212,7 @@ int DatabaseOper::ExecuteImport(const std::string &filePath, const CipherPasswor // 3. export the unpacked file to the current database. LOGI("Import the unpacked database."); - errCode = ImportUnpackedDatabase(importInfo, passwd); + errCode = ImportUnpackedDatabase(importInfo, passwd, isNeedIntegrityCheck); if (errCode != E_OK) { LOGE("Failed to import from the unpacked databases, errCode = [%d]", errCode); } diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/operation/database_oper.h b/kv_store/frameworks/libs/distributeddb/storage/src/operation/database_oper.h index 5e933b0aa61edf80bcbfe65ff4faa451a391fbc0..c46ef085b6d6d87d7ce4c66ebf256b11d0450439 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/operation/database_oper.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/operation/database_oper.h @@ -28,7 +28,8 @@ public: virtual int Rekey(const CipherPassword &passwd) = 0; - virtual int Import(const std::string &filePath, const CipherPassword &passwd) = 0; + virtual int Import(const std::string &filePath, const CipherPassword &passwd, + bool isNeedIntegrityCheck = false) = 0; virtual int Export(const std::string &filePath, const CipherPassword &passwd) const = 0; @@ -59,11 +60,13 @@ protected: static int RemoveFile(const std::string &fileName); // import begin - int ExecuteImport(const std::string &filePath, const CipherPassword &passwd, const KvDBProperties &property) const; + int ExecuteImport(const std::string &filePath, const CipherPassword &passwd, const KvDBProperties &property, + bool isNeedIntegrityCheck = false) const; virtual int BackupCurrentDatabase(const ImportFileInfo &info) const = 0; - virtual int ImportUnpackedDatabase(const ImportFileInfo &info, const CipherPassword &srcPasswd) const = 0; + virtual int ImportUnpackedDatabase(const ImportFileInfo &info, const CipherPassword &srcPasswd, + bool isNeedIntegrityCheck = false) const = 0; virtual int ImportPostHandle() const = 0; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/operation/single_ver_database_oper.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/operation/single_ver_database_oper.cpp index 8983e7fcddc6ab17ac281f60fa545d9c41497b62..2f57b7bf77cd3ce554b12931c49baaa4c9d6a6de 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/operation/single_ver_database_oper.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/operation/single_ver_database_oper.cpp @@ -62,13 +62,13 @@ int SingleVerDatabaseOper::Rekey(const CipherPassword &passwd) return ExecuteRekey(passwd, singleVerNaturalStore_->GetDbProperties()); } -int SingleVerDatabaseOper::Import(const std::string &filePath, const CipherPassword &passwd) +int SingleVerDatabaseOper::Import(const std::string &filePath, const CipherPassword &passwd, bool isNeedIntegrityCheck) { if (singleVerNaturalStore_ == nullptr || storageEngine_ == nullptr) { return -E_INVALID_DB; } - return ExecuteImport(filePath, passwd, singleVerNaturalStore_->GetDbProperties()); + return ExecuteImport(filePath, passwd, singleVerNaturalStore_->GetDbProperties(), isNeedIntegrityCheck); } int SingleVerDatabaseOper::Export(const std::string &filePath, const CipherPassword &passwd) const @@ -325,7 +325,7 @@ int SingleVerDatabaseOper::ClearCurrentDatabase(const ImportFileInfo &info) cons } int SingleVerDatabaseOper::ImportUnpackedMainDatabase(const ImportFileInfo &info, - const CipherPassword &srcPasswd) const + const CipherPassword &srcPasswd, bool isNeedIntegrityCheck) const { std::string unpackedMainFile = info.unpackedDir + DBConstant::MAINDB_DIR + "/" + DBConstant::SINGLE_VER_DATA_STORE + DBConstant::DB_EXTENSION; @@ -346,6 +346,14 @@ int SingleVerDatabaseOper::ImportUnpackedMainDatabase(const ImportFileInfo &info int errCode = E_OK; if (isMainDbExisted) { + if (isNeedIntegrityCheck) { + // Check integrity before import + errCode = SQLiteUtils::CheckIntegrity(unpackedMainFile, cipherType, srcPasswd); + if (errCode != E_OK) { + LOGE("Check main file integrity error:%d", errCode); + return -E_INVALID_FILE; + } + } errCode = SQLiteUtils::ExportDatabase(unpackedMainFile, cipherType, srcPasswd, currentMainFile, passwd); if (errCode != E_OK) { LOGE("Export the unpacked main database to current error:%d", errCode); @@ -354,6 +362,14 @@ int SingleVerDatabaseOper::ImportUnpackedMainDatabase(const ImportFileInfo &info } if (isOldMainDbExisted) { + if (isNeedIntegrityCheck) { + // Check integrity before import + errCode = SQLiteUtils::CheckIntegrity(unpackedOldMainFile, cipherType, srcPasswd); + if (errCode != E_OK) { + LOGE("Check old main file integrity error:%d", errCode); + return -E_INVALID_FILE; + } + } errCode = SQLiteUtils::ExportDatabase(unpackedOldMainFile, cipherType, srcPasswd, currentMainFile, passwd); if (errCode != E_OK) { LOGE("Export the unpacked old version(<3) main database to current error:%d", errCode); @@ -379,7 +395,8 @@ int SingleVerDatabaseOper::ImportUnpackedMetaDatabase(const ImportFileInfo &info return errCode; } -int SingleVerDatabaseOper::ImportUnpackedDatabase(const ImportFileInfo &info, const CipherPassword &srcPasswd) const +int SingleVerDatabaseOper::ImportUnpackedDatabase(const ImportFileInfo &info, const CipherPassword &srcPasswd, + bool isNeedIntegrityCheck) const { std::string unpackedMetaFile = info.unpackedDir + DBConstant::METADB_DIR + "/" + DBConstant::SINGLE_VER_META_STORE + DBConstant::DB_EXTENSION; @@ -389,7 +406,7 @@ int SingleVerDatabaseOper::ImportUnpackedDatabase(const ImportFileInfo &info, co return errCode; } - errCode = ImportUnpackedMainDatabase(info, srcPasswd); + errCode = ImportUnpackedMainDatabase(info, srcPasswd, isNeedIntegrityCheck); if (errCode != E_OK) { LOGE("import unpacked mainDb fail, errCode = [%d]", errCode); return errCode; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/operation/single_ver_database_oper.h b/kv_store/frameworks/libs/distributeddb/storage/src/operation/single_ver_database_oper.h index b0ea78704d1198f4ff9853c1d6212f80c1856c5f..b670b0d9ff63c97210392968af0761c0ff879d2f 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/operation/single_ver_database_oper.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/operation/single_ver_database_oper.h @@ -27,7 +27,7 @@ public: int Rekey(const CipherPassword &passwd) override; - int Import(const std::string &filePath, const CipherPassword &passwd) override; + int Import(const std::string &filePath, const CipherPassword &passwd, bool isNeedIntegrityCheck = false) override; int Export(const std::string &filePath, const CipherPassword &passwd) const override; @@ -45,7 +45,8 @@ protected: int BackupCurrentDatabase(const ImportFileInfo &info) const override; - int ImportUnpackedDatabase(const ImportFileInfo &info, const CipherPassword &srcPasswd) const override; + int ImportUnpackedDatabase(const ImportFileInfo &info, const CipherPassword &srcPasswd, + bool isNeedIntegrityCheck = false) const override; int ImportPostHandle() const override; @@ -64,7 +65,8 @@ private: int ClearCurrentDatabase(const ImportFileInfo &info) const; - int ImportUnpackedMainDatabase(const ImportFileInfo &info, const CipherPassword &srcPasswd) const; + int ImportUnpackedMainDatabase(const ImportFileInfo &info, const CipherPassword &srcPasswd, + bool isNeedIntegrityCheck = false) const; int ImportUnpackedMetaDatabase(const ImportFileInfo &info) const; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/package_file.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/package_file.cpp index 03ade33e270ce4a2a845c05075312c8bf6b5141a..c4c4287644e31a17a0eadd4eafa2d67a22020ec7 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/package_file.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/package_file.cpp @@ -69,7 +69,7 @@ static int GetChecksum(const string &file, vector &result) { ifstream fileHandle(file, ios::in | ios::binary); if (!fileHandle.good()) { - LOGE("[GetChecksum]Error fileHandle!"); + LOGE("[GetChecksum]Error fileHandle! sys[%d]", errno); return -E_INVALID_PATH; } ValueHashCalc calc; @@ -86,7 +86,7 @@ static int GetChecksum(const string &file, vector &result) if (fileHandle.eof()) { readEnd = true; } else if (!fileHandle.good()) { - LOGE("[GetChecksum]fileHandle error!"); + LOGE("[GetChecksum]fileHandle error! sys[%d]", errno); return -E_INVALID_PATH; } errCode = calc.Update(buffer); @@ -206,6 +206,7 @@ static int PackFileHeader(ofstream &targetFile, const FileInfo &fileInfo, uint32 } targetFile.write(reinterpret_cast(buffer.data()), buffer.size()); if (!targetFile.good()) { + LOGE("[PackFileHeader] TargetFile error! sys[%d]", errno); return -E_INVALID_PATH; } return E_OK; @@ -230,7 +231,7 @@ static int UnpackFileHeader(ifstream &sourceFile, const string &sourceFileName, vector fileHeader(FILE_HEADER_LEN, 0); sourceFile.read(reinterpret_cast(fileHeader.data()), FILE_HEADER_LEN); if (!sourceFile.good()) { - LOGE("UnpackFileHeader sourceFile error!"); + LOGE("UnpackFileHeader sourceFile error! sys[%d]", errno); return -E_INVALID_FILE; } Parcel parcel(fileHeader.data(), FILE_HEADER_LEN); @@ -299,6 +300,7 @@ static int PackFileContext(ofstream &targetFile, const FileContext &fileContext) } targetFile.write(reinterpret_cast(buffer.data()), buffer.size()); if (!targetFile.good()) { + LOGE("[PackFileContext] TargetFile error! sys[%d]", errno); return -E_INVALID_PATH; } return E_OK; @@ -309,6 +311,7 @@ static int UnpackFileContext(ifstream &sourceFile, FileContext &fileContext) vector buffer(FILE_CONTEXT_LEN, 0); sourceFile.read(reinterpret_cast(buffer.data()), buffer.size()); if (!sourceFile.good()) { + LOGE("[UnpackFileContext] sourceFile read error! sys[%d]", errno); return -E_INVALID_PATH; } Parcel parcel(buffer.data(), FILE_CONTEXT_LEN); @@ -372,7 +375,7 @@ static int UnpackFileContent(ifstream &sourceFile, const string &targetPath, con ofstream file(fileName, ios::out | ios::binary); if (!file.good()) { file.close(); - LOGE("[UnpackFileContent]Get checksum failed."); + LOGE("[UnpackFileContent]filehandle error. sys[%d]", errno); return -E_INVALID_PATH; } int errCode = FileContentCopy(sourceFile, file, fileContext.fileLen); @@ -451,7 +454,7 @@ int PackageFile::GetPackageVersion(const std::string &sourceFile, uint32_t &vers sourceHandle.read(reinterpret_cast(fileHeader.data()), FILE_HEADER_LEN); if (!sourceHandle.good()) { // LCOV_EXCL_BR_LINE - LOGE("GetPackageVersion read sourceFile handle error!"); + LOGE("[GetPackageVersion] read sourceFile handle error! sys[%d]", errno); errCode = -E_INVALID_PATH; goto END; } @@ -529,7 +532,7 @@ int PackageFile::UnpackFile(const string &sourceFile, const string &targetPath, { ifstream sourceHandle(sourceFile, ios::in | ios::binary); if (!sourceHandle.good()) { - LOGE("sourceHandle error, sys err [%d]", errno); + LOGE("[UnpackFile] sourceHandle error, sys err [%d]", errno); return -E_INVALID_PATH; } uint32_t fileNum; @@ -541,6 +544,7 @@ int PackageFile::UnpackFile(const string &sourceFile, const string &targetPath, list fileContexts; sourceHandle.seekg(static_cast(FILE_HEADER_LEN), ios_base::beg); if (!sourceHandle.good()) { + LOGE("[UnpackFile] sourceHandle error after seekg, sys err [%d]", errno); return -E_INVALID_PATH; } for (uint32_t fileCount = 0; fileCount < fileNum; fileCount++) { diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/relational/relational_sync_able_storage.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/relational/relational_sync_able_storage.cpp index f7d99629bc3fb7d3e0653f2c67b7b695d7fbd303..2dce67203fc85e8da04bf3349d9178e80882d34e 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/relational/relational_sync_able_storage.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/relational/relational_sync_able_storage.cpp @@ -1963,7 +1963,7 @@ int RelationalSyncAbleStorage::ClearUnLockingNoNeedCompensated() return E_OK; } auto *handle = GetHandle(true, errCode); - if (errCode != E_OK || handle == nullptr) { + if (errCode != E_OK) { return errCode; } errCode = handle->StartTransaction(TransactType::IMMEDIATE); @@ -2022,7 +2022,7 @@ int RelationalSyncAbleStorage::GetCompensatedSyncQueryInner(SQLiteSingleVerRelat std::vector syncDataPk; errCode = handle->GetWaitCompensatedSyncDataPk(table, syncDataPk); if (errCode != E_OK) { - LOGW("[RDBStorageEngine] Get wait compensated sync date failed, continue! errCode=%d", errCode); + LOGW("[RDBStorageEngine] Get wait compensated sync data failed, continue! errCode=%d", errCode); errCode = E_OK; continue; } @@ -2187,5 +2187,28 @@ int RelationalSyncAbleStorage::ReviseLocalModTime(const std::string &tableName, ReleaseHandle(writeHandle); return errCode; } + +int RelationalSyncAbleStorage::GetCursor(const std::string &tableName, uint64_t &cursor) +{ + if (transactionHandle_ == nullptr) { + LOGE("[RelationalSyncAbleStorage] the transaction has not been started"); + return -E_INVALID_DB; + } + return transactionHandle_->GetCursor(tableName, cursor); +} + +int RelationalSyncAbleStorage::GetLocalDataCount(const std::string &tableName, int &dataCount, + int &logicDeleteDataCount) +{ + int errCode = E_OK; + auto *handle = GetHandle(false, errCode); + if (errCode != E_OK) { + LOGE("[RelationalSyncAbleStorage] Get handle failed when get local data count: %d", errCode); + return errCode; + } + errCode = handle->GetLocalDataCount(tableName, dataCount, logicDeleteDataCount); + ReleaseHandle(handle); + return errCode; +} } #endif diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/kv/sqlite_local_kvdb_connection.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/kv/sqlite_local_kvdb_connection.cpp index 674b72e2bcfdc613a0d36681d80d23c9d4b60460..a188ea9b1fee065d603ab3c2ce57de7999f2582e 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/kv/sqlite_local_kvdb_connection.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/kv/sqlite_local_kvdb_connection.cpp @@ -459,7 +459,8 @@ int SQLiteLocalKvDBConnection::Export(const std::string &filePath, const CipherP return kvDB_->Export(filePath, passwd); } -int SQLiteLocalKvDBConnection::Import(const std::string &filePath, const CipherPassword &passwd) +int SQLiteLocalKvDBConnection::Import(const std::string &filePath, const CipherPassword &passwd, + bool isNeedIntegrityCheck) { if (kvDB_ == nullptr) { return -E_INVALID_DB; @@ -483,7 +484,7 @@ int SQLiteLocalKvDBConnection::Import(const std::string &filePath, const CipherP kvDB_->ReEnableConnection(OperatePerm::IMPORT_MONOPOLIZE_PERM); return errCode; } - errCode = kvDB_->Import(filePath, passwd); + errCode = kvDB_->Import(filePath, passwd, isNeedIntegrityCheck); GenericKvDBConnection::ResetExclusiveStatus(); kvDB_->ReEnableConnection(OperatePerm::IMPORT_MONOPOLIZE_PERM); return errCode; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/kv/sqlite_local_kvdb_connection.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/kv/sqlite_local_kvdb_connection.h index 72179df5a15f14f9edf92dcf1eed15bb4615de2b..769ef14fed50d0680f7073ec313bfdedfbcc7059 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/kv/sqlite_local_kvdb_connection.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/kv/sqlite_local_kvdb_connection.h @@ -86,7 +86,7 @@ public: int Export(const std::string &filePath, const CipherPassword &passwd) override; - int Import(const std::string &filePath, const CipherPassword &passwd) override; + int Import(const std::string &filePath, const CipherPassword &passwd, bool isNeedIntegrityCheck = false) override; private: // Start the transaction diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/simple_tracker_log_table_manager.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/simple_tracker_log_table_manager.cpp index 7511fee9460e0b81dce054a7d57c89a621eb375b..66c55e4b06ce1e41359220042f598d0fa73382c2 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/simple_tracker_log_table_manager.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/simple_tracker_log_table_manager.cpp @@ -57,7 +57,7 @@ std::string SimpleTrackerLogTableManager::GetPrimaryKeySql(const TableInfo &tabl // The parameter "identity" is a hash string that identifies a device. The same for the next two functions. std::string SimpleTrackerLogTableManager::GetInsertTrigger(const TableInfo &table, const std::string &identity) { - if (table.GetTrackerTable().GetTrackerColNames().empty()) { + if (table.GetTrackerTable().IsEmpty()) { return ""; } std::string logTblName = GetLogTableName(table); @@ -76,8 +76,7 @@ std::string SimpleTrackerLogTableManager::GetInsertTrigger(const TableInfo &tabl insertTrigger += CalcPrimaryKeyHash("NEW.", table, identity) + ", '', "; insertTrigger += table.GetTrackerTable().GetAssignValSql(); insertTrigger += ", " + CloudStorageUtils::GetSelectIncCursorSql(tableName) + ", '', '', 0);\n"; - insertTrigger += "SELECT client_observer('" + tableName + "', NEW._rowid_, 0, "; - insertTrigger += table.GetTrackerTable().GetTrackerColNames().empty() ? "0" : "1"; + insertTrigger += "SELECT client_observer('" + tableName + "', NEW._rowid_, 0, 1"; insertTrigger += ");\n"; insertTrigger += "END;"; return insertTrigger; @@ -85,7 +84,7 @@ std::string SimpleTrackerLogTableManager::GetInsertTrigger(const TableInfo &tabl std::string SimpleTrackerLogTableManager::GetUpdateTrigger(const TableInfo &table, const std::string &identity) { - if (table.GetTrackerTable().GetTrackerColNames().empty()) { + if (table.GetTrackerTable().IsEmpty()) { return ""; } (void)identity; @@ -114,7 +113,7 @@ std::string SimpleTrackerLogTableManager::GetUpdateTrigger(const TableInfo &tabl std::string SimpleTrackerLogTableManager::GetDeleteTrigger(const TableInfo &table, const std::string &identity) { - if (table.GetTrackerTable().GetTrackerColNames().empty()) { + if (table.GetTrackerTable().IsEmpty()) { return ""; } (void)identity; @@ -132,7 +131,7 @@ std::string SimpleTrackerLogTableManager::GetDeleteTrigger(const TableInfo &tabl deleteTrigger += " WHERE data_key = OLD." + std::string(DBConstant::SQLITE_INNER_ROWID) + ";"; // -1 is rowid when data is deleted, 2 means change type is delete(ClientChangeType) deleteTrigger += "SELECT client_observer('" + tableName + "', -1, 2, "; - deleteTrigger += table.GetTrackerTable().GetTrackerColNames().empty() ? "0" : "1"; + deleteTrigger += table.GetTrackerTable().IsEmpty() ? "0" : "1"; deleteTrigger += ");\n"; deleteTrigger += "END;"; return deleteTrigger; @@ -148,7 +147,7 @@ std::vector SimpleTrackerLogTableManager::GetDropTriggers(const Tab dropTriggers.emplace_back(insertTrigger); dropTriggers.emplace_back(updateTrigger); dropTriggers.emplace_back(deleteTrigger); - if (table.GetTrackerTable().GetTrackerColNames().empty()) { + if (table.GetTrackerTable().IsEmpty()) { std::string deleteLogTable = "DROP TABLE IF EXISTS " + GetLogTableName(table) + ";"; dropTriggers.emplace_back(deleteLogTable); } diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.cpp index d063d53e586d762be99c01ca965a1c96ce2a1d9f..330cde711c43eef9067b66e55d2c093aebcc1fc2 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.cpp @@ -124,7 +124,7 @@ int SQLiteRelationalStore::GetSchemaFromMeta(RelationalSchemaObject &schema) LOGE("Get relational schema from meta table failed. %d", errCode); return errCode; } else if (errCode == -E_NOT_FOUND || schemaVal.empty()) { - LOGW("No relational schema info was found."); + LOGW("No relational schema info was found. error %d size %zu", errCode, schemaVal.size()); return -E_NOT_FOUND; } @@ -190,6 +190,9 @@ int SQLiteRelationalStore::CheckProperties(RelationalDBProperties properties) LOGE("Get distributed table mode from meta failed. errcode=%d", errCode); return errCode; } + if (!isSchemaEmpty) { + return errCode; + } errCode = SaveTableModeToMeta(mode); if (errCode != E_OK) { @@ -216,9 +219,20 @@ int SQLiteRelationalStore::SaveLogTableVersionToMeta() { LOGD("save log table version to meta table, version: %s", DBConstant::LOG_TABLE_VERSION_CURRENT); const Key logVersionKey(DBConstant::LOG_TABLE_VERSION_KEY.begin(), DBConstant::LOG_TABLE_VERSION_KEY.end()); + Value logVersion; + int errCode = storageEngine_->GetMetaData(logVersionKey, logVersion); + if (errCode != E_OK && errCode != -E_NOT_FOUND) { + LOGE("Get log version from meta table failed. %d", errCode); + return errCode; + } std::string versionStr(DBConstant::LOG_TABLE_VERSION_CURRENT); Value logVersionVal(versionStr.begin(), versionStr.end()); - int errCode = storageEngine_->PutMetaData(logVersionKey, logVersionVal); + // log version is same, no need to update + if (errCode == E_OK && !logVersion.empty() && logVersionVal == logVersion) { + return errCode; + } + // If the log version does not exist or is different, update the log version + errCode = storageEngine_->PutMetaData(logVersionKey, logVersionVal); if (errCode != E_OK) { LOGE("save log table version to meta table failed. %d", errCode); } @@ -1569,5 +1583,5 @@ SyncProcess SQLiteRelationalStore::GetCloudTaskStatus(uint64_t taskId) { return cloudSyncer_->GetCloudTaskStatus(taskId); } -} //namespace DistributedDB +} // namespace DistributedDB #endif diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_utils.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_utils.cpp index cdc6eaa479886ce046c30a3e40464c70da92f425..b51bb93f379dad5bc844b61537a3cbf9ee5ba4f0 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_utils.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_utils.cpp @@ -14,10 +14,12 @@ */ #include "sqlite_relational_utils.h" +#include "db_common.h" #include "db_errno.h" #include "cloud/cloud_db_types.h" #include "sqlite_utils.h" #include "cloud/cloud_storage_utils.h" +#include "res_finalizer.h" #include "runtime_context.h" #include "cloud/cloud_db_constant.h" @@ -426,4 +428,41 @@ int SQLiteRelationalUtils::QueryCount(sqlite3 *db, const std::string &tableName, SQLiteUtils::ResetStatement(stmt, true, errCode); return errCode; } + +int SQLiteRelationalUtils::GetCursor(sqlite3 *db, const std::string &tableName, uint64_t &cursor) +{ + cursor = DBConstant::INVALID_CURSOR; + std::string sql = "SELECT value FROM " + DBConstant::RELATIONAL_PREFIX + "metadata where key = ?;"; + sqlite3_stmt *stmt = nullptr; + int errCode = SQLiteUtils::GetStatement(db, sql, stmt); + if (errCode != E_OK) { + LOGE("[Storage Executor] Get cursor of table[%s length[%u]] failed=%d", + DBCommon::StringMiddleMasking(tableName).c_str(), tableName.length(), errCode); + return errCode; + } + ResFinalizer finalizer([stmt]() { + sqlite3_stmt *statement = stmt; + int ret = E_OK; + SQLiteUtils::ResetStatement(statement, true, ret); + if (ret != E_OK) { + LOGW("Reset stmt failed %d when get cursor", ret); + } + }); + Key key; + DBCommon::StringToVector(DBCommon::GetCursorKey(tableName), key); + errCode = SQLiteUtils::BindBlobToStatement(stmt, 1, key, false); // first arg. + if (errCode != E_OK) { + LOGE("[Storage Executor] Bind failed when get cursor of table[%s length[%u]] failed=%d", + DBCommon::StringMiddleMasking(tableName).c_str(), tableName.length(), errCode); + return errCode; + } + errCode = SQLiteUtils::StepWithRetry(stmt, false); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + int64_t tmpCursor = static_cast(sqlite3_column_int64(stmt, 0)); + if (tmpCursor >= 0) { + cursor = static_cast(tmpCursor); + } + } + return cursor == DBConstant::INVALID_CURSOR ? errCode : E_OK; +} } // namespace DistributedDB \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_utils.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_utils.h index 24eb4732fb658dd40873766cb45ca846c64b71cf..e48299af6230a095504d4d5451ec5b79769ac8d6 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_utils.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_utils.h @@ -47,6 +47,8 @@ public: static int AnalysisTrackerTable(sqlite3 *db, const TrackerTable &trackerTable, TableInfo &tableInfo); static int QueryCount(sqlite3 *db, const std::string &tableName, int64_t &count); + + static int GetCursor(sqlite3 *db, const std::string &tableName, uint64_t &cursor); private: static int BindExtendStatementByType(sqlite3_stmt *statement, int cid, Type &typeVal); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_relational_storage_engine.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_relational_storage_engine.cpp index 7104e98ae8d594685a3423c606b8bfa9e8d0aa28..6bee8fb4be8f6dbcf672cc8c54edc964147c702e 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_relational_storage_engine.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_relational_storage_engine.cpp @@ -386,6 +386,21 @@ int SQLiteSingleRelationalStorageEngine::CleanDistributedDeviceTable(std::vector return errCode; } + // go fast to check missing tables without transaction + errCode = handle->CheckAndCleanDistributedTable(schema_.GetTableNames(), missingTables); + if (errCode == E_OK) { + if (missingTables.empty()) { + LOGI("Check missing distributed table is empty."); + ReleaseExecutor(handle); + return errCode; + } + } else { + LOGE("Get missing distributed table failed. %d", errCode); + ReleaseExecutor(handle); + return errCode; + } + missingTables.clear(); + std::lock_guard lock(schemaMutex_); errCode = handle->StartTransaction(TransactType::IMMEDIATE); if (errCode != E_OK) { @@ -458,16 +473,16 @@ int SQLiteSingleRelationalStorageEngine::SetTrackerTable(const TrackerSchema &sc LOGW("tracker schema is no change."); return E_OK; } - bool isUpgrade = !tracker.GetTrackerTable(schema.tableName).IsEmpty(); + bool isCheckData = tracker.GetTrackerTable(schema.tableName).GetTableName().empty() || schema.isForceUpgrade; tracker.InsertTrackerSchema(schema); - int ret = handle->CreateTrackerTable(tracker.GetTrackerTable(schema.tableName), isUpgrade); + int ret = handle->CreateTrackerTable(tracker.GetTrackerTable(schema.tableName), isCheckData); if (ret != E_OK && ret != -E_WITH_INVENTORY_DATA) { (void)handle->Rollback(); ReleaseExecutor(handle); return ret; } - if (schema.trackerColNames.empty()) { + if (schema.trackerColNames.empty() && !schema.isTrackAction) { tracker.RemoveTrackerSchema(schema); } errCode = SaveTrackerSchemaToMetaTable(handle, tracker); @@ -506,7 +521,7 @@ int SQLiteSingleRelationalStorageEngine::CheckAndCacheTrackerSchema(const Tracke LOGW("tracker schema is no change for distributed table."); return -E_IGNORE_DATA; } - isFirstCreate = tracker.GetTrackerTable(schema.tableName).IsEmpty(); + isFirstCreate = tracker.GetTrackerTable(schema.tableName).GetTableName().empty(); tracker.InsertTrackerSchema(schema); tableInfo.SetTrackerTable(tracker.GetTrackerTable(schema.tableName)); errCode = tableInfo.CheckTrackerTable(); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_executor.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_executor.cpp index ca52c0084276878af62dda2e3f608d4222e409c0..27e5d1c461711fc28d28cc66f29160b31e7fcabb 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_executor.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_executor.cpp @@ -42,7 +42,10 @@ static constexpr const char *FLAG_IS_CLOUD = "FLAG & 0x02 = 0"; // see if 1th bi static constexpr const char *FLAG_IS_CLOUD_CONSISTENCY = "FLAG & 0x20 = 0"; // see if flag is cloud_consistency // set 1th bit of flag to one which is local, clean 5th bit of flag to one which is wait compensated sync static constexpr const char *SET_FLAG_LOCAL_AND_CLEAN_WAIT_COMPENSATED_SYNC = "(CASE WHEN data_key = -1 and " - "FLAG & 0x02 = 0x02 THEN (FLAG | 0x02) & (~0x10) & (~0x20) ELSE (FLAG | 0x02 | 0x20) & (~0x10) END)"; + "FLAG & 0x02 = 0x02 THEN FLAG & (~0x10) & (~0x20) ELSE (FLAG | 0x02 | 0x20) & (~0x10) END)"; +// clean 5th bit of flag to one which is wait compensated sync +static constexpr const char *SET_FLAG_CLEAN_WAIT_COMPENSATED_SYNC = "(CASE WHEN data_key = -1 and " + "FLAG & 0x02 = 0x02 THEN FLAG & (~0x10) & (~0x20) ELSE (FLAG | 0x20) & (~0x10) END)"; static constexpr const char *FLAG_IS_LOGIC_DELETE = "FLAG & 0x08 != 0"; // see if 3th bit of a flag is logic delete // set data logic delete, exist passport, delete, not compensated and cloud static constexpr const char *SET_FLAG_WHEN_LOGOUT = "(FLAG | 0x08 | 0x800 | 0x01) & (~0x12)"; @@ -1674,10 +1677,15 @@ void SQLiteSingleVerRelationalStorageExecutor::SetLocalSchema(const RelationalSc int SQLiteSingleVerRelationalStorageExecutor::CleanCloudDataOnLogTable(const std::string &logTableName, ClearMode mode) { - std::string cleanLogSql = "UPDATE " + logTableName + " SET " + CloudDbConstant::FLAG + " = " + - SET_FLAG_LOCAL_AND_CLEAN_WAIT_COMPENSATED_SYNC + ", " + VERSION + " = '', " + - DEVICE_FIELD + " = '', " + CLOUD_GID_FIELD + " = '', " + SHARING_RESOURCE + " = '' " + - "WHERE (" + FLAG_IS_LOGIC_DELETE + ") OR " + + std::string setFlag; + if (mode == FLAG_ONLY && isLogicDelete_) { + setFlag = SET_FLAG_CLEAN_WAIT_COMPENSATED_SYNC; + } else { + setFlag = SET_FLAG_LOCAL_AND_CLEAN_WAIT_COMPENSATED_SYNC; + } + std::string cleanLogSql = "UPDATE " + logTableName + " SET " + CloudDbConstant::FLAG + " = " + setFlag + + ", " + VERSION + " = '', " + DEVICE_FIELD + " = '', " + CLOUD_GID_FIELD + " = '', " + + SHARING_RESOURCE + " = '' " + "WHERE (" + FLAG_IS_LOGIC_DELETE + ") OR " + CLOUD_GID_FIELD + " IS NOT NULL AND " + CLOUD_GID_FIELD + " != '';"; int errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, cleanLogSql); if (errCode != E_OK) { @@ -1755,10 +1763,10 @@ int SQLiteSingleVerRelationalStorageExecutor::SetDataOnUserTableWithLogicDelete( const std::string &logTableName) { UpdateCursorContext context; - context.cursor = GetCursor(tableName); - LOGI("removeData on userTable:%s length:%d start and cursor is, %d.", + int errCode = SQLiteRelationalUtils::GetCursor(dbHandle_, tableName, context.cursor); + LOGI("removeData on userTable:%s length:%d start and cursor is %llu.", DBCommon::StringMiddleMasking(tableName).c_str(), tableName.size(), context.cursor); - int errCode = CreateFuncUpdateCursor(context, &UpdateCursor); + errCode = CreateFuncUpdateCursor(context, &UpdateCursor); if (errCode != E_OK) { LOGE("Failed to create updateCursor func on userTable errCode=%d.", errCode); return errCode; @@ -1783,7 +1791,7 @@ int SQLiteSingleVerRelationalStorageExecutor::SetDataOnUserTableWithLogicDelete( LOGE("Failed to deal logic delete data flag on usertable, %d.", errCode); return errCode; } - LOGI("removeData on userTable:%s length:%d finish and cursor is, %d.", + LOGI("removeData on userTable:%s length:%d finish and cursor is %llu.", DBCommon::StringMiddleMasking(tableName).c_str(), tableName.size(), context.cursor); errCode = SetCursor(tableName, context.cursor); if (errCode != E_OK) { @@ -1797,10 +1805,10 @@ int SQLiteSingleVerRelationalStorageExecutor::SetDataOnShareTableWithLogicDelete const std::string &logTableName) { UpdateCursorContext context; - context.cursor = GetCursor(tableName); - LOGI("removeData on shareTable:%s length:%d start and cursor is, %d.", + int errCode = SQLiteRelationalUtils::GetCursor(dbHandle_, tableName, context.cursor); + LOGI("removeData on shareTable:%s length:%d start and cursor is %llu.", DBCommon::StringMiddleMasking(tableName).c_str(), tableName.size(), context.cursor); - int errCode = CreateFuncUpdateCursor(context, &UpdateCursor); + errCode = CreateFuncUpdateCursor(context, &UpdateCursor); if (errCode != E_OK) { LOGE("Failed to create updateCursor func on shareTable errCode=%d.", errCode); return errCode; @@ -1811,7 +1819,7 @@ int SQLiteSingleVerRelationalStorageExecutor::SetDataOnShareTableWithLogicDelete " AND NOT (" + FLAG_IS_LOGIC_DELETE + "));"; errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, sql); // here just clear updateCursor func, fail will not influence other function - CreateFuncUpdateCursor(context, nullptr); + (void)CreateFuncUpdateCursor(context, nullptr); if (errCode != E_OK) { LOGE("Failed to change cloud data flag on shareTable, %d.", errCode); return errCode; @@ -1824,7 +1832,7 @@ int SQLiteSingleVerRelationalStorageExecutor::SetDataOnShareTableWithLogicDelete LOGE("Failed to deal logic delete data flag on shareTable, %d.", errCode); return errCode; } - LOGI("removeData on shareTable:%s length:%d finish and cursor is, %d.", + LOGI("removeData on shareTable:%s length:%d finish and cursor is %llu.", DBCommon::StringMiddleMasking(tableName).c_str(), tableName.size(), context.cursor); return SetCursor(tableName, context.cursor); } @@ -1840,7 +1848,7 @@ int SQLiteSingleVerRelationalStorageExecutor::GetCleanCloudDataKeys(const std::s sql += FLAG_IS_CLOUD; sql += " OR "; sql += FLAG_IS_CLOUD_CONSISTENCY; - sql += " ) "; + sql += " )"; } sql += ";"; int errCode = SQLiteUtils::GetStatement(dbHandle_, sql, selectStmt); @@ -1891,7 +1899,10 @@ int SQLiteSingleVerRelationalStorageExecutor::GetUpdateLogRecordStatement(const updateLogSql += " device = 'cloud', timestamp = ?,"; updateColName.push_back(CloudDbConstant::MODIFY_FIELD); if (opType == OpType::DELETE) { - updateLogSql += GetCloudDeleteSql(tableSchema.name); + int errCode = GetCloudDeleteSql(tableSchema.name, updateLogSql); + if (errCode != E_OK) { + return errCode; + } } else { updateLogSql += GetUpdateDataFlagSql() + ", cloud_gid = ?"; updateColName.push_back(CloudDbConstant::GID_FIELD); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_executor.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_executor.h index 2af07ab80a8d9a6e25cd5e2061bee58b25ab8abf..2374572a0d029605e6cd647e2be4557d59a36cec 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_executor.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_executor.h @@ -48,7 +48,7 @@ public: struct UpdateCursorContext { int errCode = E_OK; - int cursor; + uint64_t cursor; }; SQLiteSingleVerRelationalStorageExecutor(sqlite3 *dbHandle, bool writable, DistributedTableMode mode); @@ -145,8 +145,10 @@ public: int SetLogTriggerStatus(bool status); int SetCursorIncFlag(bool flag); + int GetCursor(const std::string &tableName, uint64_t &cursor); + int AnalysisTrackerTable(const TrackerTable &trackerTable, TableInfo &tableInfo); - int CreateTrackerTable(const TrackerTable &trackerTable, bool isUpgrade); + int CreateTrackerTable(const TrackerTable &trackerTable, bool checkData); int GetOrInitTrackerSchemaFromMeta(RelationalSchemaObject &schema); int ExecuteSql(const SqlCondition &condition, std::vector &records); @@ -211,6 +213,8 @@ public: void SetTableSchema(const TableSchema &tableSchema); int ReviseLocalModTime(const std::string &tableName, const std::vector &revisedData); + + int GetLocalDataCount(const std::string &tableName, int &dataCount, int &logicDeleteDataCount); private: int DoCleanLogs(const std::vector &tableNameList, const RelationalSchemaObject &localSchema); @@ -231,9 +235,7 @@ private: int CreateFuncUpdateCursor(UpdateCursorContext &context, void(*updateCursorFunc)(sqlite3_context *ctx, int argc, sqlite3_value **argv)) const; - int GetCursor(const std::string &tableName); - - int SetCursor(const std::string &tableName, int cursor); + int SetCursor(const std::string &tableName, uint64_t cursor); int IncreaseCursorOnAssetData(const std::string &tableName, const std::string &gid); @@ -385,7 +387,7 @@ private: int BindStmtWithCloudGid(const CloudSyncData &cloudDataResult, bool ignoreEmptyGid, sqlite3_stmt *&stmt); - std::string GetCloudDeleteSql(const std::string &table); + int GetCloudDeleteSql(const std::string &table, std::string &sql); int RemoveDataAndLog(const std::string &tableName, int64_t dataKey); @@ -492,4 +494,4 @@ private: }; } // namespace DistributedDB #endif -#endif // SQLITE_SINGLE_VER_RELATIONAL_STORAGE_EXECUTOR_H \ No newline at end of file +#endif // SQLITE_SINGLE_VER_RELATIONAL_STORAGE_EXECUTOR_H diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_executor_extend.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_executor_extend.cpp index e837116d4c08a8d8b78e63fc9c745707a3a0e251..ba6e5fd5e563039745e6376f81994c33bd624f72 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_executor_extend.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_executor_extend.cpp @@ -370,7 +370,7 @@ void SQLiteSingleVerRelationalStorageExecutor::UpdateCursor(sqlite3_context *ctx } int SQLiteSingleVerRelationalStorageExecutor::CreateFuncUpdateCursor(UpdateCursorContext &context, - void (*updateCursor)(sqlite3_context *ctx, int argc, sqlite3_value **argv)) const + void(*updateCursor)(sqlite3_context *ctx, int argc, sqlite3_value **argv)) const { std::string sql = "update_cursor"; int errCode = sqlite3_create_function_v2(dbHandle_, sql.c_str(), 0, SQLITE_UTF8 | SQLITE_DIRECTONLY, @@ -382,45 +382,19 @@ int SQLiteSingleVerRelationalStorageExecutor::CreateFuncUpdateCursor(UpdateCurso return E_OK; } -int SQLiteSingleVerRelationalStorageExecutor::GetCursor(const std::string &tableName) +int SQLiteSingleVerRelationalStorageExecutor::GetCursor(const std::string &tableName, uint64_t &cursor) { - int cursor = -1; - std::string sql = "SELECT value FROM " + DBConstant::RELATIONAL_PREFIX + "metadata where key = ?;"; - sqlite3_stmt *stmt = nullptr; - int errCode = SQLiteUtils::GetStatement(dbHandle_, sql, stmt); - if (errCode != E_OK) { - LOGE("[Storage Executor]get cursor failed=%d", errCode); - return cursor; - } - ResFinalizer finalizer([stmt]() { - sqlite3_stmt *statement = stmt; - int ret = E_OK; - SQLiteUtils::ResetStatement(statement, true, ret); - if (ret != E_OK) { - LOGW("Reset stmt failed %d when get cursor", ret); - } - }); - Key key; - DBCommon::StringToVector(DBCommon::GetCursorKey(tableName), key); - errCode = SQLiteUtils::BindBlobToStatement(stmt, 1, key, false); // first arg. - if (errCode != E_OK) { - return cursor; - } - errCode = SQLiteUtils::StepWithRetry(stmt, isMemDb_); - if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { - cursor = static_cast(sqlite3_column_int64(stmt, 0)); - } - return cursor; + return SQLiteRelationalUtils::GetCursor(dbHandle_, tableName, cursor); } -int SQLiteSingleVerRelationalStorageExecutor::SetCursor(const std::string &tableName, int cursor) +int SQLiteSingleVerRelationalStorageExecutor::SetCursor(const std::string &tableName, uint64_t cursor) { std::string sql = "UPDATE " + DBConstant::RELATIONAL_PREFIX + "metadata SET VALUE = ? where KEY = ?;"; sqlite3_stmt *stmt = nullptr; int errCode = SQLiteUtils::GetStatement(dbHandle_, sql, stmt); if (errCode != E_OK) { LOGE("Set cursor sql failed=%d", errCode); - return cursor; + return errCode; } ResFinalizer finalizer([stmt]() { sqlite3_stmt *statement = stmt; @@ -440,7 +414,7 @@ int SQLiteSingleVerRelationalStorageExecutor::SetCursor(const std::string &table DBCommon::StringToVector(DBCommon::GetCursorKey(tableName), key); errCode = SQLiteUtils::BindBlobToStatement(stmt, index, key, false); if (errCode != E_OK) { - return cursor; + return errCode; } errCode = SQLiteUtils::StepWithRetry(stmt, isMemDb_); if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { @@ -479,7 +453,6 @@ int SQLiteSingleVerRelationalStorageExecutor::DoCleanLogAndData(const std::vecto return errCode; } } - return errCode; } @@ -1286,7 +1259,7 @@ bool SQLiteSingleVerRelationalStorageExecutor::IsNeedUpdateAssetIdInner(sqlite3_ return true; } Asset &assetDB = *assetDBPtr; - if (assetDB.assetId != asset.assetId) { + if (assetDB.assetId != asset.assetId || asset.status != AssetStatus::NORMAL) { return true; } } @@ -1301,8 +1274,8 @@ bool SQLiteSingleVerRelationalStorageExecutor::IsNeedUpdateAssetIdInner(sqlite3_ if (assets.size() != assetsDB.size()) { return true; } - for (uint32_t i = 0; i< assets.size(); ++i) { - if (assets[i].assetId != assetsDB[i].assetId) { + for (uint32_t i = 0; i < assets.size(); ++i) { + if (assets[i].assetId != assetsDB[i].assetId || assets[i].status != AssetStatus::NORMAL) { return true; } } @@ -1334,11 +1307,11 @@ bool SQLiteSingleVerRelationalStorageExecutor::IsNeedUpdateAssetId(const TableSc queryAssetsSql += " FROM '" + tableSchema.name + "' WHERE " + std::string(DBConstant::SQLITE_INNER_ROWID) + " = " + std::to_string(dataKey) + ";"; int errCode = SQLiteUtils::GetStatement(dbHandle_, queryAssetsSql, selectStmt); - if (errCode != E_OK || selectStmt == nullptr) { // LCOV_EXCL_BR_LINE + if (errCode != E_OK) { // LCOV_EXCL_BR_LINE LOGE("Get select assets statement failed, %d.", errCode); - return errCode; + return true; } - ResFinalizer finalizer([selectStmt] { + ResFinalizer finalizer([selectStmt]() { sqlite3_stmt *statementInner = selectStmt; int ret = E_OK; SQLiteUtils::ResetStatement(statementInner, true, ret); @@ -1351,7 +1324,7 @@ bool SQLiteSingleVerRelationalStorageExecutor::IsNeedUpdateAssetId(const TableSc if (errCode != E_OK) { return true; } - for (const auto &field : tableSchema.fields) { + for (const auto &field : assetFields) { if (IsNeedUpdateAssetIdInner(selectStmt, vBucket, field, assetInfo)) { return true; } @@ -1370,7 +1343,7 @@ int SQLiteSingleVerRelationalStorageExecutor::MarkFlagAsConsistent(const std::st " SET flag=flag&(~0x20), " + CloudDbConstant::UNLOCKING_TO_UNLOCK + " WHERE cloud_gid=? and timestamp=?;"; sqlite3_stmt *stmt = nullptr; int errCode = SQLiteUtils::GetStatement(dbHandle_, sql, stmt); - if (errCode != E_OK || stmt == nullptr) { + if (errCode != E_OK) { LOGE("Get mark flag as consistent stmt failed, %d.", errCode); return errCode; } @@ -1405,7 +1378,7 @@ int SQLiteSingleVerRelationalStorageExecutor::FillCloudVersionForUpload(const st "' SET version = ? WHERE hash_key = ? "; sqlite3_stmt *stmt = nullptr; int errCode = SQLiteUtils::GetStatement(dbHandle_, sql, stmt); - if (errCode != E_OK || stmt == nullptr) { + if (errCode != E_OK) { return errCode; } int ret = E_OK; @@ -1431,7 +1404,7 @@ int SQLiteSingleVerRelationalStorageExecutor::CheckInventoryData(const std::stri int64_t dataCount = 0; int errCode = SQLiteRelationalUtils::QueryCount(dbHandle_, tableName, dataCount); if (errCode != E_OK) { - LOGE("Query count failed.", errCode); + LOGE("Query count failed %d", errCode); return errCode; } return dataCount > 0 ? -E_WITH_INVENTORY_DATA : E_OK; @@ -1442,7 +1415,7 @@ int SQLiteSingleVerRelationalStorageExecutor::GetUploadCountInner(const Timestam { sqlite3_stmt *stmt = nullptr; int errCode = helper.GetCloudQueryStatement(false, dbHandle_, sql, stmt); - if (errCode != E_OK || stmt == nullptr) { + if (errCode != E_OK) { LOGE("failed to get count statement %d", errCode); return errCode; } @@ -1507,7 +1480,7 @@ int SQLiteSingleVerRelationalStorageExecutor::UpdateCloudLogGid(const CloudSyncD + "' SET cloud_gid = ? WHERE data_key = ? "; sqlite3_stmt *stmt = nullptr; int errCode = SQLiteUtils::GetStatement(dbHandle_, sql, stmt); - if (errCode != E_OK || stmt == nullptr) { + if (errCode != E_OK) { return errCode; } errCode = BindStmtWithCloudGid(cloudDataResult, ignoreEmptyGid, stmt); @@ -1523,7 +1496,7 @@ int SQLiteSingleVerRelationalStorageExecutor::GetSyncCloudData(const CloudUpload sqlite3_stmt *queryStmt = nullptr; bool isStepNext = false; int errCode = token.GetCloudStatement(dbHandle_, cloudDataResult, queryStmt, isStepNext); - if (errCode != E_OK || queryStmt == nullptr) { + if (errCode != E_OK) { (void)token.ReleaseCloudStatement(); return errCode; } @@ -1594,7 +1567,26 @@ int SQLiteSingleVerRelationalStorageExecutor::GetAssetInfoOnTable(sqlite3_stmt * } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { errCode = E_OK; } else { - LOGE("[RDBExecutor] Step failed when get assets from table, errCode = %d.", errCode); + LOGE("[RDBExecutor] Step failed when get asset from table, errCode = %d.", errCode); + } + return errCode; +} + +int SQLiteSingleVerRelationalStorageExecutor::GetLocalDataCount(const std::string &tableName, int &dataCount, + int &logicDeleteDataCount) +{ + std::string dataCountSql = "select count(*) from " + DBCommon::GetLogTableName(tableName) + " where data_key != -1"; + int errCode = SQLiteUtils::GetCountBySql(dbHandle_, dataCountSql, dataCount); + if (errCode != E_OK) { + LOGE("[RDBExecutor] Query local data count failed: %d", errCode); + return errCode; + } + + std::string logicDeleteDataCountSql = "select count(*) from " + DBCommon::GetLogTableName(tableName) + + " where flag&0x08!=0 and data_key != -1"; + errCode = SQLiteUtils::GetCountBySql(dbHandle_, logicDeleteDataCountSql, logicDeleteDataCount); + if (errCode != E_OK) { + LOGE("[RDBExecutor] Query local logic delete data count failed: %d", errCode); } return errCode; } diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_extend_executor.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_extend_executor.cpp index f3183f1da0b0d723c2c139f0efabca247265e774..c6715ae4cbb4f0487b92ed4ce869310090357c16 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_extend_executor.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_extend_executor.cpp @@ -146,17 +146,23 @@ int SQLiteSingleVerRelationalStorageExecutor::FillCloudAssetForDownload(const Ta int SQLiteSingleVerRelationalStorageExecutor::IncreaseCursorOnAssetData(const std::string &tableName, const std::string &gid) { - int cursor = GetCursor(tableName); + uint64_t cursor = DBConstant::INVALID_CURSOR; + int errCode = SQLiteRelationalUtils::GetCursor(dbHandle_, tableName, cursor); + if (errCode != E_OK) { + LOGE("Get cursor of table[%s length[%u]] failed when increase cursor: %d, gid[%s]", + DBCommon::StringMiddleMasking(tableName).c_str(), tableName.length(), errCode, gid.c_str()); + return errCode; + } cursor++; std::string sql = "UPDATE " + DBConstant::RELATIONAL_PREFIX + tableName + "_log"; sql += " SET cursor = ? where cloud_gid = ?;"; sqlite3_stmt *statement = nullptr; - int errCode = SQLiteUtils::GetStatement(dbHandle_, sql, statement); + errCode = SQLiteUtils::GetStatement(dbHandle_, sql, statement); if (errCode != E_OK) { LOGE("get update asset data cursor stmt failed %d.", errCode); return errCode; } - ResFinalizer finalizer([statement] { + ResFinalizer finalizer([statement]() { sqlite3_stmt *statementInner = statement; int ret = E_OK; SQLiteUtils::ResetStatement(statementInner, true, ret); @@ -327,7 +333,7 @@ int SQLiteSingleVerRelationalStorageExecutor::AnalysisTrackerTable(const Tracker return SQLiteRelationalUtils::AnalysisTrackerTable(dbHandle_, trackerTable, tableInfo); } -int SQLiteSingleVerRelationalStorageExecutor::CreateTrackerTable(const TrackerTable &trackerTable, bool isUpgrade) +int SQLiteSingleVerRelationalStorageExecutor::CreateTrackerTable(const TrackerTable &trackerTable, bool checkData) { TableInfo table; table.SetTableSyncType(TableSyncType::CLOUD_COOPERATION); @@ -336,7 +342,7 @@ int SQLiteSingleVerRelationalStorageExecutor::CreateTrackerTable(const TrackerTa return errCode; } auto tableManager = std::make_unique(); - if (trackerTable.GetTrackerColNames().empty()) { + if (trackerTable.IsEmpty()) { // drop trigger return tableManager->AddRelationalLogTableTrigger(dbHandle_, table, ""); } @@ -352,12 +358,10 @@ int SQLiteSingleVerRelationalStorageExecutor::CreateTrackerTable(const TrackerTa return errCode; } std::string calPrimaryKeyHash = tableManager->CalcPrimaryKeyHash("a.", table, ""); - if (isUpgrade) { - errCode = CleanExtendAndCursorForDeleteData(table.GetTableName()); - if (errCode != E_OK) { - LOGE("clean tracker log info for deleted data failed %d.", errCode); - return errCode; - } + errCode = CleanExtendAndCursorForDeleteData(table.GetTableName()); + if (errCode != E_OK) { + LOGE("clean tracker log info for deleted data failed %d.", errCode); + return errCode; } errCode = GeneLogInfoForExistedData(dbHandle_, trackerTable.GetTableName(), calPrimaryKeyHash, table); if (errCode != E_OK) { @@ -372,7 +376,7 @@ int SQLiteSingleVerRelationalStorageExecutor::CreateTrackerTable(const TrackerTa if (errCode != E_OK) { return errCode; } - if (!isUpgrade) { + if (checkData) { return CheckInventoryData(DBCommon::GetLogTableName(table.GetTableName())); } return E_OK; @@ -607,6 +611,8 @@ int SQLiteSingleVerRelationalStorageExecutor::CleanTrackerData(const std::string int SQLiteSingleVerRelationalStorageExecutor::CreateSharedTable(const TableSchema &tableSchema) { + LOGI("Create shared table[%s length[%u]]", DBCommon::StringMiddleMasking(tableSchema.name).c_str(), + tableSchema.name.length()); std::map cloudFieldTypeMap; cloudFieldTypeMap[TYPE_INDEX] = "NULL"; cloudFieldTypeMap[TYPE_INDEX] = "INT"; @@ -740,7 +746,7 @@ int SQLiteSingleVerRelationalStorageExecutor::DoCleanShareTableDataAndLog(const errCode = CleanShareTable(tableName); } if (errCode != E_OK) { - LOGE("clean shared table failed at table:%s, length:%d, deleteType:%d, errCode:%d", + LOGE("clean share table failed at table:%s, length:%d, deleteType:%d, errCode:%d.", DBCommon::StringMiddleMasking(tableName).c_str(), tableName.size(), isLogicDelete_ ? 1 : 0, errCode); return errCode; } @@ -755,7 +761,7 @@ int SQLiteSingleVerRelationalStorageExecutor::CleanShareTable(const std::string std::string delDataSql = "DELETE FROM '" + tableName + "';"; sqlite3_stmt *statement = nullptr; errCode = SQLiteUtils::GetStatement(dbHandle_, delDataSql, statement); - if (errCode != E_OK || statement == nullptr) { + if (errCode != E_OK) { LOGE("get clean shared data stmt failed %d.", errCode); return errCode; } @@ -770,7 +776,7 @@ int SQLiteSingleVerRelationalStorageExecutor::CleanShareTable(const std::string statement = nullptr; std::string delLogSql = "DELETE FROM '" + DBConstant::RELATIONAL_PREFIX + tableName + "_log';"; errCode = SQLiteUtils::GetStatement(dbHandle_, delLogSql, statement); - if (errCode != E_OK || statement == nullptr) { + if (errCode != E_OK) { LOGE("get clean shared log stmt failed %d.", errCode); return errCode; } @@ -1015,11 +1021,15 @@ int SQLiteSingleVerRelationalStorageExecutor::CheckIfExistUserTable(const std::s return E_OK; } -std::string SQLiteSingleVerRelationalStorageExecutor::GetCloudDeleteSql(const std::string &table) +int SQLiteSingleVerRelationalStorageExecutor::GetCloudDeleteSql(const std::string &table, std::string &sql) { - std::string logTable = DBCommon::GetLogTableName(table); - int cursor = GetCursor(table); - std::string sql; + uint64_t cursor = DBConstant::INVALID_CURSOR; + int errCode = SQLiteRelationalUtils::GetCursor(dbHandle_, table, cursor); + if (errCode != E_OK) { + LOGE("[GetCloudDeleteSql] Get cursor of table[%s length[%u]] failed: %d", + DBCommon::StringMiddleMasking(table).c_str(), table.length(), errCode); + return errCode; + } sql += " cloud_gid = '', version = '', "; if (isLogicDelete_) { // cursor already increased by DeleteCloudData, can be assigned directly here @@ -1030,14 +1040,15 @@ std::string SQLiteSingleVerRelationalStorageExecutor::GetCloudDeleteSql(const st } else { sql += "data_key = -1, flag = flag&" + std::string(CONSISTENT_FLAG) + "|" + std::to_string(static_cast(LogInfoFlag::FLAG_DELETE)) + ", sharing_resource = ''"; - int errCode = SetCursor(table, cursor + 1); + errCode = SetCursor(table, cursor + 1); if (errCode == E_OK) { sql += ", cursor = " + std::to_string(cursor + 1) + " "; } else { - LOGW("[RDBExecutor] Increase cursor failed when delete log: %d", errCode); + LOGE("[RDBExecutor] Increase cursor failed when delete log: %d", errCode); + return errCode; } } - return sql; + return E_OK; } int SQLiteSingleVerRelationalStorageExecutor::RemoveDataAndLog(const std::string &tableName, int64_t dataKey) @@ -1850,11 +1861,11 @@ int SQLiteSingleVerRelationalStorageExecutor::GetWaitCompensatedSyncDataPk(const int SQLiteSingleVerRelationalStorageExecutor::ClearUnLockingStatus(const std::string &tableName) { std::string sql; - sql += "UPDATE " + DBCommon::GetLogTableName(tableName) + " SET status = (CASE WHEN status == 1 AND flag & "+ - "0x01 != 0 THEN 0 ELSE status END);"; + sql += "UPDATE " + DBCommon::GetLogTableName(tableName) + " SET status = (CASE WHEN status == 1 "+ + "AND (cloud_gid = '' AND flag & 0x01 != 0) THEN 0 ELSE status END);"; sqlite3_stmt *stmt = nullptr; int errCode = SQLiteUtils::GetStatement(dbHandle_, sql, stmt); - if (errCode != E_OK || stmt == nullptr) { + if (errCode != E_OK) { LOGE("[RDBExecutor] Get stmt failed when clear unlocking status errCode = %d.", errCode); return errCode; } @@ -1863,7 +1874,7 @@ int SQLiteSingleVerRelationalStorageExecutor::ClearUnLockingStatus(const std::st if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { errCode = E_OK; } else { - LOGE("[Storage Execute] Step update record status stmt failed, %d.", errCode); + LOGE("[Storage Executor] Step update record status stmt failed, %d.", errCode); } SQLiteUtils::ResetStatement(stmt, true, ret); return errCode == E_OK ? ret : errCode; @@ -1922,6 +1933,5 @@ int SQLiteSingleVerRelationalStorageExecutor::BindShareValueToInsertLogStatement } return errCode; } - } // namespace DistributedDB -#endif \ No newline at end of file +#endif diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_executor_utils.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_executor_utils.cpp index 37249195748e469b758f3f60793e03cca2edaaaa..b01aa5d8a74b850d849adc8b2410c70a887e2c1e 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_executor_utils.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_executor_utils.cpp @@ -1344,7 +1344,7 @@ int SqliteCloudKvExecutorUtils::GetWaitCompensatedSyncDataUserId(sqlite3 *db, bo sqlite3_stmt *stmt = nullptr; int errCode = SQLiteUtils::GetStatement(db, SELECT_COMPENSATE_SYNC_USERID_SQL, stmt); if (errCode != E_OK) { - LOGE("[SqliteCloudKvExecutorUtils] Get compensate key stmt failed %d", errCode); + LOGE("[SqliteCloudKvExecutorUtils] Get compensate userid stmt failed %d", errCode); return errCode; } ResFinalizer finalizerData([stmt]() { @@ -1366,8 +1366,8 @@ int SqliteCloudKvExecutorUtils::GetWaitCompensatedSyncDataUserId(sqlite3 *db, bo break; } VBucket key; - errCode = GetCloudKvBlobData(CloudDbConstant::CLOUD_KV_FIELD_USERID, CLOUD_QUERY_KEY_INDEX, - stmt, key, totalSize); + errCode = GetCloudKvBlobData(CloudDbConstant::CLOUD_KV_FIELD_USERID, CLOUD_QUERY_KEY_INDEX, stmt, + key, totalSize); if (errCode != E_OK) { return errCode; } @@ -1381,12 +1381,12 @@ int SqliteCloudKvExecutorUtils::GetWaitCompensatedSyncData(sqlite3 *db, bool isM { int errCode = SqliteCloudKvExecutorUtils::GetWaitCompensatedSyncDataPk(db, isMemory, data); if (errCode != E_OK) { - LOGE("[GetWaitCompensatedSyncData] Get wait compensate sync data failed! errCode=%d", errCode); + LOGE("[GetWaitCompensatedSyncData] Get wait compensated sync data failed! errCode=%d", errCode); return errCode; } errCode = SqliteCloudKvExecutorUtils::GetWaitCompensatedSyncDataUserId(db, isMemory, users); if (errCode != E_OK) { - LOGE("[GetWaitCompensatedSyncData] Get wait compensate sync data failed! errCode=%d", errCode); + LOGE("[GetWaitCompensatedSyncData] Get wait compensated sync data failed! errCode=%d", errCode); } return errCode; } diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_store.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_store.cpp index 0dae56bd2d8839469339c601f9fea2db83309eb5..d0f9899f85aa4b624c4edbef584f4498b23dfc94 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_store.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_store.cpp @@ -419,7 +419,7 @@ void SqliteCloudKvStore::UnRegisterObserverAction(const KvStoreObserver *observe int SqliteCloudKvStore::GetCloudVersion(const std::string &device, std::map &versionMap) { - auto[errCode, handle] = storageHandle_->GetStorageExecutor(false); + auto [errCode, handle] = storageHandle_->GetStorageExecutor(false); if (errCode != E_OK) { LOGE("[SqliteCloudKvStore] get handle failed %d", errCode); return errCode; @@ -436,7 +436,7 @@ int SqliteCloudKvStore::GetCloudVersion(const std::string &device, std::mapRecycleStorageExecutor(handle); return errCode; } -} \ No newline at end of file + +int SqliteCloudKvStore::GetLocalDataCount(const std::string &tableName, int &dataCount, int &logicDeleteDataCount) +{ + auto [errCode, handle] = storageHandle_->GetStorageExecutor(true); + if (errCode != E_OK) { + LOGE("[SqliteCloudKvStore][GetLocalDataCount] Get handle failed: %d", errCode); + return errCode; + } + sqlite3 *db = nullptr; + (void)handle->GetDbHandle(db); + + std::string dataCountSql = "select count(*) from " + tableName; + errCode = SQLiteUtils::GetCountBySql(db, dataCountSql, dataCount); + if (errCode != E_OK) { + LOGE("[SqliteCloudKvStore][GetLocalDataCount] Query local data count failed: %d", errCode); + storageHandle_->RecycleStorageExecutor(handle); + return errCode; + } + + std::string logicDeleteDataCountSql = "select count(*) from " + tableName + " where flag&0x01 != 0"; + errCode = SQLiteUtils::GetCountBySql(db, logicDeleteDataCountSql, logicDeleteDataCount); + if (errCode != E_OK) { + LOGE("[SqliteCloudKvStore][GetLocalDataCount] Query local logic delete data count failed: %d", errCode); + } + storageHandle_->RecycleStorageExecutor(handle); + return errCode; +} +} diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_store.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_store.h index 9fcbe0e5ecf496cca08e320367baf566b93a2e5c..d5533b9de15b687c9093994360ae52d1b74c7682 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_store.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_store.h @@ -106,6 +106,8 @@ public: int ReviseLocalModTime(const std::string &tableName, const std::vector &revisedData) override; + + int GetLocalDataCount(const std::string &tableName, int &dataCount, int &logicDeleteDataCount) override; private: std::pair GetTransactionDbHandleAndMemoryStatus(); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_multi_ver_transaction.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_multi_ver_transaction.cpp index aa2b5fa1e200b94c65c690480100eaa9c2300b7e..243639b6e43bff05e8d56d205b4dd2308e6e3474 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_multi_ver_transaction.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_multi_ver_transaction.cpp @@ -579,7 +579,7 @@ int SQLiteMultiVerTransaction::GetPrePutValues(const Version &versionInfo, Times } // bind the clear timestamp - errCode = sqlite3_bind_int64(statement, 2, timestamp); // 2 is timestamp; bind the second argument for timestamp; + errCode = sqlite3_bind_int64(statement, 2, timestamp); // 2 is timestamp; bind the 2nd argument for timestamp; if (errCode != SQLITE_OK) { LOGE("bind the clear timestamp for delete ver data error:%d", errCode); errCode = SQLiteUtils::MapSQLiteErrno(errCode); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_database_upgrader.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_database_upgrader.cpp index f34178ee1a207969272893d8ee0aa1a17948d90e..2e9b84f5be4d9121f53d0798fa63dfb1fe308c06 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_database_upgrader.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_database_upgrader.cpp @@ -177,7 +177,7 @@ void SQLiteSingleVerDatabaseUpgrader::SetUpgradeSqls(int version, std::vector= SINGLE_VER_STORE_VERSION_V3 && isMetaUpgrade_ == true)) { + (version >= SINGLE_VER_STORE_VERSION_V3 && isMetaUpgrade_)) { sqls.emplace_back(CREATE_SINGLE_META_TABLE_SQL); sqls.emplace_back(COPY_META_TABLE_SQL); sqls.emplace_back(DROP_META_TABLE_SQL); @@ -245,8 +245,15 @@ void SQLiteSingleVerDatabaseUpgrader::SetMetaUpgrade(const SecurityOption &curre // the same version should upgrade while user open db with s3sece. bool isCurrentS3SECE = ParamCheckUtils::IsS3SECEOpt(currentOpt); bool isOpenS3SECE = ParamCheckUtils::IsS3SECEOpt(expectOpt); - if ((!OS::CheckPathExistence(secOptUpgradeFile)) && !isCurrentS3SECE && isOpenS3SECE) { + if ((!OS::CheckPathExistence(secOptUpgradeFile)) && isOpenS3SECE) { isMetaUpgrade_ = true; + bool isMetaExist = false; + int errCode = SQLiteUtils::CheckTableExists(db_, "meta_data", isMetaExist, true); + if (errCode != E_OK) { + LOGW("[SqlSingleUp] Check meta.meta_data failed %d", errCode); + } + // only create meta.meta_data if not exist + isMetaUpgrade_ = !isMetaExist; } else { isMetaUpgrade_ = false; } diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store.cpp index e0b9f1093c253dc68e05ee98cf194587cfd6cfbe..739855390687e5363eb0fd173bbae9dc3cbdc437 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store.cpp @@ -1381,7 +1381,7 @@ uint64_t SQLiteSingleVerNaturalStore::GetTimestampFromDB() localTimeOffset = result; } } else { - LOGW("GetTimestampFromDb::when sync not start get metadata from db failed,err=%d", errCode); + LOGW("[GetTimestampFromDB] when sync not start get metadata from db failed, err=%d", errCode); } uint64_t currentSysTime = TimeHelper::GetSysCurrentTime(); if (localTimeOffset < 0 && currentSysTime >= static_cast(std::abs(localTimeOffset))) { @@ -1538,7 +1538,8 @@ int SQLiteSingleVerNaturalStore::Export(const std::string &filePath, const Ciphe return errCode; } -int SQLiteSingleVerNaturalStore::Import(const std::string &filePath, const CipherPassword &passwd) +int SQLiteSingleVerNaturalStore::Import(const std::string &filePath, const CipherPassword &passwd, + bool isNeedIntegrityCheck) { if (storageEngine_ == nullptr) { return -E_INVALID_DB; @@ -1579,7 +1580,7 @@ int SQLiteSingleVerNaturalStore::Import(const std::string &filePath, const Ciphe operation = std::make_unique(this, storageEngine_); operation->SetLocalDevId(localDev); - errCode = operation->Import(filePath, passwd); + errCode = operation->Import(filePath, passwd, isNeedIntegrityCheck); if (errCode != E_OK) { goto END; } diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store.h index 637a735ff712a22ac69ca97c5691521d9fd21186..9c202175773021a79ce1fd951942c1f2d8f09f48 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store.h @@ -88,7 +88,7 @@ public: int GetSyncDataNext(std::vector &entries, ContinueToken &continueStmtToken, const DataSizeSpecInfo &dataSizeInfo) const override; - + int GetUnSyncTotal(Timestamp begin, Timestamp end, uint32_t &total) const override; int GetUnSyncTotal(QueryObject &query, const SyncTimeRange &timeRange, uint32_t &total) const override; @@ -104,7 +104,8 @@ public: int Export(const std::string &filePath, const CipherPassword &passwd) override; - int Import(const std::string &filePath, const CipherPassword &passwd) override; + int Import(const std::string &filePath, const CipherPassword &passwd, + bool isNeedIntegrityCheck = false) override; // In sync procedure, call this function int RemoveDeviceData(const std::string &deviceName, bool isNeedNotify) override; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store_connection.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store_connection.cpp index f4fea96ce796b39c49a9442d5f921ce4ac02112c..c140adf1b8f9c6b7446d504215450f97f77f2363 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store_connection.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store_connection.cpp @@ -509,7 +509,8 @@ int SQLiteSingleVerNaturalStoreConnection::Export(const std::string &filePath, c return kvDB_->Export(filePath, passwd); } -int SQLiteSingleVerNaturalStoreConnection::Import(const std::string &filePath, const CipherPassword &passwd) +int SQLiteSingleVerNaturalStoreConnection::Import(const std::string &filePath, const CipherPassword &passwd, + bool isNeedIntegrityCheck) { if (IsFileAccessControlled()) { LOGE("Forbid Import when screen locked and security label [%d]!", kvDB_->GetMyProperties().GetSecLabel()); @@ -1533,7 +1534,7 @@ int SQLiteSingleVerNaturalStoreConnection::UnpublishToLocal(const Key &key, bool } // check whether sync started to get SystemTime SQLiteSingleVerNaturalStore *naturalStore = GetDB(); - if (naturalStore == nullptr) { + if (naturalStore != nullptr) { naturalStore->WakeUpSyncer(); } diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store_connection.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store_connection.h index 1bf4b8286e9a5a46980d9eede025ca032fc9e468..51d903ed53faf21f0b0503810e6eb16491fe18e9 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store_connection.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store_connection.h @@ -83,7 +83,8 @@ public: int Export(const std::string &filePath, const CipherPassword &passwd) override; - int Import(const std::string &filePath, const CipherPassword &passwd) override; + int Import(const std::string &filePath, const CipherPassword &passwd, + bool isNeedIntegrityCheck = false) override; // Get the result set int GetResultSet(const IOption &option, const Key &keyPrefix, IKvDBResultSet *&resultSet) const override; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor.cpp index 09d4c05e4675bde4a476c5f213b355cdfa92983d..3ab3b288a8153c8a2efdcdded40547967e5fea15 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor.cpp @@ -1227,7 +1227,7 @@ int SQLiteSingleVerStorageExecutor::SaveSyncDataToDatabase(const DataItem &dataI } DataOperStatus SQLiteSingleVerStorageExecutor::JudgeSyncSaveType(DataItem &dataItem, - const DataItem &itemGet, const std::string &devName, bool isHashKeyExisted, bool isPermitForceWrite) + const DataItem &itemGet, const DeviceInfo &deviceInfo, bool isHashKeyExisted, bool isPermitForceWrite) { DataOperStatus status; status.isDeleted = ((dataItem.flag & DataItem::DELETE_FLAG) == DataItem::DELETE_FLAG || @@ -1238,12 +1238,13 @@ DataOperStatus SQLiteSingleVerStorageExecutor::JudgeSyncSaveType(DataItem &dataI } else { status.preStatus = DataStatus::EXISTED; } - std::string deviceName = DBCommon::TransferHashString(devName); + std::string deviceName = DBCommon::TransferHashString(deviceInfo.deviceName); if (itemGet.writeTimestamp >= dataItem.writeTimestamp) { // for multi user mode, no permit to forcewrite - if ((!deviceName.empty()) && IsFromDataOwner(itemGet, deviceName) && isPermitForceWrite) { - LOGI("Force overwrite the data:%" PRIu64 " vs %" PRIu64, - itemGet.writeTimestamp, dataItem.writeTimestamp); + if (((!deviceName.empty()) && IsFromDataOwner(itemGet, deviceName) && isPermitForceWrite) || + deviceInfo.isLocal) { + LOGI("Force overwrite the data:%" PRIu64 " vs %" PRIu64 " isLocal %d", + itemGet.writeTimestamp, dataItem.writeTimestamp, static_cast(deviceInfo.isLocal)); status.isDefeated = false; dataItem.writeTimestamp = itemGet.writeTimestamp + 1; dataItem.timestamp = itemGet.timestamp; @@ -1318,7 +1319,7 @@ int SQLiteSingleVerStorageExecutor::PrepareForNotifyConflictAndObserver(DataItem return ResetSaveSyncStatements(-E_IGNORE_DATA); } - notify.dataStatus = JudgeSyncSaveType(dataItem, notify.getData, deviceInfo.deviceName, isHashKeyExisted, + notify.dataStatus = JudgeSyncSaveType(dataItem, notify.getData, deviceInfo, isHashKeyExisted, isPermitForceWrite); InitCommitNotifyDataKeyStatus(notify.committedData, notify.hashKey, notify.dataStatus); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor.h index bec89c958efa6daba2d4bf57864478fa12398e70..5156b1db8d8d72eab576411731e5c1de514033b6 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor.h @@ -81,7 +81,7 @@ public: Timestamp end, const DataSizeSpecInfo &dataSizeInfo) const; int GetDeletedSyncDataByTimestamp(std::vector &dataItems, size_t appendLength, Timestamp begin, Timestamp end, const DataSizeSpecInfo &dataSizeInfo) const; - + int GetUnSyncTotalByTimestamp(Timestamp begin, Timestamp end, uint32_t &total) const; int GetDeletedSyncTotalByTimestamp(Timestamp begin, Timestamp end, uint32_t &total) const; @@ -237,7 +237,7 @@ private: const DataOperStatus &dataStatus, SingleVerNaturalStoreCommitNotifyData *commitData); DataOperStatus JudgeSyncSaveType(DataItem &dataItem, const DataItem &itemGet, - const std::string &devName, bool isHashKeyExisted, bool isPermitForceWrite = true); + const DeviceInfo &deviceInfo, bool isHashKeyExisted, bool isPermitForceWrite = true); static std::string GetOriginDevName(const DataItem &dataItem, const std::string &origDevGet); @@ -249,10 +249,10 @@ private: int PrepareForSyncDataByTime(Timestamp begin, Timestamp end, sqlite3_stmt *&statement, bool getDeletedData = false) const; - + int PrepareForUnSyncTotalByTime(Timestamp begin, Timestamp end, sqlite3_stmt *&statement, bool getDeletedData = false) const; - + int GetCountValue(sqlite3_stmt *&countStatement, uint32_t &total) const; int StepForResultEntries(bool isGetValue, sqlite3_stmt *statement, std::vector &entries) const; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor_sql.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor_sql.h index 0004f0286c806eea704d143e1fca23f9fd3ab0ca..6d5cdc2d72c98ee8fa5b2cbe28b9cbed97ba3f84 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor_sql.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor_sql.h @@ -136,11 +136,11 @@ namespace DistributedDB { constexpr const char *SELECT_SYNC_DELETED_ENTRIES_SQL = "SELECT * FROM sync_data WHERE timestamp >= ? AND timestamp < ? AND (flag&0x03=0x03) AND (flag&0x200=0) " "ORDER BY timestamp ASC;"; - + constexpr const char *COUNT_SYNC_ENTRIES_SQL = "SELECT count(key) FROM sync_data WHERE timestamp >= ? AND timestamp < ? AND (flag&0x02=0x02) " "AND (flag&0x200=0);"; - + constexpr const char *COUNT_SYNC_DELETED_ENTRIES_SQL = "SELECT count(key) FROM sync_data WHERE timestamp >= ? AND timestamp < ? AND (flag&0x03=0x03) " "AND (flag&0x200=0);"; @@ -263,18 +263,18 @@ namespace DistributedDB { constexpr const char *REMOVE_CLOUD_DEV_DATA_BY_DEVID_SQL = "DELETE FROM sync_data WHERE device=? AND (flag&0x100!=0);"; + constexpr const char *REMOVE_CLOUD_ALL_DEV_DATA_VERSION_SQL = + "DELETE FROM sync_data WHERE key LIKE 'naturalbase_cloud_version_%' AND length(device)!=0;"; + + constexpr const char *REMOVE_CLOUD_DEV_DATA_VERSION_BY_DEVID_SQL = + "DELETE FROM sync_data WHERE device=? AND key LIKE 'naturalbase_cloud_version_%';"; + constexpr const char *UPDATE_CLOUD_DEV_DATA_BY_DEVID_SQL = "UPDATE sync_data SET flag=(flag|0x02)&(~0x100) WHERE device=? AND (flag&0x100!=0);"; constexpr const char *REMOVE_CLOUD_DEV_DATA_BY_USERID_SQL = "DELETE FROM sync_data WHERE (flag&0x100!=0) AND hash_key IN" \ "(SELECT hash_key FROM naturalbase_kv_aux_sync_data_log WHERE userid =?);"; - - constexpr const char *REMOVE_CLOUD_ALL_DEV_DATA_VERSION_SQL = - "DELETE FROM sync_data WHERE key LIKE 'naturalbase_cloud_version_%' AND length(device)!=0;"; - - constexpr const char *REMOVE_CLOUD_DEV_DATA_VERSION_BY_DEVID_SQL = - "DELETE FROM sync_data WHERE device=? AND key LIKE 'naturalbase_cloud_version_%';"; constexpr const char *UPDATE_CLOUD_DEV_DATA_BY_USERID_SQL = "UPDATE sync_data SET flag=(flag|0x02)&(~0x100) WHERE (flag&0x100!=0) AND hash_key IN" \ @@ -313,7 +313,7 @@ namespace DistributedDB { "(SELECT hash_key FROM naturalbase_kv_aux_sync_data_log WHERE userid !=?);"; constexpr const char *SELECT_CLOUD_DEV_DATA_BY_USERID_SQL = - "SELECT * FROM sync_data WHERE (flag&0x100!=0) AND hash_key IN" \ + "SELECT * FROM sync_data WHERE hash_key IN" \ "(SELECT hash_key FROM naturalbase_kv_aux_sync_data_log WHERE userid =?);"; constexpr const char *REMOVE_CLOUD_ALL_HWM_DATA_SQL = diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.cpp index 1de98517de541a98777baa1f3fd099c3ee5c29e8..e7a729087f1343e7c32a6f917b469fd96df02676 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.cpp @@ -32,6 +32,7 @@ #include "value_object.h" #include "schema_utils.h" #include "schema_constant.h" +#include "sqlite_single_ver_storage_executor_sql.h" #include "time_helper.h" #include "platform_specific.h" #include "sqlite_relational_utils.h" @@ -641,6 +642,25 @@ int SQLiteUtils::CreateMetaDatabase(const std::string &metaDbPath) } return errCode; } + +int SQLiteUtils::CheckIntegrity(const std::string dbFile, CipherType type, const CipherPassword &passwd) +{ + std::vector createTableSqls; + OpenDbProperties option = {dbFile, true, false, createTableSqls, type, passwd}; + sqlite3 *db = nullptr; + int errCode = SQLiteUtils::OpenDatabase(option, db); + if (errCode != E_OK) { + LOGE("CheckIntegrity, open db error:%d", errCode); + return errCode; + } + errCode = CheckIntegrity(db, CHECK_DB_INTEGRITY_SQL); + if (db != nullptr) { + (void)sqlite3_close_v2(db); + db = nullptr; + } + return errCode; +} + int SQLiteUtils::CheckIntegrity(sqlite3 *db, const std::string &sql) { sqlite3_stmt *statement = nullptr; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.h index 99629c6fb7c893f93cc84f6e31f36cfea7bd571e..6d4a6afaeea0e79a93a5efc9ccfa9dc82a1033b0 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.h @@ -142,6 +142,8 @@ public: static int CreateMetaDatabase(const std::string &metaDbPath); + static int CheckIntegrity(const std::string dbFile, CipherType type, const CipherPassword &passwd); + static int CheckIntegrity(sqlite3 *db, const std::string &sql); #ifdef RELATIONAL_STORE static int RegisterCalcHash(sqlite3 *db); @@ -202,6 +204,8 @@ public: static int AnalysisSchemaFieldDefine(sqlite3 *db, const std::string &tableName, TableInfo &table); static int StepNext(sqlite3_stmt *stmt, bool isMemDb = false); + + static int GetCountBySql(sqlite3 *db, const std::string &sql, int &count); private: static int CreateDataBase(const OpenDbProperties &properties, sqlite3 *&dbTemp, bool setWal); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils_extend.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils_extend.cpp index e28017e15d418bf309dbd524ae3c2fe448ebc250..0b98cf2cfd44fb9d41c6c7fd21da94fa3bb844eb 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils_extend.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils_extend.cpp @@ -51,8 +51,8 @@ namespace { "type='table' AND (tbl_name=? COLLATE NOCASE));"; const constexpr char *CHECK_META_DB_TABLE_CREATED = "SELECT EXISTS(SELECT 1 FROM meta.sqlite_master WHERE " \ "type='table' AND (tbl_name=? COLLATE NOCASE));"; - } + struct ValueParseCache { ValueObject valueParsed; std::vector valueOriginal; @@ -695,4 +695,27 @@ int SQLiteUtils::StepNext(sqlite3_stmt *stmt, bool isMemDb) } return errCode; } + +int SQLiteUtils::GetCountBySql(sqlite3 *db, const std::string &sql, int &count) +{ + sqlite3_stmt *stmt = nullptr; + int errCode = SQLiteUtils::GetStatement(db, sql, stmt); + if (errCode != E_OK) { + LOGE("[SQLiteUtils][GetCountBySql] Get stmt failed when get local data count: %d", errCode); + return errCode; + } + errCode = SQLiteUtils::StepWithRetry(stmt, false); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + count = static_cast(sqlite3_column_int(stmt, 0)); + errCode = E_OK; + } else { + LOGE("[SQLiteUtils][GetCountBySql] Query local data count failed: %d", errCode); + } + int ret = E_OK; + SQLiteUtils::ResetStatement(stmt, true, ret); + if (ret != E_OK) { + LOGE("[SQLiteUtils][GetCountBySql] Reset stmt failed when get local data count: %d", ret); + } + return errCode != E_OK ? errCode : ret; +} } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/storage_proxy.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/storage_proxy.cpp index 0871dc38797883fdfcd8065a81af724d1fc8124a..a06be3273ec8f46bf6979520da19d08309c1ead2 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/storage_proxy.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/storage_proxy.cpp @@ -306,6 +306,15 @@ int StorageProxy::SetCursorIncFlag(bool flag) return store_->SetCursorIncFlag(flag); } +int StorageProxy::GetCursor(const std::string &tableName, uint64_t &cursor) +{ + std::shared_lock readLock(storeMutex_); + if (store_ == nullptr) { + return -E_INVALID_DB; + } + return store_->GetCursor(tableName, cursor); +} + int StorageProxy::PutCloudSyncData(const std::string &tableName, DownloadData &downloadData) { std::shared_lock readLock(storeMutex_); @@ -693,9 +702,30 @@ bool StorageProxy::IsTagCloudUpdateLocal(const LogInfo &localInfo, const LogInfo int StorageProxy::ReviseLocalModTime(const std::string &tableName, const std::vector &revisedData) { + std::shared_lock writeLock(storeMutex_); if (store_ == nullptr) { return -E_INVALID_DB; } return store_->ReviseLocalModTime(tableName, revisedData); } + +bool StorageProxy::IsCurrentLogicDelete() const +{ + std::shared_lock readLock(storeMutex_); + if (store_ == nullptr) { + LOGE("[StorageProxy] no store found when get logic delete flag"); + return false; + } + return store_->IsCurrentLogicDelete(); +} + +int StorageProxy::GetLocalDataCount(const std::string &tableName, int &dataCount, int &logicDeleteDataCount) +{ + std::shared_lock readLock(storeMutex_); + if (store_ == nullptr) { + LOGE("[StorageProxy] no store found when get local data"); + return false; + } + return store_->GetLocalDataCount(tableName, dataCount, logicDeleteDataCount); +} } diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_db_proxy.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_db_proxy.cpp index cffa5f6425dfecb55c607254c06828db7e128044..aaa8be0695557bd724a05f632d244a7173d0c790 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_db_proxy.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_db_proxy.cpp @@ -93,7 +93,7 @@ static void RecordSyncDataTimeStampLog(std::vector &data, uint8_t actio } int CloudDBProxy::BatchInsert(const std::string &tableName, std::vector &record, - std::vector &extend, Info &uploadInfo) + std::vector &extend, Info &uploadInfo, uint32_t &retryCount) { std::shared_lock readLock(cloudMutex_); if (iCloudDb_ == nullptr) { @@ -105,12 +105,13 @@ int CloudDBProxy::BatchInsert(const std::string &tableName, std::vector context->SetTableName(tableName); int errCode = InnerAction(context, cloudDb, INSERT); uploadInfo = context->GetInfo(); + retryCount = context->GetRetryCount(); context->MoveOutRecordAndExtend(record, extend); return errCode; } int CloudDBProxy::BatchUpdate(const std::string &tableName, std::vector &record, - std::vector &extend, Info &uploadInfo) + std::vector &extend, Info &uploadInfo, uint32_t &retryCount) { std::shared_lock readLock(cloudMutex_); if (iCloudDb_ == nullptr) { @@ -122,12 +123,13 @@ int CloudDBProxy::BatchUpdate(const std::string &tableName, std::vector context->MoveInRecordAndExtend(record, extend); int errCode = InnerAction(context, cloudDb, UPDATE); uploadInfo = context->GetInfo(); + retryCount = context->GetRetryCount(); context->MoveOutRecordAndExtend(record, extend); return errCode; } int CloudDBProxy::BatchDelete(const std::string &tableName, std::vector &record, std::vector &extend, - Info &uploadInfo) + Info &uploadInfo, uint32_t &retryCount) { std::shared_lock readLock(cloudMutex_); if (iCloudDb_ == nullptr) { @@ -139,6 +141,7 @@ int CloudDBProxy::BatchDelete(const std::string &tableName, std::vector context->SetTableName(tableName); int errCode = InnerAction(context, cloudDb, DELETE); uploadInfo = context->GetInfo(); + retryCount = context->GetRetryCount(); context->MoveOutRecordAndExtend(record, extend); return errCode; } @@ -397,9 +400,15 @@ void CloudDBProxy::InnerActionTask(const std::shared_ptr &co break; case UNLOCK: status = cloudDb->UnLock(); + if (status != OK) { + LOGE("[CloudDBProxy] UnLock cloud DB failed: %d", static_cast(status)); + } break; case HEARTBEAT: status = cloudDb->HeartBeat(); + if (status != OK) { + LOGE("[CloudDBProxy] Heart beat error: %d", static_cast(status)); + } break; default: // should not happen status = DB_ERROR; @@ -421,7 +430,9 @@ DBStatus CloudDBProxy::InnerActionLock(const std::shared_ptr std::pair lockStatus = cloudDb->Lock(); if (lockStatus.first != OK) { status = lockStatus.first; + LOGE("[CloudDBProxy] Lock cloud DB failed: %d", static_cast(status)); } else if (lockStatus.second == 0) { + LOGE("[CloudDBProxy] Lock successfully but timeout is 0"); status = CLOUD_ERROR; } lockRet.second = lockStatus.second; @@ -438,6 +449,7 @@ DBStatus CloudDBProxy::InnerActionGetEmptyCursor(const std::shared_ptr(status)); } std::pair cursorRet; cursorRet.second = cursorStatus.second; @@ -492,7 +504,8 @@ CloudDBProxy::CloudActionContext::CloudActionContext() actionRes_(OK), totalCount_(0u), successCount_(0u), - failedCount_(0u) + failedCount_(0u), + retryCount_(0u) { } @@ -597,20 +610,17 @@ bool CloudDBProxy::CloudActionContext::IsEmptyAssetId(const Assets &assets) return false; } -bool CloudDBProxy::CloudActionContext::IsRecordActionFail(const VBucket &extend, bool isInsert, DBStatus status) +bool CloudDBProxy::CloudActionContext::IsRecordActionFail(const VBucket &extend, const CloudWaterType &type, + DBStatus status) { - if (DBCommon::IsRecordAssetsMissing(extend)) { + if (DBCommon::IsRecordAssetsMissing(extend) || DBCommon::IsRecordIgnoredForReliability(extend, type) || + DBCommon::IsRecordIgnored(extend)) { return false; } - if (extend.count(CloudDbConstant::GID_FIELD) == 0) { + if (extend.count(CloudDbConstant::GID_FIELD) == 0 || DBCommon::IsRecordFailed(extend, status)) { return true; } - if (status != OK) { - if (DBCommon::IsRecordError(extend) || - (!DBCommon::IsRecordSuccess(extend) && !DBCommon::IsRecordVersionConflict(extend))) { - return true; - } - } + bool isInsert = type == CloudWaterType::INSERT; auto gid = std::get_if(&extend.at(CloudDbConstant::GID_FIELD)); if (gid == nullptr || (isInsert && (*gid).empty())) { return true; @@ -631,6 +641,7 @@ bool CloudDBProxy::CloudActionContext::IsRecordActionFail(const VBucket &extend, void CloudDBProxy::CloudActionContext::SetInfo(const CloudWaterType &type, DBStatus status, uint32_t size) { totalCount_ = size; + retryCount_ = 0; // reset retryCount in each batch // totalCount_ should be equal to extend_ or batch data failed. if (totalCount_ != extend_.size()) { @@ -638,10 +649,9 @@ void CloudDBProxy::CloudActionContext::SetInfo(const CloudWaterType &type, DBSta return; } for (auto &extend : extend_) { - if (DBCommon::IsRecordIgnoredForReliability(extend, type) || DBCommon::IsRecordIgnored(extend)) { - continue; - } - if (IsRecordActionFail(extend, type == CloudWaterType::INSERT, status)) { + if (DBCommon::IsRecordVersionConflict(extend)) { + retryCount_++; + } else if (IsRecordActionFail(extend, type, status)) { failedCount_++; } else { successCount_++; @@ -661,6 +671,12 @@ std::string CloudDBProxy::CloudActionContext::GetTableName() return tableName_; } +uint32_t CloudDBProxy::CloudActionContext::GetRetryCount() +{ + std::lock_guard autoLock(actionMutex_); + return retryCount_; +} + void CloudDBProxy::SetGenCloudVersionCallback(const GenerateCloudVersionCallback &callback) { std::lock_guard autoLock(genVersionMutex_); @@ -699,4 +715,48 @@ void CloudDBProxy::SetPrepareTraceId(const std::string &traceId) const iCloudDb->SetPrepareTraceId(traceId); } } + +int CloudDBProxy::BatchDownload(const std::string &tableName, std::vector &downloadAssets) +{ + if (IsEmptyAssetRecord(downloadAssets)) { + return E_OK; + } + std::shared_lock readLock(assetLoaderMutex_); + if (iAssetLoader_ == nullptr) { + LOGE("[CloudDBProxy] Asset loader has not been set %d", -E_NOT_SET); + return -E_NOT_SET; + } + iAssetLoader_->BatchDownload(tableName, downloadAssets); + return E_OK; +} + +int CloudDBProxy::BatchRemoveLocalAssets(const std::string &tableName, + std::vector &removeAssets) +{ + if (IsEmptyAssetRecord(removeAssets)) { + return E_OK; + } + std::shared_lock readLock(assetLoaderMutex_); + if (iAssetLoader_ == nullptr) { + LOGE("[CloudDBProxy] Asset loader has not been set %d", -E_NOT_SET); + return -E_NOT_SET; + } + iAssetLoader_->BatchRemoveLocalAssets(tableName, removeAssets); + return E_OK; +} + +bool CloudDBProxy::IsEmptyAssetRecord(const std::vector &assets) +{ + if (assets.empty()) { + return true; + } + for (const auto &record : assets) { + for (const auto &recordAssets : record.assets) { + if (!recordAssets.second.empty()) { + return false; + } + } + } + return true; +} } diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_db_proxy.h b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_db_proxy.h index c11a86962290fcfe3b4356f0d108051d10254a8b..dd5fc1efc055439281bb28505ca09f104e292bb3 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_db_proxy.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_db_proxy.h @@ -40,13 +40,13 @@ public: void SetIAssetLoader(const std::shared_ptr &loader); int BatchInsert(const std::string &tableName, std::vector &record, - std::vector &extend, Info &uploadInfo); + std::vector &extend, Info &uploadInfo, uint32_t &retryCount); int BatchUpdate(const std::string &tableName, std::vector &record, std::vector &extend, - Info &uploadInfo); + Info &uploadInfo, uint32_t &retryCount); int BatchDelete(const std::string &tableName, std::vector &record, std::vector &extend, - Info &uploadInfo); + Info &uploadInfo, uint32_t &retryCount); int Query(const std::string &tableName, VBucket &extend, std::vector &data); @@ -77,6 +77,12 @@ public: std::pair GetCloudVersion(const std::string &originVersion) const; void SetPrepareTraceId(const std::string &traceId) const; + + int BatchDownload(const std::string &tableName, std::vector &downloadAssets); + + int BatchRemoveLocalAssets(const std::string &tableName, std::vector &removeAssets); + + static int GetInnerErrorCode(DBStatus status); protected: class CloudActionContext { public: @@ -114,10 +120,12 @@ protected: void SetTableName(const std::string &tableName); std::string GetTableName(); + + uint32_t GetRetryCount(); private: static bool IsEmptyAssetId(const Assets &assets); - static bool IsRecordActionFail(const VBucket &extend, bool isInsert, DBStatus status); + static bool IsRecordActionFail(const VBucket &extend, const CloudWaterType &type, DBStatus status); std::mutex actionMutex_; std::condition_variable actionCv_; @@ -126,6 +134,7 @@ protected: uint32_t totalCount_; uint32_t successCount_; uint32_t failedCount_; + uint32_t retryCount_; std::string tableName_; std::vector record_; @@ -162,11 +171,11 @@ protected: static DBStatus InnerActionGetEmptyCursor(const std::shared_ptr &context, const std::shared_ptr &cloudDb); - static int GetInnerErrorCode(DBStatus status); - static DBStatus QueryAction(const std::shared_ptr &context, const std::shared_ptr &cloudDb); + static bool IsEmptyAssetRecord(const std::vector &assets); + mutable std::shared_mutex cloudMutex_; mutable std::shared_mutex assetLoaderMutex_; std::shared_ptr iCloudDb_; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_merge_strategy.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_merge_strategy.cpp index eb62c0938f9e9d73047534fc8cc866185165667e..1d67a71e23f9e4b24990f9259354c19c6cf2e993 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_merge_strategy.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_merge_strategy.cpp @@ -34,8 +34,7 @@ OpType CloudMergeStrategy::TagSyncDataStatus(bool existInLocal, bool isCloudWin, if (IsIgnoreUpdate(localInfo)) { return OpType::NOT_HANDLE; } - if ((localInfo.flag & static_cast(LogInfoFlag::FLAG_LOCAL)) != 0 && - localInfo.timestamp > cloudInfo.timestamp) { + if (JudgeLocallyNewer(localInfo, cloudInfo)) { return TagLocallyNewer(localInfo, cloudInfo, isCloudDelete, isLocalDelete); } if (isCloudDelete) { @@ -71,7 +70,7 @@ OpType CloudMergeStrategy::TagLocallyNewer(const LogInfo &localInfo, const LogIn { if (localInfo.cloudGid.empty()) { return isCloudDelete ? OpType::NOT_HANDLE - : ((isLocalDelete && !JudgeLocalDeleteUpload()) ? OpType::INSERT : OpType::ONLY_UPDATE_GID); + : ((isLocalDelete && !JudgeKvScene()) ? OpType::INSERT : OpType::ONLY_UPDATE_GID); } if (isCloudDelete) { return OpType::CLEAR_GID; @@ -102,4 +101,11 @@ OpType CloudMergeStrategy::TagLocalNotExist(bool isCloudDelete) } return OpType::INSERT; } + +bool CloudMergeStrategy::JudgeLocallyNewer(const LogInfo &localInfo, const LogInfo &cloudInfo) +{ + return (localInfo.timestamp > cloudInfo.timestamp) && + ((JudgeKvScene() && (localInfo.flag & static_cast(LogInfoFlag::FLAG_CLOUD_WRITE)) == 0) || + ((!JudgeKvScene()) && (localInfo.flag & static_cast(LogInfoFlag::FLAG_LOCAL)) != 0)); +} } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_merge_strategy.h b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_merge_strategy.h index 0af819a5ff9e3d1a530bf4d2f9b7b0cce5b3bfef..3b7532d9c1f289ed70f7ac522b63abcd3539c5a7 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_merge_strategy.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_merge_strategy.h @@ -36,6 +36,7 @@ private: bool isLocalDelete); OpType TagLocalNotExist(bool isCloudDelete); + bool JudgeLocallyNewer(const LogInfo &localInfo, const LogInfo &cloudInfo); }; } #endif // DIFFERENTIAL_STRATEGY_H diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_strategy.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_strategy.cpp index 907242f04ceb0d4b742d0b0b05c7cc20d2b97334..170429e228fe3326f4ad8568be875c20d8c9e27d 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_strategy.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_strategy.cpp @@ -20,9 +20,9 @@ CloudSyncStrategy::CloudSyncStrategy() : policy_(SingleVerConflictResolvePolicy: { } -void CloudSyncStrategy::SetIsLocalDeleteUpload(bool isLocalDeleteUpload) +void CloudSyncStrategy::SetIsKvScene(bool isKvScene) { - isLocalDeleteUpload_ = isLocalDeleteUpload; + isKvScene_ = isKvScene; } void CloudSyncStrategy::SetConflictResolvePolicy(SingleVerConflictResolvePolicy policy) @@ -46,9 +46,9 @@ bool CloudSyncStrategy::JudgeUpload() return false; } -bool CloudSyncStrategy::JudgeLocalDeleteUpload() +bool CloudSyncStrategy::JudgeKvScene() { - return isLocalDeleteUpload_; + return isKvScene_; } bool CloudSyncStrategy::IsDelete(const LogInfo &info) diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_strategy.h b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_strategy.h index d719c6e2b9e80e4766bd2cda6b5a378b1fa7770f..df9dae1ae64d55668a31721b422ab11854ec11f0 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_strategy.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_strategy.h @@ -27,7 +27,7 @@ public: CloudSyncStrategy(); virtual ~CloudSyncStrategy() = default; - void SetIsLocalDeleteUpload(bool isLocalDeleteUpload); + void SetIsKvScene(bool isKvScene); void SetConflictResolvePolicy(SingleVerConflictResolvePolicy policy); @@ -38,7 +38,7 @@ public: virtual bool JudgeUpload(); - bool JudgeLocalDeleteUpload(); + bool JudgeKvScene(); static bool IsDelete(const LogInfo &info); @@ -54,7 +54,10 @@ protected: SingleVerConflictResolvePolicy policy_; - bool isLocalDeleteUpload_ = false; // Whether upload to the cloud after delete local data that does not have a gid + // isKvScene_ is used to distinguish between the KV and RDB in the following scenarios: + // 1. Whether upload to the cloud after delete local data that does not have a gid. + // 2. Whether the local data need update for different flag when the local time is larger. + bool isKvScene_ = false; }; } #endif // CLOUD_SYNC_STRATEGY_H diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_tag_assets.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_tag_assets.cpp index 116391ad2b90fa0dbabada5601ef7906eb17c424..a6fe0daf316d0e7a147fb63bcd2c14b8905494bd 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_tag_assets.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_tag_assets.cpp @@ -243,6 +243,10 @@ Assets TagAsset(const std::string &assetFieldName, VBucket &coveredData, VBucket if (GetAssetsCaseInsensitive(assetFieldName, beCoveredData).index() == TYPE_INDEX) { TagAssetWithNormalStatus(setNormalStatus, AssetOpType::DELETE, std::get(GetAssetsCaseInsensitive(assetFieldName, beCoveredData)), res, errCode); + if (!setNormalStatus) { + // only not normal need fillback asset data + coveredData[assetFieldName] = std::get(GetAssetsCaseInsensitive(assetFieldName, beCoveredData)); + } } else if (GetAssetsCaseInsensitive(assetFieldName, beCoveredData).index() == TYPE_INDEX) { TagAssetsWithNormalStatus(setNormalStatus, AssetOpType::DELETE, std::get(GetAssetsCaseInsensitive(assetFieldName, beCoveredData)), res, errCode); diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_utils.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_utils.cpp index cf3fea51746d1be847c40b3f2392d0017061c70d..d7b5138734486ebab1a74b4bc1a6091f6db820d6 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_utils.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_utils.cpp @@ -405,10 +405,12 @@ int CloudSyncUtils::SaveChangedData(ICloudSyncer::SyncParam ¶m, size_t dataI // INSERT: only for single primary key situation case OpType::INSERT: param.info.downLoadInfo.insertCount++; + param.info.retryInfo.downloadBatchOpCount++; return CloudSyncUtils::SaveChangedDataByType( param.downloadData.data[dataIndex], param.changedData, dataInfo.localInfo, ChangeType::OP_INSERT); case OpType::UPDATE: param.info.downLoadInfo.updateCount++; + param.info.retryInfo.downloadBatchOpCount++; if (CloudSyncUtils::NeedSaveData(dataInfo.localInfo.logInfo, dataInfo.cloudLogInfo)) { return CloudSyncUtils::SaveChangedDataByType(param.downloadData.data[dataIndex], param.changedData, dataInfo.localInfo, ChangeType::OP_UPDATE); @@ -416,6 +418,7 @@ int CloudSyncUtils::SaveChangedData(ICloudSyncer::SyncParam ¶m, size_t dataI return E_OK; case OpType::DELETE: param.info.downLoadInfo.deleteCount++; + param.info.retryInfo.downloadBatchOpCount++; return CloudSyncUtils::SaveChangedDataByType(param.downloadData.data[dataIndex], param.changedData, dataInfo.localInfo, ChangeType::OP_DELETE); default: @@ -630,6 +633,7 @@ CloudSyncer::CloudTaskInfo CloudSyncUtils::InitCompensatedSyncTaskInfo(const Clo } else { taskInfo.users = option.users; } + taskInfo.lockAction = option.lockAction; return taskInfo; } diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer.cpp index 26818e310deee785a7cfd7b6f913ffeb94139a77..249e3f2a365d1e29142f533e83da949053ce6c1b 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer.cpp @@ -35,13 +35,13 @@ namespace DistributedDB { CloudSyncer::CloudSyncer( - std::shared_ptr storageProxy, bool isLocalDeleteUpload, SingleVerConflictResolvePolicy policy) + std::shared_ptr storageProxy, bool isKvScene, SingleVerConflictResolvePolicy policy) : lastTaskId_(INVALID_TASK_ID), storageProxy_(std::move(storageProxy)), queuedManualSyncLimit_(DBConstant::QUEUED_SYNC_LIMIT_DEFAULT), closed_(false), timerId_(0u), - isLocalDeleteUpload_(isLocalDeleteUpload), + isKvScene_(isKvScene), policy_(policy) { if (storageProxy_ != nullptr) { @@ -317,7 +317,8 @@ int CloudSyncer::DoUploadInNeed(const CloudTaskInfo &taskInfo, const bool needUp return errCode; } for (size_t i = 0u; i < taskInfo.table.size(); ++i) { - LOGD("[CloudSyncer] try upload table, index: %zu", i); + LOGD("[CloudSyncer] try upload table, index: %zu, table name: %s, length: %u", + i, DBCommon::StringMiddleMasking(taskInfo.table[i]).c_str(), taskInfo.table[i].length()); if (IsTableFinishInUpload(taskInfo.table[i])) { continue; } @@ -705,54 +706,18 @@ int CloudSyncer::DownloadAssets(InnerProcessInfo &info, const std::vectorIsBatchDownloadAssets()) { + ret = CloudDbBatchDownloadAssets(taskId, changeList, dupHashKeySet, info, changedAssets); + } else { + ret = CloudDbDownloadAssets(taskId, info, changeList, dupHashKeySet, changedAssets); + } if (ret != E_OK) { LOGE("[CloudSyncer] Can not download assets or can not handle download result %d", ret); } return ret; } -std::map CloudSyncer::GetAssetsFromVBucket(VBucket &data) -{ - std::map assets; - std::vector fields; - { - std::lock_guard autoLock(dataLock_); - fields = currentContext_.assetFields[currentContext_.tableName]; - } - for (const auto &field : fields) { - if (data.find(field.colName) != data.end()) { - if (field.type == TYPE_INDEX && data[field.colName].index() == TYPE_INDEX) { - assets[field.colName] = { std::get(data[field.colName]) }; - } else if (field.type == TYPE_INDEX && data[field.colName].index() == TYPE_INDEX) { - assets[field.colName] = std::get(data[field.colName]); - } else { - Assets emptyAssets; - assets[field.colName] = emptyAssets; - } - } - } - return assets; -} - -int CloudSyncer::TagStatus(bool isExist, SyncParam ¶m, size_t idx, DataInfo &dataInfo, VBucket &localAssetInfo) -{ - OpType strategyOpResult = OpType::NOT_HANDLE; - int errCode = TagStatusByStrategy(isExist, param, dataInfo, strategyOpResult); - if (errCode != E_OK) { - return errCode; - } - param.downloadData.opType[idx] = strategyOpResult; - if (!IsDataContainAssets()) { - return E_OK; - } - Key hashKey; - if (isExist) { - hashKey = dataInfo.localInfo.logInfo.hashKey; - } - return TagDownloadAssets(hashKey, idx, param, dataInfo, localAssetInfo); -} - int CloudSyncer::TagDownloadAssets(const Key &hashKey, size_t idx, SyncParam ¶m, const DataInfo &dataInfo, VBucket &localAssetInfo) { @@ -859,6 +824,7 @@ int CloudSyncer::SaveData(CloudSyncer::TaskId taskId, SyncParam ¶m) // Update download batch Info param.info.downLoadInfo.batchIndex += 1; param.info.downLoadInfo.total += param.downloadData.data.size(); + param.info.retryInfo.downloadBatchOpCount = 0; int ret = E_OK; DownloadList assetsDownloadList; param.assetsDownloadList = assetsDownloadList; @@ -1013,9 +979,25 @@ int CloudSyncer::SaveDataInTransaction(CloudSyncer::TaskId taskId, SyncParam &pa param.changedData.field = param.pkColNames; param.changedData.type = ChangedDataType::DATA; } + uint64_t cursor = DBConstant::INVALID_CURSOR; + std::string maskStoreId = DBCommon::StringMiddleMasking(GetStoreIdByTask(taskId)); + std::string maskTableName = DBCommon::StringMiddleMasking(param.info.tableName); + if (storageProxy_->GetCursor(param.info.tableName, cursor) == E_OK) { + LOGI("[CloudSyncer] cursor before save data is %llu, db: %s, table: %s, task id: %llu", cursor, + maskStoreId.c_str(), maskTableName.c_str(), taskId); + } (void)storageProxy_->SetCursorIncFlag(true); + if (!IsModeForcePush(taskId)) { + param.changedData.tableName = param.info.tableName; + param.changedData.field = param.pkColNames; + param.changedData.type = ChangedDataType::DATA; + } ret = SaveData(taskId, param); (void)storageProxy_->SetCursorIncFlag(false); + if (storageProxy_->GetCursor(param.info.tableName, cursor) == E_OK) { + LOGI("[CloudSyncer] cursor after save data is %llu, db: %s, table: %s, task id: %llu", cursor, + maskStoreId.c_str(), maskTableName.c_str(), taskId); + } param.insertPk.clear(); if (ret != E_OK) { LOGE("[CloudSyncer] cannot save data: %d.", ret); @@ -1219,6 +1201,9 @@ int CloudSyncer::SaveUploadData(Info &insertInfo, Info &updateInfo, Info &delete if (!uploadData.lockData.rowid.empty()) { errCode = storageProxy_->FillCloudLogAndAsset(OpType::LOCKED_NOT_HANDLE, uploadData); + if (errCode != E_OK) { + LOGE("[CloudSyncer] Failed to fill cloud log and asset after save upload data: %d", errCode); + } } return errCode; } @@ -1227,6 +1212,7 @@ int CloudSyncer::DoBatchUpload(CloudSyncData &uploadData, UploadParam &uploadPar { int errCode = storageProxy_->FillCloudLogAndAsset(OpType::SET_UPLOADING, uploadData); if (errCode != E_OK) { + LOGE("[CloudSyncer] Failed to fill cloud log and asset before save upload data: %d", errCode); return errCode; } Info insertInfo; @@ -1236,7 +1222,8 @@ int CloudSyncer::DoBatchUpload(CloudSyncData &uploadData, UploadParam &uploadPar if (errCode != E_OK) { return errCode; } - bool lastBatch = innerProcessInfo.upLoadInfo.successCount == innerProcessInfo.upLoadInfo.total; + bool lastBatch = (innerProcessInfo.upLoadInfo.successCount + innerProcessInfo.upLoadInfo.failCount) == + innerProcessInfo.upLoadInfo.total; if (lastBatch) { innerProcessInfo.tableStatus = ProcessStatus::FINISHED; } @@ -1465,6 +1452,7 @@ int CloudSyncer::CheckTaskIdValid(TaskId taskId) return -E_TASK_PAUSED; } if (cloudTaskInfos_[taskId].errCode != E_OK) { + LOGE("[CloudSyncer] task %" PRIu64 " has error: %d", taskId, cloudTaskInfos_[taskId].errCode); return cloudTaskInfos_[taskId].errCode; } return currentContext_.currentTaskId == taskId ? E_OK : -E_INVALID_ARGS; @@ -1515,12 +1503,15 @@ int CloudSyncer::PrepareSync(TaskId taskId) } else { currentContext_.notifier = std::make_shared(this); currentContext_.strategy = - StrategyFactory::BuildSyncStrategy(cloudTaskInfos_[taskId].mode, isLocalDeleteUpload_, policy_); + StrategyFactory::BuildSyncStrategy(cloudTaskInfos_[taskId].mode, isKvScene_, policy_); currentContext_.notifier->Init(cloudTaskInfos_[taskId].table, cloudTaskInfos_[taskId].devices, cloudTaskInfos_[taskId].users); currentContext_.processRecorder = std::make_shared(); } - LOGI("[CloudSyncer] exec storeId %.3s taskId %" PRIu64, cloudTaskInfos_[taskId].storeId.c_str(), taskId); + LOGI("[CloudSyncer] exec storeId %.3s taskId %" PRIu64 " priority[%d] compensated[%d] logicDelete[%d]", + cloudTaskInfos_[taskId].storeId.c_str(), taskId, static_cast(cloudTaskInfos_[taskId].priorityTask), + static_cast(cloudTaskInfos_[taskId].compensatedTask), + static_cast(storageProxy_->IsCurrentLogicDelete())); return E_OK; } @@ -1708,6 +1699,8 @@ int CloudSyncer::CleanWaterMarkInMemory(const std::set &tableNameLi void CloudSyncer::UpdateCloudWaterMark(TaskId taskId, const SyncParam ¶m) { + LOGI("[CloudSyncer] save cloud water [%s] of table [%s length[%u]]", param.cloudWaterMark.c_str(), + DBCommon::StringMiddleMasking(param.tableName).c_str(), param.tableName.length()); { std::lock_guard autoLock(dataLock_); currentContext_.cloudWaterMarks[currentContext_.currentUserIndex][param.info.tableName] = param.cloudWaterMark; @@ -1999,10 +1992,7 @@ int CloudSyncer::DownloadOneAssetRecord(const std::set &dupHashKeySet, cons changedAssets.primaryData[ChangeType::OP_UPDATE].push_back(downloadItem.primaryKeyValList); } } - // If the assets are DELETE, needn't fill back cloud assets. - if (downloadItem.strategy == OpType::DELETE) { - return E_OK; - } + return errorCode; } @@ -2069,6 +2059,7 @@ int CloudSyncer::DownloadDataFromCloud(TaskId taskId, SyncParam ¶m, bool &ab param.info.tableStatus = ProcessStatus::PROCESSING; param.downloadData = {}; int ret = QueryCloudData(taskId, param.info.tableName, param.cloudWaterMark, param.downloadData); + CheckQueryCloudData(cloudTaskInfos_[taskId].prepareTraceId, param.downloadData, param.pkColNames); if (ret == -E_QUERY_END) { // Won't break here since downloadData may not be null param.isLastBatch = true; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer.h b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer.h index ff7a6fc3818f4f83048e97c4295e6711565946d9..bc2cfd5648c09b010a753f2600bee8fb8511faf3 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer.h @@ -40,7 +40,7 @@ namespace DistributedDB { using DownloadCommitList = std::vector, bool>>; class CloudSyncer : public ICloudSyncer { public: - explicit CloudSyncer(std::shared_ptr storageProxy, bool isLocalDeleteUpload = false, + explicit CloudSyncer(std::shared_ptr storageProxy, bool isKvScene = false, SingleVerConflictResolvePolicy policy = SingleVerConflictResolvePolicy::DEFAULT_LAST_WIN); void InitCloudSyncStateMachine(); ~CloudSyncer() override = default; @@ -135,6 +135,12 @@ protected: Timestamp lastLocalWatermark = 0u; int downloadStatus = E_OK; }; + struct DownloadItems { + DownloadItem downloadItem; + std::map assetsToRemove; + std::map assetsToDownload; + std::map> flags; + }; int TriggerSync(); @@ -246,8 +252,6 @@ protected: int NotifyChangedData(ChangedData &&changedData); - std::map GetAssetsFromVBucket(VBucket &data); - std::map TagAssetsInSingleRecord(VBucket &coveredData, VBucket &beCoveredData, bool setNormalStatus, int &errCode); @@ -295,9 +299,6 @@ protected: int CommitDownloadResult(const DownloadItem &downloadItem, InnerProcessInfo &info, DownloadCommitList &commitList, int errCode); - void SeparateNormalAndFailAssets(const std::map &assetsMap, VBucket &normalAssets, - VBucket &failedAssets); - int GetLocalInfo(size_t index, SyncParam ¶m, DataInfoWithLog &logInfo, std::map &localLogInfoCache, VBucket &localAssetInfo); @@ -342,7 +343,7 @@ protected: void ReloadUploadInfoIfNeed(TaskId taskId, const UploadParam ¶m, InnerProcessInfo &info); - void GetLastUploadInfo(const std::string &tableName, Info &lastUploadInfo); + void GetLastUploadInfo(const std::string &tableName, Info &lastUploadInfo, UploadRetryInfo &retryInfo); QuerySyncObject GetQuerySyncObject(const std::string &tableName); @@ -379,6 +380,9 @@ protected: int CommitDownloadAssets(const DownloadItem &downloadItem, const std::string &tableName, DownloadCommitList &commitList, uint32_t &successCount); + void SeparateNormalAndFailAssets(const std::map &assetsMap, VBucket &normalAssets, + VBucket &failedAssets); + void ChkIgnoredProcess(InnerProcessInfo &info, const CloudSyncData &uploadData, UploadParam &uploadParam); int SaveCursorIfNeed(const std::string &tableName); @@ -436,6 +440,37 @@ protected: int GenerateTaskIdIfNeed(CloudTaskInfo &taskInfo); + void ProcessVersionConflictInfo(InnerProcessInfo &innerProcessInfo, uint32_t retryCount); + + std::string GetStoreIdByTask(TaskId taskId); + + void CheckDataAfterDownload(const std::string &tableName); + + void CheckQueryCloudData(std::string &traceId, DownloadData &downloadData, std::vector &pkColNames); + + int CloudDbBatchDownloadAssets(TaskId taskId, const DownloadList &downloadList, const std::set &dupHashKeySet, + InnerProcessInfo &info, ChangedData &changedAssets); + + void FillDownloadItem(const std::set &dupHashKeySet, const DownloadList &downloadList, + const InnerProcessInfo &info, bool isSharedTable, DownloadItems &record); + + using DownloadItemRecords = std::vector; + using RemoveAssetsRecords = std::vector; + using DownloadAssetsRecords = std::vector; + using DownloadAssetDetail = std::tuple; + DownloadAssetDetail GetDownloadRecords(const DownloadList &downloadList, const std::set &dupHashKeySet, + bool isSharedTable, InnerProcessInfo &info); + + int BatchDownloadAndCommitRes(const DownloadList &downloadList, const std::set &dupHashKeySet, + InnerProcessInfo &info, ChangedData &changedAssets, + std::tuple &downloadDetail); + + static void StatisticDownloadRes(const IAssetLoader::AssetRecord &downloadRecord, + const IAssetLoader::AssetRecord &removeRecord, InnerProcessInfo &info, DownloadItem &downloadItem); + + static void AddNotifyDataFromDownloadAssets(const std::set &dupHashKeySet, DownloadItem &downloadItem, + ChangedData &changedAssets); + mutable std::mutex dataLock_; TaskId lastTaskId_; std::list taskQueue_; @@ -461,7 +496,11 @@ protected: std::map failedHeartbeatCount_; std::string id_; - bool isLocalDeleteUpload_; // Whether upload to the cloud after delete local data that does not have a gid. + + // isKvScene_ is used to distinguish between the KV and RDB in the following scenarios: + // 1. Whether upload to the cloud after delete local data that does not have a gid. + // 2. Whether the local data need update for different flag when the local time is larger. + bool isKvScene_; std::atomic policy_; static constexpr const TaskId INVALID_TASK_ID = 0u; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer_extend.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer_extend.cpp index 89235b5385f235388aa19d3c47718a35c98f18b3..e0361b6d32a5f49adf292fe2a7b5948fc246f288 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer_extend.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer_extend.cpp @@ -51,21 +51,23 @@ void CloudSyncer::ReloadUploadInfoIfNeed(TaskId taskId, const UploadParam ¶m { info.upLoadInfo.total = static_cast(param.count); Info lastUploadInfo; - GetLastUploadInfo(info.tableName, lastUploadInfo); + UploadRetryInfo retryInfo; + GetLastUploadInfo(info.tableName, lastUploadInfo, retryInfo); info.upLoadInfo.total += lastUploadInfo.successCount; info.upLoadInfo.successCount += lastUploadInfo.successCount; info.upLoadInfo.failCount += lastUploadInfo.failCount; info.upLoadInfo.insertCount += lastUploadInfo.insertCount; info.upLoadInfo.updateCount += lastUploadInfo.updateCount; info.upLoadInfo.deleteCount += lastUploadInfo.deleteCount; + info.retryInfo.uploadBatchRetryCount = retryInfo.uploadBatchRetryCount; LOGD("[CloudSyncer] resume upload, last success count %" PRIu32 ", last fail count %" PRIu32, lastUploadInfo.successCount, lastUploadInfo.failCount); } -void CloudSyncer::GetLastUploadInfo(const std::string &tableName, Info &lastUploadInfo) +void CloudSyncer::GetLastUploadInfo(const std::string &tableName, Info &lastUploadInfo, UploadRetryInfo &retryInfo) { std::lock_guard autoLock(dataLock_); - return currentContext_.notifier->GetLastUploadInfo(tableName, lastUploadInfo); + return currentContext_.notifier->GetLastUploadInfo(tableName, lastUploadInfo, retryInfo); } int CloudSyncer::FillDownloadExtend(TaskId taskId, const std::string &tableName, const std::string &cloudWaterMark, @@ -131,6 +133,7 @@ void CloudSyncer::UpdateProcessWhenUploadFailed(InnerProcessInfo &info) info.tableStatus = ProcessStatus::FINISHED; std::lock_guard autoLock(dataLock_); currentContext_.notifier->UpdateProcess(info); + currentContext_.notifier->UpdateUploadRetryInfo(info); } void CloudSyncer::NotifyUploadFailed(int errCode, InnerProcessInfo &info) @@ -146,11 +149,15 @@ void CloudSyncer::NotifyUploadFailed(int errCode, InnerProcessInfo &info) int CloudSyncer::BatchInsert(Info &insertInfo, CloudSyncData &uploadData, InnerProcessInfo &innerProcessInfo) { + uint32_t retryCount = 0; int errCode = cloudDB_.BatchInsert(uploadData.tableName, uploadData.insData.record, - uploadData.insData.extend, insertInfo); + uploadData.insData.extend, insertInfo, retryCount); innerProcessInfo.upLoadInfo.successCount += insertInfo.successCount; + innerProcessInfo.upLoadInfo.failCount += insertInfo.failCount; innerProcessInfo.upLoadInfo.insertCount += insertInfo.successCount; - innerProcessInfo.upLoadInfo.total -= insertInfo.total - insertInfo.successCount - insertInfo.failCount; + if (errCode == -E_CLOUD_VERSION_CONFLICT) { + ProcessVersionConflictInfo(innerProcessInfo, retryCount); + } if (errCode != E_OK) { LOGE("[CloudSyncer][BatchInsert] BatchInsert with error, ret is %d.", errCode); } @@ -165,7 +172,7 @@ int CloudSyncer::BatchInsert(Info &insertInfo, CloudSyncData &uploadData, InnerP } if (!isSharedTable) { ret = CloudSyncUtils::FillAssetIdToAssets(uploadData.insData, errCode, CloudWaterType::INSERT); - if (ret != errCode) { + if (ret != E_OK) { LOGW("[CloudSyncer][BatchInsert] FillAssetIdToAssets with error, ret is %d.", ret); } } @@ -191,11 +198,15 @@ int CloudSyncer::BatchInsert(Info &insertInfo, CloudSyncData &uploadData, InnerP int CloudSyncer::BatchUpdate(Info &updateInfo, CloudSyncData &uploadData, InnerProcessInfo &innerProcessInfo) { + uint32_t retryCount = 0; int errCode = cloudDB_.BatchUpdate(uploadData.tableName, uploadData.updData.record, - uploadData.updData.extend, updateInfo); + uploadData.updData.extend, updateInfo, retryCount); innerProcessInfo.upLoadInfo.successCount += updateInfo.successCount; + innerProcessInfo.upLoadInfo.failCount += updateInfo.failCount; innerProcessInfo.upLoadInfo.updateCount += updateInfo.successCount; - innerProcessInfo.upLoadInfo.total -= updateInfo.total - updateInfo.successCount - updateInfo.failCount; + if (errCode == -E_CLOUD_VERSION_CONFLICT) { + ProcessVersionConflictInfo(innerProcessInfo, retryCount); + } if (errCode != E_OK) { LOGE("[CloudSyncer][BatchUpdate] BatchUpdate with error, ret is %d.", errCode); } @@ -341,6 +352,7 @@ int CloudSyncer::IsNeedSkipDownload(bool isSharedTable, int &errCode, const Inne return true; } if (tmpCode != E_OK) { + LOGE("[CloudSyncer] Get assets from DB failed: %d, return errCode: %d", tmpCode, errCode); errCode = (errCode != E_OK) ? errCode : tmpCode; return true; } @@ -362,35 +374,65 @@ bool CloudSyncer::CheckDownloadOrDeleteCode(int &errCode, int downloadCode, int return true; } -int CloudSyncer::DownloadAssetsOneByOneInner(bool isSharedTable, const InnerProcessInfo &info, - DownloadItem &downloadItem, std::map &downloadAssets) +void GetAssetsToDownload(std::map &downloadAssets, VBucket &dbAssets, bool isSharedTable, + std::map &assetsToDownload, std::map> &tmpFlags) { - int errCode = E_OK; - std::map tmpAssetsToDownload; - std::map tmpAssetsToDelete; - std::map> tmpFlags; + if (isSharedTable) { + LOGD("[CloudSyncer] skip download for shared table"); + return; + } for (auto &[col, assets] : downloadAssets) { for (auto &asset : assets) { - VBucket dbAssets; - if (IsNeedSkipDownload(isSharedTable, errCode, info, downloadItem, dbAssets)) { - break; - } - if (!isSharedTable && asset.flag == static_cast(AssetOpType::DELETE)) { - asset.status = static_cast(AssetStatus::DELETE); - tmpAssetsToDelete[col].push_back(asset); - } else if (!isSharedTable && AssetOperationUtils::CalAssetOperation(col, asset, dbAssets, + if (asset.flag != static_cast(AssetOpType::DELETE) && + AssetOperationUtils::CalAssetOperation(col, asset, dbAssets, AssetOperationUtils::CloudSyncAction::START_DOWNLOAD) == AssetOperationUtils::AssetOpType::HANDLE) { asset.status = asset.flag == static_cast(AssetOpType::INSERT) ? static_cast(AssetStatus::INSERT) : static_cast(AssetStatus::UPDATE); - tmpAssetsToDownload[col].push_back(asset); + assetsToDownload[col].push_back(asset); tmpFlags[col].push_back(asset.flag); } else { LOGD("[CloudSyncer] skip download asset..."); } } } +} + +void GetAssetsToRemove(std::map &downloadAssets, VBucket &dbAssets, bool isSharedTable, + std::map &assetsToRemove) +{ + if (isSharedTable) { + LOGD("[CloudSyncer] skip remove for shared table"); + return; + } + for (auto &[col, assets] : downloadAssets) { + for (auto &asset : assets) { + if (asset.flag == static_cast(AssetOpType::DELETE) && + AssetOperationUtils::CalAssetOperation(col, asset, dbAssets, + AssetOperationUtils::CloudSyncAction::START_DOWNLOAD) == AssetOperationUtils::AssetOpType::HANDLE) { + asset.status = static_cast(AssetStatus::DELETE); + assetsToRemove[col].push_back(asset); + } + } + } +} + +int CloudSyncer::DownloadAssetsOneByOneInner(bool isSharedTable, const InnerProcessInfo &info, + DownloadItem &downloadItem, std::map &downloadAssets) +{ + int errCode = E_OK; + VBucket dbAssets; + std::map tmpAssetsToRemove; + if (!IsNeedSkipDownload(isSharedTable, errCode, info, downloadItem, dbAssets)) { + GetAssetsToRemove(downloadAssets, dbAssets, isSharedTable, tmpAssetsToRemove); + } auto deleteCode = cloudDB_.RemoveLocalAssets(info.tableName, downloadItem.gid, downloadItem.prefix, - tmpAssetsToDelete); + tmpAssetsToRemove); + + std::map tmpAssetsToDownload; + std::map> tmpFlags; + if (!IsNeedSkipDownload(isSharedTable, errCode, info, downloadItem, dbAssets)) { + GetAssetsToDownload(downloadAssets, dbAssets, isSharedTable, tmpAssetsToDownload, tmpFlags); + } auto downloadCode = cloudDB_.Download(info.tableName, downloadItem.gid, downloadItem.prefix, tmpAssetsToDownload); if (!CheckDownloadOrDeleteCode(errCode, downloadCode, deleteCode, downloadItem)) { return errCode; @@ -398,7 +440,7 @@ int CloudSyncer::DownloadAssetsOneByOneInner(bool isSharedTable, const InnerProc // copy asset back downloadAssets = BackFillAssetsAfterDownload(downloadCode, deleteCode, tmpFlags, tmpAssetsToDownload, - tmpAssetsToDelete); + tmpAssetsToRemove); return errCode; } @@ -416,9 +458,10 @@ void CloudSyncer::SeparateNormalAndFailAssets(const std::map 0) { failedAssets[key] = std::move(tempFailedAssets); @@ -597,11 +640,15 @@ int CloudSyncer::UpdateFlagForSavedRecord(const SyncParam ¶m) int CloudSyncer::BatchDelete(Info &deleteInfo, CloudSyncData &uploadData, InnerProcessInfo &innerProcessInfo) { + uint32_t retryCount = 0; int errCode = cloudDB_.BatchDelete(uploadData.tableName, uploadData.delData.record, - uploadData.delData.extend, deleteInfo); + uploadData.delData.extend, deleteInfo, retryCount); innerProcessInfo.upLoadInfo.successCount += deleteInfo.successCount; innerProcessInfo.upLoadInfo.deleteCount += deleteInfo.successCount; - innerProcessInfo.upLoadInfo.total -= deleteInfo.total - deleteInfo.successCount - deleteInfo.failCount; + innerProcessInfo.upLoadInfo.failCount += deleteInfo.failCount; + if (errCode == -E_CLOUD_VERSION_CONFLICT) { + ProcessVersionConflictInfo(innerProcessInfo, retryCount); + } if (errCode != E_OK) { LOGE("[CloudSyncer] Failed to batch delete, %d", errCode); storageProxy_->FillCloudGidIfSuccess(OpType::DELETE, uploadData); @@ -714,7 +761,8 @@ int CloudSyncer::DoDownloadInNeed(const CloudTaskInfo &taskInfo, const bool need taskInfo.table[i])) { continue; } - LOGD("[CloudSyncer] try download table, index: %zu", i); + LOGD("[CloudSyncer] try download table, index: %zu, table name: %s, length: %u", + i, DBCommon::StringMiddleMasking(taskInfo.table[i]).c_str(), taskInfo.table[i].length()); currentContext_.tableName = taskInfo.table[i]; table = currentContext_.tableName; } @@ -722,6 +770,7 @@ int CloudSyncer::DoDownloadInNeed(const CloudTaskInfo &taskInfo, const bool need if (errCode != E_OK) { return errCode; } + CheckDataAfterDownload(table); MarkDownloadFinishIfNeed(table); // needUpload indicate that the syncMode need push if (needUpload) { @@ -963,6 +1012,9 @@ int CloudSyncer::HandleBatchUpload(UploadParam &uploadParam, InnerProcessInfo &i break; } SetUploadDataFlag(uploadParam.taskId, uploadData); + LOGI("[CloudSyncer] Write local water after upload one batch, table[%s length[%u]], water[%llu]", + DBCommon::StringMiddleMasking(uploadData.tableName).c_str(), uploadData.tableName.length(), + uploadParam.localMark); RecordWaterMark(uploadParam.taskId, uploadParam.localMark); ret = storageProxy_->GetCloudDataNext(continueStmtToken, uploadData); if ((ret != E_OK) && (ret != -E_UNFINISHED)) { @@ -1132,6 +1184,8 @@ int CloudSyncer::DoUploadByMode(const std::string &tableName, UploadParam &uploa CloudSyncData uploadData(tableName, uploadParam.mode); SetUploadDataFlag(uploadParam.taskId, uploadData); auto [err, localWater] = GetLocalWater(tableName, uploadParam); + LOGI("[CloudSyncer] Get local water before upload result: %d, table[%s length[%u]], water[%llu]", err, + DBCommon::StringMiddleMasking(tableName).c_str(), tableName.length(), localWater); if (err != E_OK) { return err; } @@ -1250,4 +1304,221 @@ int CloudSyncer::GenerateTaskIdIfNeed(CloudTaskInfo &taskInfo) taskInfo.taskId = lastTaskId_; return E_OK; } + +void CloudSyncer::ProcessVersionConflictInfo(InnerProcessInfo &innerProcessInfo, uint32_t retryCount) +{ + innerProcessInfo.retryInfo.uploadBatchRetryCount = retryCount; + CloudSyncConfig config = storageProxy_->GetCloudSyncConfig(); + { + std::lock_guard autoLock(dataLock_); + if (config.maxRetryConflictTimes >= 0 && + currentContext_.repeatCount + 1 > config.maxRetryConflictTimes) { + innerProcessInfo.upLoadInfo.failCount = + innerProcessInfo.upLoadInfo.total - innerProcessInfo.upLoadInfo.successCount; + } + } +} + +std::string CloudSyncer::GetStoreIdByTask(TaskId taskId) +{ + std::lock_guard autoLock(dataLock_); + return cloudTaskInfos_[taskId].storeId; +} + +void CloudSyncer::CheckDataAfterDownload(const std::string &tableName) +{ + int dataCount = 0; + int logicDeleteDataCount = 0; + int errCode = storageProxy_->GetLocalDataCount(tableName, dataCount, logicDeleteDataCount); + if (errCode == E_OK) { + LOGI("[CloudSyncer] Check local data after download[%s[%u]], data count: %d, logic delete data count: %d", + DBCommon::StringMiddleMasking(tableName).c_str(), tableName.length(), dataCount, logicDeleteDataCount); + } else { + LOGW("[CloudSyncer] Get local data after download fail: %d", errCode); + } +} + +void CloudSyncer::CheckQueryCloudData(std::string &traceId, DownloadData &downloadData, + std::vector &pkColNames) +{ + for (auto &data : downloadData.data) { + bool isVersionExist = data.count(CloudDbConstant::VERSION_FIELD) != 0; + bool isContainAllPk = true; + for (auto &pkColName : pkColNames) { + if (data.count(pkColName) == 0) { + isContainAllPk = false; + break; + } + } + std::string gid; + (void)CloudStorageUtils::GetValueFromVBucket(CloudDbConstant::GID_FIELD, data, gid); + if (!isVersionExist || !isContainAllPk) { + LOGE("[CloudSyncer] Invalid data from cloud, no version[%d], lost primary key[%d], gid[%s], traceId[%s]", + static_cast(!isVersionExist), static_cast(!isContainAllPk), gid.c_str(), traceId.c_str()); + } + } +} + +int CloudSyncer::TagStatus(bool isExist, SyncParam ¶m, size_t idx, DataInfo &dataInfo, VBucket &localAssetInfo) +{ + OpType strategyOpResult = OpType::NOT_HANDLE; + int errCode = TagStatusByStrategy(isExist, param, dataInfo, strategyOpResult); + if (errCode != E_OK) { + return errCode; + } + param.downloadData.opType[idx] = strategyOpResult; + if (!IsDataContainAssets()) { + return E_OK; + } + Key hashKey; + if (isExist) { + hashKey = dataInfo.localInfo.logInfo.hashKey; + } + return TagDownloadAssets(hashKey, idx, param, dataInfo, localAssetInfo); +} + +int CloudSyncer::CloudDbBatchDownloadAssets(TaskId taskId, const DownloadList &downloadList, + const std::set &dupHashKeySet, InnerProcessInfo &info, ChangedData &changedAssets) +{ + int errorCode = CheckTaskIdValid(taskId); + if (errorCode != E_OK) { + return errorCode; + } + bool isSharedTable = false; + errorCode = storageProxy_->IsSharedTable(info.tableName, isSharedTable); + if (errorCode != E_OK) { + LOGE("[CloudSyncer] check is shared table failed %d", errorCode); + return errorCode; + } + // prepare download data + auto [downloadRecord, removeAssets, downloadAssets] = + GetDownloadRecords(downloadList, dupHashKeySet, isSharedTable, info); + std::tuple detail = { + std::move(downloadRecord), std::move(removeAssets), std::move(downloadAssets), isSharedTable + }; + return BatchDownloadAndCommitRes(downloadList, dupHashKeySet, info, changedAssets, detail); +} + +void CloudSyncer::FillDownloadItem(const std::set &dupHashKeySet, const DownloadList &downloadList, + const InnerProcessInfo &info, bool isSharedTable, DownloadItems &record) +{ + CloudStorageUtils::EraseNoChangeAsset(record.downloadItem.assets); + if (record.downloadItem.assets.empty()) { // Download data (include deleting) + return; + } + if (isSharedTable) { + // share table will not download asset, need to reset the status + for (auto &entry: record.downloadItem.assets) { + for (auto &asset: entry.second) { + asset.status = AssetStatus::NORMAL; + } + } + return; + } + int errCode = E_OK; + VBucket dbAssets; + if (!IsNeedSkipDownload(isSharedTable, errCode, info, record.downloadItem, dbAssets)) { + GetAssetsToRemove(record.downloadItem.assets, dbAssets, isSharedTable, record.assetsToRemove); + GetAssetsToDownload(record.downloadItem.assets, dbAssets, isSharedTable, record.assetsToDownload, record.flags); + } +} + +CloudSyncer::DownloadAssetDetail CloudSyncer::GetDownloadRecords(const DownloadList &downloadList, + const std::set &dupHashKeySet, bool isSharedTable, InnerProcessInfo &info) +{ + DownloadItemRecords downloadRecord; + RemoveAssetsRecords removeAssets; + DownloadAssetsRecords downloadAssets; + for (size_t i = 0; i < downloadList.size(); i++) { + DownloadItems record; + GetDownloadItem(downloadList, i, record.downloadItem); + FillDownloadItem(dupHashKeySet, downloadList, info, isSharedTable, record); + + IAssetLoader::AssetRecord removeAsset = { + record.downloadItem.gid, record.downloadItem.prefix, std::move(record.assetsToRemove) + }; + removeAssets.push_back(std::move(removeAsset)); + IAssetLoader::AssetRecord downloadAsset = { + record.downloadItem.gid, record.downloadItem.prefix, std::move(record.assetsToDownload) + }; + downloadAssets.push_back(std::move(downloadAsset)); + downloadRecord.push_back(std::move(record)); + } + return {downloadRecord, removeAssets, downloadAssets}; +} + +int CloudSyncer::BatchDownloadAndCommitRes(const DownloadList &downloadList, const std::set &dupHashKeySet, + InnerProcessInfo &info, ChangedData &changedAssets, + std::tuple &downloadDetail) +{ + auto &[downloadRecord, removeAssets, downloadAssets, isSharedTable] = downloadDetail; + // download and remove in batch + auto deleteRes = cloudDB_.BatchRemoveLocalAssets(info.tableName, removeAssets); + auto downloadRes = cloudDB_.BatchDownload(info.tableName, downloadAssets); + if (deleteRes == -E_NOT_SET || downloadRes == -E_NOT_SET) { + return -E_NOT_SET; + } + int errorCode = E_OK; + int index = 0; + for (auto &item : downloadRecord) { + auto deleteCode = CloudDBProxy::GetInnerErrorCode(removeAssets[index].status); + auto downloadCode = CloudDBProxy::GetInnerErrorCode(downloadAssets[index].status); + if (!isSharedTable) { + item.downloadItem.assets = BackFillAssetsAfterDownload(downloadCode, deleteCode, item.flags, + downloadAssets[index].assets, removeAssets[index].assets); + } + StatisticDownloadRes(downloadAssets[index], removeAssets[index], info, item.downloadItem); + AddNotifyDataFromDownloadAssets(dupHashKeySet, item.downloadItem, changedAssets); + if (item.downloadItem.strategy == OpType::DELETE) { + item.downloadItem.assets = {}; + item.downloadItem.gid = ""; + } + // commit download res + DownloadCommitList commitList; + // Process result of each asset + commitList.push_back(std::make_tuple(item.downloadItem.gid, std::move(item.downloadItem.assets), + deleteCode == E_OK && downloadCode == E_OK)); + errorCode = (errorCode != E_OK) ? errorCode : deleteCode; + errorCode = (errorCode != E_OK) ? errorCode : downloadCode; + int ret = CommitDownloadResult(item.downloadItem, info, commitList, errorCode); + if (ret != E_OK && ret != -E_REMOVE_ASSETS_FAILED) { + errorCode = errorCode == E_OK ? ret : errorCode; + } + index++; + } + return errorCode; +} + +void CloudSyncer::StatisticDownloadRes(const IAssetLoader::AssetRecord &downloadRecord, + const IAssetLoader::AssetRecord &removeRecord, InnerProcessInfo &info, DownloadItem &downloadItem) +{ + if ((downloadRecord.status == OK) && (removeRecord.status == OK)) { + return; + } + if ((downloadRecord.status == CLOUD_RECORD_EXIST_CONFLICT) || + (removeRecord.status == CLOUD_RECORD_EXIST_CONFLICT)) { + downloadItem.recordConflict = true; + return; + } + info.downLoadInfo.failCount += 1; + if (info.downLoadInfo.successCount == 0) { + LOGW("[CloudSyncer] Invalid successCount"); + } else { + info.downLoadInfo.successCount -= 1; + } +} + +void CloudSyncer::AddNotifyDataFromDownloadAssets(const std::set &dupHashKeySet, DownloadItem &downloadItem, + ChangedData &changedAssets) +{ + if (downloadItem.assets.empty()) { + return; + } + if (dupHashKeySet.find(downloadItem.hashKey) == dupHashKeySet.end()) { + changedAssets.primaryData[CloudSyncUtils::OpTypeToChangeType(downloadItem.strategy)].push_back( + downloadItem.primaryKeyValList); + } else if (downloadItem.strategy == OpType::INSERT) { + changedAssets.primaryData[ChangeType::OP_UPDATE].push_back(downloadItem.primaryKeyValList); + } } +} \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/icloud_syncer.h b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/icloud_syncer.h index afa96547c4a88f0f5232baf7f4c3286444f8844e..56ec607e73230c00b2a66d6aa41c065b7ff180f6 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/icloud_syncer.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/icloud_syncer.h @@ -47,11 +47,17 @@ public: std::string prepareTraceId; }; + struct UploadRetryInfo { + uint32_t uploadBatchRetryCount = 0; + uint32_t downloadBatchOpCount = 0; + }; + struct InnerProcessInfo { std::string tableName; ProcessStatus tableStatus = ProcessStatus::PREPARED; Info downLoadInfo; Info upLoadInfo; + UploadRetryInfo retryInfo; }; struct WithoutRowIdData { diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/process_notifier.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/process_notifier.cpp index f852a2a783557a283b193de8dbbc546e16ac9f6c..de7212624ffc0bdd617be2f27ba298579c3b3ff5 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/process_notifier.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/process_notifier.cpp @@ -53,6 +53,15 @@ void ProcessNotifier::InitSyncProcess(const std::vector &tableName, } } +void ProcessNotifier::UpdateUploadRetryInfo(const ICloudSyncer::InnerProcessInfo &process) +{ + if (process.tableName.empty()) { + return; + } + std::lock_guard autoLock(processMutex_); + processRetryInfo_[process.tableName] = process.retryInfo.uploadBatchRetryCount; +} + void ProcessNotifier::UpdateProcess(const ICloudSyncer::InnerProcessInfo &process) { if (process.tableName.empty()) { @@ -86,6 +95,7 @@ void ProcessNotifier::NotifyProcess(const ICloudSyncer::CloudTaskInfo &taskInfo, syncProcess_.process = taskInfo.status; multiSyncProcess_[user_].errCode = TransferDBErrno(taskInfo.errCode, true); multiSyncProcess_[user_].process = taskInfo.status; + UpdateUploadInfoIfNeeded(process); if (user_.empty()) { for (const auto &device : devices_) { // make sure only one device @@ -154,11 +164,15 @@ void ProcessNotifier::ResetUploadBatchIndex(const std::string &tableName) } } -void ProcessNotifier::GetLastUploadInfo(const std::string &tableName, Info &lastUploadInfo) const +void ProcessNotifier::GetLastUploadInfo(const std::string &tableName, Info &lastUploadInfo, + ICloudSyncer::UploadRetryInfo &retryInfo) const { Info lastInfo; std::lock_guard autoLock(processMutex_); auto &syncProcess = IsMultiUser() ? multiSyncProcess_.at(user_) : syncProcess_; + if (processRetryInfo_.find(tableName) != processRetryInfo_.end()) { + retryInfo.uploadBatchRetryCount = processRetryInfo_.at(tableName); + } if (syncProcess.tableProcess.find(tableName) != syncProcess_.tableProcess.end()) { lastInfo = syncProcess.tableProcess.at(tableName).upLoadInfo; } @@ -177,7 +191,7 @@ void ProcessNotifier::GetDownloadInfoByTableName(ICloudSyncer::InnerProcessInfo } else { syncProcess = multiSyncProcess_[user_]; } - + if (syncProcess.tableProcess.find(process.tableName) != syncProcess.tableProcess.end()) { process.downLoadInfo = syncProcess.tableProcess[process.tableName].downLoadInfo; } @@ -211,4 +225,16 @@ std::map ProcessNotifier::GetCurrentTableProcess( std::lock_guard autoLock(processMutex_); return syncProcess_.tableProcess; } + +void ProcessNotifier::UpdateUploadInfoIfNeeded(const ICloudSyncer::InnerProcessInfo &process) +{ + auto &syncProcess = IsMultiUser() ? multiSyncProcess_.at(user_) : syncProcess_; + auto tableProcess = syncProcess.tableProcess.find(process.tableName); + auto retryInfo = processRetryInfo_.find(process.tableName); + if (tableProcess != syncProcess.tableProcess.end() && retryInfo != processRetryInfo_.end()) { + uint32_t downloadOpCount = process.retryInfo.downloadBatchOpCount; + uint32_t uploadRetryCount = retryInfo->second; + tableProcess->second.upLoadInfo.successCount += std::min(uploadRetryCount, downloadOpCount); + } +} } diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/process_notifier.h b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/process_notifier.h index 87e2cdfc1b60dceb5f84f003063be83dc1177438..a26ec87e497f4dd8228ce9f32849b6f999550a3f 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/process_notifier.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/process_notifier.h @@ -36,7 +36,10 @@ public: void ResetUploadBatchIndex(const std::string &tableName); - void GetLastUploadInfo(const std::string &tableName, Info &lastUploadInfo) const; + void UpdateUploadRetryInfo(const ICloudSyncer::InnerProcessInfo &process); + + void GetLastUploadInfo(const std::string &tableName, Info &lastUploadInfo, + ICloudSyncer::UploadRetryInfo &retryInfo) const; void GetDownloadInfoByTableName(ICloudSyncer::InnerProcessInfo &process); @@ -52,9 +55,13 @@ protected: std::vector devices_; ICloudSyncer *syncer_; std::string user_; + std::map processRetryInfo_; private: static void InitSyncProcess(const std::vector &tableName, SyncProcess &syncProcess); bool IsMultiUser() const; + + /* update success count of previous upload batch after download retry. */ + void UpdateUploadInfoIfNeeded(const ICloudSyncer::InnerProcessInfo &process); }; } #endif // PROCESS_NOTIFIER_H diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/strategy_factory.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/strategy_factory.cpp index f95ba94b5cb29d71fa12a5ebe88d0d086976d00c..f8fb527208db33cd60bdd86463837bb039406891 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/strategy_factory.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/strategy_factory.cpp @@ -20,7 +20,7 @@ namespace DistributedDB { std::shared_ptr StrategyFactory::BuildSyncStrategy( - SyncMode mode, bool isLocalDeleteUpload, SingleVerConflictResolvePolicy policy) + SyncMode mode, bool isKvScene, SingleVerConflictResolvePolicy policy) { std::shared_ptr strategy; switch (mode) { @@ -38,7 +38,7 @@ std::shared_ptr StrategyFactory::BuildSyncStrategy( strategy = std::make_shared(); } strategy->SetConflictResolvePolicy(policy); - strategy->SetIsLocalDeleteUpload(isLocalDeleteUpload); + strategy->SetIsKvScene(isKvScene); return strategy; } } diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/strategy_factory.h b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/strategy_factory.h index d2a66d01a9f2a2fff3ccd57f80ced0932a24609e..82c4ae385ff9d68bcc88aceb03cf951bd9173386 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/strategy_factory.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/strategy_factory.h @@ -21,7 +21,7 @@ namespace DistributedDB { class StrategyFactory { public: - static std::shared_ptr BuildSyncStrategy(SyncMode mode, bool isLocalDeleteUpload = false, + static std::shared_ptr BuildSyncStrategy(SyncMode mode, bool isKvScene = false, SingleVerConflictResolvePolicy policy = SingleVerConflictResolvePolicy::DEFAULT_LAST_WIN); }; } diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/ability_sync.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/device/ability_sync.cpp index 9a65b4bd455617a9fbfb8ee5333d480de15db544..3e75eefdc6cd32aa7d09f2fcb2edc65bad6cb53f 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/ability_sync.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/ability_sync.cpp @@ -1361,7 +1361,7 @@ void AbilitySync::InitAbilitySyncFinishStatus(ISyncTaskContext &context) LOGI("[AbilitySync] Mark ability sync finish from db status"); syncFinished_ = true; if (context.GetRemoteSoftwareVersion() == 0u) { // LCOV_EXCL_BR_LINE - LOGD("[AbilitySync] Init remote version with default"); + LOGI("[AbilitySync] Init remote version with default"); context.SetRemoteSoftwareVersion(SOFTWARE_VERSION_RELEASE_9_0); // remote version >= 109 } InitRemoteDBAbility(context); diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/generic_syncer.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/device/generic_syncer.cpp index f991cfcf65322d0bffc1b7595eabe32df4140a02..dba378975b9e6fcd7a841d3761aa23ec40e15466 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/generic_syncer.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/generic_syncer.cpp @@ -240,6 +240,7 @@ int GenericSyncer::PrepareSync(const SyncParma ¶m, uint32_t syncId, uint64_t SubQueuedSyncSize(); return -E_OUT_OF_MEMORY; } + ISyncEngine *engine = nullptr; { std::lock_guard autoLock(syncerLock_); diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/multiver/multi_ver_sync_engine.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/device/multiver/multi_ver_sync_engine.cpp index 25d6351edcf1b7f20963ccefa92fdd117303be1c..54bbe224edf7bf9a93f7676bc008b55e52ccc72d 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/multiver/multi_ver_sync_engine.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/multiver/multi_ver_sync_engine.cpp @@ -18,7 +18,7 @@ #include "multi_ver_sync_task_context.h" namespace DistributedDB { -ISyncTaskContext *MultiVerSyncEngine::CreateSyncTaskContext(const ISyncInterface &syncInterface) +ISyncTaskContext *MultiVerSyncEngine::CreateSyncTaskContext() { return new (std::nothrow) MultiVerSyncTaskContext; } diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/multiver/multi_ver_sync_engine.h b/kv_store/frameworks/libs/distributeddb/syncer/src/device/multiver/multi_ver_sync_engine.h index f29f88e1141e89a0fdb749df9f1fa554d5a45cc1..0c23ae95c44ae1eb316c50a8f4e1c2fadbfcefa7 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/multiver/multi_ver_sync_engine.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/multiver/multi_ver_sync_engine.h @@ -30,7 +30,7 @@ protected: ~MultiVerSyncEngine() override {}; // Create a context - ISyncTaskContext *CreateSyncTaskContext(const ISyncInterface &syncInterface) override; + ISyncTaskContext *CreateSyncTaskContext() override; private: DECLARE_OBJECT_TAG(MultiVerSyncEngine); diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_packet.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_packet.cpp index aaf525ec8b4df318c70a3ad4e9729c5459c53f8a..c2a7f12bf259ec269362a3280f15d5b6c56e075b 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_packet.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_packet.cpp @@ -203,7 +203,7 @@ uint32_t DataRequestPacket::CalculateLen(uint32_t messageId) const totalLen += Parcel::GetUInt32Len(); // totalDataCount totalLen = Parcel::GetEightByteAlign(totalLen); } - + return totalLen > INT32_MAX ? 0 : totalLen; } diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_sync.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_sync.cpp index 4c8a2524473198830c70e4e7cbde43351da12576..7048bb2d33bda6d63d95b2fc05004e81aba01a3d 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_sync.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_sync.cpp @@ -1096,6 +1096,7 @@ int SingleVerDataSync::SendPullResponseDataPkt(int ackCode, SyncEntry &syncOutDa LOGD("[SendPullResponseDataPkt] GetUnsyncTotal total=%u", total); packet->SetTotalDataCount(total); } + uint32_t packetLen = packet->CalculateLen(SingleVerDataSyncUtils::GetMessageId(syncType)); Message *message = new (std::nothrow) Message(SingleVerDataSyncUtils::GetMessageId(syncType)); if (message == nullptr) { diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_sync.h b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_sync.h index abe0b5a0e952403e127f02ca38b4a1e77fda6af3..ce774443c9ab60a2193220fcf3231b812ca87cc4 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_sync.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_sync.h @@ -229,7 +229,7 @@ protected: void FillRequestReSendPacket(SingleVerSyncTaskContext *context, DataRequestPacket *packet, DataSyncReSendInfo reSendInfo, SyncEntry &syncData, int sendCode); - + void FillRequestReSendPacketV2(const SingleVerSyncTaskContext *context, DataRequestPacket *packet); void UpdateMtuSize(); diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_sync_utils.h b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_sync_utils.h index 97569cc8762bddcd45a191a397c81032be37df9e..f01eb4de42b6fd5c917fd087dabaaeb6f09f68b3 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_sync_utils.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_sync_utils.h @@ -108,7 +108,7 @@ public: uint32_t &total); static int GetUnsyncTotal(const SingleVerSyncTaskContext *context, const SyncGenericInterface *storage, SyncTimeRange &waterMarkInfo, uint32_t &total); - + static bool IsSupportRequestTotal(uint32_t version); static void UpdateSyncProcess(SingleVerSyncTaskContext *context, const DataRequestPacket *packet); diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_state_machine.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_state_machine.cpp index 703c701735bc1fb3e64f8aee6b9dff3567e37afa..6f7783baf8121390da4dea1f6a6541610f347dd2 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_state_machine.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_state_machine.cpp @@ -518,6 +518,7 @@ Event SingleVerSyncStateMachine::DoAbilitySync() const remoteCommunicatorVersion, handler, context_); if (errCode != E_OK) { LOGE("[StateMachine][DoAbilitySync] ability sync start failed,errCode=%d", errCode); + context_->SetTaskErrCode(errCode); return TransformErrCodeToEvent(errCode); } return Event::WAIT_ACK_EVENT; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_task_context.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_task_context.cpp index 7f49227a1f4ebaea371da0912b2d0fa18fdf04b4..995fa508055c9510667c0a6b23b49be6f284b4ae 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_task_context.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_task_context.cpp @@ -230,7 +230,7 @@ void SingleVerSyncTaskContext::Abort(int status) { std::lock_guard lock(operationLock_); if (syncOperation_ != nullptr) { - syncOperation_->SetStatus(deviceId_, status); + syncOperation_->SetStatus(deviceId_, status, GetCommErrCode()); if ((status >= SyncOperation::OP_FINISHED_ALL)) { UnlockObj(); if (syncOperation_->CheckIsAllFinished()) { @@ -293,6 +293,7 @@ void SingleVerSyncTaskContext::ClearAllSyncTask() if (GetTaskExecStatus() == SyncTaskContext::RUNNING) { // clear syncing task. stateMachine_->CommErrAbort(); + SetCommFailErrCode(static_cast(COMM_FAILURE)); } // reset last push status for sync merge ResetLastPushTaskStatus(); diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_engine.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_engine.cpp index 43c156a2e540e2c3cf53db8c1fd709d3b457cb34..0a784b1a55d3675d1616f1946738da44b677d9f1 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_engine.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_engine.cpp @@ -1043,9 +1043,9 @@ void SyncEngine::SchemaChange() std::vector tmpContextVec; { std::lock_guard lock(contextMapLock_); - for (const auto &entry : syncTaskContextMap_) { + for (const auto &entry : syncTaskContextMap_) { // LCOV_EXCL_BR_LINE auto context = entry.second; - if (context == nullptr || context->IsKilled()) { // LCOV_EXCL_BR_LINE + if (context == nullptr || context->IsKilled()) { continue; } RefObject::IncObjRef(context); diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_task_context.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_task_context.cpp index 97a27ae7235fbd3607afd7a3d6df3a0e22558184..2237712ae1c027cfa91c967bf3878a58052a2b96 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_task_context.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_task_context.cpp @@ -54,6 +54,7 @@ SyncTaskContext::SyncTaskContext() remoteSoftwareVersionId_(0), isCommNormal_(true), taskErrCode_(E_OK), + commErrCode_(E_OK), syncTaskRetryStatus_(false), isSyncRetry_(false), negotiationCount_(0), @@ -541,6 +542,11 @@ void SyncTaskContext::CommErrHandlerFuncInner(int errCode, uint32_t sessionId) } } LOGE("[SyncTaskContext][CommErr] errCode %d", errCode); + if (errCode > 0) { + SetCommFailErrCode(static_cast(COMM_FAILURE)); + } else { + SetCommFailErrCode(errCode); + } stateMachine_->CommErrAbort(sessionId); } @@ -570,6 +576,7 @@ void SyncTaskContext::CopyTargetData(const ISyncTarget *target, const TaskParam taskErrCode_ = E_OK; packetId_ = 0; isCommNormal_ = true; // reset comm status here + commErrCode_ = E_OK; syncTaskRetryStatus_ = isSyncRetry_; timeout_ = static_cast(taskParam.timeout); negotiationCount_ = 0; @@ -840,4 +847,14 @@ int32_t SyncTaskContext::GetResponseTaskCount() std::lock_guard autoLock(targetQueueLock_); return static_cast(responseTargetQueue_.size()); } + +int SyncTaskContext::GetCommErrCode() const +{ + return commErrCode_; +} + +void SyncTaskContext::SetCommFailErrCode(int errCode) +{ + commErrCode_ = errCode; +} } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_task_context.h b/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_task_context.h index 685baabf64dcd1979ec14a4f7b78e8ac2d766ba8..07d474fab12a5f5318b95cf23a740049b86783a3 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_task_context.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_task_context.h @@ -216,6 +216,10 @@ public: void TimeChange() override; int32_t GetResponseTaskCount() override; + + int GetCommErrCode() const; + + void SetCommFailErrCode(int errCode); protected: const static int KILL_WAIT_SECONDS = INT32_MAX; @@ -284,6 +288,7 @@ protected: volatile bool isCommNormal_; volatile int taskErrCode_; + volatile int commErrCode_; volatile uint64_t packetId_ = 0; // used for assignment to reSendMap_.ReSendInfo.packetId in 103 version or above volatile bool syncTaskRetryStatus_; volatile bool isSyncRetry_; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/syncer_proxy.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/device/syncer_proxy.cpp index 8a96086105eba18d994574c932f1d3c010ebd318..0c8d6fd62d8667c73bb587ea71c7705faba6fe55 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/syncer_proxy.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/syncer_proxy.cpp @@ -74,7 +74,7 @@ int SyncerProxy::Sync(const SyncParma &parma, uint64_t connectionId) int SyncerProxy::CancelSync(uint32_t syncId) { - if (syncer_ == nullptr) { + if (syncer_ == nullptr) { // LCOV_EXCL_BR_LINE return -E_NOT_INIT; } return syncer_->CancelSync(syncId); @@ -82,7 +82,7 @@ int SyncerProxy::CancelSync(uint32_t syncId) int SyncerProxy::RemoveSyncOperation(int syncId) { - if (syncer_ == nullptr) { // LCOV_EXCL_BR_LINE + if (syncer_ == nullptr) { return -E_NOT_INIT; } return syncer_->RemoveSyncOperation(syncId); diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/sync_operation.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/sync_operation.cpp index db3466dd3987e2f8fb82347d0212719cd76b3b94..a9df29eb709ed949513c8e118e279f7ee23a0ecf 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/sync_operation.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/sync_operation.cpp @@ -89,9 +89,9 @@ void SyncOperation::SetOnSyncFinished(const OnSyncFinished &callback) onFinished_ = callback; } -void SyncOperation::SetStatus(const std::string &deviceId, int status) +void SyncOperation::SetStatus(const std::string &deviceId, int status, int commErrCode) { - LOGD("[SyncOperation] SetStatus dev %s{private} status %d", deviceId.c_str(), status); + LOGD("[SyncOperation] SetStatus dev %s{private} status %d commErrCode %d", deviceId.c_str(), status, commErrCode); AutoLock lockGuard(this); if (IsKilled()) { LOGE("[SyncOperation] SetStatus failed, the SyncOperation has been killed!"); @@ -114,7 +114,10 @@ void SyncOperation::SetStatus(const std::string &deviceId, int status) return; } iter->second = status; - return; + if ((status != OP_COMM_ABNORMAL) || (commErrCode == E_OK)) { + return; + } + commErrCodeMap_.insert(std::pair(deviceId, commErrCode)); } } @@ -158,6 +161,20 @@ int SyncOperation::GetMode() const return mode_; } +void SyncOperation::ReplaceCommErrCode(std::map &finishStatus) +{ + for (auto &item : finishStatus) { + if (item.second != OP_COMM_ABNORMAL) { + continue; + } + std::string deviceId = item.first; + auto iter = commErrCodeMap_.find(deviceId); + if (iter != commErrCodeMap_.end()) { + item.second = iter->second; + } + } +} + void SyncOperation::Finished() { std::map tmpStatus; @@ -170,6 +187,7 @@ void SyncOperation::Finished() isFinished_ = true; tmpStatus = statuses_; tmpProcessMap = syncProcessMap_; + ReplaceCommErrCode(tmpStatus); } PerformanceAnalysis *performance = PerformanceAnalysis::GetInstance(); if (performance != nullptr) { @@ -427,28 +445,29 @@ DBStatus SyncOperation::DBStatusTrans(int operationStatus) { static_cast(OP_USER_CHANGED), USER_CHANGED }, { static_cast(OP_DENIED_SQL), NO_PERMISSION }, { static_cast(OP_NOTADB_OR_CORRUPTED), INVALID_PASSWD_OR_CORRUPTED_DB }, + { static_cast(OP_FAILED), DB_ERROR }, }; const auto &result = std::find_if(std::begin(syncOperationStatusNodes), std::end(syncOperationStatusNodes), [operationStatus](const auto &node) { return node.operationStatus == operationStatus; }); - return result == std::end(syncOperationStatusNodes) ? DB_ERROR : result->status; + return result == std::end(syncOperationStatusNodes) ? static_cast(operationStatus) : result->status; } ProcessStatus SyncOperation::DBStatusTransProcess(int operationStatus) { static const SyncOperationProcessStatus syncOperationProcessStatus[] = { - { static_cast(OP_WAITING), PREPARED }, - { static_cast(OP_SYNCING), PROCESSING }, - { static_cast(OP_SEND_FINISHED), PROCESSING }, - { static_cast(OP_RECV_FINISHED), PROCESSING }, - { static_cast(OP_FINISHED_ALL), FINISHED }, - { static_cast(OP_COMM_ABNORMAL), FINISHED }, + { static_cast(OP_WAITING), PREPARED }, + { static_cast(OP_SYNCING), PROCESSING }, + { static_cast(OP_SEND_FINISHED), PROCESSING }, + { static_cast(OP_RECV_FINISHED), PROCESSING }, + { static_cast(OP_FINISHED_ALL), FINISHED }, + { static_cast(OP_COMM_ABNORMAL), FINISHED }, }; const auto &result = std::find_if(std::begin(syncOperationProcessStatus), std::end(syncOperationProcessStatus), - [operationStatus](const auto &node) { - return node.operationStatus == operationStatus; - }); + [operationStatus](const auto &node) { + return node.operationStatus == operationStatus; + }); return result == std::end(syncOperationProcessStatus) ? FINISHED : result->proStatus; } diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/sync_operation.h b/kv_store/frameworks/libs/distributeddb/syncer/src/sync_operation.h index 4c762676d0be9c460c552e2574287891a097ba27..f3f00a5de05f5d244700da390863874e7d074004 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/sync_operation.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/sync_operation.h @@ -78,7 +78,7 @@ public: void SetOnSyncFinished(const OnSyncFinished &callback); // Set the sync status, running or finished - void SetStatus(const std::string &deviceId, int status); + void SetStatus(const std::string &deviceId, int status, int commErrCode = E_OK); // Set the unfinished devices sync status, running or finished void SetUnfinishedDevStatus(int status); @@ -153,6 +153,8 @@ private: static std::string GetFinishDetailMsg(const std::map &finishStatus); + void ReplaceCommErrCode(std::map &finishStatus); + // The device list const std::vector devices_; @@ -177,6 +179,9 @@ private: // The device id we sync with std::map statuses_; + // passthrough errCode + std::map commErrCodeMap_; + // Is this operation is a block sync volatile bool isBlockSync_; diff --git a/kv_store/frameworks/libs/distributeddb/test/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/BUILD.gn index e4661333445b0839d0d03b73870fd7858fdd5347..cd3cb62127c539e3d6cae8735e24306f6770c98c 100644 --- a/kv_store/frameworks/libs/distributeddb/test/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/BUILD.gn @@ -114,7 +114,6 @@ config("module_private_config") { "TRACE_SQLITE_EXECUTE", "SQLITE_ENABLE_DROPTABLE_CALLBACK", "OPENSSL_SUPPRESS_DEPRECATED", - "USE_RD_KERNEL", ] if (is_ohos) { defines += [ "USE_FFRT" ] @@ -189,7 +188,6 @@ ohos_source_set("src_file") { deps = [ "//third_party/googletest:gtest_main", "//third_party/sqlite:sqlite", - "//third_party/zlib:libz", ] configs += [ "//third_party/jsoncpp:jsoncpp_config" ] @@ -208,6 +206,7 @@ ohos_source_set("src_file") { "hilog:libhilog", "hisysevent:libhisysevent", "hitrace:hitrace_meter", + "zlib:libz", ] part_name = "kv_store" } @@ -228,7 +227,6 @@ template("distributeddb_unittest") { "//third_party/googletest:gmock_main", "//third_party/googletest:gtest_main", "//third_party/sqlite:sqlite", - "//third_party/zlib:libz", ] configs += [ "//third_party/jsoncpp:jsoncpp_config" ] ldflags = [ "-Wl,--exclude-libs,ALL" ] @@ -242,6 +240,7 @@ template("distributeddb_unittest") { "hilog:libhilog", "hisysevent:libhisysevent", "hitrace:hitrace_meter", + "zlib:libz", ] } } @@ -272,6 +271,10 @@ distributeddb_unittest("DistributedDBInterfacesImportAndExportTest") { sources = [ "unittest/common/interfaces/distributeddb_interfaces_import_and_export_test.cpp" ] } +distributeddb_unittest("DistributedDBInterfacesImportAndExportRdTest") { + sources = [ "unittest/common/interfaces/distributeddb_interfaces_import_and_export_rd_test.cpp" ] +} + distributeddb_unittest("DistributedDBCloudInterfacesReferenceTest") { sources = [ "unittest/common/interfaces/distributeddb_cloud_interfaces_reference_test.cpp" ] } @@ -378,6 +381,10 @@ distributeddb_unittest("DistributedDBInterfacesNBDelegateTest") { ] } +distributeddb_unittest("DistributedDBInterfacesNBDelegateExtendTest") { + sources = [ "unittest/common/interfaces/distributeddb_interfaces_nb_delegate_extend_test.cpp" ] +} + distributeddb_unittest("DistributedDBCloudInterfacesRelationalExtTest") { sources = [ "unittest/common/interfaces/distributeddb_cloud_interfaces_relational_ext_test.cpp" ] } @@ -917,9 +924,11 @@ group("unittest") { ":DistributedDBInterfacesDatabaseTest", ":DistributedDBInterfacesEncryptDatabaseTest", ":DistributedDBInterfacesEncryptDelegateTest", + ":DistributedDBInterfacesImportAndExportRdTest", ":DistributedDBInterfacesImportAndExportTest", ":DistributedDBInterfacesIndexUnitTest", ":DistributedDBInterfacesLogTest", + ":DistributedDBInterfacesNBDelegateExtendTest", ":DistributedDBInterfacesNBDelegateLocalBatchTest", ":DistributedDBInterfacesNBDelegateSchemaPutTest", ":DistributedDBInterfacesNBDelegateTest", diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/nbdelegate_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/nbdelegate_fuzzer/BUILD.gn index 66bf82ae8471c4b6b9d84f9a9fe0e97a3ad4ff40..75dc50ad39aa4c0f59fca75e7684f98f523fa57a 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/nbdelegate_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/nbdelegate_fuzzer/BUILD.gn @@ -82,7 +82,7 @@ ohos_fuzztest("NbDelegateFuzzTest") { sources = distributeddb_src sources += [ - "../../../test/fuzztest/common/fuzzer_data.cpp", + "../common/fuzzer_data.cpp", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/test/fuzztest/common/distributeddb_tools_test.cpp", "nbdelegate_fuzzer.cpp", ] diff --git a/kv_store/frameworks/libs/distributeddb/test/moduletest/common/distributeddb/src/distributed_test_sysinfo.cpp b/kv_store/frameworks/libs/distributeddb/test/moduletest/common/distributeddb/src/distributed_test_sysinfo.cpp index 3b7be386dd7eb747fe1be2878ab85c54735b2888..ae92d04bb4525895cc67b77f2cfc3a5b26cbd51f 100644 --- a/kv_store/frameworks/libs/distributeddb/test/moduletest/common/distributeddb/src/distributed_test_sysinfo.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/moduletest/common/distributeddb/src/distributed_test_sysinfo.cpp @@ -58,19 +58,19 @@ void DistributedTestSysInfo::GetSysMemOccpy(SeqNo seqNo) return; } - fgets(buff, sizeof(buff), fp); + (void)fgets(buff, sizeof(buff), fp); int result1 = sscanf_s(buff, "%s %llu ", memOccupy->memTotalName_, sizeof(memOccupy->memTotalName_), &memOccupy->memTotal_); - fgets(buff, sizeof(buff), fp); + (void)fgets(buff, sizeof(buff), fp); int result2 = sscanf_s(buff, "%s %llu ", memOccupy->memFreeName_, sizeof(memOccupy->memFreeName_), &memOccupy->memFree_); - fgets(buff, sizeof(buff), fp); + (void)fgets(buff, sizeof(buff), fp); int result3 = sscanf_s(buff, "%s %llu ", memOccupy->buffersName_, sizeof(memOccupy->buffersName_), &memOccupy->buffers_); - fgets(buff, sizeof(buff), fp); + (void)fgets(buff, sizeof(buff), fp); int result4 = sscanf_s(buff, "%s %llu ", memOccupy->cachedName_, sizeof(memOccupy->cachedName_), &memOccupy->cached_); - fgets(buff, sizeof(buff), fp); + (void)fgets(buff, sizeof(buff), fp); int result5 = sscanf_s(buff, "%s %llu", memOccupy->swapCachedName_, sizeof(memOccupy->swapCachedName_), &memOccupy->swapCached_); if (result1 != 2 || result2 != 2) { // there are 2 incoming param. @@ -82,7 +82,7 @@ void DistributedTestSysInfo::GetSysMemOccpy(SeqNo seqNo) MST_LOG(" [MemTotal] = %" PRIu64 " \n [MemFree] = %" PRIu64 " \n [Buffers] = %" PRIu64 " \n [Cached] = %" PRIu64 \ " \n [SwapCached] = %" PRIu64, memOccupy->memTotal_, memOccupy->memFree_, memOccupy->buffers_, memOccupy->cached_, memOccupy->swapCached_); - fclose(fp); + (void)fclose(fp); fp = nullptr; } @@ -90,50 +90,49 @@ void GetSysCpuInfo(CpuOccupy &cpuStatFirst_, CpuOccupy &cpuStatSecond_, uint64_t { FILE *fp = nullptr; char buff[PROC_BUFFER_LENGTH] = { 0 }; - uint64_t allFirst, allSecond, idleFirst, idleSecond; fp = fopen(SYS_CPU_FILE.c_str(), FILE_READ_PERMISSION.c_str()); if (fp == nullptr) { perror("fopen:"); exit(0); } - fgets(buff, sizeof(buff), fp); + (void)fgets(buff, sizeof(buff), fp); int result = sscanf_s(buff, "%s %llu %llu %llu %llu %llu %llu %llu", cpuStatFirst_.name_, sizeof(cpuStatFirst_.name_), &cpuStatFirst_.user_, &cpuStatFirst_.nice_, &cpuStatFirst_.system_, &cpuStatFirst_.idle_, &cpuStatFirst_.iowait_, &cpuStatFirst_.irq_, &cpuStatFirst_.softirq_); if (result != 8) { // there are 8 incoming param. - fclose(fp); + (void)fclose(fp); return; } - allFirst = cpuStatFirst_.user_ + cpuStatFirst_.nice_ + cpuStatFirst_.system_ + cpuStatFirst_.idle_ + + uint64_t allFirst = cpuStatFirst_.user_ + cpuStatFirst_.nice_ + cpuStatFirst_.system_ + cpuStatFirst_.idle_ + cpuStatFirst_.iowait_ + cpuStatFirst_.irq_ + cpuStatFirst_.softirq_; - idleFirst = cpuStatFirst_.idle_; + uint64_t idleFirst = cpuStatFirst_.idle_; rewind(fp); std::this_thread::sleep_for(std::chrono::microseconds(microSeconds)); if (memset_s(buff, sizeof(buff), 0, sizeof(buff)) != EOK) { MST_LOG("set buffer to 0 failed!"); - fclose(fp); + (void)fclose(fp); return; } - fgets(buff, sizeof(buff), fp); + (void)fgets(buff, sizeof(buff), fp); result = sscanf_s(buff, "%s %llu %llu %llu %llu %llu %llu %llu", cpuStatSecond_.name_, sizeof(cpuStatSecond_.name_), &cpuStatSecond_.user_, &cpuStatSecond_.nice_, &cpuStatSecond_.system_, &cpuStatSecond_.idle_, &cpuStatSecond_.iowait_, &cpuStatSecond_.irq_, &cpuStatSecond_.softirq_); if (result < 0) { - fclose(fp); + (void)fclose(fp); return; } - allSecond = cpuStatSecond_.user_ + cpuStatSecond_.nice_ + cpuStatSecond_.system_ + cpuStatSecond_.idle_ + + uint64_t allSecond = cpuStatSecond_.user_ + cpuStatSecond_.nice_ + cpuStatSecond_.system_ + cpuStatSecond_.idle_ + cpuStatSecond_.iowait_ + cpuStatSecond_.irq_ + cpuStatSecond_.softirq_; - idleSecond = cpuStatSecond_.idle_; + uint64_t idleSecond = cpuStatSecond_.idle_; *cpuStatUsage = (static_cast(allSecond - allFirst - (idleSecond - idleFirst))) / (allSecond - allFirst) * PERCENTAGE_FACTOR; MST_LOG(" [CpuUsage] = %.2f%%", *cpuStatUsage); - fclose(fp); + (void)fclose(fp); fp = nullptr; return; } @@ -169,12 +168,12 @@ float DistributedTestSysInfo::ReadSysValFromFile(const std::string &filePath) return FLOAT_RET_ERROR; } - fgets(buff, sizeof(buff), fp); + (void)fgets(buff, sizeof(buff), fp); if (sscanf_s(buff, "%f", &val_) != 1) { - fclose(fp); + (void)fclose(fp); return FLOAT_RET_ERROR; } - fclose(fp); + (void)fclose(fp); return val_; } diff --git a/kv_store/frameworks/libs/distributeddb/test/moduletest/common/distributeddb/src/distributed_test_tools.cpp b/kv_store/frameworks/libs/distributeddb/test/moduletest/common/distributeddb/src/distributed_test_tools.cpp index abca43468f7d057a76336900e96883aff6f3e5af..80e74b67ebe25a9dfd658ac50eb5ebd59913cba2 100644 --- a/kv_store/frameworks/libs/distributeddb/test/moduletest/common/distributeddb/src/distributed_test_tools.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/moduletest/common/distributeddb/src/distributed_test_tools.cpp @@ -295,6 +295,16 @@ private: vector entries_ = {}; }; +static int GetDirStat(const char *dir, struct stat &dirStat) +{ + // getting dir attribution fails + if (stat(dir, &dirStat) < 0) { + perror("get directory stat error"); + return -1; + } + return 0; +} + // delete dir(directory) recursively int RemoveDir(const std::string &dirSrc) { @@ -315,13 +325,12 @@ int RemoveDir(const std::string &dirSrc) if (access(dir, F_OK) != 0) { return 0; } - // getting dir attribution fails - if (stat(dir, &dirStat) < 0) { - perror("get directory stat error"); - return -1; - } + GetDirStat(dir, dirStat); // if dir is a common file if (S_ISREG(dirStat.st_mode)) { +#ifdef DB_DEBUG_ENV + MST_LOG("---> remove db directory: %s", dir); +#endif remove(dir); } else if (S_ISDIR(dirStat.st_mode)) { // if dir is directory, delete it recursively @@ -344,6 +353,9 @@ int RemoveDir(const std::string &dirSrc) RemoveDir(std::string(dirName)); } closedir(dirp); +#ifdef DB_DEBUG_ENV + MST_LOG("---> remove db directory: %s", directory.c_str()); +#endif remove(directory.c_str()); } else { perror("unknown file type!"); @@ -356,14 +368,13 @@ int SetDir(const std::string &directory, const int authRight) { MST_LOG("create directory: %s", directory.c_str()); char dir[MAX_DIR_LENGTH] = { 0 }; - int i, len; errno_t ret = strcpy_s(dir, MAX_DIR_LENGTH, directory.c_str()); if (ret != E_OK) { MST_LOG("strcpy_s failed(%d)!", ret); return -1; } - len = strlen(dir); + int len = strlen(dir); if (dir[len - 1] != '/') { ret = strcat_s(dir, sizeof(dir) - strlen(dir) - 1, "/"); if (ret != E_OK) { @@ -373,27 +384,29 @@ int SetDir(const std::string &directory, const int authRight) len++; } - for (i = 1; i < len; i++) { + for (int i = 1; i < len; i++) { if (dir[i] != '/') { continue; } dir[i] = '\0'; - if (access(dir, F_OK) != E_OK) { - mode_t mode = umask(0); + if (access(dir, F_OK) == E_OK) { + dir[i] = '/'; + continue; + } + mode_t mode = umask(0); #if defined(RUNNING_ON_LINUX) - if (mkdir(dir, authRight) == E_ERROR) { + if (mkdir(dir, authRight) == E_ERROR) { #else - std::string stringDir = dir; - if (OS::MakeDBDirectory(stringDir) == E_ERROR) { + std::string stringDir = dir; + if (OS::MakeDBDirectory(stringDir) == E_ERROR) { #endif - MST_LOG("mkdir(%s) failed(%d)!", dir, errno); - return -1; - } - if (chdir(dir) == E_ERROR) { - MST_LOG("chdir(%s) failed(%d)!", dir, errno); - } - umask(mode); + MST_LOG("mkdir(%s) failed(%d)!", dir, errno); + return -1; } + if (chdir(dir) == E_ERROR) { + MST_LOG("chdir(%s) failed(%d)!", dir, errno); + } + umask(mode); dir[i] = '/'; } MST_LOG("check dir = %s", dir); @@ -703,13 +716,14 @@ DBStatus DistributedTestTools::DeleteBatch(KvStoreDelegate &kvStoreDelegate, con for (const auto &iter : keys) { keyBatch.push_back(iter); cnt++; - if (cnt % BATCH_RECORDS == 0 || cnt == static_cast(keys.size())) { - status = kvStoreDelegate.DeleteBatch(keyBatch); - if (status != DBStatus::OK) { - return status; - } - keyBatch.clear(); + if (cnt % BATCH_RECORDS != 0 && cnt != static_cast(keys.size())) { + continue; + } + status = kvStoreDelegate.DeleteBatch(keyBatch); + if (status != DBStatus::OK) { + return status; } + keyBatch.clear(); } return status; } else { diff --git a/kv_store/frameworks/libs/distributeddb/test/moduletest/common/distributeddb/src/distributeddb_data_generator.cpp b/kv_store/frameworks/libs/distributeddb/test/moduletest/common/distributeddb/src/distributeddb_data_generator.cpp index 865291fe0bb221fd7edc6a60af748ada58c52d22..8844bdde3bc1b2e795eda8d1e394b1bc921cd471 100644 --- a/kv_store/frameworks/libs/distributeddb/test/moduletest/common/distributeddb/src/distributeddb_data_generator.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/moduletest/common/distributeddb/src/distributeddb_data_generator.cpp @@ -397,7 +397,7 @@ std::vector GenerateFixedLenRandRecords(std::vector &sch GetLongSchemaDefine(param, validLargeSchema); validLargeSchema.erase(validLargeSchema.size() - 1, 1); validLargeSchema.append(",\"field0\":\"STRING,NOT NULL,DEFAULT 'kkkkk1'\"}"); - std::string splicSchema, largeIndexRes, largeIndex; + std::string splicSchema = ""; + std::string largeIndexRes = ""; + std::string largeIndex = ""; for (int index = 0; index < KEY_THIRTYTWO_BYTE; index++) { largeIndexRes = largeIndexRes + "\"$.field" + std::to_string(index) + "\","; } @@ -502,28 +504,34 @@ void GenerateLargeValidSchema(Schema &validSchema, std::vector &sch schema.push_back(splicSchema); } +void GenerateSplicSchema(const std::string &version, const std::string &mode, const Schema &validSchema, + std::vector &schema, bool hasIndex) +{ + std::string splicSchema; + if (hasIndex) { + for (auto iter3 = validSchema.index.begin(); iter3 != validSchema.index.end(); iter3++) { + splicSchema = SpliceToSchema(version, mode, validSchema.define.at(0), *iter3); + schema.push_back(splicSchema); + } + } else { + for (auto iter3 = validSchema.define.begin(); iter3 != validSchema.define.end(); iter3++) { + splicSchema = SpliceToSchema(version, mode, *iter3, validSchema.index.at(0)); + schema.push_back(splicSchema); + } + } +} + std::vector GetValidSchema(Schema &validSchema, bool hasIndex) { std::vector schema; for (auto iter1 = validSchema.version.begin(); iter1 != validSchema.version.end(); iter1++) { for (auto iter2 = validSchema.mode.begin(); iter2 != validSchema.mode.end(); iter2++) { - std::string splicSchema; - if (hasIndex) { - for (auto iter3 = validSchema.index.begin(); iter3 != validSchema.index.end(); iter3++) { - splicSchema = SpliceToSchema(*iter1, *iter2, validSchema.define.at(0), *iter3); - schema.push_back(splicSchema); - } - } else { - for (auto iter3 = validSchema.define.begin(); iter3 != validSchema.define.end(); iter3++) { - splicSchema = SpliceToSchema(*iter1, *iter2, *iter3, validSchema.index.at(0)); - schema.push_back(splicSchema); - } - } + GenerateSplicSchema(*iter1, *iter2, validSchema, schema, hasIndex); } } GenerateLongValidSchema(validSchema, schema); GenerateLargeValidSchema(validSchema, schema); - std::string schemaWithoutIndex; + std::string schemaWithoutIndex = ""; schemaWithoutIndex = schemaWithoutIndex + "{" + "\"SCHEMA_VERSION\"" + ":" + "\"" + validSchema.version.at(0) + "\"" + "," + "\"SCHEMA_MODE\"" + ":" + "\"" + validSchema.mode.at(0) + "\"" + "," + "\"SCHEMA_DEFINE\"" + ":" + validSchema.define.at(0) + "}"; @@ -534,7 +542,10 @@ std::vector GetValidSchema(Schema &validSchema, bool hasIndex) void GetLongIndex(Schema &validSchema, std::vector &schema) { - std::string validLargeSchema, largeIndexRes, largeIndex, splicSchema; + std::string validLargeSchema = ""; + std::string largeIndexRes = ""; + std::string largeIndex = ""; + std::string splicSchema = ""; LongDefine param; param.recordNum = FIFTY_RECORDS; param.recordSize = KEY_SIX_BYTE; diff --git a/kv_store/frameworks/libs/distributeddb/test/moduletest/common/distributeddb/src/distributeddb_schema_test_tools.cpp b/kv_store/frameworks/libs/distributeddb/test/moduletest/common/distributeddb/src/distributeddb_schema_test_tools.cpp index 21f88d963f65b7b3bce9f3649afdf4f53a5efe48..4347adacbfad6c2757be06cc70d40a2084288125 100644 --- a/kv_store/frameworks/libs/distributeddb/test/moduletest/common/distributeddb/src/distributeddb_schema_test_tools.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/moduletest/common/distributeddb/src/distributeddb_schema_test_tools.cpp @@ -311,16 +311,15 @@ void DistributedDBSchemaTestTools::GenerateSpecificSchemaEntries(const int start int switchFactor; vector keys; vector schemasValue; - std::string indexNumStr, field1, field3, field5, field7, field8, value, switchFactorStr; for (int indexNum = startPoint; indexNum < startPoint + recordNumber; indexNum++) { - indexNumStr = std::to_string(indexNum); - field1 = "\"field1\":\"SubscribeRemoteQueryTest" + indexNumStr + "\""; - field3 = "\"field3\":false"; - field5 = "\"field5\":" + indexNumStr; - field7 = "\"field7\":" + indexNumStr; - field8 = "\"field8\":" + indexNumStr + ".1234"; + std::string indexNumStr = std::to_string(indexNum); + std::string field1 = "\"field1\":\"SubscribeRemoteQueryTest" + indexNumStr + "\""; + std::string field3 = "\"field3\":false"; + std::string field5 = "\"field5\":" + indexNumStr; + std::string field7 = "\"field7\":" + indexNumStr; + std::string field8 = "\"field8\":" + indexNumStr + ".1234"; for (auto &iter : values) { - switchFactorStr = iter[INDEX_ZEROTH]; + std::string switchFactorStr = iter[INDEX_ZEROTH]; switchFactor = switchFactorStr.back() - '0'; switch (switchFactor) { case 1: // field 1 has assigned value @@ -343,7 +342,7 @@ void DistributedDBSchemaTestTools::GenerateSpecificSchemaEntries(const int start break; } } - value = "{" + field1 + ",\"field2\":{" + field3 + ",\"field4\":{" + field5 + ",\"field6\":{" + std::string value = "{" + field1 + ",\"field2\":{" + field3 + ",\"field4\":{" + field5 + ",\"field6\":{" + field7 + "," + field8 + "}}}}"; indexNumStr = "k" + indexNumStr; Key key(indexNumStr.begin(), indexNumStr.end()); diff --git a/kv_store/frameworks/libs/distributeddb/test/moduletest/src/distributeddb_kv_concurrency_crud_test.cpp b/kv_store/frameworks/libs/distributeddb/test/moduletest/src/distributeddb_kv_concurrency_crud_test.cpp index 95bfcdc403fac9ca4162767b68d794e56bed0c85..7bf8e325caeab9151b54443d7e98a888c90c1e61 100644 --- a/kv_store/frameworks/libs/distributeddb/test/moduletest/src/distributeddb_kv_concurrency_crud_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/moduletest/src/distributeddb_kv_concurrency_crud_test.cpp @@ -67,7 +67,8 @@ void ConcurOperThread(ConcurParam* args) auto paramsPtr = static_cast(args); DBStatus status; Value valueResult; - string strKey, strValue; + string strKey = ""; + string strValue = ""; if (paramsPtr->tag_ == READ) { valueResult = DistributedTestTools::Get(*g_kvStoreConcurDelegate, paramsPtr->entryPtr_->key); @@ -226,8 +227,12 @@ HWTEST_F(DistributeddbKvConcurrencyCrudTest, Read002, TestSize.Level3) void StartRandThread() { std::vector threads; - std::random_device randDevReadKeyNo, randDevWriteKeyNo, randDevTag; - std::mt19937 genRandReadKeyNo(randDevReadKeyNo()), genRandWriteKeyNo(randDevWriteKeyNo()), genRandTag(randDevTag()); + std::random_device randDevReadKeyNo; + std::random_device randDevWriteKeyNo; + std::random_device randDevTag; + std::mt19937 genRandReadKeyNo(randDevReadKeyNo()); + std::mt19937 genRandWriteKeyNo(randDevWriteKeyNo()); + std::mt19937 genRandTag(randDevTag()); std::uniform_int_distribution disRandReadKeyNo(READ_RECORDS_NUM_START, READ_RECORDS_NUM_END); std::uniform_int_distribution disRandWriteKeyNo(WRITE_RECORDS_NUM_START, WRITE_RECORDS_NUM_END); std::uniform_int_distribution disRandTag(READ, WRITE); diff --git a/kv_store/frameworks/libs/distributeddb/test/moduletest/src/distributeddb_kv_create_test.cpp b/kv_store/frameworks/libs/distributeddb/test/moduletest/src/distributeddb_kv_create_test.cpp index 0a414765e2f075904bb9bcb51e808aa44caf31ea..af7ee4dae7905bb5fc104bbb905ff8600498def5 100644 --- a/kv_store/frameworks/libs/distributeddb/test/moduletest/src/distributeddb_kv_create_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/moduletest/src/distributeddb_kv_create_test.cpp @@ -1792,7 +1792,8 @@ void RunDbRekeyFive() result5 = DistributedTestTools::GetDelegateSuccess(manager5, g_kvdbParameter5, option); ASSERT_TRUE(manager5 != nullptr && result5 != nullptr); vector entries1; - vector allKey1, allKey2; + vector allKey1; + vector allKey2; GenerateRecords(BATCH_RECORDS, DEFAULT_START, allKey1, entries1, K_SEARCH_3); DBStatus status = DistributedTestTools::PutBatch(*result5, entries1); ASSERT_TRUE(status == DBStatus::OK); diff --git a/kv_store/frameworks/libs/distributeddb/test/moduletest/src/distributeddb_kv_observer_snap_test.cpp b/kv_store/frameworks/libs/distributeddb/test/moduletest/src/distributeddb_kv_observer_snap_test.cpp index f31d47f5f05d36f67a5dbe48ef6d3caf33d0973a..4db30d759c4b7f5d36d8bbcab68077f5b38d7f97 100644 --- a/kv_store/frameworks/libs/distributeddb/test/moduletest/src/distributeddb_kv_observer_snap_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/moduletest/src/distributeddb_kv_observer_snap_test.cpp @@ -1085,7 +1085,9 @@ vector ObserverSnapVerifyTransactionCommit(KvStoreDelegate *&delegate1, K } statusDelete = DistributedTestTools::DeleteBatch(*delegate1, keys1); EXPECT_TRUE(statusDelete == DBStatus::OK); - vector insertEntries, updateEntries, deleteEntries; + vector insertEntries; + vector updateEntries; + vector deleteEntries; EXPECT_TRUE(VerifyObserverResult(observer1, CHANGED_ZERO_TIME, INSERT_LIST, insertEntries)); EXPECT_TRUE(VerifyObserverResult(observer1, CHANGED_ZERO_TIME, UPDATE_LIST, updateEntries)); EXPECT_TRUE(VerifyObserverResult(observer1, CHANGED_ZERO_TIME, DELETE_LIST, deleteEntries)); diff --git a/kv_store/frameworks/libs/distributeddb/test/moduletest/src/distributeddb_kv_observer_test.cpp b/kv_store/frameworks/libs/distributeddb/test/moduletest/src/distributeddb_kv_observer_test.cpp index 97f9303e1748f11226c352355a0ab4d61ad60b41..bd3f2ad99a2eb3820be53145200bcac69483c118 100644 --- a/kv_store/frameworks/libs/distributeddb/test/moduletest/src/distributeddb_kv_observer_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/moduletest/src/distributeddb_kv_observer_test.cpp @@ -79,8 +79,7 @@ void DistributeddbKvObserverTest::TearDownTestCase(void) { EXPECT_TRUE(g_observerManager->CloseKvStore(g_observerDelegate) == OK); g_observerDelegate = nullptr; - DBStatus status; - status = g_observerManager->DeleteKvStore(STORE_ID_1); + DBStatus status = g_observerManager->DeleteKvStore(STORE_ID_1); EXPECT_EQ(status, DistributedDB::DBStatus::OK) << "fail to delete exist kvdb"; delete g_observerManager; g_observerManager = nullptr; diff --git a/kv_store/frameworks/libs/distributeddb/test/moduletest/src/distributeddb_nb_batch_crud_test.cpp b/kv_store/frameworks/libs/distributeddb/test/moduletest/src/distributeddb_nb_batch_crud_test.cpp index 42c54c928d4d22606ca8a5c5f2e3169647412cc6..4e6932e758cd06af9f12a42c16ce00ddd7688bb9 100644 --- a/kv_store/frameworks/libs/distributeddb/test/moduletest/src/distributeddb_nb_batch_crud_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/moduletest/src/distributeddb_nb_batch_crud_test.cpp @@ -1833,7 +1833,8 @@ void ConsistencyBatchCheck(vector *keyLeft, vector *keyRight, int time delegate = DistributedDBNbTestTools::GetNbDelegateSuccess(delegateManager, g_dbParameter1, g_option); ASSERT_TRUE(delegateManager != nullptr && delegate != nullptr) << "ConsistencyBatchCheck get delegate failed."; - Value leftValue, rightValue; + Value leftValue; + Value rightValue; while (!g_batchThreadComplete) { for (int i = 0; i < times; ++i) { leftValue.clear(); @@ -1877,7 +1878,8 @@ void ConsistencyCheckTransaction(vector &entries1, vector &entries * @tc.steps: step4. getEntries with keyprefix before updateBatch. * @tc.expected: step4. getEntries successfully that the size of them is 20. */ - vector values1, values2; + vector values1; + vector values2; EXPECT_EQ(DistributedDBNbTestTools::GetEntries(*g_nbBatchCrudDelegate, query1, values1), OK); EXPECT_EQ(DistributedDBNbTestTools::GetEntries(*g_nbBatchCrudDelegate, query2, values2), OK); EXPECT_EQ(static_cast(values1.size()), TWENTY_RECORDS); diff --git a/kv_store/frameworks/libs/distributeddb/test/moduletest/src/distributeddb_nb_crud_test.cpp b/kv_store/frameworks/libs/distributeddb/test/moduletest/src/distributeddb_nb_crud_test.cpp index 7d06a2ddabc3e43744e3fbdc329799f659f1dba2..4184c3bdcb86aafa27076609fed268114e9e9269 100644 --- a/kv_store/frameworks/libs/distributeddb/test/moduletest/src/distributeddb_nb_crud_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/moduletest/src/distributeddb_nb_crud_test.cpp @@ -1410,29 +1410,27 @@ HWTEST_F(DistributeddbNbCrudTest, Pressure006, TestSize.Level1) vector GenerateDataForBatch(vector &KeyCrud) { - DistributedDB::Key key1, key2, key3, key4, key5, key6, key7, key8; - key1 = {'a', 'b', 'c'}; - key2 = {'a', 'b', 'c', 'd', 'e'}; - key3 = {'a', 'b', 'c'}; - key4 = {'a', 'b', 'c', 'd', 'a', 's', 'd'}; - key5 = {'a', 'b', 'c', 'd', 's'}; - key6 = {'b', 'c'}; - key7 = {'d', 'a', 'b'}; - key8 = {'d', 'a', 'b', 'c'}; + DistributedDB::Key key1 = {'a', 'b', 'c'}; + DistributedDB::Key key2 = {'a', 'b', 'c', 'd', 'e'}; + DistributedDB::Key key3 = {'a', 'b', 'c'}; + DistributedDB::Key key4 = {'a', 'b', 'c', 'd', 'a', 's', 'd'}; + DistributedDB::Key key5 = {'a', 'b', 'c', 'd', 's'}; + DistributedDB::Key key6 = {'b', 'c'}; + DistributedDB::Key key7 = {'d', 'a', 'b'}; + DistributedDB::Key key8 = {'d', 'a', 'b', 'c'}; KeyCrud = { key1, key2, key3, key4, key5, key6, key7, key8 }; - DistributedDB::Value value1, value2, value3, value4, value5, value6, value7, value8; - value1 = {'l', 'o', 'c', 'a', 'l', 'V', '1'}; - value2 = {'l', 'o', 'c', 'a', 'l', 'V', '2'}; - value3 = {'s', 'y', 'n', 'V', '1'}; - value4 = {'s', 'y', 'n', 'V', '2'}; - value5 = {'s', 'y', 'n', 'V', '3'}; - value6 = {'s', 'y', 'n', 'V', '4'}; - value7 = {'s', 'y', 'n', 'V', '5'}; - value8 = {'s', 'y', 'n', 'V', '6'}; + DistributedDB::Value value1 = {'l', 'o', 'c', 'a', 'l', 'V', '1'}; + DistributedDB::Value value2 = {'l', 'o', 'c', 'a', 'l', 'V', '2'}; + DistributedDB::Value value3 = {'s', 'y', 'n', 'V', '1'}; + DistributedDB::Value value4 = {'s', 'y', 'n', 'V', '2'}; + DistributedDB::Value value5 = {'s', 'y', 'n', 'V', '3'}; + DistributedDB::Value value6 = {'s', 'y', 'n', 'V', '4'}; + DistributedDB::Value value7 = {'s', 'y', 'n', 'V', '5'}; + DistributedDB::Value value8 = {'s', 'y', 'n', 'V', '6'}; vector ValueCrud = { value1, value2, value3, value4, value5, value6, @@ -1703,9 +1701,12 @@ HWTEST_F(DistributeddbNbCrudTest, Concurrency002, TestSize.Level3) void StartThreadForLongReadWrite(vector &entriesBatch) { std::vector threads; - std::random_device randDevReadKeyNo, randDevWriteKeyNo, randDevTag; - std::mt19937 genRandReadKeyNo(randDevReadKeyNo()), genRandWriteKeyNo(randDevWriteKeyNo()), - genRandTag(randDevTag()); + std::random_device randDevReadKeyNo; + std::random_device randDevWriteKeyNo; + std::random_device randDevTag; + std::mt19937 genRandReadKeyNo(randDevReadKeyNo()); + std::mt19937 genRandWriteKeyNo(randDevWriteKeyNo()); + std::mt19937 genRandTag(randDevTag()); std::uniform_int_distribution disRandReadKeyNo(READ_RECORDS_NUM_START, READ_RECORDS_NUM_END); std::uniform_int_distribution disRandWriteKeyNo(WRITE_RECORDS_NUM_START, WRITE_RECORDS_NUM_END); std::uniform_int_distribution disRandTag(READ, WRITE); @@ -1800,13 +1801,17 @@ void JudgeInLongWriteWrite(vector &entriesBatch, ConcurParam *threadParam void StartThreadForLongWriteWrite(vector &entriesBatch) { std::vector threads; - std::random_device randDevWriteKeyNo, randDevDeleteKeyNo, randDevTag; - std::mt19937 genRandWriteKeyNo(randDevWriteKeyNo()), genRandDeleteKeyNo(randDevDeleteKeyNo()), - genRandTag(randDevTag()); + std::random_device randDevWriteKeyNo; + std::random_device randDevDeleteKeyNo; + std::random_device randDevTag; + std::mt19937 genRandWriteKeyNo(randDevWriteKeyNo()); + std::mt19937 genRandDeleteKeyNo(randDevDeleteKeyNo()); + std::mt19937 genRandTag(randDevTag()); std::uniform_int_distribution disRandWriteKeyNo(WRITE_RECORDS_NUM_START, WRITE_RECORDS_NUM_END); std::uniform_int_distribution disRandDeleteKeyNo(DELETE_RECORDS_NUM_START, DELETE_RECORDS_NUM_END); std::uniform_int_distribution disRandTag(WRITE, DELETE); - unsigned long randKeyNo, randRandTag; + unsigned long randKeyNo = 0; + unsigned long randRandTag = 0; unsigned int threadCurId = 0; SysTime start; diff --git a/kv_store/frameworks/libs/distributeddb/test/moduletest/src/distributeddb_nb_cursor_testcase.cpp b/kv_store/frameworks/libs/distributeddb/test/moduletest/src/distributeddb_nb_cursor_testcase.cpp index 00c24875c2e24e00c910c31ed36112a6d60f1bbe..0ed1a7ce86f08cdda8313983eaacaf6d9d6cd191 100644 --- a/kv_store/frameworks/libs/distributeddb/test/moduletest/src/distributeddb_nb_cursor_testcase.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/moduletest/src/distributeddb_nb_cursor_testcase.cpp @@ -966,7 +966,8 @@ void DistributeddbNbCursorTestcase::ResultSetDb013(KvStoreNbDelegate *delegate, std::vector entries; EntrySize entrySize = {KEY_SIX_BYTE, VALUE_HUNDRED_K_BYTE}; GenerateAppointPrefixAndSizeRecords(entries, entrySize, ONE_HUNDRED_RECORDS); - Entry entry4M, entry2M; + Entry entry4M; + Entry entry2M; entry4M.key.assign(KEY_SIX_BYTE, 'k'); entry4M.value.assign(FOUR_M_LONG_STRING, 'v'); entry2M.key.assign(KEY_THIRTYTWO_BYTE, 'k'); @@ -1256,8 +1257,10 @@ void DistributeddbNbCursorTestcase::ResultSetDb018(KvStoreNbDelegate *delegate, { ASSERT_TRUE(delegate != nullptr); SetResultSetCacheMode(delegate, isRowIdMode); - vector entriesKA, entriesKB; - vector allKeysKA, allKeysKB; + vector entriesKA; + vector entriesKB; + vector allKeysKA; + vector allKeysKB; std::vector ka = { 'k', 'a' }; std::vector kb = { 'k', 'b' }; GenerateRecords(ONE_HUNDRED_RECORDS, DEFAULT_START, allKeysKA, entriesKA, ka); @@ -2033,7 +2036,8 @@ void DistributeddbNbCursorTestcase::ResultSetDb027(bool isRowIdMode) ASSERT_TRUE(managers[INDEX_ZEROTH] != nullptr && delegates[INDEX_ZEROTH] != nullptr); SetResultSetCacheMode(delegates[INDEX_ZEROTH], isRowIdMode); - vector entriesKA, entriesKB; + vector entriesKA; + vector entriesKB; std::vector ka = { 'k', 'a' }; std::vector kb = { 'k', 'b' }; EntrySize entrySizeKA = { FIVE_BYTE_KEY, ONE_K_LONG_STRING }; diff --git a/kv_store/frameworks/libs/distributeddb/test/moduletest/src/distributeddb_nb_observer_test.cpp b/kv_store/frameworks/libs/distributeddb/test/moduletest/src/distributeddb_nb_observer_test.cpp index 2048716912052b0cb80583af46fb06e115a0e87c..17a8ca19692d1f2a04e0ceb12338eb1a4c003eb4 100644 --- a/kv_store/frameworks/libs/distributeddb/test/moduletest/src/distributeddb_nb_observer_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/moduletest/src/distributeddb_nb_observer_test.cpp @@ -1259,14 +1259,14 @@ HWTEST_F(DistributeddbNbObserverTest, Pressure007, TestSize.Level1) if (opCnt == NB_OPERATION_CNT_START) { EXPECT_EQ(status, OK); } else { - EXPECT_EQ(status, ALREADY_SET); + EXPECT_EQ(status, DB_ERROR); } status = g_nbObserverDelegate->RegisterObserver(KEY_1, OBSERVER_CHANGES_NATIVE | OBSERVER_CHANGES_FOREIGN, &observerSync); if (opCnt == NB_OPERATION_CNT_START) { EXPECT_EQ(status, OK); } else { - EXPECT_EQ(status, ALREADY_SET); + EXPECT_EQ(status, DB_ERROR); } } @@ -1346,7 +1346,7 @@ HWTEST_F(DistributeddbNbObserverTest, Pressure008, TestSize.Level1) if (opCnt == NB_OPERATION_CNT_START) { EXPECT_EQ(status, OK); } else { - EXPECT_EQ(status, ALREADY_SET); + EXPECT_EQ(status, DB_ERROR); } } @@ -1435,7 +1435,7 @@ HWTEST_F(DistributeddbNbObserverTest, Pressure009, TestSize.Level1) if (opCnt == NB_OPERATION_CNT_START) { EXPECT_EQ(status, OK); } else { - EXPECT_EQ(status, ALREADY_SET); + EXPECT_EQ(status, DB_ERROR); } } @@ -2040,8 +2040,10 @@ void CheckPressureLongCompare(vector &entriesBatch, ConcurParam *threadPa void CheckPressureLongConcurrency(vector &entriesBatch) { - std::random_device randDevAnyKeyNo, randDevTag; - std::mt19937 genRandAnyKeyNo(randDevAnyKeyNo()), genRandTag(randDevTag()); + std::random_device randDevAnyKeyNo; + std::random_device randDevTag; + std::mt19937 genRandAnyKeyNo(randDevAnyKeyNo()); + std::mt19937 genRandTag(randDevTag()); std::uniform_int_distribution disRandAnyKeyNo(ANY_RECORDS_NUM_START, ANY_RECORDS_NUM_END); std::uniform_int_distribution disRandTag(static_cast(ReadOrWriteTag::READ), static_cast(ReadOrWriteTag::REGISTER)); @@ -2049,7 +2051,8 @@ void CheckPressureLongConcurrency(vector &entriesBatch) unsigned int threadCurId = 0; int randFlag; - std::chrono::time_point start, end; + std::chrono::time_point start; + std::chrono::time_point end; std::chrono::duration dur; double operInterval = 0.0; diff --git a/kv_store/frameworks/libs/distributeddb/test/moduletest/src/distributeddb_nb_predicate_query_test.cpp b/kv_store/frameworks/libs/distributeddb/test/moduletest/src/distributeddb_nb_predicate_query_test.cpp index e1e45929f45dadac4d0f210ab1355382d6939c62..496198bc1dc150fe8d100a49fcc638df8833f529 100644 --- a/kv_store/frameworks/libs/distributeddb/test/moduletest/src/distributeddb_nb_predicate_query_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/moduletest/src/distributeddb_nb_predicate_query_test.cpp @@ -202,19 +202,20 @@ bool CheckSchemaNotExist(KvStoreNbDelegate *&delegate) { bool result = true; vector entries; - bool valueBool = true; // boolean true int valueInt = 10; // int value 10 int64_t valueLong = 15; // long value 15 double valueDouble = 10.5; // double value 10.5 string fieldStr = "$.field1"; - vector queries1, queries2, queries3; + vector queries1; + vector queries2; + vector queries3; bool functionChoiceComp1[INTERFACE_QTY_6] = {true, false, false, false, false, false}; - QueryGenerate::Instance().GenerateQueryComp(queries1, functionChoiceComp1, fieldStr, valueBool); + QueryGenerate::Instance().GenerateQueryComp(queries1, functionChoiceComp1, fieldStr, true); bool functionChoiceComp2[INTERFACE_QTY_6] = {false, true, false, false, false, false}; - QueryGenerate::Instance().GenerateQueryComp(queries2, functionChoiceComp2, fieldStr, valueBool); + QueryGenerate::Instance().GenerateQueryComp(queries2, functionChoiceComp2, fieldStr, true); bool functionChoiceComp3[INTERFACE_QTY_6] = {false, false, true, true, true, true}; - QueryGenerate::Instance().GenerateQueryComp(queries3, functionChoiceComp3, fieldStr, valueBool); + QueryGenerate::Instance().GenerateQueryComp(queries3, functionChoiceComp3, fieldStr, true); bool functionChoiceComp4[INTERFACE_QTY_6] = {true, false, false, false, true, true}; QueryGenerate::Instance().GenerateQueryComp(queries1, functionChoiceComp4, fieldStr, valueInt); @@ -433,13 +434,14 @@ bool CheckSchemaBoolNotExist(KvStoreNbDelegate *&delegate, vector &entrie double valueDouble = 10.5; // double value 10.5 float valueFloat = 5.0; // float value 5.0 - vector queries1, queries2; + vector queries1; queries1.push_back(Query::Select().EqualTo("$.field1", valueStringTrue)); queries1.push_back(Query::Select().EqualTo("$.field1", valueString)); queries1.push_back(Query::Select().EqualTo("$.field1", valueLong)); queries1.push_back(Query::Select().EqualTo("$.field1", valueDouble)); queries1.push_back(Query::Select().EqualTo("$.field1", valueFloat)); + vector queries2; queries2.push_back(Query::Select().NotEqualTo("$.field1", valueStringTrue)); queries2.push_back(Query::Select().NotEqualTo("$.field1", valueString)); queries2.push_back(Query::Select().NotEqualTo("$.field1", valueLong)); @@ -658,13 +660,13 @@ bool CheckSchemaExceptionValue(KvStoreNbDelegate *&delegate, vector &entr string valueStringTen = "10"; // string 10 string valueString = "abc"; float valueFloat = 10.0; // float 10.0 - bool valueBool = false; // boolean false - vector queries1, queries2, queries3; + vector queries1; queries1.push_back(Query::Select().EqualTo("$.field1", valueString)); - queries1.push_back(Query::Select().EqualTo("$.field1", valueBool)); + queries1.push_back(Query::Select().EqualTo("$.field1", false)); + vector queries2; queries2.push_back(Query::Select().NotEqualTo("$.field1", valueString)); - queries2.push_back(Query::Select().NotEqualTo("$.field1", valueBool)); + queries2.push_back(Query::Select().NotEqualTo("$.field1", false)); vector valuesString = {"abc"}; vector valuesBool = {false}; @@ -678,12 +680,13 @@ bool CheckSchemaExceptionValue(KvStoreNbDelegate *&delegate, vector &entr queries2.push_back(Query::Select().NotIn("$.field1", valuesDouble)); queries1.push_back(Query::Select().GreaterThan("$.field1", valueString)); - queries3.push_back(Query::Select().GreaterThan("$.field1", valueBool)); + vector queries3; + queries3.push_back(Query::Select().GreaterThan("$.field1", false)); queries2.push_back(Query::Select().GreaterThanOrEqualTo("$.field1", valueStringTen)); queries2.push_back(Query::Select().GreaterThanOrEqualTo("$.field1", valueFloat)); queries1.push_back(Query::Select().GreaterThanOrEqualTo("$.field1", valueString)); - queries3.push_back(Query::Select().GreaterThanOrEqualTo("$.field1", valueBool)); + queries3.push_back(Query::Select().GreaterThanOrEqualTo("$.field1", false)); vector expectEntry3 = {}; Query query = Query::Select().LessThan("$.field1", valueStringTen); @@ -692,17 +695,17 @@ bool CheckSchemaExceptionValue(KvStoreNbDelegate *&delegate, vector &entr result = CheckSchemaQuery(delegate, query, expectEntry3, 0, DBStatus::NOT_FOUND) && result; queries2.push_back(Query::Select().LessThan("$.field1", valueString)); - queries3.push_back(Query::Select().LessThan("$.field1", valueBool)); + queries3.push_back(Query::Select().LessThan("$.field1", false)); queries2.push_back(Query::Select().LessThanOrEqualTo("$.field1", valueString)); - queries3.push_back(Query::Select().LessThanOrEqualTo("$.field1", valueBool)); + queries3.push_back(Query::Select().LessThanOrEqualTo("$.field1", false)); vector entries1; for (auto const &it : queries1) { result = (delegate->GetEntries(it, entries1) == NOT_FOUND) && result; } - vector expectEntry2 = - {entries[INDEX_ZEROTH], entries[INDEX_SECOND], entries[INDEX_THIRD], entries[INDEX_FORTH]}; + vector expectEntry2 = { entries[INDEX_ZEROTH], entries[INDEX_SECOND], entries[INDEX_THIRD], + entries[INDEX_FORTH] }; for (auto &it : queries2) { result = CheckSchemaQuery(delegate, it, expectEntry2, SCHEMA_GOT_COUNT_4, DBStatus::OK) && result; } @@ -1060,10 +1063,11 @@ bool CheckSchemaDoubleExceptionValue(KvStoreNbDelegate *&delegate, vector bool result = true; string valueString = "abc"; int64_t valueLong = 15; // long value 15 - vector queries1, queries2; + vector queries1; queries1.push_back(Query::Select().EqualTo("$.field1", valueString)); queries1.push_back(Query::Select().EqualTo("$.field1", valueLong)); + vector queries2; queries2.push_back(Query::Select().NotEqualTo("$.field1", valueString)); queries2.push_back(Query::Select().NotEqualTo("$.field1", valueLong)); diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_common_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_common_test.cpp index 802bd8d66834499308ceedac2bb031a8dd3da49e..7bf98eb51b869846942b250012f6af4545bf1b2a 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_common_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_common_test.cpp @@ -593,7 +593,7 @@ HWTEST_F(DistributedDBCommonTest, PerformanceAnalysisTest002, TestSize.Level1) /** * @tc.steps: step2. Call interfaces with the para is greater than stepNum. - * @tc.expected: step2. success; + * @tc.expected: step2. success. */ performance->StepTimeRecordStart(RECORD_ACK_RECV_TO_USER_CALL_BACK); performance->StepTimeRecordEnd(RECORD_ACK_RECV_TO_USER_CALL_BACK); @@ -692,7 +692,7 @@ HWTEST_F(DistributedDBCommonTest, TimeTickMonitorTest, TestSize.Level1) /** * @tc.steps: step3. Call RegisterTimeChangedLister after Stop TimeTickMonitor. - * @tc.expected: step3. success; + * @tc.expected: step3. success. */ EXPECT_EQ(monitor.StartTimeTickMonitor(), E_OK); monitor.StopTimeTickMonitor(); @@ -714,7 +714,7 @@ HWTEST_F(DistributedDBCommonTest, LockStatusObserverTest, TestSize.Level1) { /** * @tc.steps: step1. Call RegisterLockStatusChangedLister with null para. - * @tc.expected: step1. -E_INVALID_ARGS. + * @tc.expected: step1. return -E_INVALID_ARGS. */ LockStatusObserver observer; EXPECT_EQ(observer.Start(), E_OK); @@ -727,7 +727,7 @@ HWTEST_F(DistributedDBCommonTest, LockStatusObserverTest, TestSize.Level1) /** * @tc.steps: step2. Call RegisterLockStatusChangedLister after stop observer. - * @tc.expected: step2. -E_NOT_INIT. + * @tc.expected: step2. return -E_NOT_INIT. */ EXPECT_EQ(observer.Start(), E_OK); observer.Stop(); diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_parcel_unit_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_parcel_unit_test.cpp index 43b8cc5937114fbb806b7ea830700210daddefb6..d3c1b8cede626867a4aab3f3e73786930501b470 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_parcel_unit_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_parcel_unit_test.cpp @@ -694,7 +694,7 @@ HWTEST_F(DistributedDBParcelTest, WriteBoolTest, TestSize.Level1) bool writeData = true; uint32_t len = Parcel::GetBoolLen(); len = Parcel::GetEightByteAlign(len); - uint8_t *buf = new(nothrow) uint8_t[len]; + uint8_t *buf = new (nothrow) uint8_t[len]; ASSERT_NE(buf, nullptr); Parcel writeParcel(buf, len); @@ -745,7 +745,7 @@ HWTEST_F(DistributedDBParcelTest, ParcelErrTest, TestSize.Level1) EXPECT_EQ(parcel.ReadBlob(nullptr, 0), expectedVal); /** - * @tc.steps:step3. WriteDouble when Parcel para is null; + * @tc.steps: step3. WriteDouble when Parcel para is null; * @tc.expected: step3. return -E_PARSE_FAIL; */ ret = parcel.WriteBlob("", 1); diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_relational_schema_object_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_relational_schema_object_test.cpp index 6ebac3f096600219e7016a5ff9dc73a914c74844..edb68a09b799e0e93a248098136f1be2da0f5ec0 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_relational_schema_object_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_relational_schema_object_test.cpp @@ -868,7 +868,7 @@ HWTEST_F(DistributedDBRelationalSchemaObjectTest, FieldInfoCompareTest, TestSize /** * @tc.name: TableInfoInterfacesTest - * @tc.desc: Test TableInfo interfaces + * @tc.desc: Test TableInfo Interfaces * @tc.type: FUNC * @tc.require: * @tc.author: suyue diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_tools_unit_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_tools_unit_test.cpp index 31df882bf6c9776f89cdd34878af642fb412dd08..5f7668e3fa186dcc5a9d0ec107b7e4d02049fb68 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_tools_unit_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_tools_unit_test.cpp @@ -990,7 +990,7 @@ DBStatus DistributedDBToolsUnitTest::SyncTest(KvStoreNbDelegate* delegate, return callStatus; } -static bool CheckSyncCondVarWaitResult(DBStatus status, std::map &syncProcessMap) +static bool WaitUntilReady(DBStatus status, const std::map &syncProcessMap) { if (status != OK) { return true; @@ -998,10 +998,11 @@ static bool CheckSyncCondVarWaitResult(DBStatus status, std::map &processMap) { syncProcessMap = processMap; - std::unique_lock innerLock(this->syncLock_); + std::unique_lock innerlock(this->syncLock_); this->syncCondVar_.notify_one(); }; DBStatus status = delegate->Sync(option, onProcess); @@ -1021,7 +1022,7 @@ DBStatus DistributedDBToolsUnitTest::SyncTest(KvStoreNbDelegate *delegate, Devic if (!option.isWait) { std::unique_lock lock(this->syncLock_); this->syncCondVar_.wait(lock, [status, &syncProcessMap]() { - return CheckSyncCondVarWaitResult(status, syncProcessMap); + return WaitUntilReady(status, syncProcessMap); }); } return status; diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_tools_unit_test.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_tools_unit_test.h index cc2f3bd8b5d2887bbea38d60d70f4fb05ab57666..ccc1cf1e1a09f80770e239c9a49d84d85cdea076 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_tools_unit_test.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_tools_unit_test.h @@ -158,10 +158,10 @@ public: const std::vector& devices, DistributedDB::SyncMode mode, std::map& statuses, const DistributedDB::Query &query); - DistributedDB::DBStatus SyncTest(DistributedDB::KvStoreNbDelegate *delegate, + DistributedDB::DBStatus SyncTest(DistributedDB::KvStoreNbDelegate* delegate, DistributedDB::DeviceSyncOption option, std::map &syncProcessMap); - + static void GetRandomKeyValue(std::vector &value, uint32_t defaultSize = 0); static bool IsValueEqual(const DistributedDB::Value &read, const DistributedDB::Value &origin); diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/communicator/distributeddb_communicator_deep_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/communicator/distributeddb_communicator_deep_test.cpp index 03d0a988d0bd41c49503263292d9d9472dd530b1..484e8d8904701550d9e9ee141add3ee8129c9dbc 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/communicator/distributeddb_communicator_deep_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/communicator/distributeddb_communicator_deep_test.cpp @@ -919,7 +919,7 @@ HWTEST_F(DistributedDBCommunicatorDeepTest, NetworkAdapter006, TestSize.Level1) return false; }); auto data = std::make_shared(1); - EXPECT_EQ(adapter->SendBytes("", data.get(), 1, 0), -E_PERIPHERAL_INTERFACE_FAIL); + EXPECT_EQ(adapter->SendBytes("", data.get(), 1, 0), static_cast(DB_ERROR)); RuntimeContext::GetInstance()->StopTaskPool(); EXPECT_EQ(adapter->IsDeviceOnline(""), false); ExtendInfo info; diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_relational_ext_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_relational_ext_test.cpp index dbdc9612a615f6a4894f99693fd761a2e465ea31..d2ed594389d55c390419d8e12c83253045cfe747 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_relational_ext_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_relational_ext_test.cpp @@ -1743,7 +1743,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, AbnormalDelegateImplTest EXPECT_EQ(status, OK); ASSERT_NE(delegate, nullptr); - /** + /** * @tc.steps: step2. close delegate. * @tc.expected: step2. return ok. */ @@ -1808,7 +1808,6 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, AbnormalDelegateImplTest auto delegateImpl = static_cast(delegate); const CloudSyncConfig config; EXPECT_EQ(delegateImpl->SetCloudSyncConfig(config), OK); - DistributedDB::SqlCondition sqlCondition; std::vector records = {}; EXPECT_EQ(delegateImpl->ExecuteSql(sqlCondition, records), INVALID_ARGS); diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_relational_remove_device_data_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_relational_remove_device_data_test.cpp index 4ec5e21d144cbc8389a1b10f31d2885599acb03e..6b4c0cd541ac7ce53372967ef5de17e256259a9a 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_relational_remove_device_data_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_relational_remove_device_data_test.cpp @@ -345,7 +345,7 @@ namespace { { int i = 0; for (const auto &tableName: tableList) { - std::string sql = "select count() from " + DBCommon::GetLogTableName(tableName) + + std::string sql = "select count(*) from " + DBCommon::GetLogTableName(tableName) + " where flag & 0x10 != 0;"; EXPECT_EQ(sqlite3_exec(db, sql.c_str(), QueryCountCallback, reinterpret_cast(countList[i]), nullptr), SQLITE_OK); @@ -388,7 +388,7 @@ namespace { EXPECT_EQ(sqlite3_exec(db, sql2.c_str(), QueryCountCallback, reinterpret_cast(count), nullptr), SQLITE_OK); std::string sql3 = "select count(*) from " + DBCommon::GetLogTableName(tableName) + - " where (flag & 0x02 = 0 or flag & 0x20 = 0);"; + " where (flag & 0x2 = 0 or flag & 0x20 = 0);"; EXPECT_EQ(sqlite3_exec(db, sql3.c_str(), QueryCountCallback, reinterpret_cast(count), nullptr), SQLITE_OK); } @@ -398,8 +398,8 @@ namespace { { int i = 0; for (const auto &tableName: tableList) { - std::string sql = "select count(*) from " + tableName; - EXPECT_EQ(sqlite3_exec(db, sql.c_str(), QueryCountCallback, + std::string local_sql = "select count(*) from " + tableName + ";"; + EXPECT_EQ(sqlite3_exec(db, local_sql.c_str(), QueryCountCallback, reinterpret_cast(countList[i]), nullptr), SQLITE_OK); i++; } @@ -419,7 +419,7 @@ namespace { EXPECT_EQ(sqlite3_exec(db, sql2.c_str(), QueryCountCallback, reinterpret_cast(count), nullptr), SQLITE_OK); std::string sql3 = "select count(*) from " + DBCommon::GetLogTableName(tableName) + - " where (flag & 0x02 = 0 or flag & 0x20 = 0);"; + " where (flag & 0x2 = 0 or flag & 0x20 = 0);"; EXPECT_EQ(sqlite3_exec(db, sql3.c_str(), QueryCountCallback, reinterpret_cast(count), nullptr), SQLITE_OK); std::string local_sql = "select count(*) from " + tableName +";"; @@ -551,6 +551,7 @@ namespace { g_delegate->UnRegisterObserver(g_observer); } delete g_observer; + g_observer = nullptr; g_virtualCloudDb = nullptr; if (g_delegate != nullptr) { EXPECT_EQ(g_mgr.CloseStore(g_delegate), DBStatus::OK); @@ -1256,7 +1257,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.type: FUNC * @tc.require: * @tc.author: wangxiangdong -**/ + */ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest014, TestSize.Level0) { /** @@ -1294,7 +1295,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.type: FUNC * @tc.require: * @tc.author: wangxiangdong -**/ + */ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest015, TestSize.Level0) { /** @@ -1351,12 +1352,12 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD */ int upIdx = 0; g_virtualCloudDb->ForkUpload([&upIdx](const std::string &tableName, VBucket &extend) { - LOGD("cloud db upload index:%d", ++upIdx); - if (upIdx == 2) { // 2 is index - extend[CloudDbConstant::ERROR_FIELD] = static_cast(DBStatus::CLOUD_RECORD_ALREADY_EXISTED); - } + LOGD("cloud db upload index:%d", ++upIdx); + if (upIdx == 2) { // 2 is index + extend[CloudDbConstant::ERROR_FIELD] = static_cast(DBStatus::CLOUD_RECORD_ALREADY_EXISTED); + } }); - /* + /** * @tc.steps: step4. call Sync with cloud merge strategy, and check flag before and after. */ CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate); @@ -1397,7 +1398,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.steps: step3. call Sync with cloud merge strategy, and check flag before and after. */ CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate); - /* + /** * @tc.steps: step4. make logic delete and local delete then call Sync. */ DeleteCloudTableRecordByGid(0, 5); @@ -1439,8 +1440,8 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD */ CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate); - /* - * @tc.steps: step4.remove device data. + /** + * @tc.steps: step4. remove device data. * @tc.expected: OK. */ std::string device; @@ -1449,7 +1450,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.steps: step5.call Sync then check cursor. */ CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate); - std::string sql = "select count() from " + DBCommon::GetLogTableName(g_tables[0]) + + std::string sql = "select count(*) from " + DBCommon::GetLogTableName(g_tables[0]) + " where cursor='40';"; EXPECT_EQ(sqlite3_exec(db, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback, reinterpret_cast(1), nullptr), SQLITE_OK); @@ -1475,14 +1476,13 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.steps: step2. call Sync with cloud merge strategy, and check flag before and after. */ CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate); - - /* + /** * @tc.steps: step3.make logic delete and local delete then call Sync. * @tc.expected: OK. */ DeleteCloudTableRecordByGid(0, 5); CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate); - std::string sql = "select count() from " + DBCommon::GetLogTableName(g_tables[0]) + + std::string sql = "select count(*) from " + DBCommon::GetLogTableName(g_tables[0]) + " where cursor='20';"; EXPECT_EQ(sqlite3_exec(db, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback, reinterpret_cast(1), nullptr), SQLITE_OK); @@ -1514,7 +1514,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.steps: step3. call Sync with cloud merge strategy, and check flag before and after. */ CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate); - /* + /** * @tc.steps: step4. make logic delete and local delete then call Sync. */ DeleteCloudTableRecordByGid(0, 5); @@ -1539,7 +1539,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD /* * @tc.name: CleanCloudDataTest021 - * @tc.desc: Test conflict, not dound, exis errCode will deal. + * @tc.desc: Test conflict, not found, exist errCode of cloudSpace will deal. * @tc.type: FUNC * @tc.require: * @tc.author: wangxiangdong @@ -1571,20 +1571,20 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD extend[CloudDbConstant::ERROR_FIELD] = static_cast(DBStatus::CLOUD_RECORD_EXIST_CONFLICT); } if (upIdx == 4) { - // CLOUD_RECORD_NOT_FOUND means cloud and terminal is consitenct + // CLOUD_RECORD_NOT_FOUND means cloud and terminal is consistency extend[CloudDbConstant::ERROR_FIELD] = static_cast(DBStatus::CLOUD_RECORD_NOT_FOUND); } if (upIdx == 5) { - // CLOUD_RECORD_NOT_FOUND means no error + // std::string("x") means no error extend[CloudDbConstant::ERROR_FIELD] = std::string("x"); } }); - /* - * @tc.steps: step4. call Sync, and check consitency. + /** + * @tc.steps: step4. call Sync, and check consistency. */ CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate); g_virtualCloudDb->ForkUpload(nullptr); - std::string sql = "select count() from " + DBCommon::GetLogTableName(g_tables[0]) + + std::string sql = "select count(*) from " + DBCommon::GetLogTableName(g_tables[0]) + " where flag & 0x20 = 0;"; EXPECT_EQ(sqlite3_exec(db, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback, reinterpret_cast(18), nullptr), SQLITE_OK); @@ -1610,7 +1610,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.steps: step2. call Sync with cloud merge strategy, and check flag before and after. */ CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate); - /* + /** * @tc.steps: step3. make local delete then call Sync. */ DeleteUserTableRecord(db, 0, 5); @@ -1620,11 +1620,11 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD */ std::string device; ASSERT_EQ(g_delegate->RemoveDeviceData(device, DistributedDB::FLAG_AND_DATA), DBStatus::OK); - std::string sql = "select count() from " + DBCommon::GetLogTableName(g_tables[0]) + + std::string sql = "select count(*) from " + DBCommon::GetLogTableName(g_tables[0]) + " where flag & 0x800 == 0;"; EXPECT_EQ(sqlite3_exec(db, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback, reinterpret_cast(5), nullptr), SQLITE_OK); - sql = "select count() from " + DBCommon::GetLogTableName(g_tables[0]) + + sql = "select count(*) from " + DBCommon::GetLogTableName(g_tables[0]) + " where flag & 0x800 != 0;"; EXPECT_EQ(sqlite3_exec(db, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback, reinterpret_cast(0), nullptr), SQLITE_OK); @@ -1656,15 +1656,15 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD * @tc.steps: step3. call Sync with cloud merge strategy. */ CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate); - /* - * @tc.steps: step4. make local delete then call Sync. + /** + * @tc.steps: step4. make local delete and cloud delete then call Sync. */ DeleteUserTableRecord(db, 0, 5); DeleteCloudTableRecordByGid(5, 10); CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate); /** - * @tc.steps: step5.remove device data and check cursor, cloud_gid, version sharing_resource.. + * @tc.steps: step5. remove device data and check cursor, cloud_gid, version sharing_resource. * @tc.expected: OK. */ DeleteUserTableRecord(db, 10, 15); @@ -1709,7 +1709,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD /* * @tc.name: CleanCloudDataTest024 - * @tc.desc: Test logic deleted data and log will deleted after DropLogicDeleteData. + * @tc.desc: Test logic deleted data and log will deleted after DropLogicDeletedData. * @tc.type: FUNC * @tc.require: * @tc.author: wangxiangdong @@ -1729,32 +1729,32 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD int localCount = 20; InsertUserTableRecord(db, 0, localCount, paddingSize, false); /** - * @tc.steps: step3. call Sync, and check flag before and after . + * @tc.steps: step3. call Sync with cloud merge strategy, and check flag before and after. */ CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate); - /* + /** * @tc.steps: step4.make local logic delete then call Sync. */ DeleteCloudTableRecordByGid(0, 5); DeleteUserTableRecord(db, 5, 10); CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate); - /* - * @tc.steps: step5.after remove device data and check log num. - * @tc.expectd: OK. + /** + * @tc.steps: step5. before remove device data and check log num. + * @tc.expected: OK. */ std::string device; ASSERT_EQ(g_delegate->RemoveDeviceData(device, DistributedDB::FLAG_AND_DATA), DBStatus::OK); - std::string sql = "select count() from " + DBCommon::GetLogTableName(g_tables[0]) + - " where flag & 0x08 = 0x08;"; + std::string sql = "select count(*) from " + DBCommon::GetLogTableName(g_tables[0]) + + " where flag & 0x08 == 0x08;"; EXPECT_EQ(sqlite3_exec(db, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback, reinterpret_cast(15), nullptr), SQLITE_OK); - /* - * @tc.steps: step6.DropLogicDeletedData and check log num. - * @tc.expectd: OK. + /** + * @tc.steps: step6. DropLogicDeletedData and check log num. + * @tc.expected: OK. */ EXPECT_EQ(DropLogicDeletedData(db, g_tables[0], 0u), OK); - sql = "select count() from " + DBCommon::GetLogTableName(g_tables[0]) + - " where flag & 0x08 = 0x08;"; + sql = "select count(*) from " + DBCommon::GetLogTableName(g_tables[0]) + + " where flag & 0x08 == 0x08;"; EXPECT_EQ(sqlite3_exec(db, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback, reinterpret_cast(0), nullptr), SQLITE_OK); CloseDb(); @@ -1784,18 +1784,18 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD InsertUserTableRecord(db, 0, localCount, paddingSize, false); CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate); - /* + /** * @tc.steps: step3. logic delete record 1 and 2 from cloud, then sync */ DeleteCloudTableRecordByGid(0, 2); CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate); - /* + /** * @tc.steps: step4. clear logically deleted data */ DropLogicDeletedData(db, g_tables[0], 0); - /* + /** * @tc.steps: step5. logic delete record 3 from cloud, then sync */ DeleteCloudTableRecordByGid(3, 1); @@ -1811,5 +1811,80 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD CloseDb(); } + +/* + * @tc.name: CleanCloudDataTest026 + * @tc.desc: Test logic deleted data and flag_only. + * @tc.type: FUNC + * @tc.require: + * @tc.author: wangxiangdong + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest026, TestSize.Level0) +{ + /** + * @tc.steps: step1. Set data is logicDelete + * @tc.expected: OK. + */ + bool logicDelete = true; + auto data = static_cast(&logicDelete); + g_delegate->Pragma(LOGIC_DELETE_SYNC_DATA, data); + /** + * @tc.steps: step2. make data: 20 records on cloud + * @tc.expected: OK. + */ + int64_t paddingSize = 20; + int cloudCount = 20; + InsertCloudTableRecord(0, cloudCount, paddingSize, false); + /** + * @tc.steps: step3. call Sync with cloud merge strategy. + * @tc.expected: OK. + */ + CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate); + /** + * @tc.steps: step4. after remove device data and check log num. + * @tc.expected: OK. + */ + std::string device; + ASSERT_EQ(g_delegate->RemoveDeviceData(device, DistributedDB::FLAG_ONLY), DBStatus::OK); + std::string sql = "select count(*) from " + DBCommon::GetLogTableName(g_tables[0]) + + " where flag & 0x02 == 0x02;"; + EXPECT_EQ(sqlite3_exec(db, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback, + reinterpret_cast(0), nullptr), SQLITE_OK); + CloseDb(); +} + +/* + * @tc.name: CleanCloudDataTest027 + * @tc.desc: Test flag_only not logic delete. + * @tc.type: FUNC + * @tc.require: + * @tc.author: wangxiangdong + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest027, TestSize.Level0) +{ + /** + * @tc.steps: step1. make data: 20 records on cloud + * @tc.expected: OK. + */ + int64_t paddingSize = 20; + int cloudCount = 20; + InsertCloudTableRecord(0, cloudCount, paddingSize, false); + /** + * @tc.steps: step2. call Sync with cloud merge strategy. + * @tc.expected: OK. + */ + CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate); + /** + * @tc.steps: step3. after remove device data and check log num. + * @tc.expected: OK. + */ + std::string device; + ASSERT_EQ(g_delegate->RemoveDeviceData(device, DistributedDB::FLAG_ONLY), DBStatus::OK); + std::string sql = "select count(*) from " + DBCommon::GetLogTableName(g_tables[0]) + + " where flag & 0x02 == 0x02;"; + EXPECT_EQ(sqlite3_exec(db, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback, + reinterpret_cast(cloudCount), nullptr), SQLITE_OK); + CloseDb(); +} } #endif // RELATIONAL_STORE \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_set_cloud_schema_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_set_cloud_schema_test.cpp index 39565217ec48a61bc86ff21455d70322ebbf0585..788c9cdf13e429de830e89a35dce1f2193ad1bee 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_set_cloud_schema_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_set_cloud_schema_test.cpp @@ -282,7 +282,7 @@ namespace { return "SELECT COUNT(*) FROM " + DBCommon::GetLogTableName(tableName); } - std::string QueryByCursorCountSql(const std::string &tableName, int cursor) + std::string QueryByCursorSql(const std::string &tableName, int cursor) { return "SELECT COUNT(*) FROM " + DBCommon::GetLogTableName(tableName) + " where cursor > " + std::to_string(cursor) + " and sharing_resource='' and cloud_gid=''"; @@ -1888,7 +1888,7 @@ namespace { /** * @tc.name: SharedTableSync014 - * @tc.desc: Test shared table logic delete + * @tc.desc: Test shared table logic delete. * @tc.type: FUNC * @tc.require: * @tc.author: wangxiangdong @@ -1896,7 +1896,7 @@ namespace { HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync014, TestSize.Level0) { /** - * @tc.steps:step1. Set data is logicDelete + * @tc.steps: step1. Set data is logicDelete * @tc.expected: step1. return OK */ bool logicDelete = true; @@ -1904,7 +1904,7 @@ namespace { g_delegate->Pragma(LOGIC_DELETE_SYNC_DATA, data); /** - * @tc.steps:step2. init cloud data and sync + * @tc.steps:step2. init cloud share data and sync * @tc.expected: step2. return OK */ InitCloudEnv(); @@ -1940,7 +1940,7 @@ namespace { /** * @tc.name: SharedTableSync015 - * @tc.desc: Test shared table logic delete + * @tc.desc: Test shared table remove logic delete. * @tc.type: FUNC * @tc.require: * @tc.author: wangxiangdong @@ -1948,7 +1948,7 @@ namespace { HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync015, TestSize.Level0) { /** - * @tc.steps:step1. Set data is logicDelete + * @tc.steps: step1. Set data is logicDelete * @tc.expected: step1. return OK */ bool logicDelete = true; @@ -1956,7 +1956,7 @@ namespace { g_delegate->Pragma(LOGIC_DELETE_SYNC_DATA, data); /** - * @tc.steps:step2. init cloud data and sync + * @tc.steps:step2. init cloud share data and sync * @tc.expected: step2. return OK */ InitCloudEnv(); @@ -1969,7 +1969,7 @@ namespace { forkInsertFunc_ = nullptr; /** - * @tc.steps:step3. delete cloud data + * @tc.steps:step3. delete cloud data and sync * @tc.expected: step3. return OK */ int beginGid = 0; @@ -1979,7 +1979,7 @@ namespace { BlockSync(query, g_delegate, DBStatus::OK); /** - * @tc.steps:step4. sync and check count + * @tc.steps:step4. check count * @tc.expected: step4. return OK */ std::string sql = QueryResourceCountSql(g_sharedTableName1); @@ -1990,8 +1990,8 @@ namespace { reinterpret_cast(cloudCount - delCount), nullptr), SQLITE_OK); /** - * @tc.steps:step6. drop logic data, check sharing_resource - * @tc.expected: step6. return OK + * @tc.steps:step5. remove device data and check count + * @tc.expected: step5. return OK */ g_delegate->RemoveDeviceData("", CLEAR_SHARED_TABLE); sql = QueryResourceCountSql(g_sharedTableName1); @@ -2000,12 +2000,12 @@ namespace { sql = QueryAllCountSql(g_sharedTableName1); EXPECT_EQ(sqlite3_exec(db_, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback, reinterpret_cast(cloudCount), nullptr), SQLITE_OK); - sql = QueryByCursorCountSql(g_sharedTableName1, 15); + sql = QueryByCursorSql(g_sharedTableName1, 15); EXPECT_EQ(sqlite3_exec(db_, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback, reinterpret_cast(cloudCount - delCount), nullptr), SQLITE_OK); /** - * @tc.steps:step6. drop logic data and check count + * @tc.steps:step6. drop logic delete data and check count. * @tc.expected: step6. return OK */ EXPECT_EQ(DropLogicDeletedData(db_, g_sharedTableName1, 0u), OK); @@ -2016,7 +2016,7 @@ namespace { /** * @tc.name: SharedTableSync016 - * @tc.desc: Test remove device data of shared table and notify + * @tc.desc: Test remove device data of shared table and notify. * @tc.type: FUNC * @tc.require: * @tc.author: wangxiangdong @@ -2024,7 +2024,7 @@ namespace { HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync016, TestSize.Level0) { /** - * @tc.steps:step1. Set data is logicDelete + * @tc.steps: step1. Set data is logicDelete * @tc.expected: step1. return OK */ bool logicDelete = true; @@ -2032,7 +2032,7 @@ namespace { g_delegate->Pragma(LOGIC_DELETE_SYNC_DATA, data); /** - * @tc.steps:step2. init cloud data and sync + * @tc.steps:step2. init cloud share data and sync * @tc.expected: step2. return OK */ InitCloudEnv(); @@ -2045,7 +2045,7 @@ namespace { forkInsertFunc_ = nullptr; /** - * @tc.steps:step3. delete cloud data + * @tc.steps:step3. delete cloud data and sync * @tc.expected: step3. return OK */ int beginGid = 0; @@ -2055,7 +2055,7 @@ namespace { BlockSync(query, g_delegate, DBStatus::OK); /** - * @tc.steps:step4. removeDeviceData and check notify + * @tc.steps:step4. remove device data and check notify * @tc.expected: step4. return OK */ g_delegate->RemoveDeviceData("", CLEAR_SHARED_TABLE); @@ -2070,7 +2070,7 @@ namespace { EXPECT_EQ(g_observer->IsAllChangedDataEq(), true); /** - * @tc.steps:step5. drop logic delete data and check count + * @tc.steps:step5. drop logic delete data and check count. * @tc.expected: step5. return OK */ EXPECT_EQ(DropLogicDeletedData(db_, g_sharedTableName1, 0u), OK); @@ -2146,7 +2146,7 @@ namespace { HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SetCloudDbSchemaTest018, TestSize.Level0) { /** - * @tc.steps:step1. use SetCloudDBSchema while conn is nullptr + * @tc.steps:step1. use SetCloudDbSchema while conn is nullptr * @tc.expected: step1. return DB_ERROR */ DataBaseSchema dataBaseSchema; @@ -2158,7 +2158,7 @@ namespace { dataBaseSchema.tables.push_back(tableSchema); auto relationalStoreImpl = static_cast(g_delegate); EXPECT_EQ(relationalStoreImpl->Close(), OK); - EXPECT_EQ(g_delegate->SetCloudDbSchema(dataBaseSchema), DBStatus::DB_ERROR); + ASSERT_EQ(g_delegate->SetCloudDbSchema(dataBaseSchema), DBStatus::DB_ERROR); } /** diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_import_and_export_rd_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_import_and_export_rd_test.cpp index 2bd696666c1e485f7a479e87595b900c92dd9660..65d6201f1962e8c80151d8d4a4e4256bd0830475 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_import_and_export_rd_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_import_and_export_rd_test.cpp @@ -1210,7 +1210,7 @@ HWTEST_F(DistributedDBInterfacesImportAndExportRdTest, abortHandle001, TestSize. threads.emplace_back(thread([&]() { g_kvNbDelegatePtr->CheckIntegrity(); })); - threads.emplace_back(&KvStoreNbDelegate::Import, g_kvNbDelegatePtr, singleExportFileName, passwd); + threads.emplace_back(&KvStoreNbDelegate::Import, g_kvNbDelegatePtr, singleExportFileName, passwd, false); threads.emplace_back(thread([&i]() { std::this_thread::sleep_for(std::chrono::milliseconds(i)); g_kvNbDelegatePtr->CheckIntegrity(); diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_import_and_export_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_import_and_export_test.cpp index 2332acf1781c98abb6bc650b97ce063c4b6f92f8..4bc4836b1f6b5454fb06e01b1bc561b02687cb9a 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_import_and_export_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_import_and_export_test.cpp @@ -1299,7 +1299,7 @@ HWTEST_F(DistributedDBInterfacesImportAndExportTest, abortHandle001, TestSize.Le threads.emplace_back(thread([&]() { g_kvNbDelegatePtr->CheckIntegrity(); })); - threads.emplace_back(&KvStoreNbDelegate::Import, g_kvNbDelegatePtr, singleExportFileName, passwd); + threads.emplace_back(&KvStoreNbDelegate::Import, g_kvNbDelegatePtr, singleExportFileName, passwd, false); threads.emplace_back(thread([&i]() { std::this_thread::sleep_for(std::chrono::milliseconds(i)); g_kvNbDelegatePtr->CheckIntegrity(); diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_extend_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_extend_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..36f91fa1e0e445b80eac20142d1129b671708eb6 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_extend_test.cpp @@ -0,0 +1,1161 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "db_common.h" +#include "db_constant.h" +#include "db_errno.h" +#include "distributeddb_data_generate_unit_test.h" +#include "distributeddb_tools_unit_test.h" +#include "log_print.h" +#include "platform_specific.h" +#include "process_system_api_adapter_impl.h" +#include "runtime_context.h" +#include "sqlite_single_ver_natural_store.h" +#include "storage_engine_manager.h" +#ifdef DB_DEBUG_ENV +#include "system_time.h" +#endif // DB_DEBUG_ENV +#include "kv_store_result_set_impl.h" +#include "kv_store_nb_delegate_impl.h" +#include "kv_virtual_device.h" +#include "virtual_communicator_aggregator.h" + +using namespace testing::ext; +using namespace DistributedDB; +using namespace DistributedDBUnitTest; +using namespace std; + +namespace { + // define some variables to init a KvStoreDelegateManager object. + KvStoreDelegateManager g_mgr(APP_ID, USER_ID); + string g_testDir; + KvStoreConfig g_config; + Key g_keyPrefix = {'A', 'B', 'C'}; + const int RESULT_SET_COUNT = 9; + const int RESULT_SET_INIT_POS = -1; + uint8_t g_testDict[RESULT_SET_COUNT] = {'1', '2', '3', '4', '5', '6', '7', '8', '9'}; + + // define the g_kvNbDelegateCallback, used to get some information when open a kv store. + DBStatus g_kvDelegateStatus = INVALID_ARGS; + KvStoreNbDelegate *g_kvNbDelegatePtr = nullptr; +#ifndef OMIT_MULTI_VER + KvStoreDelegate *g_kvDelegatePtr = nullptr; + + // the type of g_kvDelegateCallback is function + auto g_kvDelegateCallback = bind(&DistributedDBToolsUnitTest::KvStoreDelegateCallback, placeholders::_1, + placeholders::_2, std::ref(g_kvDelegateStatus), std::ref(g_kvDelegatePtr)); +#endif // OMIT_MULTI_VER + const int OBSERVER_SLEEP_TIME = 100; + const int BATCH_PRESET_SIZE_TEST = 10; + const int DIVIDE_BATCH_PRESET_SIZE = 5; + const int VALUE_OFFSET = 5; + + const int DEFAULT_KEY_VALUE_SIZE = 10; + + const int CON_PUT_THREAD_NUM = 4; + const int PER_THREAD_PUT_NUM = 100; + + const std::string DEVICE_B = "deviceB"; + VirtualCommunicatorAggregator* g_communicatorAggregator = nullptr; + KvVirtualDevice *g_deviceB = nullptr; + VirtualSingleVerSyncDBInterface *g_syncInterfaceB = nullptr; + + // the type of g_kvNbDelegateCallback is function + auto g_kvNbDelegateCallback = bind(&DistributedDBToolsUnitTest::KvStoreNbDelegateCallback, placeholders::_1, + placeholders::_2, std::ref(g_kvDelegateStatus), std::ref(g_kvNbDelegatePtr)); + + enum LockState { + UNLOCKED = 0, + LOCKED + }; + + void InitResultSet() + { + Key testKey; + Value testValue; + for (int i = 0; i < RESULT_SET_COUNT; i++) { + testKey.clear(); + testValue.clear(); + // set key + testKey = g_keyPrefix; + testKey.push_back(g_testDict[i]); + // set value + testValue.push_back(g_testDict[i]); + // insert entry + EXPECT_EQ(g_kvNbDelegatePtr->Put(testKey, testValue), OK); + } + } + + void InitVirtualDevice(const std::string &devId, KvVirtualDevice *&devices, + VirtualSingleVerSyncDBInterface *&syncInterface) + { + devices = new (std::nothrow) KvVirtualDevice(devId); + ASSERT_TRUE(devices != nullptr); + syncInterface = new (std::nothrow) VirtualSingleVerSyncDBInterface(); + ASSERT_TRUE(syncInterface != nullptr); + ASSERT_EQ(devices->Initialize(g_communicatorAggregator, syncInterface), E_OK); + } + +class DistributedDBInterfacesNBDelegateExtendTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void DistributedDBInterfacesNBDelegateExtendTest::SetUpTestCase(void) +{ + DistributedDBToolsUnitTest::TestDirInit(g_testDir); + g_config.dataDir = g_testDir; + g_mgr.SetKvStoreConfig(g_config); + if (DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir) != 0) { + LOGE("rm test db files error!"); + } + + g_communicatorAggregator = new (std::nothrow) VirtualCommunicatorAggregator(); + ASSERT_TRUE(g_communicatorAggregator != nullptr); + RuntimeContext::GetInstance()->SetCommunicatorAggregator(g_communicatorAggregator); +} + +void DistributedDBInterfacesNBDelegateExtendTest::TearDownTestCase(void) +{ + RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(nullptr); + + RuntimeContext::GetInstance()->SetCommunicatorAggregator(nullptr); +} + +void DistributedDBInterfacesNBDelegateExtendTest::SetUp(void) +{ + DistributedDBToolsUnitTest::PrintTestCaseInfo(); + g_kvDelegateStatus = INVALID_ARGS; + g_kvNbDelegatePtr = nullptr; +#ifndef OMIT_MULTI_VER + g_kvDelegatePtr = nullptr; +#endif // OMIT_MULTI_VER +} + +void DistributedDBInterfacesNBDelegateExtendTest::TearDown(void) +{ + if (g_kvNbDelegatePtr != nullptr) { + g_mgr.CloseKvStore(g_kvNbDelegatePtr); + g_kvNbDelegatePtr = nullptr; + } + RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(nullptr); +} + +#ifdef DB_DEBUG_ENV +/** + * @tc.name: TimeChangeWithCloseStoreTest001 + * @tc.desc: Test close store with time changed + * @tc.type: FUNC + * @tc.require: + * @tc.author: lianhuix + */ +HWTEST_F(DistributedDBInterfacesNBDelegateExtendTest, TimeChangeWithCloseStoreTest001, TestSize.Level3) +{ + KvStoreDelegateManager mgr(APP_ID, USER_ID); + mgr.SetKvStoreConfig(g_config); + + std::atomic isFinished(false); + + std::vector slowThreads; + for (int i = 0; i < 10; i++) { // 10: thread to slow donw system + std::thread th([&isFinished]() { + while (!isFinished) { + // pass + } + }); + slowThreads.emplace_back(std::move(th)); + } + + std::thread th([&isFinished]() { + int timeChangedCnt = 0; + while (!isFinished.load()) { + OS::SetOffsetBySecond(100 - timeChangedCnt++ * 2); // 100 2 : fake system time change + std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 100: wait for a while + } + }); + + for (int i = 0; i < 100; i++) { // run 100 times + const KvStoreNbDelegate::Option option = {true, false, false}; + mgr.GetKvStore(STORE_ID_1, option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_EQ(g_kvDelegateStatus, OK); + EXPECT_EQ(mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + g_kvNbDelegatePtr = nullptr; + } + + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); // 1000: wait for a while + isFinished.store(true); + th.join(); + for (auto &it : slowThreads) { + it.join(); + } + EXPECT_EQ(mgr.DeleteKvStore(STORE_ID_1), OK); +} + +/** + * @tc.name: TimeChangeWithCloseStoreTest002 + * @tc.desc: Test close store with time changed + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBInterfacesNBDelegateExtendTest, TimeChangeWithCloseStoreTest002, TestSize.Level3) +{ + KvStoreDelegateManager mgr(APP_ID, USER_ID); + mgr.SetKvStoreConfig(g_config); + + const KvStoreNbDelegate::Option option = {true, false, false}; + mgr.GetKvStore(STORE_ID_1, option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_EQ(g_kvDelegateStatus, OK); + const int threadPoolMax = 10; + for (int i = 0; i < threadPoolMax; ++i) { + (void) RuntimeContext::GetInstance()->ScheduleTask([]() { + std::this_thread::sleep_for(std::chrono::seconds(10)); // sleep 10s for block thread pool + }); + } + OS::SetOffsetBySecond(100); // 100 2 : fake system time change + std::this_thread::sleep_for(std::chrono::seconds(1)); // sleep 1s for time tick + + EXPECT_EQ(mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + g_kvNbDelegatePtr = nullptr; + + EXPECT_EQ(mgr.DeleteKvStore(STORE_ID_1), OK); + RuntimeContext::GetInstance()->StopTaskPool(); // stop all async task +} + +/** + * @tc.name: TimeChangeWithCloseStoreTest003 + * @tc.desc: Test store close with timechange listener + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBInterfacesNBDelegateExtendTest, TimeChangeWithCloseStoreTest003, TestSize.Level3) +{ + /** + * @tc.steps:step1. Create database. + * @tc.expected: step1. Returns a non-null kvstore. + */ + KvStoreNbDelegate::Option option; + g_mgr.GetKvStore("TimeChangeWithCloseStoreTest003", option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + std::shared_ptr timeChange = std::make_shared(false); + int errCode = E_OK; + auto *listener = RuntimeContext::GetInstance()->RegisterTimeChangedLister([timeChange](void *) { + std::this_thread::sleep_for(std::chrono::seconds(10)); // block close store 10s + *timeChange = true; + }, nullptr, errCode); + /** + * @tc.steps:step2. Block time change 10s and trigger time change. + * @tc.expected: step2. close store cost time > 5s. + */ + ASSERT_EQ(errCode, E_OK); + OS::SetOffsetBySecond(100); // 100 : fake system time change + std::this_thread::sleep_for(std::chrono::seconds(1)); // wait 1s for time change + Timestamp beginTime; + (void)OS::GetCurrentSysTimeInMicrosecond(beginTime); + ASSERT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + Timestamp endTime; + (void)OS::GetCurrentSysTimeInMicrosecond(endTime); + if (*timeChange) { + EXPECT_GE(static_cast(endTime - beginTime), 5 * 1000 * 1000); // 5 * 1000 * 1000 = 5s + } + listener->Drop(true); + OS::SetOffsetBySecond(-100); // -100 : fake system time change + g_kvNbDelegatePtr = nullptr; + EXPECT_EQ(g_mgr.DeleteKvStore("TimeChangeWithCloseStoreTest003"), OK); +} +#endif // DB_DEBUG_ENV + +/** + * @tc.name: ResultSetLimitTest001 + * @tc.desc: Get result set over limit + * @tc.type: FUNC + * @tc.require: + * @tc.author: lianhuix + */ +HWTEST_F(DistributedDBInterfacesNBDelegateExtendTest, ResultSetLimitTest001, TestSize.Level0) +{ + /** + * @tc.steps:step1. Create database. + * @tc.expected: step1. Returns a non-null kvstore. + */ + KvStoreNbDelegate::Option option; + g_mgr.GetKvStore("ResultSetLimitTest001", option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + + /** + * @tc.steps:step2. Put the random entry into the database. + * @tc.expected: step2. Returns OK. + */ + EXPECT_EQ(g_kvNbDelegatePtr->Put(KEY_1, VALUE_1), OK); + EXPECT_EQ(g_kvNbDelegatePtr->Put(KEY_2, VALUE_2), OK); + EXPECT_EQ(g_kvNbDelegatePtr->Put(KEY_3, VALUE_3), OK); + + /** + * @tc.steps:step3. Get the resultset overlimit. + * @tc.expected: step3. In limit returns OK, else return OVER_MAX_LIMITS. + */ + std::vector dataResultSet; + for (int i = 0; i < 8; i++) { // 8: max result set count + KvStoreResultSet *resultSet = nullptr; + EXPECT_EQ(g_kvNbDelegatePtr->GetEntries(Key{}, resultSet), OK); + dataResultSet.push_back(resultSet); + EXPECT_NE(resultSet, nullptr); + } + + KvStoreResultSet *resultSet = nullptr; + EXPECT_EQ(g_kvNbDelegatePtr->GetEntries(Key{}, resultSet), OVER_MAX_LIMITS); + EXPECT_EQ(resultSet, nullptr); + if (resultSet != nullptr) { + EXPECT_EQ(g_kvNbDelegatePtr->CloseResultSet(resultSet), OK); + } + + /** + * @tc.steps:step4. Close result set and store. + * @tc.expected: step4. Returns OK. + */ + for (auto it : dataResultSet) { + EXPECT_EQ(g_kvNbDelegatePtr->CloseResultSet(it), OK); + } + + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + EXPECT_EQ(g_mgr.DeleteKvStore("ResultSetLimitTest001"), OK); + g_kvNbDelegatePtr = nullptr; +} + +/** + * @tc.name: LocalStore001 + * @tc.desc: Test get kv store with localOnly + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBInterfacesNBDelegateExtendTest, LocalStore001, TestSize.Level1) +{ + KvStoreDelegateManager mgr(APP_ID, USER_ID); + mgr.SetKvStoreConfig(g_config); + + /** + * @tc.steps:step1. Create database with localOnly. + * @tc.expected: step1. Returns a non-null store. + */ + KvStoreNbDelegate::Option option = {true, false, false}; + option.localOnly = true; + DBStatus openStatus = DBStatus::DB_ERROR; + KvStoreNbDelegate *openDelegate = nullptr; + mgr.GetKvStore(STORE_ID_1, option, [&openStatus, &openDelegate](DBStatus status, KvStoreNbDelegate *delegate) { + openStatus = status; + openDelegate = delegate; + }); + ASSERT_TRUE(openDelegate != nullptr); + EXPECT_EQ(openStatus, OK); + /** + * @tc.steps:step2. call sync and put/get interface. + * @tc.expected: step2. sync return NOT_ACTIVE. + */ + DBStatus actionStatus = openDelegate->Sync({}, SyncMode::SYNC_MODE_PUSH_ONLY, nullptr); + EXPECT_EQ(actionStatus, DBStatus::NOT_ACTIVE); + Key key = {'k'}; + Value expectValue = {'v'}; + EXPECT_EQ(openDelegate->Put(key, expectValue), OK); + Value actualValue; + EXPECT_EQ(openDelegate->Get(key, actualValue), OK); + EXPECT_EQ(actualValue, expectValue); + + int pragmaData = 1; + auto input = static_cast(&pragmaData); + EXPECT_EQ(openDelegate->Pragma(SET_SYNC_RETRY, input), NOT_SUPPORT); + + EXPECT_EQ(mgr.CloseKvStore(openDelegate), OK); + EXPECT_EQ(mgr.DeleteKvStore(STORE_ID_1), OK); + openDelegate = nullptr; +} + +/** + * @tc.name: LocalStore002 + * @tc.desc: Test get kv store different local mode + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBInterfacesNBDelegateExtendTest, LocalStore002, TestSize.Level1) +{ + KvStoreDelegateManager mgr(APP_ID, USER_ID); + mgr.SetKvStoreConfig(g_config); + + /** + * @tc.steps:step1. Create database with localOnly. + * @tc.expected: step1. Returns a non-null store. + */ + KvStoreNbDelegate::Option option = {true, false, false}; + option.localOnly = true; + DBStatus openStatus = DBStatus::DB_ERROR; + KvStoreNbDelegate *localDelegate = nullptr; + mgr.GetKvStore(STORE_ID_1, option, [&openStatus, &localDelegate](DBStatus status, KvStoreNbDelegate *delegate) { + openStatus = status; + localDelegate = delegate; + }); + ASSERT_TRUE(localDelegate != nullptr); + EXPECT_EQ(openStatus, OK); + /** + * @tc.steps:step2. Create database without localOnly. + * @tc.expected: step2. Returns a null store. + */ + option.localOnly = false; + KvStoreNbDelegate *syncDelegate = nullptr; + mgr.GetKvStore(STORE_ID_1, option, [&openStatus, &syncDelegate](DBStatus status, KvStoreNbDelegate *delegate) { + openStatus = status; + syncDelegate = delegate; + }); + EXPECT_EQ(syncDelegate, nullptr); + EXPECT_EQ(openStatus, INVALID_ARGS); + EXPECT_EQ(mgr.CloseKvStore(localDelegate), OK); + EXPECT_EQ(mgr.DeleteKvStore(STORE_ID_1), OK); + localDelegate = nullptr; +} + +/** + * @tc.name: PutSync001 + * @tc.desc: put data and sync at same time + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBInterfacesNBDelegateExtendTest, PutSync001, TestSize.Level3) +{ + /** + * @tc.steps:step1. Create database with localOnly. + * @tc.expected: step1. Returns a non-null store. + */ + KvStoreDelegateManager mgr(APP_ID, USER_ID); + mgr.SetKvStoreConfig(g_config); + const KvStoreNbDelegate::Option option = {true, false, false}; + mgr.GetKvStore(STORE_ID_1, option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_EQ(g_kvDelegateStatus, OK); + /** + * @tc.steps:step2. Put data async. + * @tc.expected: step2. Always returns OK. + */ + std::atomic finish = false; + std::thread putThread([&finish]() { + while (!finish) { + EXPECT_EQ(g_kvNbDelegatePtr->Put(KEY_1, VALUE_1), OK); + } + }); + /** + * @tc.steps:step3. Call sync async. + * @tc.expected: step3. Always returns OK. + */ + std::thread syncThread([]() { + std::vector devices; + devices.emplace_back(""); + Key key = {'k'}; + for (int i = 0; i < 100; ++i) { // sync 100 times + Query query = Query::Select().PrefixKey(key); + DBStatus status = g_kvNbDelegatePtr->Sync(devices, SYNC_MODE_PULL_ONLY, nullptr, query, true); + EXPECT_EQ(status, OK); + } + }); + syncThread.join(); + finish = true; + putThread.join(); + EXPECT_EQ(mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + g_kvNbDelegatePtr = nullptr; + EXPECT_EQ(mgr.DeleteKvStore(STORE_ID_1), OK); +} + +/** + * @tc.name: UpdateKey001 + * @tc.desc: Test update key + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBInterfacesNBDelegateExtendTest, UpdateKey001, TestSize.Level0) +{ + /** + * @tc.steps:step1. Create database. + * @tc.expected: step1. Returns a non-null kvstore. + */ + KvStoreNbDelegate::Option option; + g_mgr.GetKvStore("UpdateKey001", option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + /** + * @tc.steps:step2. Put (k1, v1) into the database. + * @tc.expected: step2. Returns OK. + */ + Key k1 = {'k', '1'}; + EXPECT_EQ(g_kvNbDelegatePtr->Put(k1, VALUE_1), OK); + /** + * @tc.steps:step3. Update (k1, v1) to (k10, v1). + * @tc.expected: step3. Returns OK and get k1 return not found. + */ + g_kvNbDelegatePtr->UpdateKey([](const Key &originKey, Key &newKey) { + newKey = originKey; + newKey.push_back('0'); + }); + Value actualValue; + EXPECT_EQ(g_kvNbDelegatePtr->Get(k1, actualValue), NOT_FOUND); + k1.push_back('0'); + EXPECT_EQ(g_kvNbDelegatePtr->Get(k1, actualValue), OK); + EXPECT_EQ(actualValue, VALUE_1); + /** + * @tc.steps:step4. Close store. + * @tc.expected: step4. Returns OK. + */ + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + EXPECT_EQ(g_mgr.DeleteKvStore("UpdateKey001"), OK); + g_kvNbDelegatePtr = nullptr; +} + +/** + * @tc.name: UpdateKey002 + * @tc.desc: Test update key with transaction + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBInterfacesNBDelegateExtendTest, UpdateKey002, TestSize.Level0) +{ + /** + * @tc.steps:step1. Create database. + * @tc.expected: step1. Returns a non-null kvstore. + */ + KvStoreNbDelegate::Option option; + g_mgr.GetKvStore("UpdateKey002", option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + /** + * @tc.steps:step2. Put (k1, v1) into the database . + * @tc.expected: step2. Returns OK. + */ + Key k1 = {'k', '1'}; + EXPECT_EQ(g_kvNbDelegatePtr->Put(k1, VALUE_1), OK); + g_kvNbDelegatePtr->StartTransaction(); + /** + * @tc.steps:step3. Update (k1, v1) to (k10, v1). + * @tc.expected: step3. Returns OK and get k1 return not found. + */ + g_kvNbDelegatePtr->UpdateKey([](const Key &originKey, Key &newKey) { + newKey = originKey; + newKey.push_back('0'); + }); + Value actualValue; + EXPECT_EQ(g_kvNbDelegatePtr->Get(k1, actualValue), NOT_FOUND); + Key k10 = {'k', '1', '0'}; + EXPECT_EQ(g_kvNbDelegatePtr->Get(k10, actualValue), OK); + EXPECT_EQ(actualValue, VALUE_1); + /** + * @tc.steps:step5. Rollback Transaction. + * @tc.expected: step5. k10 not exist in db. + */ + g_kvNbDelegatePtr->Rollback(); + EXPECT_EQ(g_kvNbDelegatePtr->Get(k10, actualValue), NOT_FOUND); + EXPECT_EQ(g_kvNbDelegatePtr->Get(k1, actualValue), OK); + /** + * @tc.steps:step5. Commit transaction. + * @tc.expected: step5. data exist in db. + */ + g_kvNbDelegatePtr->StartTransaction(); + g_kvNbDelegatePtr->UpdateKey([](const Key &originKey, Key &newKey) { + newKey = originKey; + newKey.push_back('0'); + }); + g_kvNbDelegatePtr->Commit(); + EXPECT_EQ(g_kvNbDelegatePtr->Get(k10, actualValue), OK); + /** + * @tc.steps:step6. Close store. + * @tc.expected: step6. Returns OK. + */ + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + EXPECT_EQ(g_mgr.DeleteKvStore("UpdateKey002"), OK); + g_kvNbDelegatePtr = nullptr; +} + +/** + * @tc.name: UpdateKey003 + * @tc.desc: Test update key with invalid args + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBInterfacesNBDelegateExtendTest, UpdateKey003, TestSize.Level0) +{ + /** + * @tc.steps:step1. Create database. + * @tc.expected: step1. Returns a non-null kvstore. + */ + KvStoreNbDelegate::Option option; + g_mgr.GetKvStore("UpdateKey003", option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + /** + * @tc.steps:step2. Put (k1, v1) into the database . + * @tc.expected: step2. Returns OK. + */ + Key k1 = {'k', '1'}; + Key k2 = {'k', '2'}; + EXPECT_EQ(g_kvNbDelegatePtr->Put(k1, VALUE_1), OK); + EXPECT_EQ(g_kvNbDelegatePtr->Put(k2, VALUE_1), OK); + /** + * @tc.steps:step3. Update key with nullptr or invalid key. + * @tc.expected: step3. Returns INVALID_ARGS. + */ + EXPECT_EQ(g_kvNbDelegatePtr->UpdateKey(nullptr), INVALID_ARGS); + DBStatus status = g_kvNbDelegatePtr->UpdateKey([](const Key &originKey, Key &newKey) { + newKey.clear(); + }); + EXPECT_EQ(status, INVALID_ARGS); + status = g_kvNbDelegatePtr->UpdateKey([](const Key &originKey, Key &newKey) { + newKey.assign(2048u, '0'); // 2048 is invalid len + }); + EXPECT_EQ(status, INVALID_ARGS); + status = g_kvNbDelegatePtr->UpdateKey([](const Key &originKey, Key &newKey) { + newKey = {'k', '3'}; + }); + EXPECT_EQ(status, CONSTRAINT); + /** + * @tc.steps:step4. Close store. + * @tc.expected: step4. Returns OK. + */ + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + EXPECT_EQ(g_mgr.DeleteKvStore("UpdateKey003"), OK); + g_kvNbDelegatePtr = nullptr; +} + +/** + * @tc.name: BlockTimer001 + * @tc.desc: Test open close function with block timer + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBInterfacesNBDelegateExtendTest, BlockTimer001, TestSize.Level0) +{ + /** + * @tc.steps:step1. Create database. + * @tc.expected: step1. Returns a non-null store. + */ + KvStoreNbDelegate::Option option; + g_mgr.GetKvStore("BlockTimer001", option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + /** + * @tc.steps:step2. Create block timer. + * @tc.expected: step2. create ok. + */ + TimerId timerId = 0u; + bool timerFinalize = false; + std::condition_variable cv; + std::mutex finalizeMutex; + bool triggerTimer = false; + std::condition_variable triggerCv; + std::mutex triggerMutex; + int errCode = RuntimeContext::GetInstance()->SetTimer(1, [&triggerTimer, &triggerCv, &triggerMutex](TimerId id) { + { + std::lock_guard autoLock(triggerMutex); + triggerTimer = true; + } + triggerCv.notify_all(); + std::this_thread::sleep_for(std::chrono::seconds(5)); + return -E_END_TIMER; + }, [&timerFinalize, &finalizeMutex, &cv]() { + { + std::lock_guard autoLock(finalizeMutex); + timerFinalize = true; + } + cv.notify_all(); + }, timerId); + ASSERT_EQ(errCode, E_OK); + { + std::unique_lock uniqueLock(triggerMutex); + triggerCv.wait(uniqueLock, [&triggerTimer]() { + return triggerTimer; + }); + } + /** + * @tc.steps:step3. Close store. + * @tc.expected: step3. Returns OK. + */ + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + std::unique_lock uniqueLock(finalizeMutex); + EXPECT_TRUE(timerFinalize); + cv.wait(uniqueLock, [&timerFinalize]() { + return timerFinalize; + }); + EXPECT_EQ(g_mgr.DeleteKvStore("BlockTimer001"), OK); + g_kvNbDelegatePtr = nullptr; +} + +/** + * @tc.name: MigrateDeadLockTest0011 + * @tc.desc: Test the will not be deadlock in migration. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshijie + */ +HWTEST_F(DistributedDBInterfacesNBDelegateExtendTest, MigrateDeadLockTest001, TestSize.Level2) +{ + std::shared_ptr g_adapter = std::make_shared(); + RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(g_adapter); + /** + * @tc.steps:step1. Get the nb delegate. + * @tc.expected: step1. Get results OK and non-null delegate. + */ + KvStoreNbDelegate::Option option = {true, false, false}; + option.secOption = {S3, SECE}; + std::string storeId = "distributed_nb_delegate_test"; + g_mgr.GetKvStore(storeId, option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + + KvDBProperties property; + property.SetStringProp(KvDBProperties::DATA_DIR, g_testDir); + property.SetStringProp(KvDBProperties::STORE_ID, storeId); + property.SetIntProp(KvDBProperties::SECURITY_LABEL, S3); + property.SetIntProp(KvDBProperties::SECURITY_FLAG, SECE); + + std::string identifier = DBCommon::GenerateIdentifierId(storeId, APP_ID, USER_ID); + property.SetStringProp(KvDBProperties::IDENTIFIER_DATA, DBCommon::TransferHashString(identifier)); + property.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE_SQLITE); + + int errCode; + SQLiteSingleVerStorageEngine *storageEngine = + static_cast(StorageEngineManager::GetStorageEngine(property, errCode)); + ASSERT_EQ(errCode, E_OK); + ASSERT_NE(storageEngine, nullptr); + storageEngine->SetEngineState(EngineState::CACHEDB); + + /** + * @tc.steps:step2. create cache db + * @tc.expected: step2. operation ok + */ + std::string cacheDir = g_testDir + "/" + DBCommon::TransferStringToHex(DBCommon::TransferHashString(identifier)) + + "/" + DBConstant::SINGLE_SUB_DIR + "/" + DBConstant::CACHEDB_DIR; + std::string cacheDB = cacheDir + "/" + DBConstant::SINGLE_VER_CACHE_STORE + DBConstant::DB_EXTENSION; + EXPECT_EQ(OS::CreateFileByFileName(cacheDB), E_OK); + + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + g_mgr.GetKvStore(storeId, option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + + std::this_thread::sleep_for(std::chrono::seconds(3)); // 3 is sleep seconds + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + EXPECT_EQ(g_mgr.DeleteKvStore(storeId), OK); + g_kvNbDelegatePtr = nullptr; + if (DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir) != 0) { + LOGE("rm test db files error!"); + } +} + +/** + * @tc.name: InvalidQueryTest001 + * @tc.desc: Test GetEntries with range query filter by sqlite + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DistributedDBInterfacesNBDelegateExtendTest, InvalidQueryTest001, TestSize.Level1) +{ + /** + * @tc.steps:step1. Get the nb delegate. + * @tc.expected: step1. Get results OK and non-null delegate. + */ + KvStoreNbDelegate::Option option; + g_mgr.GetKvStore("InvalidQueryTest001", option, g_kvNbDelegateCallback); + std::vector entries; + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + + /** + * @tc.steps: step2. Use range query conditions to obtain the resultset when use sqlite engine. + * @tc.expected: step2. return NOT_SUPPORT. + */ + KvStoreResultSet *resultSet = nullptr; + Query inValidQuery = Query::Select().Range({}, {}); + EXPECT_EQ(g_kvNbDelegatePtr->GetEntries(inValidQuery, resultSet), NOT_SUPPORT); + EXPECT_EQ(g_kvNbDelegatePtr->GetEntries(inValidQuery, entries), NOT_SUPPORT); + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + EXPECT_EQ(g_mgr.DeleteKvStore("InvalidQueryTest001"), OK); + g_kvNbDelegatePtr = nullptr; +} + +/** + * @tc.name: InvalidQueryTest002 + * @tc.desc: Test GetEntries with range query filter by sqlite while conn is nullptr. + * @tc.type: FUNC + * @tc.require: + * @tc.author: caihaoting + */ +HWTEST_F(DistributedDBInterfacesNBDelegateExtendTest, InvalidQueryTest002, TestSize.Level1) +{ + /** + * @tc.steps: step1. initialize result set. + * @tc.expected: step1. Success. + */ + KvStoreNbDelegate::Option option = {true, false, false}; + g_mgr.GetKvStore("InvalidQueryTest002", option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + InitResultSet(); + + /** + * @tc.steps: step2. get entries using result set while conn is nullptr. + * @tc.expected: step2. DB_ERROR. + */ + KvStoreResultSet *readResultSet = nullptr; + auto kvStoreImpl = static_cast(g_kvNbDelegatePtr); + EXPECT_EQ(kvStoreImpl->Close(), OK); + EXPECT_EQ(g_kvNbDelegatePtr->GetEntries(g_keyPrefix, readResultSet), DB_ERROR); + ASSERT_TRUE(readResultSet == nullptr); + + std::vector entries; + Query query = Query::Select().PrefixKey({'a', 'c'}); + EXPECT_EQ(g_kvNbDelegatePtr->GetEntries(query, entries), DB_ERROR); + EXPECT_EQ(entries.size(), 0UL); + + EXPECT_EQ(g_kvNbDelegatePtr->GetEntries(query, readResultSet), DB_ERROR); + ASSERT_TRUE(readResultSet == nullptr); + + int count = -1; + EXPECT_EQ(g_kvNbDelegatePtr->GetCount(query, count), DB_ERROR); + EXPECT_EQ(count, -1); + + /** + * @tc.steps: step3. close kvStore. + * @tc.expected: step3. Success. + */ + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + EXPECT_EQ(g_mgr.DeleteKvStore("InvalidQueryTest002"), OK); + g_kvNbDelegatePtr = nullptr; +} + +/** + * @tc.name: SyncRangeQuery001 + * @tc.desc: test sync query with range + * @tc.type: FUNC + * @tc.require: DTS2023112110763 + * @tc.author: mazhao + */ +HWTEST_F(DistributedDBInterfacesNBDelegateExtendTest, SyncRangeQuery001, TestSize.Level3) +{ + /** + * @tc.steps:step1. Create database with localOnly. + * @tc.expected: step1. Returns a non-null store. + */ + InitVirtualDevice(DEVICE_B, g_deviceB, g_syncInterfaceB); + KvStoreDelegateManager mgr(APP_ID, USER_ID); + mgr.SetKvStoreConfig(g_config); + const KvStoreNbDelegate::Option option = {true, false, false}; + mgr.GetKvStore(STORE_ID_1, option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_EQ(g_kvDelegateStatus, OK); + /** + * @tc.steps:step2. Construct invalid query with range, Call sync async. + * @tc.expected: step2. returns NOT_SUPPORT. + */ + std::vector devices; + devices.emplace_back(DEVICE_B); + Query inValidQuery = Query::Select().Range({}, {}); + DBStatus status = g_kvNbDelegatePtr->Sync(devices, SYNC_MODE_PULL_ONLY, nullptr, inValidQuery, true); + EXPECT_EQ(status, NOT_SUPPORT); + EXPECT_EQ(mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + g_kvNbDelegatePtr = nullptr; + EXPECT_EQ(mgr.DeleteKvStore(STORE_ID_1), OK); +} + +/** + * @tc.name: OptionValidCheck001 + * @tc.desc: test validation of option mode + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshijie + */ +HWTEST_F(DistributedDBInterfacesNBDelegateExtendTest, OptionModeValidCheck001, TestSize.Level0) +{ + /** + * @tc.steps:step1. Get the nb delegate. + * @tc.expected: step1. Get results OK and non-null delegate. + */ + KvStoreNbDelegate::Option option = {true, false, false}; + KvStoreObserverUnitTest *observer = new KvStoreObserverUnitTest(); + ASSERT_TRUE(observer != nullptr); + option.observer = observer; + std::vector invalidModeVec = {0, 5, 6, 7, 9, 16}; + std::string storeId = "OptionModeValidCheck001"; + for (size_t i = 0; i < invalidModeVec.size(); i++) { + option.mode = invalidModeVec.at(i); + g_mgr.GetKvStore(storeId, option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr == nullptr); + EXPECT_EQ(g_kvDelegateStatus, INVALID_ARGS); + } + + std::vector validModeVec = {1, 2, 3, 4, 8}; + for (size_t i = 0; i < validModeVec.size(); i++) { + option.mode = validModeVec.at(i); + g_mgr.GetKvStore(storeId, option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_EQ(g_kvDelegateStatus, OK); + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + EXPECT_EQ(g_mgr.DeleteKvStore(storeId), OK); + g_kvNbDelegatePtr = nullptr; + } + + delete observer; +} + +/** + * @tc.name: AbnormalKvStoreTest001 + * @tc.desc: Test KvStoreNbDelegateImpl interface while conn is nullptr. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBInterfacesNBDelegateExtendTest, AbnormalKvStoreTest001, TestSize.Level1) +{ + /** + * @tc.steps: step1. GetKvStore for initialize g_kvNbDelegatePtr. + * @tc.expected: step1. Success. + */ + KvStoreNbDelegate::Option option = {true, false, false}; + g_mgr.GetKvStore("AbnormalKvStoreTest001", option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + InitResultSet(); + + /** + * @tc.steps: step2. test KvStoreNbDelegateImpl interface while conn is nullptr. + * @tc.expected: step2. return DB_ERROR. + */ + auto kvStoreImpl = static_cast(g_kvNbDelegatePtr); + EXPECT_EQ(kvStoreImpl->Close(), OK); + + const Key key = {0}; + EXPECT_EQ(kvStoreImpl->PublishLocal(key, true, true, nullptr), DB_ERROR); + EXPECT_EQ(kvStoreImpl->UnpublishToLocal(key, true, true), DB_ERROR); + EXPECT_EQ(kvStoreImpl->UnpublishToLocal({}, true, true), INVALID_ARGS); + EXPECT_EQ(kvStoreImpl->RemoveDeviceData(""), DB_ERROR); + EXPECT_EQ(kvStoreImpl->CancelSync(0), DB_ERROR); + bool autoSync = true; + PragmaData data = static_cast(&autoSync); + EXPECT_EQ(kvStoreImpl->Pragma(AUTO_SYNC, data), DB_ERROR); + EXPECT_EQ(kvStoreImpl->SetConflictNotifier(0, nullptr), DB_ERROR); + CipherPassword password; + EXPECT_EQ(kvStoreImpl->Rekey(password), DB_ERROR); + EXPECT_EQ(kvStoreImpl->Export("", password, true), DB_ERROR); + EXPECT_EQ(kvStoreImpl->Import("", password), DB_ERROR); + EXPECT_EQ(kvStoreImpl->StartTransaction(), DB_ERROR); + EXPECT_EQ(kvStoreImpl->Commit(), DB_ERROR); + EXPECT_EQ(kvStoreImpl->Rollback(), DB_ERROR); + EXPECT_EQ(kvStoreImpl->CheckIntegrity(), DB_ERROR); + SecurityOption securityOption; + EXPECT_EQ(kvStoreImpl->GetSecurityOption(securityOption), DB_ERROR); + EXPECT_EQ(kvStoreImpl->SetRemotePushFinishedNotify(nullptr), DB_ERROR); + EXPECT_EQ(kvStoreImpl->SetEqualIdentifier("", {}), DB_ERROR); + EXPECT_EQ(kvStoreImpl->SetPushDataInterceptor(nullptr), DB_ERROR); + + /** + * @tc.steps: step3. close kvStore. + * @tc.expected: step3. Success. + */ + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + EXPECT_EQ(g_mgr.DeleteKvStore("AbnormalKvStoreTest001"), OK); + g_kvNbDelegatePtr = nullptr; +} + +/** + * @tc.name: AbnormalKvStoreTest002 + * @tc.desc: Test KvStoreNbDelegateImpl interface while conn is nullptr. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBInterfacesNBDelegateExtendTest, AbnormalKvStoreTest002, TestSize.Level1) +{ + /** + * @tc.steps: step1. GetKvStore for initialize g_kvNbDelegatePtr. + * @tc.expected: step1. Success. + */ + KvStoreNbDelegate::Option option = {true, false, false}; + g_mgr.GetKvStore("AbnormalKvStoreTest002", option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + InitResultSet(); + + /** + * @tc.steps: step2. test KvStoreNbDelegateImpl interface while conn is nullptr. + * @tc.expected: step2. return DB_ERROR. + */ + auto kvStoreImpl = static_cast(g_kvNbDelegatePtr); + EXPECT_EQ(kvStoreImpl->Close(), OK); + + Query query; + EXPECT_EQ(kvStoreImpl->SubscribeRemoteQuery({}, nullptr, query, true), DB_ERROR); + EXPECT_EQ(kvStoreImpl->UnSubscribeRemoteQuery({}, nullptr, query, true), DB_ERROR); + EXPECT_EQ(kvStoreImpl->RemoveDeviceData(), DB_ERROR); + const Key key = {0}; + std::vector keys; + EXPECT_EQ(kvStoreImpl->GetKeys(key, keys), DB_ERROR); + uint32_t expectedVal = 0; + EXPECT_EQ(kvStoreImpl->GetSyncDataSize(""), expectedVal); + EXPECT_EQ(kvStoreImpl->UpdateKey(nullptr), DB_ERROR); + const std::string device = "test"; + std::pair info = kvStoreImpl->GetWatermarkInfo(device); + EXPECT_EQ(info.first, DB_ERROR); + EXPECT_EQ(kvStoreImpl->GetTaskCount(), DB_ERROR); + EXPECT_EQ(kvStoreImpl->SetReceiveDataInterceptor(nullptr), DB_ERROR); + CloudSyncConfig config; + EXPECT_EQ(kvStoreImpl->SetCloudSyncConfig(config), DB_ERROR); + const IOption iOption; + std::vector entries; + EXPECT_EQ(kvStoreImpl->GetEntries(key, entries), DB_ERROR); + + /** + * @tc.steps: step3. close kvStore. + * @tc.expected: step3. Success. + */ + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + EXPECT_EQ(g_mgr.DeleteKvStore("AbnormalKvStoreTest002"), OK); + g_kvNbDelegatePtr = nullptr; +} + +/** + * @tc.name: AbnormalKvStoreResultSetTest + * @tc.desc: Test KvStoreResultSetImpl interface when class para is nullptr. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBInterfacesNBDelegateExtendTest, AbnormalKvStoreResultSetTest, TestSize.Level1) +{ + /** + * @tc.steps: step1. Call interfaces when class para is null. + * @tc.expected: step1. return failInfo. + */ + KvStoreResultSetImpl kvStoreObj(nullptr); + EXPECT_EQ(kvStoreObj.GetCount(), 0); + EXPECT_EQ(kvStoreObj.GetPosition(), INIT_POSITION); + EXPECT_EQ(kvStoreObj.Move(0), false); + EXPECT_EQ(kvStoreObj.MoveToPosition(0), false); + EXPECT_EQ(kvStoreObj.MoveToFirst(), false); + EXPECT_EQ(kvStoreObj.MoveToLast(), false); + EXPECT_EQ(kvStoreObj.IsFirst(), false); + EXPECT_EQ(kvStoreObj.IsLast(), false); + EXPECT_EQ(kvStoreObj.IsBeforeFirst(), false); + EXPECT_EQ(kvStoreObj.IsAfterLast(), false); + std::vector columnNames; + kvStoreObj.GetColumnNames(columnNames); + Entry entry; + EXPECT_EQ(kvStoreObj.GetEntry(entry), DB_ERROR); + EXPECT_EQ(kvStoreObj.IsClosed(), false); + kvStoreObj.Close(); + + /** + * @tc.steps: step2. Call unsupported interfaces. + * @tc.expected: step2. return NOT_SUPPORT. + */ + std::string columnName; + int columnIndex = 0; + EXPECT_EQ(kvStoreObj.GetColumnIndex(columnName, columnIndex), NOT_SUPPORT); + EXPECT_EQ(kvStoreObj.GetColumnName(columnIndex, columnName), NOT_SUPPORT); + std::vector vecVal; + EXPECT_EQ(kvStoreObj.Get(columnIndex, vecVal), NOT_SUPPORT); + std::string strVal; + EXPECT_EQ(kvStoreObj.Get(columnIndex, strVal), NOT_SUPPORT); + int64_t intVal; + EXPECT_EQ(kvStoreObj.Get(columnIndex, intVal), NOT_SUPPORT); + double doubleVal; + EXPECT_EQ(kvStoreObj.Get(columnIndex, doubleVal), NOT_SUPPORT); + bool isNull; + EXPECT_EQ(kvStoreObj.IsColumnNull(columnIndex, isNull), NOT_SUPPORT); + std::map data; + EXPECT_EQ(kvStoreObj.GetRow(data), NOT_SUPPORT); +} + +/** + * @tc.name: AbnormalKvStoreTest003 + * @tc.desc: Test SqliteCloudKvStore interface when para is invalid. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBInterfacesNBDelegateExtendTest, AbnormalKvStoreTest003, TestSize.Level1) +{ + /** + * @tc.steps: step1. Call defaule interfaces. + * @tc.expected: step1. return E_OK. + */ + SqliteCloudKvStore kvStoreObj(nullptr); + DataBaseSchema schema; + EXPECT_EQ(kvStoreObj.SetCloudDbSchema(schema), E_OK); + EXPECT_EQ(kvStoreObj.Commit(), E_OK); + EXPECT_EQ(kvStoreObj.Rollback(), E_OK); + const TableName tableName = "test"; + VBucket vBucket; + EXPECT_EQ(kvStoreObj.FillCloudAssetForDownload(tableName, vBucket, true), E_OK); + EXPECT_EQ(kvStoreObj.SetLogTriggerStatus(true), E_OK); + QuerySyncObject query; + EXPECT_EQ(kvStoreObj.CheckQueryValid(query), E_OK); + ContinueToken continueStmtToken = nullptr; + EXPECT_EQ(kvStoreObj.ReleaseCloudDataToken(continueStmtToken), E_OK); + std::vector syncQuery; + std::vector users; + EXPECT_EQ(kvStoreObj.GetCompensatedSyncQuery(syncQuery, users), E_OK); + + /** + * @tc.steps: step2. Call interfaces when class para is null. + * @tc.expected: step2. return failInfo. + */ + DataInfoWithLog log; + EXPECT_EQ(kvStoreObj.GetInfoByPrimaryKeyOrGid(tableName, vBucket, log, vBucket), -E_INTERNAL_ERROR); + DownloadData downloadData; + EXPECT_EQ(kvStoreObj.PutCloudSyncData(tableName, downloadData), -E_INTERNAL_ERROR); + Timestamp timestamp = 0; + int64_t count = 0; + EXPECT_EQ(kvStoreObj.GetUploadCount(query, timestamp, true, true, count), -E_INTERNAL_ERROR); + std::vector timestampVec; + EXPECT_EQ(kvStoreObj.GetAllUploadCount(query, timestampVec, true, true, count), -E_INTERNAL_ERROR); + + /** + * @tc.steps: step3. Get and set Schema with different para when class para is null. + * @tc.expected: step3. return failInfo. + */ + TableSchema tableSchema; + EXPECT_EQ(kvStoreObj.GetCloudTableSchema(tableName, tableSchema), -E_NOT_FOUND); + CloudSyncData cloudDataResult; + EXPECT_EQ(kvStoreObj.GetCloudDataNext(continueStmtToken, cloudDataResult), -E_INVALID_ARGS); + std::map schemaMap; + EXPECT_EQ(kvStoreObj.SetCloudDbSchema(schemaMap), -E_INVALID_SCHEMA); + schema.tables = {tableSchema, tableSchema}; + schemaMap.insert(std::pair(tableName, schema)); + EXPECT_EQ(kvStoreObj.SetCloudDbSchema(schemaMap), -E_INVALID_SCHEMA); + const std::string user = "user1"; + kvStoreObj.SetUser(user); + EXPECT_EQ(kvStoreObj.GetCloudTableSchema(tableName, tableSchema), -E_SCHEMA_MISMATCH); +} +} diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_test.cpp index bfe33284f6e9429bc454727f779140c34742096f..68d93661bfa283a4ef25ddffcec53696e3ae62bc 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_test.cpp @@ -453,7 +453,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, CombineTest003, TestSize.Level1) EXPECT_EQ(g_kvNbDelegatePtr->Get(key, valueRead), NOT_FOUND); /** * @tc.steps:step3. Put the local data. - * @tc.expected: step3. Returns OK. + * @tc.expected: step3. Put returns OK. */ EXPECT_EQ(g_kvNbDelegatePtr->Put(key, value), OK); std::this_thread::sleep_for(std::chrono::milliseconds(OBSERVER_SLEEP_TIME)); @@ -464,7 +464,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, CombineTest003, TestSize.Level1) EXPECT_EQ(g_kvNbDelegatePtr->Get(key, valueRead), OK); /** * @tc.steps:step5. Delete the local data. - * @tc.expected: step5. Delete return OK. + * @tc.expected: step5. Delete returns OK. */ EXPECT_EQ(g_kvNbDelegatePtr->Delete(key), OK); std::this_thread::sleep_for(std::chrono::milliseconds(OBSERVER_SLEEP_TIME)); @@ -1955,6 +1955,8 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, SingleVerGetSecurityOption001, T ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); EXPECT_TRUE(g_kvDelegateStatus == OK); EXPECT_TRUE(g_kvNbDelegatePtr->GetSecurityOption(savedOption) == OK); + SecurityOption secOption = {option.secOption.securityLabel, option.secOption.securityFlag}; + EXPECT_TRUE(savedOption != secOption); EXPECT_TRUE(savedOption.securityLabel == 0); EXPECT_TRUE(savedOption.securityFlag == 0); @@ -2437,996 +2439,4 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, RemoveDeviceDataTest001, TestSiz FreeVirtualDevice(g_deviceC); FreeVirtualDevice(g_deviceD); } - -#ifdef DB_DEBUG_ENV -/** - * @tc.name: TimeChangeWithCloseStoreTest001 - * @tc.desc: Test close store with time changed - * @tc.type: FUNC - * @tc.require: - * @tc.author: lianhuix - */ -HWTEST_F(DistributedDBInterfacesNBDelegateTest, TimeChangeWithCloseStoreTest001, TestSize.Level3) -{ - KvStoreDelegateManager mgr(APP_ID, USER_ID); - mgr.SetKvStoreConfig(g_config); - - std::atomic isFinished(false); - - std::vector slowThreads; - for (int i = 0; i < 10; i++) { // 10: thread to slow donw system - std::thread th([&isFinished]() { - while (!isFinished) { - // pass - } - }); - slowThreads.emplace_back(std::move(th)); - } - - std::thread th([&isFinished]() { - int timeChangedCnt = 0; - while (!isFinished.load()) { - OS::SetOffsetBySecond(100 - timeChangedCnt++ * 2); // 100 2 : fake system time change - std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 100: wait for a while - } - }); - - for (int i = 0; i < 100; i++) { // run 100 times - const KvStoreNbDelegate::Option option = {true, false, false}; - mgr.GetKvStore(STORE_ID_1, option, g_kvNbDelegateCallback); - ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); - EXPECT_EQ(g_kvDelegateStatus, OK); - EXPECT_EQ(mgr.CloseKvStore(g_kvNbDelegatePtr), OK); - g_kvNbDelegatePtr = nullptr; - } - - std::this_thread::sleep_for(std::chrono::milliseconds(1000)); // 1000: wait for a while - isFinished.store(true); - th.join(); - for (auto &it : slowThreads) { - it.join(); - } - EXPECT_EQ(mgr.DeleteKvStore(STORE_ID_1), OK); -} - -/** - * @tc.name: TimeChangeWithCloseStoreTest002 - * @tc.desc: Test close store with time changed - * @tc.type: FUNC - * @tc.require: - * @tc.author: zhangqiquan - */ -HWTEST_F(DistributedDBInterfacesNBDelegateTest, TimeChangeWithCloseStoreTest002, TestSize.Level3) -{ - KvStoreDelegateManager mgr(APP_ID, USER_ID); - mgr.SetKvStoreConfig(g_config); - - const KvStoreNbDelegate::Option option = {true, false, false}; - mgr.GetKvStore(STORE_ID_1, option, g_kvNbDelegateCallback); - ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); - EXPECT_EQ(g_kvDelegateStatus, OK); - const int threadPoolMax = 10; - for (int i = 0; i < threadPoolMax; ++i) { - (void) RuntimeContext::GetInstance()->ScheduleTask([]() { - std::this_thread::sleep_for(std::chrono::seconds(10)); // sleep 10s for block thread pool - }); - } - OS::SetOffsetBySecond(100); // 100 2 : fake system time change - std::this_thread::sleep_for(std::chrono::seconds(1)); // sleep 1s for time tick - - EXPECT_EQ(mgr.CloseKvStore(g_kvNbDelegatePtr), OK); - g_kvNbDelegatePtr = nullptr; - - EXPECT_EQ(mgr.DeleteKvStore(STORE_ID_1), OK); - RuntimeContext::GetInstance()->StopTaskPool(); // stop all async task -} - -/** - * @tc.name: TimeChangeWithCloseStoreTest003 - * @tc.desc: Test store close with timechange listener - * @tc.type: FUNC - * @tc.require: - * @tc.author: zhangqiquan - */ -HWTEST_F(DistributedDBInterfacesNBDelegateTest, TimeChangeWithCloseStoreTest003, TestSize.Level3) -{ - /** - * @tc.steps:step1. Create database. - * @tc.expected: step1. Returns a non-null kvstore. - */ - KvStoreNbDelegate::Option option; - g_mgr.GetKvStore("TimeChangeWithCloseStoreTest003", option, g_kvNbDelegateCallback); - ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); - EXPECT_TRUE(g_kvDelegateStatus == OK); - std::shared_ptr timeChange = std::make_shared(false); - int errCode = E_OK; - auto *listener = RuntimeContext::GetInstance()->RegisterTimeChangedLister([timeChange](void *) { - std::this_thread::sleep_for(std::chrono::seconds(10)); // block close store 10s - *timeChange = true; - }, nullptr, errCode); - /** - * @tc.steps:step2. Block time change 10s and trigger time change. - * @tc.expected: step2. close store cost time > 5s. - */ - ASSERT_EQ(errCode, E_OK); - OS::SetOffsetBySecond(100); // 100 : fake system time change - std::this_thread::sleep_for(std::chrono::seconds(1)); // wait 1s for time change - Timestamp beginTime; - (void)OS::GetCurrentSysTimeInMicrosecond(beginTime); - ASSERT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); - Timestamp endTime; - (void)OS::GetCurrentSysTimeInMicrosecond(endTime); - if (*timeChange) { - EXPECT_GE(static_cast(endTime - beginTime), 5 * 1000 * 1000); // 5 * 1000 * 1000 = 5s - } - listener->Drop(true); - OS::SetOffsetBySecond(-100); // -100 : fake system time change - g_kvNbDelegatePtr = nullptr; - EXPECT_EQ(g_mgr.DeleteKvStore("TimeChangeWithCloseStoreTest003"), OK); -} -#endif // DB_DEBUG_ENV - -/** - * @tc.name: ResultSetLimitTest001 - * @tc.desc: Get result set over limit - * @tc.type: FUNC - * @tc.require: - * @tc.author: lianhuix - */ -HWTEST_F(DistributedDBInterfacesNBDelegateTest, ResultSetLimitTest001, TestSize.Level0) -{ - /** - * @tc.steps:step1. Create database. - * @tc.expected: step1. Returns a non-null kvstore. - */ - KvStoreNbDelegate::Option option; - g_mgr.GetKvStore("ResultSetLimitTest001", option, g_kvNbDelegateCallback); - ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); - EXPECT_TRUE(g_kvDelegateStatus == OK); - - /** - * @tc.steps:step2. Put the random entry into the database. - * @tc.expected: step2. Returns OK. - */ - EXPECT_EQ(g_kvNbDelegatePtr->Put(KEY_1, VALUE_1), OK); - EXPECT_EQ(g_kvNbDelegatePtr->Put(KEY_2, VALUE_2), OK); - EXPECT_EQ(g_kvNbDelegatePtr->Put(KEY_3, VALUE_3), OK); - - /** - * @tc.steps:step3. Get the resultset overlimit. - * @tc.expected: step3. In limit returns OK, else return OVER_MAX_LIMITS. - */ - std::vector dataResultSet; - for (int i = 0; i < 8; i++) { // 8: max result set count - KvStoreResultSet *resultSet = nullptr; - EXPECT_EQ(g_kvNbDelegatePtr->GetEntries(Key{}, resultSet), OK); - dataResultSet.push_back(resultSet); - EXPECT_NE(resultSet, nullptr); - } - - KvStoreResultSet *resultSet = nullptr; - EXPECT_EQ(g_kvNbDelegatePtr->GetEntries(Key{}, resultSet), OVER_MAX_LIMITS); - EXPECT_EQ(resultSet, nullptr); - if (resultSet != nullptr) { - EXPECT_EQ(g_kvNbDelegatePtr->CloseResultSet(resultSet), OK); - } - - /** - * @tc.steps:step4. Close result set and store. - * @tc.expected: step4. Returns OK. - */ - for (auto it : dataResultSet) { - EXPECT_EQ(g_kvNbDelegatePtr->CloseResultSet(it), OK); - } - - EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); - EXPECT_EQ(g_mgr.DeleteKvStore("ResultSetLimitTest001"), OK); - g_kvNbDelegatePtr = nullptr; -} - -/** - * @tc.name: LocalStore001 - * @tc.desc: Test get kv store with localOnly - * @tc.type: FUNC - * @tc.require: - * @tc.author: zhangqiquan - */ -HWTEST_F(DistributedDBInterfacesNBDelegateTest, LocalStore001, TestSize.Level1) -{ - KvStoreDelegateManager mgr(APP_ID, USER_ID); - mgr.SetKvStoreConfig(g_config); - - /** - * @tc.steps:step1. Create database with localOnly. - * @tc.expected: step1. Returns a non-null store. - */ - KvStoreNbDelegate::Option option = {true, false, false}; - option.localOnly = true; - DBStatus openStatus = DBStatus::DB_ERROR; - KvStoreNbDelegate *openDelegate = nullptr; - mgr.GetKvStore(STORE_ID_1, option, [&openStatus, &openDelegate](DBStatus status, KvStoreNbDelegate *delegate) { - openStatus = status; - openDelegate = delegate; - }); - ASSERT_TRUE(openDelegate != nullptr); - EXPECT_EQ(openStatus, OK); - /** - * @tc.steps:step2. call sync and put/get interface. - * @tc.expected: step2. sync return NOT_ACTIVE. - */ - DBStatus actionStatus = openDelegate->Sync({}, SyncMode::SYNC_MODE_PUSH_ONLY, nullptr); - EXPECT_EQ(actionStatus, DBStatus::NOT_ACTIVE); - Key key = {'k'}; - Value expectValue = {'v'}; - EXPECT_EQ(openDelegate->Put(key, expectValue), OK); - Value actualValue; - EXPECT_EQ(openDelegate->Get(key, actualValue), OK); - EXPECT_EQ(actualValue, expectValue); - - int pragmaData = 1; - auto input = static_cast(&pragmaData); - EXPECT_EQ(openDelegate->Pragma(SET_SYNC_RETRY, input), NOT_SUPPORT); - - EXPECT_EQ(mgr.CloseKvStore(openDelegate), OK); -} - -/** - * @tc.name: LocalStore002 - * @tc.desc: Test get kv store different local mode - * @tc.type: FUNC - * @tc.require: - * @tc.author: zhangqiquan - */ -HWTEST_F(DistributedDBInterfacesNBDelegateTest, LocalStore002, TestSize.Level1) -{ - KvStoreDelegateManager mgr(APP_ID, USER_ID); - mgr.SetKvStoreConfig(g_config); - - /** - * @tc.steps:step1. Create database with localOnly. - * @tc.expected: step1. Returns a non-null store. - */ - KvStoreNbDelegate::Option option = {true, false, false}; - option.localOnly = true; - DBStatus openStatus = DBStatus::DB_ERROR; - KvStoreNbDelegate *localDelegate = nullptr; - mgr.GetKvStore(STORE_ID_1, option, [&openStatus, &localDelegate](DBStatus status, KvStoreNbDelegate *delegate) { - openStatus = status; - localDelegate = delegate; - }); - ASSERT_TRUE(localDelegate != nullptr); - EXPECT_EQ(openStatus, OK); - /** - * @tc.steps:step2. Create database without localOnly. - * @tc.expected: step2. Returns a null store. - */ - option.localOnly = false; - KvStoreNbDelegate *syncDelegate = nullptr; - mgr.GetKvStore(STORE_ID_1, option, [&openStatus, &syncDelegate](DBStatus status, KvStoreNbDelegate *delegate) { - openStatus = status; - syncDelegate = delegate; - }); - EXPECT_EQ(syncDelegate, nullptr); - EXPECT_EQ(openStatus, INVALID_ARGS); - EXPECT_EQ(mgr.CloseKvStore(localDelegate), OK); - EXPECT_EQ(mgr.DeleteKvStore(STORE_ID_1), OK); -} - -/** - * @tc.name: PutSync001 - * @tc.desc: put data and sync at same time - * @tc.type: FUNC - * @tc.require: - * @tc.author: zhangqiquan - */ -HWTEST_F(DistributedDBInterfacesNBDelegateTest, PutSync001, TestSize.Level3) -{ - /** - * @tc.steps:step1. Create database with localOnly. - * @tc.expected: step1. Returns a non-null store. - */ - KvStoreDelegateManager mgr(APP_ID, USER_ID); - mgr.SetKvStoreConfig(g_config); - const KvStoreNbDelegate::Option option = {true, false, false}; - mgr.GetKvStore(STORE_ID_1, option, g_kvNbDelegateCallback); - ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); - EXPECT_EQ(g_kvDelegateStatus, OK); - /** - * @tc.steps:step2. Put data async. - * @tc.expected: step2. Always returns OK. - */ - std::atomic finish = false; - std::thread putThread([&finish]() { - while (!finish) { - EXPECT_EQ(g_kvNbDelegatePtr->Put(KEY_1, VALUE_1), OK); - } - }); - /** - * @tc.steps:step3. Call sync async. - * @tc.expected: step3. Always returns OK. - */ - std::thread syncThread([]() { - std::vector devices; - devices.emplace_back(""); - Key key = {'k'}; - for (int i = 0; i < 100; ++i) { // sync 100 times - Query query = Query::Select().PrefixKey(key); - DBStatus status = g_kvNbDelegatePtr->Sync(devices, SYNC_MODE_PULL_ONLY, nullptr, query, true); - EXPECT_EQ(status, OK); - } - }); - syncThread.join(); - finish = true; - putThread.join(); - EXPECT_EQ(mgr.CloseKvStore(g_kvNbDelegatePtr), OK); - g_kvNbDelegatePtr = nullptr; - EXPECT_EQ(mgr.DeleteKvStore(STORE_ID_1), OK); -} - -/** - * @tc.name: UpdateKey001 - * @tc.desc: Test update key - * @tc.type: FUNC - * @tc.require: - * @tc.author: zhangqiquan - */ -HWTEST_F(DistributedDBInterfacesNBDelegateTest, UpdateKey001, TestSize.Level0) -{ - /** - * @tc.steps:step1. Create database. - * @tc.expected: step1. Returns a non-null kvstore. - */ - KvStoreNbDelegate::Option option; - g_mgr.GetKvStore("UpdateKey001", option, g_kvNbDelegateCallback); - ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); - EXPECT_TRUE(g_kvDelegateStatus == OK); - /** - * @tc.steps:step2. Put (k1, v1) into the database. - * @tc.expected: step2. Returns OK. - */ - Key k1 = {'k', '1'}; - EXPECT_EQ(g_kvNbDelegatePtr->Put(k1, VALUE_1), OK); - /** - * @tc.steps:step3. Update (k1, v1) to (k10, v1). - * @tc.expected: step3. Returns OK and get k1 return not found. - */ - g_kvNbDelegatePtr->UpdateKey([](const Key &originKey, Key &newKey) { - newKey = originKey; - newKey.push_back('0'); - }); - Value actualValue; - EXPECT_EQ(g_kvNbDelegatePtr->Get(k1, actualValue), NOT_FOUND); - k1.push_back('0'); - EXPECT_EQ(g_kvNbDelegatePtr->Get(k1, actualValue), OK); - EXPECT_EQ(actualValue, VALUE_1); - /** - * @tc.steps:step4. Close store. - * @tc.expected: step4. Returns OK. - */ - EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); - EXPECT_EQ(g_mgr.DeleteKvStore("UpdateKey001"), OK); - g_kvNbDelegatePtr = nullptr; -} - -/** - * @tc.name: UpdateKey002 - * @tc.desc: Test update key with transaction - * @tc.type: FUNC - * @tc.require: - * @tc.author: zhangqiquan - */ -HWTEST_F(DistributedDBInterfacesNBDelegateTest, UpdateKey002, TestSize.Level0) -{ - /** - * @tc.steps:step1. Create database. - * @tc.expected: step1. Returns a non-null kvstore. - */ - KvStoreNbDelegate::Option option; - g_mgr.GetKvStore("UpdateKey002", option, g_kvNbDelegateCallback); - ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); - EXPECT_TRUE(g_kvDelegateStatus == OK); - /** - * @tc.steps:step2. Put (k1, v1) into the database . - * @tc.expected: step2. Returns OK. - */ - Key k1 = {'k', '1'}; - EXPECT_EQ(g_kvNbDelegatePtr->Put(k1, VALUE_1), OK); - g_kvNbDelegatePtr->StartTransaction(); - /** - * @tc.steps:step3. Update (k1, v1) to (k10, v1). - * @tc.expected: step3. Returns OK and get k1 return not found. - */ - g_kvNbDelegatePtr->UpdateKey([](const Key &originKey, Key &newKey) { - newKey = originKey; - newKey.push_back('0'); - }); - Value actualValue; - EXPECT_EQ(g_kvNbDelegatePtr->Get(k1, actualValue), NOT_FOUND); - Key k10 = {'k', '1', '0'}; - EXPECT_EQ(g_kvNbDelegatePtr->Get(k10, actualValue), OK); - EXPECT_EQ(actualValue, VALUE_1); - /** - * @tc.steps:step5. Rollback Transaction. - * @tc.expected: step5. k10 not exist in db. - */ - g_kvNbDelegatePtr->Rollback(); - EXPECT_EQ(g_kvNbDelegatePtr->Get(k10, actualValue), NOT_FOUND); - EXPECT_EQ(g_kvNbDelegatePtr->Get(k1, actualValue), OK); - /** - * @tc.steps:step5. Commit transaction. - * @tc.expected: step5. data exist in db. - */ - g_kvNbDelegatePtr->StartTransaction(); - g_kvNbDelegatePtr->UpdateKey([](const Key &originKey, Key &newKey) { - newKey = originKey; - newKey.push_back('0'); - }); - g_kvNbDelegatePtr->Commit(); - EXPECT_EQ(g_kvNbDelegatePtr->Get(k10, actualValue), OK); - /** - * @tc.steps:step6. Close store. - * @tc.expected: step6. Returns OK. - */ - EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); - EXPECT_EQ(g_mgr.DeleteKvStore("UpdateKey002"), OK); - g_kvNbDelegatePtr = nullptr; -} - -/** - * @tc.name: UpdateKey003 - * @tc.desc: Test update key with invalid args - * @tc.type: FUNC - * @tc.require: - * @tc.author: zhangqiquan - */ -HWTEST_F(DistributedDBInterfacesNBDelegateTest, UpdateKey003, TestSize.Level0) -{ - /** - * @tc.steps:step1. Create database. - * @tc.expected: step1. Returns a non-null kvstore. - */ - KvStoreNbDelegate::Option option; - g_mgr.GetKvStore("UpdateKey003", option, g_kvNbDelegateCallback); - ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); - EXPECT_TRUE(g_kvDelegateStatus == OK); - /** - * @tc.steps:step2. Put (k1, v1) into the database . - * @tc.expected: step2. Returns OK. - */ - Key k1 = {'k', '1'}; - Key k2 = {'k', '2'}; - EXPECT_EQ(g_kvNbDelegatePtr->Put(k1, VALUE_1), OK); - EXPECT_EQ(g_kvNbDelegatePtr->Put(k2, VALUE_1), OK); - /** - * @tc.steps:step3. Update key with nullptr or invalid key. - * @tc.expected: step3. Returns INVALID_ARGS. - */ - EXPECT_EQ(g_kvNbDelegatePtr->UpdateKey(nullptr), INVALID_ARGS); - DBStatus status = g_kvNbDelegatePtr->UpdateKey([](const Key &originKey, Key &newKey) { - newKey.clear(); - }); - EXPECT_EQ(status, INVALID_ARGS); - status = g_kvNbDelegatePtr->UpdateKey([](const Key &originKey, Key &newKey) { - newKey.assign(2048u, '0'); // 2048 is invalid len - }); - EXPECT_EQ(status, INVALID_ARGS); - status = g_kvNbDelegatePtr->UpdateKey([](const Key &originKey, Key &newKey) { - newKey = {'k', '3'}; - }); - EXPECT_EQ(status, CONSTRAINT); - /** - * @tc.steps:step4. Close store. - * @tc.expected: step4. Returns OK. - */ - EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); - EXPECT_EQ(g_mgr.DeleteKvStore("UpdateKey003"), OK); - g_kvNbDelegatePtr = nullptr; -} - -/** - * @tc.name: BlockTimer001 - * @tc.desc: Test open close function with block timer - * @tc.type: FUNC - * @tc.require: - * @tc.author: zhangqiquan - */ -HWTEST_F(DistributedDBInterfacesNBDelegateTest, BlockTimer001, TestSize.Level0) -{ - /** - * @tc.steps:step1. Create database. - * @tc.expected: step1. Returns a non-null store. - */ - KvStoreNbDelegate::Option option; - g_mgr.GetKvStore("BlockTimer001", option, g_kvNbDelegateCallback); - ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); - EXPECT_TRUE(g_kvDelegateStatus == OK); - /** - * @tc.steps:step2. Create block timer. - * @tc.expected: step2. create ok. - */ - TimerId timerId = 0u; - bool timerFinalize = false; - std::condition_variable cv; - std::mutex finalizeMutex; - bool triggerTimer = false; - std::condition_variable triggerCv; - std::mutex triggerMutex; - int errCode = RuntimeContext::GetInstance()->SetTimer(1, [&triggerTimer, &triggerCv, &triggerMutex](TimerId id) { - { - std::lock_guard autoLock(triggerMutex); - triggerTimer = true; - } - triggerCv.notify_all(); - std::this_thread::sleep_for(std::chrono::seconds(5)); - return -E_END_TIMER; - }, [&timerFinalize, &finalizeMutex, &cv]() { - { - std::lock_guard autoLock(finalizeMutex); - timerFinalize = true; - } - cv.notify_all(); - }, timerId); - ASSERT_EQ(errCode, E_OK); - { - std::unique_lock uniqueLock(triggerMutex); - triggerCv.wait(uniqueLock, [&triggerTimer]() { - return triggerTimer; - }); - } - /** - * @tc.steps:step3. Close store. - * @tc.expected: step3. Returns OK. - */ - EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); - std::unique_lock uniqueLock(finalizeMutex); - EXPECT_TRUE(timerFinalize); - cv.wait(uniqueLock, [&timerFinalize]() { - return timerFinalize; - }); - EXPECT_EQ(g_mgr.DeleteKvStore("BlockTimer001"), OK); - g_kvNbDelegatePtr = nullptr; -} - -/** - * @tc.name: MigrateDeadLockTest0011 - * @tc.desc: Test the will not be deadlock in migration. - * @tc.type: FUNC - * @tc.require: - * @tc.author: zhangshijie - */ -HWTEST_F(DistributedDBInterfacesNBDelegateTest, MigrateDeadLockTest001, TestSize.Level2) -{ - std::shared_ptr g_adapter = std::make_shared(); - RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(g_adapter); - /** - * @tc.steps:step1. Get the nb delegate. - * @tc.expected: step1. Get results OK and non-null delegate. - */ - KvStoreNbDelegate::Option option = {true, false, false}; - option.secOption = {S3, SECE}; - std::string storeId = "distributed_nb_delegate_test"; - g_mgr.GetKvStore(storeId, option, g_kvNbDelegateCallback); - ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); - EXPECT_TRUE(g_kvDelegateStatus == OK); - - KvDBProperties property; - property.SetStringProp(KvDBProperties::DATA_DIR, g_testDir); - property.SetStringProp(KvDBProperties::STORE_ID, storeId); - property.SetIntProp(KvDBProperties::SECURITY_LABEL, S3); - property.SetIntProp(KvDBProperties::SECURITY_FLAG, SECE); - - std::string identifier = DBCommon::GenerateIdentifierId(storeId, APP_ID, USER_ID); - property.SetStringProp(KvDBProperties::IDENTIFIER_DATA, DBCommon::TransferHashString(identifier)); - property.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE_SQLITE); - - int errCode; - SQLiteSingleVerStorageEngine *storageEngine = - static_cast(StorageEngineManager::GetStorageEngine(property, errCode)); - ASSERT_EQ(errCode, E_OK); - ASSERT_NE(storageEngine, nullptr); - storageEngine->SetEngineState(EngineState::CACHEDB); - - /** - * @tc.steps:step2. create cache db - * @tc.expected: step2. operation ok - */ - std::string cacheDir = g_testDir + "/" + DBCommon::TransferStringToHex(DBCommon::TransferHashString(identifier)) + - "/" + DBConstant::SINGLE_SUB_DIR + "/" + DBConstant::CACHEDB_DIR; - std::string cacheDB = cacheDir + "/" + DBConstant::SINGLE_VER_CACHE_STORE + DBConstant::DB_EXTENSION; - EXPECT_EQ(OS::CreateFileByFileName(cacheDB), E_OK); - - EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); - g_mgr.GetKvStore(storeId, option, g_kvNbDelegateCallback); - ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); - EXPECT_TRUE(g_kvDelegateStatus == OK); - - std::this_thread::sleep_for(std::chrono::seconds(3)); // 3 is sleep seconds - EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); - g_kvNbDelegatePtr = nullptr; - if (DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir) != 0) { - LOGE("rm test db files error!"); - } -} - -/** - * @tc.name: InvalidQueryTest001 - * @tc.desc: Test GetEntries with range query filter by sqlite - * @tc.type: FUNC - * @tc.require: - * @tc.author: mazhao - */ -HWTEST_F(DistributedDBInterfacesNBDelegateTest, InvalidQueryTest001, TestSize.Level1) -{ - /** - * @tc.steps:step1. Get the nb delegate. - * @tc.expected: step1. Get results OK and non-null delegate. - */ - KvStoreNbDelegate::Option option; - g_mgr.GetKvStore("InvalidQueryTest001", option, g_kvNbDelegateCallback); - std::vector entries; - ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); - EXPECT_TRUE(g_kvDelegateStatus == OK); - - /** - * @tc.steps: step2. Use range query conditions to obtain the resultset when use sqlite engine. - * @tc.expected: step2. return NOT_SUPPORT. - */ - KvStoreResultSet *resultSet = nullptr; - Query inValidQuery = Query::Select().Range({}, {}); - EXPECT_EQ(g_kvNbDelegatePtr->GetEntries(inValidQuery, resultSet), NOT_SUPPORT); - EXPECT_EQ(g_kvNbDelegatePtr->GetEntries(inValidQuery, entries), NOT_SUPPORT); -} - -/** - * @tc.name: InvalidQueryTest002 - * @tc.desc: Test GetEntries with range query filter by sqlite while conn is nullptr. - * @tc.type: FUNC - * @tc.require: - * @tc.author: caihaoting - */ -HWTEST_F(DistributedDBInterfacesNBDelegateTest, InvalidQueryTest002, TestSize.Level1) -{ - /** - * @tc.steps: step1. initialize result set. - * @tc.expected: step1. Success. - */ - KvStoreNbDelegate::Option option = {true, false, false}; - g_mgr.GetKvStore("InvalidQueryTest002", option, g_kvNbDelegateCallback); - ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); - EXPECT_TRUE(g_kvDelegateStatus == OK); - InitResultSet(); - - /** - * @tc.steps: step2. get entries using result set while conn is nullptr. - * @tc.expected: step2. DB_ERROR. - */ - KvStoreResultSet *readResultSet = nullptr; - auto kvStoreImpl = static_cast(g_kvNbDelegatePtr); - EXPECT_EQ(kvStoreImpl->Close(), OK); - EXPECT_EQ(g_kvNbDelegatePtr->GetEntries(g_keyPrefix, readResultSet), DB_ERROR); - ASSERT_TRUE(readResultSet == nullptr); - - std::vector entries; - Query query = Query::Select().PrefixKey({'a', 'c'}); - EXPECT_EQ(g_kvNbDelegatePtr->GetEntries(query, entries), DB_ERROR); - EXPECT_EQ(entries.size(), 0UL); - - EXPECT_EQ(g_kvNbDelegatePtr->GetEntries(query, readResultSet), DB_ERROR); - ASSERT_TRUE(readResultSet == nullptr); - - int count = -1; - EXPECT_EQ(g_kvNbDelegatePtr->GetCount(query, count), DB_ERROR); - EXPECT_EQ(count, -1); - - /** - * @tc.steps: step3. close kvStore. - * @tc.expected: step3. Success. - */ - EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); - EXPECT_EQ(g_mgr.DeleteKvStore("InvalidQueryTest002"), OK); - g_kvNbDelegatePtr = nullptr; -} - -/** - * @tc.name: SyncRangeQuery001 - * @tc.desc: test sync query with range - * @tc.type: FUNC - * @tc.require: DTS2023112110763 - * @tc.author: mazhao - */ -HWTEST_F(DistributedDBInterfacesNBDelegateTest, SyncRangeQuery001, TestSize.Level3) -{ - /** - * @tc.steps:step1. Create database with localOnly. - * @tc.expected: step1. Returns a non-null store. - */ - InitVirtualDevice(DEVICE_B, g_deviceB, g_syncInterfaceB); - KvStoreDelegateManager mgr(APP_ID, USER_ID); - mgr.SetKvStoreConfig(g_config); - const KvStoreNbDelegate::Option option = {true, false, false}; - mgr.GetKvStore(STORE_ID_1, option, g_kvNbDelegateCallback); - ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); - EXPECT_EQ(g_kvDelegateStatus, OK); - /** - * @tc.steps:step2. Construct invalid query with range, Call sync async. - * @tc.expected: step2. returns NOT_SUPPORT. - */ - std::vector devices; - devices.emplace_back(DEVICE_B); - Query inValidQuery = Query::Select().Range({}, {}); - DBStatus status = g_kvNbDelegatePtr->Sync(devices, SYNC_MODE_PULL_ONLY, nullptr, inValidQuery, true); - EXPECT_EQ(status, NOT_SUPPORT); - EXPECT_EQ(mgr.CloseKvStore(g_kvNbDelegatePtr), OK); - g_kvNbDelegatePtr = nullptr; - EXPECT_EQ(mgr.DeleteKvStore(STORE_ID_1), OK); -} - -/** - * @tc.name: OptionValidCheck001 - * @tc.desc: test validation of option mode - * @tc.type: FUNC - * @tc.require: - * @tc.author: zhangshijie - */ -HWTEST_F(DistributedDBInterfacesNBDelegateTest, OptionModeValidCheck001, TestSize.Level0) -{ - /** - * @tc.steps:step1. Get the nb delegate. - * @tc.expected: step1. Get results OK and non-null delegate. - */ - KvStoreNbDelegate::Option option = {true, false, false}; - KvStoreObserverUnitTest *observer = new KvStoreObserverUnitTest(); - ASSERT_TRUE(observer != nullptr); - option.observer = observer; - std::vector invalidModeVec = {0, 5, 6, 7, 9, 16}; - std::string storeId = "OptionModeValidCheck001"; - for (size_t i = 0; i < invalidModeVec.size(); i++) { - option.mode = invalidModeVec.at(i); - g_mgr.GetKvStore(storeId, option, g_kvNbDelegateCallback); - ASSERT_TRUE(g_kvNbDelegatePtr == nullptr); - EXPECT_EQ(g_kvDelegateStatus, INVALID_ARGS); - } - - std::vector validModeVec = {1, 2, 3, 4, 8}; - for (size_t i = 0; i < validModeVec.size(); i++) { - option.mode = validModeVec.at(i); - g_mgr.GetKvStore(storeId, option, g_kvNbDelegateCallback); - ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); - EXPECT_EQ(g_kvDelegateStatus, OK); - EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); - EXPECT_EQ(g_mgr.DeleteKvStore(storeId), OK); - g_kvNbDelegatePtr = nullptr; - } - - delete observer; -} - -/** - * @tc.name: AbnormalKvStoreTest001 - * @tc.desc: Test KvStoreNbDelegateImpl interface while conn is nullptr. - * @tc.type: FUNC - * @tc.require: - * @tc.author: suyue - */ -HWTEST_F(DistributedDBInterfacesNBDelegateTest, AbnormalKvStoreTest001, TestSize.Level1) -{ - /** - * @tc.steps: step1. GetKvStore for initialize g_kvNbDelegatePtr. - * @tc.expected: step1. Success. - */ - KvStoreNbDelegate::Option option = {true, false, false}; - g_mgr.GetKvStore("AbnormalKvStoreTest001", option, g_kvNbDelegateCallback); - ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); - EXPECT_TRUE(g_kvDelegateStatus == OK); - InitResultSet(); - - /** - * @tc.steps: step2. test KvStoreNbDelegateImpl interface while conn is nullptr. - * @tc.expected: step2. return DB_ERROR. - */ - auto kvStoreImpl = static_cast(g_kvNbDelegatePtr); - EXPECT_EQ(kvStoreImpl->Close(), OK); - - const Key key = {0}; - EXPECT_EQ(kvStoreImpl->PublishLocal(key, true, true, nullptr), DB_ERROR); - EXPECT_EQ(kvStoreImpl->UnpublishToLocal(key, true, true), DB_ERROR); - EXPECT_EQ(kvStoreImpl->UnpublishToLocal({}, true, true), INVALID_ARGS); - EXPECT_EQ(kvStoreImpl->RemoveDeviceData(""), DB_ERROR); - bool autoSync = true; - PragmaData data = static_cast(&autoSync); - EXPECT_EQ(kvStoreImpl->Pragma(AUTO_SYNC, data), DB_ERROR); - EXPECT_EQ(kvStoreImpl->SetConflictNotifier(0, nullptr), DB_ERROR); - CipherPassword password; - EXPECT_EQ(kvStoreImpl->Rekey(password), DB_ERROR); - EXPECT_EQ(kvStoreImpl->Export("", password, true), DB_ERROR); - EXPECT_EQ(kvStoreImpl->Import("", password), DB_ERROR); - EXPECT_EQ(kvStoreImpl->StartTransaction(), DB_ERROR); - EXPECT_EQ(kvStoreImpl->Commit(), DB_ERROR); - EXPECT_EQ(kvStoreImpl->Rollback(), DB_ERROR); - EXPECT_EQ(kvStoreImpl->CheckIntegrity(), DB_ERROR); - SecurityOption securityOption; - EXPECT_EQ(kvStoreImpl->GetSecurityOption(securityOption), DB_ERROR); - EXPECT_EQ(kvStoreImpl->SetRemotePushFinishedNotify(nullptr), DB_ERROR); - EXPECT_EQ(kvStoreImpl->SetEqualIdentifier("", {}), DB_ERROR); - EXPECT_EQ(kvStoreImpl->SetPushDataInterceptor(nullptr), DB_ERROR); - - /** - * @tc.steps: step3. close kvStore. - * @tc.expected: step3. Success. - */ - EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); - EXPECT_EQ(g_mgr.DeleteKvStore("AbnormalKvStoreTest001"), OK); - g_kvNbDelegatePtr = nullptr; -} - -/** - * @tc.name: AbnormalKvStoreTest002 - * @tc.desc: Test KvStoreNbDelegateImpl interface while conn is nullptr. - * @tc.type: FUNC - * @tc.require: - * @tc.author: suyue - */ -HWTEST_F(DistributedDBInterfacesNBDelegateTest, AbnormalKvStoreTest002, TestSize.Level1) -{ - /** - * @tc.steps: step1. GetKvStore for initialize g_kvNbDelegatePtr. - * @tc.expected: step1. Success. - */ - KvStoreNbDelegate::Option option = {true, false, false}; - g_mgr.GetKvStore("AbnormalKvStoreTest002", option, g_kvNbDelegateCallback); - ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); - EXPECT_TRUE(g_kvDelegateStatus == OK); - InitResultSet(); - - /** - * @tc.steps: step2. test KvStoreNbDelegateImpl interface while conn is nullptr. - * @tc.expected: step2. return DB_ERROR. - */ - auto kvStoreImpl = static_cast(g_kvNbDelegatePtr); - EXPECT_EQ(kvStoreImpl->Close(), OK); - - Query query; - EXPECT_EQ(kvStoreImpl->SubscribeRemoteQuery({}, nullptr, query, true), DB_ERROR); - EXPECT_EQ(kvStoreImpl->UnSubscribeRemoteQuery({}, nullptr, query, true), DB_ERROR); - EXPECT_EQ(kvStoreImpl->RemoveDeviceData(), DB_ERROR); - const Key key = {0}; - std::vector keys; - EXPECT_EQ(kvStoreImpl->GetKeys(key, keys), DB_ERROR); - uint32_t expectedVal = 0; - EXPECT_EQ(kvStoreImpl->GetSyncDataSize(""), expectedVal); - EXPECT_EQ(kvStoreImpl->UpdateKey(nullptr), DB_ERROR); - const std::string device = "test"; - std::pair info = kvStoreImpl->GetWatermarkInfo(device); - EXPECT_EQ(info.first, DB_ERROR); - EXPECT_EQ(kvStoreImpl->GetTaskCount(), DB_ERROR); - EXPECT_EQ(kvStoreImpl->SetReceiveDataInterceptor(nullptr), DB_ERROR); - CloudSyncConfig config; - EXPECT_EQ(kvStoreImpl->SetCloudSyncConfig(config), DB_ERROR); - const IOption iOption; - std::vector entries; - EXPECT_EQ(kvStoreImpl->GetEntries(key, entries), DB_ERROR); - - /** - * @tc.steps: step3. close kvStore. - * @tc.expected: step3. Success. - */ - EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); - EXPECT_EQ(g_mgr.DeleteKvStore("AbnormalKvStoreTest002"), OK); - g_kvNbDelegatePtr = nullptr; -} - -/** - * @tc.name: AbnormalKvStoreResultSetTest - * @tc.desc: Test KvStoreResultSetImpl interface when class para is nullptr. - * @tc.type: FUNC - * @tc.require: - * @tc.author: suyue - */ -HWTEST_F(DistributedDBInterfacesNBDelegateTest, AbnormalKvStoreResultSetTest, TestSize.Level1) -{ - /** - * @tc.steps: step1. Call interfaces when calss para is null. - * @tc.expected: step1. return failInfo. - */ - KvStoreResultSetImpl kvStoreObj(nullptr); - EXPECT_EQ(kvStoreObj.GetCount(), 0); - EXPECT_EQ(kvStoreObj.GetPosition(), INIT_POSITION); - EXPECT_EQ(kvStoreObj.Move(0), false); - EXPECT_EQ(kvStoreObj.MoveToPosition(0), false); - EXPECT_EQ(kvStoreObj.MoveToFirst(), false); - EXPECT_EQ(kvStoreObj.MoveToLast(), false); - EXPECT_EQ(kvStoreObj.IsFirst(), false); - EXPECT_EQ(kvStoreObj.IsLast(), false); - EXPECT_EQ(kvStoreObj.IsBeforeFirst(), false); - EXPECT_EQ(kvStoreObj.IsAfterLast(), false); - std::vector columnNames; - kvStoreObj.GetColumnNames(columnNames); - Entry entry; - EXPECT_EQ(kvStoreObj.GetEntry(entry), DB_ERROR); - EXPECT_EQ(kvStoreObj.IsClosed(), false); - kvStoreObj.Close(); - - /** - * @tc.steps: step2. Call unsupported interfaces. - * @tc.expected: step2. return NOT_SUPPORT. - */ - std::string columnName; - int columnIndex = 0; - EXPECT_EQ(kvStoreObj.GetColumnIndex(columnName, columnIndex), NOT_SUPPORT); - EXPECT_EQ(kvStoreObj.GetColumnName(columnIndex, columnName), NOT_SUPPORT); - std::vector vecVal; - EXPECT_EQ(kvStoreObj.Get(columnIndex, vecVal), NOT_SUPPORT); - std::string strVal; - EXPECT_EQ(kvStoreObj.Get(columnIndex, strVal), NOT_SUPPORT); - int64_t intVal; - EXPECT_EQ(kvStoreObj.Get(columnIndex, intVal), NOT_SUPPORT); - double doubleVal; - EXPECT_EQ(kvStoreObj.Get(columnIndex, doubleVal), NOT_SUPPORT); - bool isNull; - EXPECT_EQ(kvStoreObj.IsColumnNull(columnIndex, isNull), NOT_SUPPORT); - std::map data; - EXPECT_EQ(kvStoreObj.GetRow(data), NOT_SUPPORT); -} - -/** - * @tc.name: AbnormalKvStoreTest003 - * @tc.desc: Test SqliteCloudKvStore interface when para is invalid. - * @tc.type: FUNC - * @tc.require: - * @tc.author: suyue - */ -HWTEST_F(DistributedDBInterfacesNBDelegateTest, AbnormalKvStoreTest003, TestSize.Level1) -{ - /** - * @tc.steps: step1. Call defaule interfaces. - * @tc.expected: step1. return E_OK. - */ - SqliteCloudKvStore kvStoreObj(nullptr); - DataBaseSchema schema; - EXPECT_EQ(kvStoreObj.SetCloudDbSchema(schema), E_OK); - EXPECT_EQ(kvStoreObj.Commit(), E_OK); - EXPECT_EQ(kvStoreObj.Rollback(), E_OK); - const TableName tableName = "test"; - VBucket vBucket; - EXPECT_EQ(kvStoreObj.FillCloudAssetForDownload(tableName, vBucket, true), E_OK); - EXPECT_EQ(kvStoreObj.SetLogTriggerStatus(true), E_OK); - QuerySyncObject query; - EXPECT_EQ(kvStoreObj.CheckQueryValid(query), E_OK); - ContinueToken continueStmtToken = nullptr; - EXPECT_EQ(kvStoreObj.ReleaseCloudDataToken(continueStmtToken), E_OK); - std::vector syncQuery; - std::vector users; - EXPECT_EQ(kvStoreObj.GetCompensatedSyncQuery(syncQuery, users), E_OK); - - /** - * @tc.steps: step2. Call interfaces when class para is null. - * @tc.expected: step2. return failInfo. - */ - DataInfoWithLog log; - EXPECT_EQ(kvStoreObj.GetInfoByPrimaryKeyOrGid(tableName, vBucket, log, vBucket), -E_INTERNAL_ERROR); - DownloadData downloadData; - EXPECT_EQ(kvStoreObj.PutCloudSyncData(tableName, downloadData), -E_INTERNAL_ERROR); - Timestamp timestamp = 0; - int64_t count = 0; - EXPECT_EQ(kvStoreObj.GetUploadCount(query, timestamp, true, true, count), -E_INTERNAL_ERROR); - std::vector timestampVec; - EXPECT_EQ(kvStoreObj.GetAllUploadCount(query, timestampVec, true, true, count), -E_INTERNAL_ERROR); - - /** - * @tc.steps: step3. Get and set Schema with different para when class para is null. - * @tc.expected: step3. return failInfo. - */ - TableSchema tableSchema; - EXPECT_EQ(kvStoreObj.GetCloudTableSchema(tableName, tableSchema), -E_NOT_FOUND); - CloudSyncData cloudDataResult; - EXPECT_EQ(kvStoreObj.GetCloudDataNext(continueStmtToken, cloudDataResult), -E_INVALID_ARGS); - std::map schemaMap; - EXPECT_EQ(kvStoreObj.SetCloudDbSchema(schemaMap), -E_INVALID_SCHEMA); - schema.tables = {tableSchema, tableSchema}; - schemaMap.insert(std::pair(tableName, schema)); - EXPECT_EQ(kvStoreObj.SetCloudDbSchema(schemaMap), -E_INVALID_SCHEMA); - const std::string user = "user1"; - kvStoreObj.SetUser(user); - EXPECT_EQ(kvStoreObj.GetCloudTableSchema(tableName, tableSchema), -E_SCHEMA_MISMATCH); } -} \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_query_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_query_test.cpp index f5a1264b6a9a707409b9c0ba870b58fd92110af2..489bb98726aecde7810698dace82766ae37d666a 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_query_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_query_test.cpp @@ -228,12 +228,12 @@ HWTEST_F(DistributedDBInterfacesQueryTest, Query003, TestSize.Level1) } /** - * @tc.name: Query004 - * @tc.desc: Check QueryExpression abnormal scene - * @tc.type: FUNC - * @tc.require: - * @tc.author: suyue - */ + * @tc.name: Query004 + * @tc.desc: Check QueryExpression abnormal scene + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ HWTEST_F(DistributedDBInterfacesQueryTest, Query004, TestSize.Level1) { /** diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_sync_test.cpp index 10f0c9034c56c01b28c19b7cef6ee1f661ad4b3f..2e9356fa297a294ae53eba8db73b3e62231df93e 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_sync_test.cpp @@ -1098,7 +1098,7 @@ HWTEST_F(DistributedDBInterfacesRelationalSyncTest, RelationalSyncRangeTest001, * @tc.type: FUNC * @tc.require: * @tc.author: caihaoting - */ + */ HWTEST_F(DistributedDBInterfacesRelationalSyncTest, RelationalSyncTest011, TestSize.Level1) { sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_tracker_table_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_tracker_table_test.cpp index 3ead474087391c0c6ac94bbdf4a34513c2bc814f..9553ba83f650385a211d40ded5fb04c18f1ef7b9 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_tracker_table_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_tracker_table_test.cpp @@ -139,10 +139,10 @@ namespace { BatchDeleteTableName2Data(num); } - void CheckExtendAndCursor(uint64_t num, int start) + void CheckExtendAndCursor(uint64_t num, int start, const std::string &tableName, bool addNum = true) { int index = 0; - string querySql = "select extend_field, cursor from " + DBConstant::RELATIONAL_PREFIX + TABLE_NAME2 + "_log" + + string querySql = "select extend_field, cursor from " + DBConstant::RELATIONAL_PREFIX + tableName + "_log" + " where data_key <= " + std::to_string(num); sqlite3_stmt *stmt = nullptr; EXPECT_EQ(SQLiteUtils::GetStatement(g_db, querySql, stmt), E_OK); @@ -153,12 +153,19 @@ namespace { EXPECT_EQ(extendVal, "Local" + std::to_string(index % num)); std::string cursorVal; EXPECT_EQ(SQLiteUtils::GetColumnTextValue(stmt, 1, cursorVal), E_OK); - EXPECT_EQ(cursorVal, std::to_string(num + (++index) + start)); + auto expectCursor = (++index) + start; + auto expectCursorStr = addNum ? std::to_string(num + expectCursor) : std::to_string(expectCursor); + EXPECT_EQ(cursorVal, expectCursorStr); } int errCode; SQLiteUtils::ResetStatement(stmt, true, errCode); } + void CheckExtendAndCursor(uint64_t num, int start) + { + CheckExtendAndCursor(num, start, TABLE_NAME2); + } + void OpenStore() { if (g_db == nullptr) { @@ -1812,6 +1819,123 @@ HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest027, CloseStore(); } +/** + * @tc.name: TrackerTableTest028 + * @tc.desc: Test set tracker table colNames from not empty to empty + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest028, TestSize.Level0) +{ + /** + * @tc.steps:step1. trackerColNames is empty + * @tc.expected: step1. Return OK. + */ + TrackerSchema schema; + schema.tableName = TABLE_NAME2; + SetTrackerTableTest(schema, OK); + + /** + * @tc.steps:step2. trackerColNames is not empty + * @tc.expected: step2. Return OK. + */ + schema.extendColName = EXTEND_COL_NAME2; + schema.trackerColNames = LOCAL_TABLE_TRACKER_NAME_SET2; + SetTrackerTableTest(schema, OK); + + /** + * @tc.steps:step3. trackerColNames is empty and track action + * @tc.expected: step3. Return OK. + */ + schema.trackerColNames = {}; + schema.isTrackAction = true; + SetTrackerTableTest(schema, OK); + SetTrackerTableTest(schema, OK); + + OpenStore(); + uint64_t num = 10; + BatchInsertTableName2Data(num); + CheckExtendAndCursor(num, 0, schema.tableName, false); + BatchUpdateTableName2Data(num, {"age"}); + CheckExtendAndCursor(num, num, schema.tableName, false); + CloseStore(); +} + +/** + * @tc.name: TrackerTableTest029 + * @tc.desc: Test set tracker table with force upgrade + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest029, TestSize.Level0) +{ + CreateMultiTable(); + OpenStore(); + /** + * @tc.steps:step1. set tracker table + * @tc.expected: step1. Return OK. + */ + TrackerSchema schema; + schema.tableName = TABLE_NAME2; + schema.trackerColNames = LOCAL_TABLE_TRACKER_NAME_SET2; + EXPECT_EQ(g_delegate->SetTrackerTable(schema), OK); + /** + * @tc.steps:step2. rebuild table and insert data + * @tc.expected: step2. Return OK. + */ + EXPECT_EQ(RelationalTestUtils::ExecSql(g_db, "DROP TABLE " + schema.tableName), SQLITE_OK); + EXPECT_EQ(RelationalTestUtils::ExecSql(g_db, CREATE_LOCAL_PK_TABLE_SQL), SQLITE_OK); + uint64_t num = 10; + BatchInsertTableName2Data(num); + /** + * @tc.steps:step3. rebuild table and insert data + * @tc.expected: step3. Return OK. + */ + schema.isForceUpgrade = true; + EXPECT_EQ(g_delegate->SetTrackerTable(schema), WITH_INVENTORY_DATA); + CloseStore(); +} + +/** + * @tc.name: TrackerTableTest030 + * @tc.desc: Test clean trackTable when table is distributedTable + * @tc.type: FUNC + * @tc.require: + * @tc.author: wangxiangdong + */ +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest030, TestSize.Level0) +{ + /** + * @tc.steps:step1. SetTrackerTable + * @tc.expected: step1. Return OK. + */ + CreateMultiTable(); + + OpenStore(); + EXPECT_EQ(g_delegate->CreateDistributedTable(TABLE_NAME2), OK); + + /** + * @tc.steps:step2. Insert data to table2 + * @tc.expected: step2. Return E_OK. + */ + uint64_t num = 10; + BatchInsertTableName2Data(num); + BatchDeleteTableName2Data(num / HALF); + + /** + * @tc.steps:step3. CleanTrackerData + * @tc.expected: step3. Return OK. + */ + EXPECT_EQ(g_delegate->CleanTrackerData(TABLE_NAME2, num + (num / HALF)), OK); + std::string sql = "select count(*) from " + DBConstant::RELATIONAL_PREFIX + TABLE_NAME2 + "_log" + + " where extend_field is NULL;"; + EXPECT_EQ(sqlite3_exec(g_db, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback, + reinterpret_cast(num), nullptr), SQLITE_OK); + CloseStore(); +} + /** * @tc.name: SchemaStrTest001 * @tc.desc: Test open reOpen stroe when schemaStr is empty diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/process_system_api_adapter_impl.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/process_system_api_adapter_impl.cpp index b730aa9ebc33001990529d48fdfa7a92cd3a46b7..6b7ca36a1550207ba263840e2ad1a4e74ad7aa88 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/process_system_api_adapter_impl.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/process_system_api_adapter_impl.cpp @@ -180,4 +180,10 @@ void ProcessSystemApiAdapterImpl::ForkCheckDeviceSecurityAbility( { checkDeviceCallBack_ = callBack; } + +std::map ProcessSystemApiAdapterImpl::GetExistSecOpt() const +{ + std::lock_guard autoLock(adapterlock_); + return pathSecOptDic_; +} }; diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/process_system_api_adapter_impl.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/process_system_api_adapter_impl.h index 98ce816cbc7505eac57017bb118f671ce0158261..0847fddf09bab87a6330f70fe99637f7234063af 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/process_system_api_adapter_impl.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/process_system_api_adapter_impl.h @@ -41,6 +41,7 @@ public: void ForkGetSecurityOption(std::function callBack); void ForkCheckDeviceSecurityAbility(std::function callBack); + std::map GetExistSecOpt() const; private: mutable std::mutex adapterlock_; OnAccessControlledEvent callback_; diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/runtime_context_process_system_api_adapter_impl_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/runtime_context_process_system_api_adapter_impl_test.cpp index 8d592cf5ae1775d3f69aea24bafb93830994b3fd..1b535aa93c0ecbad77e8222044b8f4ed89183fbd 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/runtime_context_process_system_api_adapter_impl_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/runtime_context_process_system_api_adapter_impl_test.cpp @@ -380,6 +380,106 @@ HWTEST_F(RuntimeContextProcessSystemApiAdapterImplTest, SecurityOptionUpgrade002 EXPECT_EQ(g_kvDelegateStatus, OK); ASSERT_NE(g_kvNbDelegatePtr, nullptr); EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + EXPECT_EQ(g_mgr.DeleteKvStore(storeId), OK); + RuntimeContext::GetInstance()->SetCommunicatorAggregator(nullptr); + RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(nullptr); +} + +/** + * @tc.name: SecurityOptionUpgrade003 + * @tc.desc: Test upgrade with error security label. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(RuntimeContextProcessSystemApiAdapterImplTest, SecurityOptionUpgrade003, TestSize.Level0) +{ + /** + * @tc.steps: step1. set g_adapter and open with not set + * @tc.expected: step1. return true + */ + RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(g_adapter); + RuntimeContext::GetInstance()->SetCommunicatorAggregator(new(std::nothrow) VirtualCommunicatorAggregator); + EXPECT_TRUE(g_mgr.IsProcessSystemApiAdapterValid()); + g_config.dataDir = g_testDir; + EXPECT_EQ(g_mgr.SetKvStoreConfig(g_config), OK); + + const std::string storeId = "SecurityOptionUpgrade003"; + KvStoreNbDelegate::Option option = {true, false, false}; + option.secOption = { NOT_SET, ECE }; + g_mgr.GetKvStore(storeId, option, g_kvNbDelegateCallback); + EXPECT_EQ(g_kvDelegateStatus, OK); + ASSERT_NE(g_kvNbDelegatePtr, nullptr); + /** + * @tc.steps: step2. re open with s3 + * @tc.expected: step2. open ok + */ + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + auto existSecOpt = g_adapter->GetExistSecOpt(); + option.secOption = { S3, SECE }; + for (const auto &item : existSecOpt) { + g_adapter->SetSecurityOption(item.first, option.secOption); + } + + g_mgr.GetKvStore(storeId, option, g_kvNbDelegateCallback); + EXPECT_EQ(g_kvDelegateStatus, OK); + ASSERT_NE(g_kvNbDelegatePtr, nullptr); + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + EXPECT_EQ(g_mgr.DeleteKvStore(storeId), OK); + RuntimeContext::GetInstance()->SetCommunicatorAggregator(nullptr); + RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(nullptr); +} + +/** + * @tc.name: SecurityOptionUpgrade004 + * @tc.desc: Test upgrade security label when set failed. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(RuntimeContextProcessSystemApiAdapterImplTest, SecurityOptionUpgrade004, TestSize.Level0) +{ + /** + * @tc.steps: step1. set g_adapter and open with not set + * @tc.expected: step1. return true + */ + RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(g_adapter); + RuntimeContext::GetInstance()->SetCommunicatorAggregator(new(std::nothrow) VirtualCommunicatorAggregator); + EXPECT_TRUE(g_mgr.IsProcessSystemApiAdapterValid()); + g_config.dataDir = g_testDir; + EXPECT_EQ(g_mgr.SetKvStoreConfig(g_config), OK); + + const std::string storeId = "SecurityOptionUpgrade004"; + KvStoreNbDelegate::Option option = {true, false, false}; + option.secOption = { S1, ECE }; + g_mgr.GetKvStore(storeId, option, g_kvNbDelegateCallback); + EXPECT_EQ(g_kvDelegateStatus, OK); + ASSERT_NE(g_kvNbDelegatePtr, nullptr); + /** + * @tc.steps: step2. re open with s2 but get s3 + * @tc.expected: step2. open ok + */ + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + auto existSecOpt = g_adapter->GetExistSecOpt(); + option.secOption = { S3, SECE }; + for (const auto &item : existSecOpt) { + if (item.first.substr(item.first.size() - std::string(".db").size()) != std::string(".db")) { + continue; + } + g_adapter->SetSecurityOption(item.first, option.secOption); + } + option.secOption = { S2, ECE }; + g_mgr.GetKvStore(storeId, option, g_kvNbDelegateCallback); + EXPECT_EQ(g_kvDelegateStatus, OK); + ASSERT_NE(g_kvNbDelegatePtr, nullptr); + existSecOpt = g_adapter->GetExistSecOpt(); + for (const auto &item : existSecOpt) { + if (item.first.substr(item.first.size() - std::string(".db").size()) != std::string(".db")) { + continue; + } + EXPECT_EQ(item.second.securityLabel, option.secOption.securityLabel); + } + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + EXPECT_EQ(g_mgr.DeleteKvStore(storeId), OK); RuntimeContext::GetInstance()->SetCommunicatorAggregator(nullptr); RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(nullptr); } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_assets_operation_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_assets_operation_sync_test.cpp index 249139cedad8d00e236e1bdc316cf6fb6dfe28c1..00607b548f82ab9f07827da427d8da9a97748a98 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_assets_operation_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_assets_operation_sync_test.cpp @@ -44,6 +44,7 @@ const char *g_createSQL = "assets ASSETS," \ "age INT);"; const int64_t g_syncWaitTime = 60; +const int g_assetsNum = 3; const Asset g_localAsset = { .version = 2, .name = "Phone", .assetId = "0", .subpath = "/local/sync", .uri = "/cloud/sync", .modifyTime = "123456", .createTime = "0", .size = "1024", .hash = "DEC" @@ -56,7 +57,7 @@ void CreateUserDBAndTable(sqlite3 *&db) EXPECT_EQ(RelationalTestUtils::ExecSql(db, g_createSQL), SQLITE_OK); } -void BlockSync(const Query &query, RelationalStoreDelegate *delegate) +void BlockSync(const Query &query, RelationalStoreDelegate *delegate, SyncMode syncMode = SYNC_MODE_CLOUD_MERGE) { std::mutex dataMutex; std::condition_variable cv; @@ -75,7 +76,7 @@ void BlockSync(const Query &query, RelationalStoreDelegate *delegate) } }; LOGW("begin call sync"); - ASSERT_EQ(delegate->Sync({ "CLOUD" }, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime), OK); + ASSERT_EQ(delegate->Sync({ "CLOUD" }, syncMode, query, callback, g_syncWaitTime), OK); std::unique_lock uniqueLock(dataMutex); cv.wait(uniqueLock, [&finish]() { return finish; @@ -90,17 +91,23 @@ public: static void TearDownTestCase(); void SetUp() override; void TearDown() override; + void WriteDataWithoutCommitTransaction(); protected: void InitTestDir(); DataBaseSchema GetSchema(); void CloseDb(); void InsertUserTableRecord(const std::string &tableName, int64_t begin, int64_t count, size_t assetCount = 2u, const Assets &templateAsset = {}); - void CheckAssetsCount(const std::vector &expectCount); + void UpdateLocalTableRecord(const std::string &tableName, int64_t begin, int64_t count, size_t assetCount = 2u, + bool updateAssets = true); + void CheckAssetsCount(const std::vector &expectCount, bool checkAsset = false); void UpdateCloudTableRecord(int64_t begin, int64_t count, bool assetIsNull); void ForkDownloadAndRemoveAsset(DBStatus removeStatus, int &downLoadCount, int &removeCount); + void InsertLocalAssetData(const std::string &assetHash); + void InsertCloudAssetData(const std::string &assetHash); + void PrepareForAssetOperation010(); + void UpdateAssetWhenSyncUpload(); std::vector GetAssets(const std::string &baseName, const Assets &templateAsset, size_t assetCount); - void CheckAssetData(); std::string testDir_; std::string storePath_; sqlite3 *db_ = nullptr; @@ -111,6 +118,9 @@ protected: std::shared_ptr mgr_ = nullptr; std::string tableName_ = "DistributedDBCloudAssetsOperationSyncTest"; VirtualCommunicatorAggregator *communicatorAggregator_ = nullptr; + TrackerSchema trackerSchema = { + .tableName = tableName_, .extendColName = "name", .trackerColNames = {"age"} + }; }; void DistributedDBCloudAssetsOperationSyncTest::SetUpTestCase() @@ -124,6 +134,7 @@ void DistributedDBCloudAssetsOperationSyncTest::TearDownTestCase() void DistributedDBCloudAssetsOperationSyncTest::SetUp() { DistributedDBToolsUnitTest::PrintTestCaseInfo(); + RuntimeContext::GetInstance()->SetBatchDownloadAssets(false); InitTestDir(); if (DistributedDBToolsUnitTest::RemoveTestDbFiles(testDir_) != 0) { LOGE("rm test db files error."); @@ -138,6 +149,7 @@ void DistributedDBCloudAssetsOperationSyncTest::SetUp() ASSERT_EQ(mgr_->OpenStore(storePath_, STORE_ID_1, option, delegate_), DBStatus::OK); ASSERT_NE(delegate_, nullptr); ASSERT_EQ(delegate_->CreateDistributedTable(tableName_, CLOUD_COOPERATION), DBStatus::OK); + ASSERT_EQ(delegate_->SetTrackerTable(trackerSchema), DBStatus::OK); virtualCloudDb_ = std::make_shared(); virtualAssetLoader_ = std::make_shared(); ASSERT_EQ(delegate_->SetCloudDB(virtualCloudDb_), DBStatus::OK); @@ -223,6 +235,34 @@ void DistributedDBCloudAssetsOperationSyncTest::InsertUserTableRecord(const std: } } +void DistributedDBCloudAssetsOperationSyncTest::UpdateLocalTableRecord(const std::string &tableName, int64_t begin, + int64_t count, size_t assetCount, bool updateAssets) +{ + int errCode; + std::vector assetBlob; + std::vector assetsBlob; + std::string hash = updateAssets ? "new_hash" : g_localAsset.hash; + for (int64_t i = begin; i < begin + count; ++i) { + std::string name = g_localAsset.name + std::to_string(i); + Asset asset = g_localAsset; + asset.name = name; + asset.hash = hash; + RuntimeContext::GetInstance()->AssetToBlob(asset, assetBlob); + std::vector assets = GetAssets(name, {}, assetCount); + RuntimeContext::GetInstance()->AssetsToBlob(assets, assetsBlob); + std::string dataName = "new_name_" + std::to_string(i); + std::string sql = "UPDATE " + tableName + " SET name = ?, asset = ?, assets = ? where id = " + + std::to_string(i); + sqlite3_stmt *stmt = nullptr; + ASSERT_EQ(SQLiteUtils::GetStatement(db_, sql, stmt), E_OK); + ASSERT_EQ(SQLiteUtils::BindTextToStatement(stmt, 1, dataName), E_OK); // 1st bind + ASSERT_EQ(SQLiteUtils::BindBlobToStatement(stmt, 2, assetBlob, false), E_OK); // 2nd bind + ASSERT_EQ(SQLiteUtils::BindBlobToStatement(stmt, 3, assetsBlob, false), E_OK); // 3rd bind + EXPECT_EQ(SQLiteUtils::StepWithRetry(stmt), SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)); + SQLiteUtils::ResetStatement(stmt, true, errCode); + } +} + std::vector DistributedDBCloudAssetsOperationSyncTest::GetAssets(const std::string &baseName, const Assets &templateAsset, size_t assetCount) { @@ -274,7 +314,8 @@ void DistributedDBCloudAssetsOperationSyncTest::UpdateCloudTableRecord(int64_t b ASSERT_EQ(virtualCloudDb_->BatchUpdate(tableName_, std::move(record), extend), DBStatus::OK); } -void DistributedDBCloudAssetsOperationSyncTest::CheckAssetsCount(const std::vector &expectCount) +void DistributedDBCloudAssetsOperationSyncTest::CheckAssetsCount(const std::vector &expectCount, + bool checkAsset) { std::vector allData; auto dbSchema = GetSchema(); @@ -292,8 +333,14 @@ void DistributedDBCloudAssetsOperationSyncTest::CheckAssetsCount(const std::vect Type colValue = data.at("assets"); auto translate = std::dynamic_pointer_cast(virtualTranslator_); auto assets = RelationalTestUtils::GetAssets(colValue, translate); + size_t size = assets.size(); + if (checkAsset) { + Type colValue1 = data.at("asset"); + auto assets1 = RelationalTestUtils::GetAssets(colValue1, translate, true); + size += assets1.size(); + } LOGI("[DistributedDBCloudAssetsOperationSyncTest] Check data index %d", index); - EXPECT_EQ(assets.size(), expectCount[index]); + EXPECT_EQ(static_cast(size), expectCount[index]); for (const auto &item : assets) { LOGI("[DistributedDBCloudAssetsOperationSyncTest] Asset name %s status %" PRIu32, item.name.c_str(), item.status); @@ -319,27 +366,6 @@ void DistributedDBCloudAssetsOperationSyncTest::ForkDownloadAndRemoveAsset(DBSta }); } -void DistributedDBCloudAssetsOperationSyncTest::CheckAssetData() -{ - virtualCloudDb_->ForkUpload(nullptr); - std::vector allData; - auto dbSchema = GetSchema(); - ASSERT_GT(dbSchema.tables.size(), 0u); - ASSERT_EQ(RelationalTestUtils::SelectData(db_, dbSchema.tables[0], allData), E_OK); - ASSERT_EQ(allData.size(), 60ul); - auto data = allData[54]; // update data - auto data1 = allData[55]; // no update data - - Type colValue = data.at("asset"); - auto translate = std::dynamic_pointer_cast(virtualTranslator_); - auto assets = RelationalTestUtils::GetAssets(colValue, translate, true); - ASSERT_EQ(assets[0].hash, std::string("123")); - - Type colValue1 = data1.at("asset"); - auto assets1 = RelationalTestUtils::GetAssets(colValue1, translate, true); - ASSERT_EQ(assets1[0].hash, std::string("DEC")); -} - /** * @tc.name: SyncWithAssetOperation001 * @tc.desc: Delete Assets When Download @@ -472,6 +498,23 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation004, T CheckAssetsCount(expectCount); } +void DistributedDBCloudAssetsOperationSyncTest::UpdateAssetWhenSyncUpload() +{ + string sql = "UPDATE " + tableName_ + " SET asset = ? WHERE id = '54';"; + Asset asset = g_localAsset; + asset.hash = "123"; + const int assetId = 54; + asset.name = g_localAsset.name + std::to_string(assetId); + std::vector assetBlob; + RuntimeContext::GetInstance()->AssetToBlob(asset, assetBlob); + sqlite3_stmt *stmt = nullptr; + ASSERT_EQ(SQLiteUtils::GetStatement(db_, sql, stmt), E_OK); + ASSERT_EQ(SQLiteUtils::BindBlobToStatement(stmt, 1, assetBlob, false), E_OK); + EXPECT_EQ(SQLiteUtils::StepWithRetry(stmt), SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)); + int errCode; + SQLiteUtils::ResetStatement(stmt, true, errCode); +} + /** * @tc.name: SyncWithAssetOperation005 * @tc.desc: check asset when update in fill before upload sync process @@ -486,13 +529,13 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation005, T * @tc.expected: step1. ok. */ InsertUserTableRecord(tableName_, 0, 60); - + /** * @tc.steps:step2. Sync to cloud and wait in upload. * @tc.expected: step2. ok. */ bool isUpload = false; - virtualCloudDb_->ForkUpload([&isUpload](const std::string &tableName, VBucket &extend) { + virtualCloudDb_->ForkUpload([&isUpload](const std::string &, VBucket &) { if (isUpload == true) { return; } @@ -503,7 +546,7 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation005, T bool finish = false; auto callback = [&finish](const std::map &process) { - for (const auto &item: process) { + for (const auto &item : process) { if (item.second.process == DistributedDB::FINISHED) { { finish = true; @@ -511,7 +554,7 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation005, T } } }; - ASSERT_EQ(delegate_->Sync({ "CLOUD" }, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime), OK); + ASSERT_EQ(delegate_->Sync({"CLOUD"}, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime), OK); while (isUpload == false) { std::this_thread::sleep_for(std::chrono::milliseconds(50)); @@ -521,18 +564,7 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation005, T * @tc.steps:step3. update asset when sync upload. * @tc.expected: step3. ok. */ - string sql = "UPDATE " + tableName_ + " SET asset = ? WHERE id = '54';"; - Asset asset = g_localAsset; - asset.hash = "123"; - asset.name = g_localAsset.name + std::to_string(54); - std::vector assetBlob; - RuntimeContext::GetInstance()->AssetToBlob(asset, assetBlob); - sqlite3_stmt *stmt = nullptr; - ASSERT_EQ(SQLiteUtils::GetStatement(db_, sql, stmt), E_OK); - ASSERT_EQ(SQLiteUtils::BindBlobToStatement(stmt, 1, assetBlob, false), E_OK); - EXPECT_EQ(SQLiteUtils::StepWithRetry(stmt), SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)); - int errCode; - SQLiteUtils::ResetStatement(stmt, true, errCode); + UpdateAssetWhenSyncUpload(); /** * @tc.steps:step4. check asset data. @@ -541,7 +573,23 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation005, T while (finish == false) { std::this_thread::sleep_for(std::chrono::milliseconds(50)); } - CheckAssetData(); + virtualCloudDb_->ForkUpload(nullptr); + std::vector allData; + auto dbSchema = GetSchema(); + ASSERT_GT(dbSchema.tables.size(), 0u); + ASSERT_EQ(RelationalTestUtils::SelectData(db_, dbSchema.tables[0], allData), E_OK); + ASSERT_EQ(allData.size(), 60ul); + auto data = allData[54]; // update data + auto data1 = allData[55]; // no update data + + Type colValue = data.at("asset"); + auto translate = std::dynamic_pointer_cast(virtualTranslator_); + auto assets = RelationalTestUtils::GetAssets(colValue, translate, true); + ASSERT_EQ(assets[0].hash, std::string("123")); + + Type colValue1 = data1.at("asset"); + auto assets1 = RelationalTestUtils::GetAssets(colValue1, translate, true); + ASSERT_EQ(assets1[0].hash, std::string("DEC")); } /** @@ -604,10 +652,285 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation007, T */ std::string sql = "SELECT cursor FROM " + DBCommon::GetLogTableName(tableName_) + " where data_key=1"; EXPECT_EQ(sqlite3_exec(db_, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback, - reinterpret_cast(7), nullptr), SQLITE_OK); + reinterpret_cast(7), nullptr), SQLITE_OK); sql = "SELECT cursor FROM " + DBCommon::GetLogTableName(tableName_) + " where data_key=5"; EXPECT_EQ(sqlite3_exec(db_, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback, - reinterpret_cast(5), nullptr), SQLITE_OK); + reinterpret_cast(5), nullptr), SQLITE_OK); +} + +/** + * @tc.name: SyncWithAssetOperation008 + * @tc.desc: Test assetId fill when assetId changed + * @tc.type: FUNC + * @tc.require: + * @tc.author: wangxiangdong + */ +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation008, TestSize.Level0) +{ + /** + * @tc.steps:step1. Insert 5 records and sync. + * @tc.expected: step1. ok. + */ + const int actualCount = 5; + InsertUserTableRecord(tableName_, 0, actualCount); + Query query = Query::Select().FromTable({ tableName_ }); + BlockSync(query, delegate_); + /** + * @tc.steps:step2. modify data and sync. + * @tc.expected: step2. ok. + */ + UpdateCloudTableRecord(0, 1, true); + int removeCount = 0; + virtualAssetLoader_->SetRemoveLocalAssetsCallback([&removeCount](std::map &assets) { + removeCount = assets["asset"].size() + assets["assets"].size(); + return LOCAL_ASSET_NOT_FOUND; + }); + BlockSync(query, delegate_); + EXPECT_EQ(removeCount, 3); // one record has 3 asset + virtualAssetLoader_->SetRemoveLocalAssetsCallback(nullptr); + /** + * @tc.steps:step3. check asset number. + * @tc.expected: step3. ok. + */ + std::vector expectCount = { 3, 3, 3, 3, 3 }; + CheckAssetsCount(expectCount, true); + /** + * @tc.steps:step4. sync and check. + * @tc.expected: step4. ok. + */ + BlockSync(query, delegate_); + expectCount = { 0, 3, 3, 3, 3 }; + CheckAssetsCount(expectCount, true); +} + +/** + * @tc.name: SyncWithAssetOperation009 + * @tc.desc: Test asset remove local and check db asset empty finally. + * @tc.type: FUNC + * @tc.require: + * @tc.author: wangxiangdong + */ +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation009, TestSize.Level0) +{ + /** + * @tc.steps:step1. Insert 5 records and sync. + * @tc.expected: step1. ok. + */ + const int actualCount = 5; + RelationalTestUtils::InsertCloudRecord(0, actualCount, tableName_, virtualCloudDb_); + InsertUserTableRecord(tableName_, 0, actualCount); + /** + * @tc.steps:step2. modify data and sync. + * @tc.expected: step2. ok. + */ + UpdateCloudTableRecord(0, 1, true); + Query query = Query::Select().FromTable({ tableName_ }); + BlockSync(query, delegate_); + /** + * @tc.steps:step3. check asset number. + * @tc.expected: step3. ok. + */ + std::vector expectCount = { 0, 3, 3, 3, 3 }; + CheckAssetsCount(expectCount, true); +} + +void DistributedDBCloudAssetsOperationSyncTest::InsertLocalAssetData(const std::string &assetHash) +{ + Assets assets; + std::string assetNameBegin = "Phone"; + for (int j = 1; j <= g_assetsNum; ++j) { + Asset asset; + asset.name = assetNameBegin + "_" + std::to_string(j); + asset.status = AssetStatus::NORMAL; + asset.flag = static_cast(AssetOpType::NO_CHANGE); + asset.hash = assetHash + "_" + std::to_string(j); + asset.assetId = std::to_string(j); + assets.push_back(asset); + } + string sql = "INSERT OR REPLACE INTO " + tableName_ + " (id,name,asset,assets) VALUES('0','CloudTest0',?,?);"; + sqlite3_stmt *stmt = nullptr; + ASSERT_EQ(SQLiteUtils::GetStatement(db_, sql, stmt), E_OK); + std::vector assetBlob; + std::vector assetsBlob; + RuntimeContext::GetInstance()->AssetToBlob(g_localAsset, assetBlob); + RuntimeContext::GetInstance()->AssetsToBlob(assets, assetsBlob); + ASSERT_EQ(SQLiteUtils::BindBlobToStatement(stmt, 1, assetBlob, false), E_OK); + ASSERT_EQ(SQLiteUtils::BindBlobToStatement(stmt, 2, assetsBlob, false), E_OK); // 2 is assetsBlob + EXPECT_EQ(SQLiteUtils::StepWithRetry(stmt), SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)); + int errCode; + SQLiteUtils::ResetStatement(stmt, true, errCode); +} + +void DistributedDBCloudAssetsOperationSyncTest::InsertCloudAssetData(const std::string &assetHash) +{ + std::vector record; + std::vector extend; + Timestamp now = DistributedDB::TimeHelper::GetSysCurrentTime(); + VBucket data; + data.insert_or_assign("id", "0"); + data.insert_or_assign("name", "CloudTest0"); + Asset asset = g_localAsset; + data.insert_or_assign("asset", "asset"); + Assets assets; + std::string assetNameBegin = "Phone"; + for (int j = 1; j <= g_assetsNum; ++j) { + Asset assetTmp; + assetTmp.name = assetNameBegin + "_" + std::to_string(j); + assetTmp.status = AssetStatus::NORMAL; + assetTmp.hash = assetHash + "_" + std::to_string(j); + assetTmp.assetId = std::to_string(j); + assets.push_back(assetTmp); + } + data.insert_or_assign("assets", assets); + record.push_back(data); + VBucket log; + log.insert_or_assign(DistributedDB::CloudDbConstant::CREATE_FIELD, static_cast( + now / DistributedDB::CloudDbConstant::TEN_THOUSAND)); + log.insert_or_assign(DistributedDB::CloudDbConstant::MODIFY_FIELD, static_cast( + now / DistributedDB::CloudDbConstant::TEN_THOUSAND)); + log.insert_or_assign(DistributedDB::CloudDbConstant::DELETE_FIELD, false); + extend.push_back(log); + virtualCloudDb_->BatchInsert(tableName_, std::move(record), extend); +} + +void DistributedDBCloudAssetsOperationSyncTest::PrepareForAssetOperation010() +{ + InsertCloudAssetData("cloudAsset"); + InsertLocalAssetData("localAsset"); +} + +/** + * @tc.name: SyncWithAssetOperation010 + * @tc.desc: Test check status of asset, when the hash of asset is different. + * @tc.type: FUNC + * @tc.require: + * @tc.author: liufuchenxing + */ +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation010, TestSize.Level0) +{ + /** + * @tc.steps:step1. prepare local and cloud asset data. + * @tc.expected: step1. ok. + */ + PrepareForAssetOperation010(); + + /** + * @tc.steps:step2. sync and check the status of assets. + * @tc.expected: step2. ok. + */ + virtualCloudDb_->ForkBeforeBatchUpdate([](const std::string &, std::vector &record, + std::vector &extend, bool) { + ASSERT_EQ(static_cast(record.size()), 1); + VBucket &bucket = record[0]; + ASSERT_TRUE(bucket.find("assets") != bucket.end()); + Assets assets = std::get(bucket["assets"]); + ASSERT_EQ(static_cast(assets.size()), 3); + for (size_t i = 0; i < assets.size(); i++) { + ASSERT_EQ(assets[i].status, AssetStatus::UPDATE); + } + }); + + Query query = Query::Select().FromTable({ tableName_ }); + BlockSync(query, delegate_, SYNC_MODE_CLOUD_FORCE_PUSH); +} + +void DistributedDBCloudAssetsOperationSyncTest::WriteDataWithoutCommitTransaction() +{ + ASSERT_NE(db_, nullptr); + SQLiteUtils::BeginTransaction(db_); + InsertLocalAssetData("localAsset"); + constexpr int kSleepDurationSeconds = 3; + std::this_thread::sleep_for(std::chrono::seconds(kSleepDurationSeconds)); +} + +/** + * @tc.name: TestOpenDatabaseBusy001 + * @tc.desc: Test open database when the database is busy. + * @tc.type: FUNC + * @tc.require: + * @tc.author: liufuchenxing + */ +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, TestOpenDatabaseBusy001, TestSize.Level2) +{ + /** + * @tc.steps:step1. close store. + * @tc.expected:step1. check ok. + */ + EXPECT_EQ(mgr_->CloseStore(delegate_), DBStatus::OK); + delegate_ = nullptr; + /** + * @tc.steps:step2. Another thread write data into database into database without commit. + * @tc.expected:step2. check ok. + */ + std::thread thread(&DistributedDBCloudAssetsOperationSyncTest::WriteDataWithoutCommitTransaction, this); + std::this_thread::sleep_for(std::chrono::seconds(1)); + /** + * @tc.steps:step3. open relational delegate. + * @tc.expected:step3. open success. + */ + RelationalStoreDelegate::Option option; + ASSERT_EQ(mgr_->OpenStore(storePath_, STORE_ID_1, option, delegate_), DBStatus::OK); + thread.join(); +} + +/** + * @tc.name: SyncWithAssetOperation011 + * @tc.desc: Test change assets between download and remove + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation011, TestSize.Level0) +{ + /** + * @tc.steps:step1. Insert 5 records and sync. + * @tc.expected: step1. ok. + */ + const int actualCount = 5; + InsertUserTableRecord(tableName_, 0, actualCount); + Query query = Query::Select().FromTable({ tableName_ }); + BlockSync(query, delegate_); + /** + * @tc.steps:step2. modify assets of cloud data. update 1st asset and delete 2nd asset. + * @tc.expected: step2. ok. + */ + std::vector record; + std::vector extend; + int dataNum = 0; + Timestamp now = TimeHelper::GetSysCurrentTime(); + VBucket data; + data.insert_or_assign("id", std::to_string(dataNum)); + data.insert_or_assign("name", "Cloud" + std::to_string(dataNum)); + Asset cloudAsset = g_localAsset; + cloudAsset.name += std::to_string(dataNum); + cloudAsset.hash = "new_hash"; + Assets cloudAssets = {cloudAsset}; + data.insert_or_assign("assets", cloudAssets); + record.push_back(data); + VBucket log; + log.insert_or_assign(CloudDbConstant::CREATE_FIELD, static_cast( + now / CloudDbConstant::TEN_THOUSAND)); + log.insert_or_assign(CloudDbConstant::MODIFY_FIELD, static_cast( + now / CloudDbConstant::TEN_THOUSAND)); + log.insert_or_assign(CloudDbConstant::DELETE_FIELD, false); + log.insert_or_assign(CloudDbConstant::GID_FIELD, std::to_string(dataNum)); + extend.push_back(log); + ASSERT_EQ(virtualCloudDb_->BatchUpdate(tableName_, std::move(record), extend), DBStatus::OK); + /** + * @tc.steps:step3. Update local assets between remove and download, sync and check whether download is invoked. + * @tc.expected: step3. ok. + */ + virtualAssetLoader_->SetRemoveLocalAssetsCallback([&](std::map &assets) { + UpdateLocalTableRecord(tableName_, 0, 1); + return OK; + }); + virtualAssetLoader_->ForkDownload([](std::map &assets) { + EXPECT_TRUE(false); + }); + BlockSync(query, delegate_); + + virtualAssetLoader_->SetRemoveLocalAssetsCallback(nullptr); + virtualAssetLoader_->ForkDownload(nullptr); } /** @@ -750,7 +1073,7 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, UpsertData002, TestSize.Leve records.push_back(record); } EXPECT_EQ(delegate_->UpsertData(tableName_, records), OK); - // check cursor has been increase + // check cursor has been increased checkLogSql = "SELECT count(*) FROM " + DBCommon::GetLogTableName(tableName_) + " where cursor = 10"; RelationalTestUtils::ExecSql(db_, checkLogSql, nullptr, [&dataCnt](sqlite3_stmt *stmt) { dataCnt = sqlite3_column_int(stmt, 0); @@ -860,7 +1183,7 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, UpsertDataInvalid002, TestSi * @tc.expected: step1. INVALID_ARGS. */ const char *createSQL = - "CREATE TABLE IF NOT EXISTS devTable(" \ + "CREATE TABLE IF NOT EXISTS deviceTable(" \ "id TEXT PRIMARY KEY," \ "name TEXT," \ "height REAL ," \ @@ -878,7 +1201,7 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, UpsertDataInvalid002, TestSi RelationalStoreDelegate::Option option; ASSERT_EQ(mgr1->OpenStore(storePath_, STORE_ID_1, option, delegate1), DBStatus::OK); ASSERT_NE(delegate1, nullptr); - std::string deviceTableName = "devTable"; + std::string deviceTableName = "deviceTable"; ASSERT_EQ(delegate1->CreateDistributedTable(deviceTableName, DEVICE_COOPERATION), DBStatus::OK); DataBaseSchema dataBaseSchema; TableSchema tableSchema; @@ -900,6 +1223,7 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, UpsertDataInvalid002, TestSi delegate1 = nullptr; mgr1 = nullptr; } + /** * @tc.name: DownloadAssetStatusTest004 * @tc.desc: Test upload asset status @@ -1025,9 +1349,9 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, UploadAssetsTest001, TestSiz Query query = Query::Select().FromTable({ tableName_ }); BlockSync(query, delegate_); for (const auto &table : lastProcess_.tableProcess) { - EXPECT_EQ(table.second.upLoadInfo.total, 9u); + EXPECT_EQ(table.second.upLoadInfo.total, 10u); EXPECT_EQ(table.second.upLoadInfo.failCount, 3u); - EXPECT_EQ(table.second.upLoadInfo.successCount, 6u); + EXPECT_EQ(table.second.upLoadInfo.successCount, 7u); } virtualCloudDb_->ForkUpload(nullptr); } @@ -1102,9 +1426,9 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, UploadAssetsTest003, TestSiz BlockSync(query, delegate_); for (const auto &table : lastProcess_.tableProcess) { EXPECT_EQ(table.second.upLoadInfo.batchIndex, 4u); - EXPECT_EQ(table.second.upLoadInfo.total, 70u); + EXPECT_EQ(table.second.upLoadInfo.total, 100u); EXPECT_EQ(table.second.upLoadInfo.failCount, 0u); - EXPECT_EQ(table.second.upLoadInfo.successCount, 70u); + EXPECT_EQ(table.second.upLoadInfo.successCount, 100u); EXPECT_EQ(table.second.process, ProcessStatus::FINISHED); } virtualCloudDb_->ForkUpload(nullptr); @@ -1151,9 +1475,9 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, UploadAssetsTest004, TestSiz */ BlockSync(query, delegate_); for (const auto &table : lastProcess_.tableProcess) { - EXPECT_EQ(table.second.upLoadInfo.total, 25u); + EXPECT_EQ(table.second.upLoadInfo.total, 50u); EXPECT_EQ(table.second.upLoadInfo.failCount, 0u); - EXPECT_EQ(table.second.upLoadInfo.successCount, 25u); + EXPECT_EQ(table.second.upLoadInfo.successCount, 50u); } virtualCloudDb_->ForkUpload(nullptr); } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_check_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_check_sync_test.cpp index 98fa565037adaf6ead387bf2c4af2fe6b9e33f56..44b998c0c89e45615309d5a41411836389cf4ac3 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_check_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_check_sync_test.cpp @@ -16,7 +16,9 @@ #include #include "cloud/cloud_db_constant.h" #include "cloud/cloud_db_types.h" +#include "cloud/cloud_sync_utils.h" #include "cloud_db_sync_utils_test.h" +#include "cloud_syncer.h" #include "db_common.h" #include "distributeddb_data_generate_unit_test.h" #include "log_print.h" @@ -193,6 +195,7 @@ protected: void InitTestDir(); DataBaseSchema GetSchema(); void CloseDb(); + void InitDataAndSync(); void InsertUserTableRecord(const std::string &tableName, int64_t recordCounts, int64_t begin = 0); void InsertCloudTableRecord(int64_t begin, int64_t count, int64_t photoSize, bool assetIsNull); void InsertCloudTableRecord(const std::string &tableName, int64_t begin, int64_t count, int64_t photoSize, @@ -217,8 +220,7 @@ protected: void CheckUploadInfo(const Info &actualUploadInfo, const Info &expectUploadInfo); void CheckDownloadInfo(const Info &actualDownloadInfo, const Info &expectDownloadInfo); void SyncDataStatusTest(bool isCompensatedSyncOnly); - void WaitCommonUpload(); - void CheckUploadInfoAfterSync(const int recordCount, SyncProcess &normalLast); + void CheckUploadInfoAfterSync(int recordCount, SyncProcess &normalLast); std::string testDir_; std::string storePath_; sqlite3 *db_ = nullptr; @@ -300,7 +302,7 @@ DataBaseSchema DistributedDBCloudCheckSyncTest::GetSchema() DataBaseSchema schema; TableSchema tableSchema; tableSchema.name = tableName_; - tableSchema.sharedTableName = tableName_ + "_shared"; + tableSchema.sharedTableName = tableNameShared_; tableSchema.fields = { {"id", TYPE_INDEX, true}, {"name", TYPE_INDEX}, {"height", TYPE_INDEX}, {"photo", TYPE_INDEX}, {"age", TYPE_INDEX} @@ -400,7 +402,7 @@ void DistributedDBCloudCheckSyncTest::DeleteUserTableRecord(int64_t id) void DistributedDBCloudCheckSyncTest::DeleteUserTableRecord(int64_t begin, int64_t end) { ASSERT_NE(db_, nullptr); - string sql = "DELETE FROM " + tableName_ + " WHERE id IN ("; + std::string sql = "DELETE FROM " + tableName_ + " WHERE id IN ("; for (int64_t i = begin; i <= end; ++i) { sql += "'" + std::to_string(i) + "',"; } @@ -452,8 +454,8 @@ bool DistributedDBCloudCheckSyncTest::CheckSyncCount(const Info actualInfo, cons return true; } -bool DistributedDBCloudCheckSyncTest::CheckSyncProcessInner( - SyncProcess &actualSyncProcess, SyncProcess &expectSyncProcess) +bool DistributedDBCloudCheckSyncTest::CheckSyncProcessInner(SyncProcess &actualSyncProcess, + SyncProcess &expectSyncProcess) { for (const auto &itInner : actualSyncProcess.tableProcess) { std::string tableName = itInner.first; @@ -508,25 +510,29 @@ void DistributedDBCloudCheckSyncTest::PriorityAndNormalSync(const Query &normalQ bool priorityFinish = false; auto normalCallback = [&cv, &dataMutex, &normalFinish, &priorityFinish, &prioritySyncProcess, &isCheckProcess]( const std::map &process) { - for (const auto &item: process) { - if (item.second.process == DistributedDB::FINISHED) { - normalFinish = true; - ASSERT_EQ(isCheckProcess ? priorityFinish : true, true); - cv.notify_one(); - } + auto foundFinishedProcess = std::find_if(process.begin(), process.end(), [](const auto &item) { + return item.second.process == DistributedDB::FINISHED; + }); + if (foundFinishedProcess != process.end()) { + normalFinish = true; + if (isCheckProcess) { + ASSERT_EQ(priorityFinish, true); } - prioritySyncProcess.emplace_back(process); - }; + cv.notify_one(); + } + prioritySyncProcess.emplace_back(process); + }; auto priorityCallback = [&cv, &priorityFinish, &prioritySyncProcess]( const std::map &process) { - for (const auto &item: process) { - if (item.second.process == DistributedDB::FINISHED) { - priorityFinish = true; - cv.notify_one(); - } - } - prioritySyncProcess.emplace_back(process); - }; + auto it = std::find_if(process.begin(), process.end(), [](const auto &item) { + return item.second.process == DistributedDB::FINISHED; + }); + if (it != process.end()) { + priorityFinish = true; + cv.notify_one(); + } + prioritySyncProcess.emplace_back(process); + }; CloudSyncOption option; PrepareOption(option, normalQuery, false); virtualCloudDb_->SetBlockTime(500); // 500 ms @@ -625,7 +631,7 @@ void DistributedDBCloudCheckSyncTest::CheckLogCleaned(int64_t expectCount) EXPECT_EQ(sqlite3_exec(db_, sql2.c_str(), QueryCountCallback, reinterpret_cast(expectCount), nullptr), SQLITE_OK); std::string sql3 = "select count(*) from " + DBCommon::GetLogTableName(tableName_) + - " where flag & 0x02 = 0;"; + " where flag & 0x02 != 0;"; EXPECT_EQ(sqlite3_exec(db_, sql3.c_str(), QueryCountCallback, reinterpret_cast(expectCount), nullptr), SQLITE_OK); } @@ -652,23 +658,6 @@ void DistributedDBCloudCheckSyncTest::CheckDownloadInfo(const Info &actualDownlo EXPECT_EQ(actualDownloadInfo.deleteCount, expectDownloadInfo.deleteCount); } -void DistributedDBCloudCheckSyncTest::WaitCommonUpload() -{ - uint32_t times = virtualCloudDb_->GetQueryTimes(tableName_); - ASSERT_EQ(times, 3u); - virtualCloudDb_->ForkUpload(nullptr); -} - -void DistributedDBCloudCheckSyncTest::CheckUploadInfoAfterSync(const int recordCount, SyncProcess &normalLast) -{ - const Info expectUploadInfo = {2u, recordCount, recordCount, 0u, recordCount, 0u, 0u}; - for (const auto &table : normalLast.tableProcess) { - CheckUploadInfo(table.second.upLoadInfo, expectUploadInfo); - EXPECT_EQ(table.second.process, ProcessStatus::FINISHED); - } - virtualCloudDb_->ForkUpload(nullptr); -} - /** * @tc.name: CloudSyncTest001 * @tc.desc: sync with device sync query @@ -778,6 +767,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest004, TestSize.Level0) EXPECT_EQ(virtualCloudDb_->GetDataStatus("0", deleteStatus), OK); EXPECT_EQ(deleteStatus, true); } + /** * @tc.name: CloudSyncTest005 * @tc.desc: check device in process after sync @@ -809,9 +799,18 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest005, TestSize.Level0) BlockCompensatedSync(query, delegate_, OK, callback); } +void DistributedDBCloudCheckSyncTest::InitDataAndSync() +{ + const int localCount = 120; // 120 is count of local + const int cloudCount = 100; // 100 is count of cloud + InsertUserTableRecord(tableName_, localCount, 0); + InsertUserTableRecord(tableWithoutPrimaryName_, cloudCount, 0); + InsertCloudTableRecord(tableWithoutPrimaryName_, 80, cloudCount, 0, false); // 80 is begin sync number +} + /** * @tc.name: CloudSyncTest006 - * @tc.desc: check redownload when common sync pause. + * @tc.desc: check reDownload when common sync pause. * @tc.type: FUNC * @tc.require: * @tc.author: luoguo @@ -822,14 +821,10 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest006, TestSize.Level0) * @tc.steps:step1. init data and sync * @tc.expected: step1. ok. */ - const int localCount = 120; // 120 is count of local - const int cloudCount = 100; // 100 is count of cloud - InsertUserTableRecord(tableName_, localCount, 0); - InsertUserTableRecord(tableWithoutPrimaryName_, cloudCount, 0); - InsertCloudTableRecord(tableWithoutPrimaryName_, 80, cloudCount, 0, false); + InitDataAndSync(); /** - * @tc.steps:step2. common sync will pasue. + * @tc.steps:step2. common sync will pause * @tc.expected: step2. ok. */ std::vector tableNames = {tableName_, tableWithoutPrimaryName_}; @@ -848,12 +843,12 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest006, TestSize.Level0) std::this_thread::sleep_for(std::chrono::milliseconds(blockTime)); } }); - bool isFinsh = false; + bool isFinished = false; bool priorityFinish = false; - auto normalCallback = [&isFinsh, &priorityFinish](const std::map &process) { - for (const auto &item: process) { + auto normalCallback = [&isFinished, &priorityFinish](const std::map &process) { + for (const auto &item : process) { if (item.second.process == DistributedDB::FINISHED) { - isFinsh = true; + isFinished = true; ASSERT_EQ(priorityFinish, true); } } @@ -861,30 +856,31 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest006, TestSize.Level0) ASSERT_EQ(delegate_->Sync(option, normalCallback), OK); /** - * @tc.steps:step3. wait common upload and pritority sync. + * @tc.steps:step3. wait common upload and priority sync. * @tc.expected: step3. ok. */ while (isUpload == false) { std::this_thread::sleep_for(std::chrono::milliseconds(50)); } auto priorityCallback = [&priorityFinish](const std::map &process) { - for (const auto &item: process) { + for (const auto &item : process) { if (item.second.process == DistributedDB::FINISHED) { priorityFinish = true; } } }; ASSERT_EQ(delegate_->Sync(priorityOption, priorityCallback), OK); - while (isFinsh == false || priorityFinish == false) { + while (isFinished == false || priorityFinish == false) { std::this_thread::sleep_for(std::chrono::milliseconds(50)); } - /** - * @tc.steps:step3. wait common upload and pritority sync. - * @tc.expected: step3. ok. + * @tc.steps:step4. wait common sync and priority sync finish, check query Times. + * @tc.expected: step4. ok. */ - WaitCommonUpload(); + uint32_t times = virtualCloudDb_->GetQueryTimes(tableName_); + ASSERT_EQ(times, 3u); + virtualCloudDb_->ForkUpload(nullptr); } /** @@ -917,12 +913,12 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest007, TestSize.Level0) std::this_thread::sleep_for(std::chrono::milliseconds(2000)); } }); - bool isFinsh = false; + bool isFinished = false; std::map retSyncProcess; - auto normalCallback = [&isFinsh, &retSyncProcess](const std::map &process) { - for (const auto &item: process) { + auto normalCallback = [&isFinished, &retSyncProcess](const std::map &process) { + for (const auto &item : process) { if (item.second.process == DistributedDB::FINISHED) { - isFinsh = true; + isFinished = true; ASSERT_EQ(process.empty(), false); auto lastProcess = process.rbegin(); retSyncProcess = lastProcess->second.tableProcess; @@ -953,7 +949,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest007, TestSize.Level0) * @tc.steps:step5. wait sync process end and check data. * @tc.expected: step5. ok. */ - while (isFinsh == false) { + while (isFinished == false) { std::this_thread::sleep_for(std::chrono::milliseconds(50)); } ASSERT_EQ(retSyncProcess.empty(), false); @@ -1747,6 +1743,16 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest013, TestSize.Lev CheckCloudTableCount(tableName_, 0); } +void DistributedDBCloudCheckSyncTest::CheckUploadInfoAfterSync(int recordCount, SyncProcess &normalLast) +{ + uint32_t uintRecordCount = static_cast(recordCount); + const Info expectUploadInfo = {2u, uintRecordCount, uintRecordCount, 0u, uintRecordCount, 0u, 0u}; + for (const auto &table : normalLast.tableProcess) { + CheckUploadInfo(table.second.upLoadInfo, expectUploadInfo); + EXPECT_EQ(table.second.process, ProcessStatus::FINISHED); + } +} + /** * @tc.name: CloudPrioritySyncTest014 * @tc.desc: Check the uploadInfo after the normal sync is paused by the priority sync @@ -1815,14 +1821,15 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest014, TestSize.Lev * @tc.expected: step3. ok. */ CheckUploadInfoAfterSync(recordCount, normalLast); + virtualCloudDb_->ForkUpload(nullptr); } /** * @tc.name: CloudPrioritySyncTest015 - * @tc.desc: Check the uploadInfo the downloadInfo after the normal sync is paused by the priority sync + * @tc.desc: Check the uploadInfo and the downloadInfo after the normal sync is paused by the priority sync * @tc.type: FUNC * @tc.require: - * @tc.author: suyue + * @tc.author: caihaoting */ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest015, TestSize.Level0) { @@ -1877,8 +1884,10 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest015, TestSize.Lev * @tc.steps:step3. check uploadInfo and downloadInfo after sync finished. * @tc.expected: step3. ok. */ - const Info expectUploadInfo = {1u, localCount, localCount, 0u, localCount, 0u, 0u}; - const Info expectDownloadInfo = {1u, cloudCount, cloudCount, 0u, cloudCount, 0u, 0u}; + uint32_t uintLocalCount = static_cast(localCount); + uint32_t uintCloudCount = static_cast(cloudCount); + const Info expectUploadInfo = {1u, uintLocalCount, uintLocalCount, 0u, uintLocalCount, 0u, 0u}; + const Info expectDownloadInfo = {1u, uintCloudCount, uintCloudCount, 0u, uintCloudCount, 0u, 0u}; for (const auto &table : normalLast.tableProcess) { CheckUploadInfo(table.second.upLoadInfo, expectUploadInfo); CheckDownloadInfo(table.second.downLoadInfo, expectDownloadInfo); @@ -1903,7 +1912,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest016, TestSize.Lev const int actualCount = 60; // 60 is count of records InsertCloudTableRecord(0, actualCount, 0, false); InsertUserTableRecord(tableName_, 10); - + /** * @tc.steps:step2. begin normal sync and priority sync. * @tc.expected: step2. ok. @@ -2170,6 +2179,34 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, LogicDeleteSyncTest008, TestSize.Level reinterpret_cast(0), nullptr), SQLITE_OK); } +/** + * @tc.name: LockActionTest001 + * @tc.desc: InitCompensatedSyncTaskInfo and check lockAction. + * @tc.type: FUNC + * @tc.require: + * @tc.author: wangxiangdong + */ +HWTEST_F(DistributedDBCloudCheckSyncTest, LockActionTest001, TestSize.Level0) +{ + /** + * @tc.steps:step1. InitCompensatedSyncTaskInfo and check. + * @tc.expected: step1. ok. + */ + CloudSyncOption option; + option.devices = { "CLOUD" }; + option.mode = SYNC_MODE_CLOUD_MERGE; + option.query = Query::Select().FromTable({ tableName_ }); + option.waitTime = g_syncWaitTime; + auto action = static_cast(LockAction::INSERT) | static_cast(LockAction::UPDATE) + | static_cast(LockAction::DELETE); + option.lockAction = static_cast(action); + option.priorityTask = true; + option.compensatedSyncOnly = true; + const SyncProcessCallback onProcess; + CloudSyncer::CloudTaskInfo taskInfo = CloudSyncUtils::InitCompensatedSyncTaskInfo(option, onProcess); + EXPECT_EQ(taskInfo.lockAction, option.lockAction); +} + /** * @tc.name: LogicCreateRepeatedTableNameTest001 * @tc.desc: test create repeated table name with different cases diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_interfaces_relational_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_interfaces_relational_sync_test.cpp index 56e7d9e4c1ab28bf00586653052b5ea8c5caee09..9670fa77aae4df5bcb9d9883abe97024715d47f5 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_interfaces_relational_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_interfaces_relational_sync_test.cpp @@ -425,7 +425,6 @@ namespace { for (const Asset &asset: assets) { ASSERT_EQ(asset.status, static_cast(AssetStatus::NORMAL)); ASSERT_EQ(asset.name, names[index]); - LOGE("lyh_test: name: %s", names[index].c_str()); index++; } } @@ -1105,6 +1104,7 @@ namespace { void DistributedDBCloudInterfacesRelationalSyncTest::SetUp(void) { + RuntimeContext::GetInstance()->SetBatchDownloadAssets(false); if (DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir) != 0) { LOGE("rm test db files error."); } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_meta_data_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_meta_data_test.cpp index 453d7a0a934684d0ca672b716c53155d4da1facf..ccfb326a335867321f95b7d1736bde60ce4fe6e2 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_meta_data_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_meta_data_test.cpp @@ -202,12 +202,12 @@ namespace { } /** - * @tc.name: AbnormalStorageProxyTest001 - * @tc.desc: Check StorageProxy interfaces when para is invalid. - * @tc.type: FUNC - * @tc.require: - * @tc.author: suyue - */ + * @tc.name: AbnormalStorageProxyTest001 + * @tc.desc: Check StorageProxy interfaces when para is invalid. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ HWTEST_F(DistributedDBCloudMetaDataTest, AbnormalStorageProxyTest001, TestSize.Level0) { /** @@ -261,12 +261,12 @@ namespace { } /** - * @tc.name: AbnormalStorageProxyTest002 - * @tc.desc: Check StorageProxy interfaces when para is invalid. - * @tc.type: FUNC - * @tc.require: - * @tc.author: suyue - */ + * @tc.name: AbnormalStorageProxyTest002 + * @tc.desc: Check StorageProxy interfaces when para is invalid. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ HWTEST_F(DistributedDBCloudMetaDataTest, AbnormalStorageProxyTest002, TestSize.Level0) { /** diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_sqlite_single_ver_natural_executor_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_sqlite_single_ver_natural_executor_test.cpp index 514d6fd9aaf2a2657c3b1d3e05756c7bc4faa463..9a03f2e6938ee8397ac7df6eaa8f6a7b2e31cce2 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_sqlite_single_ver_natural_executor_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_sqlite_single_ver_natural_executor_test.cpp @@ -1128,12 +1128,12 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalExecutorTest, ExecutorCache00 } /** - * @tc.name: AbnormalSqlExecutorTest001 - * @tc.desc: Check SQLiteStorageExecutor interfaces abnormal scene. - * @tc.type: FUNC - * @tc.require: - * @tc.author: suyue - */ + * @tc.name: AbnormalSqlExecutorTest001 + * @tc.desc: Check SQLiteStorageExecutor interfaces abnormal scene. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalExecutorTest, AbnormalSqlExecutorTest001, TestSize.Level1) { /** @@ -1161,12 +1161,12 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalExecutorTest, AbnormalSqlExec } /** - * @tc.name: AbnormalSqlExecutorTest002 - * @tc.desc: Check SQLiteSingleVerStorageExecutor interfaces abnormal scene. - * @tc.type: FUNC - * @tc.require: - * @tc.author: suyue - */ + * @tc.name: AbnormalSqlExecutorTest002 + * @tc.desc: Check SQLiteSingleVerStorageExecutor interfaces abnormal scene. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalExecutorTest, AbnormalSqlExecutorTest002, TestSize.Level1) { /** @@ -1201,12 +1201,12 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalExecutorTest, AbnormalSqlExec } /** - * @tc.name: AbnormalSqlExecutorTest003 - * @tc.desc: Check SQLiteSingleVerStorageExecutor interfaces abnormal scene. - * @tc.type: FUNC - * @tc.require: - * @tc.author: suyue - */ + * @tc.name: AbnormalSqlExecutorTest003 + * @tc.desc: Check SQLiteSingleVerStorageExecutor interfaces abnormal scene. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalExecutorTest, AbnormalSqlExecutorTest003, TestSize.Level1) { /** diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_sqlite_single_ver_storage_engine_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_sqlite_single_ver_storage_engine_test.cpp index 09aa6711b405a5e55ea1235e2b463f4339ae2ac3..d274ddfd60fabd0b29293a2cc06cecbc90c13076 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_sqlite_single_ver_storage_engine_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_sqlite_single_ver_storage_engine_test.cpp @@ -178,7 +178,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerStorageEngineTest, DataTest003, Test invalidConnection = new (std::nothrow) SQLiteSingleVerNaturalStoreConnection(invalidStore); ASSERT_NE(invalidConnection, nullptr); /** - * @tc.steps::step2. test RegisterObserver with invalid SQLiteSingleVerNaturalStore + * @tc.steps:step2. test RegisterObserver with invalid SQLiteSingleVerNaturalStore * @tc.expected: step2. return -E_INVALID_CONNECTION. */ int errCode = E_OK; @@ -190,7 +190,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerStorageEngineTest, DataTest003, Test errCode); EXPECT_EQ(errCode, -E_INVALID_CONNECTION); /** - * @tc.steps::step3. test UnRegisterObserver with invalid SQLiteSingleVerNaturalStore + * @tc.steps:step3. test UnRegisterObserver with invalid SQLiteSingleVerNaturalStore * @tc.expected: step3. return -E_INVALID_CONNECTION. */ auto observerHandle = g_connection->RegisterObserver( @@ -200,7 +200,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerStorageEngineTest, DataTest003, Test errCode = invalidConnection->UnRegisterObserver(observerHandle); EXPECT_EQ(errCode, -E_INVALID_CONNECTION); /** - * @tc.steps::step4. test GetSecurityOption with invalid SQLiteSingleVerNaturalStore + * @tc.steps:step4. test GetSecurityOption with invalid SQLiteSingleVerNaturalStore * @tc.expected: step4. return -E_INVALID_CONNECTION. */ int securityLabel = NOT_SET; @@ -208,13 +208,13 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerStorageEngineTest, DataTest003, Test errCode = invalidConnection->GetSecurityOption(securityLabel, securityFlag); EXPECT_EQ(errCode, -E_INVALID_CONNECTION); /** - * @tc.steps::step5. test Close with invalid SQLiteSingleVerNaturalStore + * @tc.steps:step5. test Close with invalid SQLiteSingleVerNaturalStore * @tc.expected: step5. return -E_INVALID_CONNECTION. */ errCode = invalidConnection->Close(); EXPECT_EQ(errCode, -E_INVALID_CONNECTION); /** - * @tc.steps::step6. delete invalid SQLiteSingleVerNaturalStoreConnection + * @tc.steps:step6. delete invalid SQLiteSingleVerNaturalStoreConnection * @tc.expected: step6. return OK. */ if (invalidConnection != nullptr) { diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/cloud_syncer_test.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/cloud_syncer_test.h index fe63ac21c4aa402a53c15f56e7e958968c434e53..503c3b2ccb834b263465f026f935553bf83cd238 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/cloud_syncer_test.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/cloud_syncer_test.h @@ -61,7 +61,7 @@ public: currentContext_.processRecorder = std::make_shared(); currentContext_.notifier->Init({currentContext_.tableName}, { "cloud" }, cloudTaskInfos_[taskId].users); currentContext_.strategy = std::make_shared(); - currentContext_.strategy->SetIsLocalDeleteUpload(isLocalDeleteUpload_); + currentContext_.strategy->SetIsKvScene(isKvScene_); closed_ = false; cloudTaskInfos_[taskId].callback = [this, taskId](const std::map &process) { if (process.size() >= 1u) { diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_db_proxy_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_db_proxy_test.cpp index efea28538637d6459db091e2f06b4f65bc15ad3e..6c2d6224355e3d756708c80d6bc191751bf616b3 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_db_proxy_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_db_proxy_test.cpp @@ -201,7 +201,8 @@ HWTEST_F(DistributedDBCloudDBProxyTest, CloudDBProxyTest002, TestSize.Level0) std::vector expectExtends = CloudDBDataUtils::GenerateExtends(10); // generate 10 extends Info uploadInfo; std::vector insert = expectRecords; - EXPECT_EQ(proxy.BatchInsert(TABLE_NAME, insert, expectExtends, uploadInfo), E_OK); + uint32_t retryCount = 0; + EXPECT_EQ(proxy.BatchInsert(TABLE_NAME, insert, expectExtends, uploadInfo, retryCount), E_OK); VBucket extend; extend[CloudDbConstant::CURSOR_FIELD] = std::string(""); @@ -254,14 +255,15 @@ HWTEST_F(DistributedDBCloudDBProxyTest, CloudDBProxyTest003, TestSize.Level0) std::vector expectExtends = CloudDBDataUtils::GenerateExtends(10); // generate 10 extends Info uploadInfo; std::vector insert = expectRecords; - EXPECT_EQ(proxy.BatchInsert(TABLE_NAME, insert, expectExtends, uploadInfo), E_OK); + uint32_t retryCount = 0; + EXPECT_EQ(proxy.BatchInsert(TABLE_NAME, insert, expectExtends, uploadInfo, retryCount), E_OK); /** * @tc.steps: step3. update data to cloud db * @tc.expected: step3. E_OK */ ModifyRecords(expectRecords); std::vector update = expectRecords; - EXPECT_EQ(proxy.BatchUpdate(TABLE_NAME, update, expectExtends, uploadInfo), E_OK); + EXPECT_EQ(proxy.BatchUpdate(TABLE_NAME, update, expectExtends, uploadInfo, retryCount), E_OK); /** * @tc.steps: step3. proxy close cloud db * @tc.expected: step3. E_OK @@ -563,7 +565,7 @@ HWTEST_F(DistributedDBCloudDBProxyTest, CloudDBProxyTest011, TestSize.Level2) HWTEST_F(DistributedDBCloudDBProxyTest, CloudDBProxyTest012, TestSize.Level2) { /** - * @tc.steps: step1. set cloud db to proxy + * @tc.steps: step1. construct data * @tc.expected: step1. E_OK */ Assets assets; @@ -572,40 +574,40 @@ HWTEST_F(DistributedDBCloudDBProxyTest, CloudDBProxyTest012, TestSize.Level2) asset1.assetId = ""; asset1.modifyTime = "20240730"; assets.push_back(asset1); - + Asset asset2; asset2.name = "assetName1"; - asset2.assetId = "123"; + asset2.assetId = "1"; asset2.modifyTime = "20240730"; assets.push_back(asset2); Asset asset3; asset3.name = "assetName2"; - asset3.assetId = "456"; + asset3.assetId = "2"; asset3.modifyTime = "20240730"; assets.push_back(asset3); Asset asset4; asset4.name = "assetName2"; - asset4.assetId = "789"; + asset4.assetId = "3"; asset4.modifyTime = "20240731"; assets.push_back(asset4); Asset asset5; asset5.name = "assetName3"; - asset5.assetId = "123"; + asset5.assetId = "4"; asset5.modifyTime = "20240730"; assets.push_back(asset5); Asset asset6; asset6.name = "assetName3"; - asset6.assetId = "789"; + asset6.assetId = "5"; asset6.modifyTime = "20240730"; assets.push_back(asset6); Asset asset7; asset7.name = "assetName1"; - asset7.assetId = "456"; + asset7.assetId = "6"; asset7.modifyTime = "20240731"; assets.push_back(asset7); @@ -616,7 +618,7 @@ HWTEST_F(DistributedDBCloudDBProxyTest, CloudDBProxyTest012, TestSize.Level2) * @tc.expected: step2. E_OK */ std::string assetNameArr[] = {"assetName2", "assetName3", "assetName1"}; - std::string assetIdArr[] = {"789", "123", "456"}; + std::string assetIdArr[] = {"3", "5", "6"}; EXPECT_EQ(assets.size(), 3u); for (std::vector::size_type i = 0; i < assets.size(); ++i) { EXPECT_EQ(assets.at(i).name, assetNameArr[i]); @@ -624,6 +626,47 @@ HWTEST_F(DistributedDBCloudDBProxyTest, CloudDBProxyTest012, TestSize.Level2) } } +/** + * @tc.name: CloudDBProxyTest014 + * @tc.desc: Test asset deduplication with empty assetId. + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(DistributedDBCloudDBProxyTest, CloudDBProxyTest014, TestSize.Level0) +{ + /** + * @tc.steps: step1. set cloud db to proxy + * @tc.expected: step1. E_OK + */ + Assets assets; + Asset asset1; + asset1.name = "assetName"; + asset1.assetId = ""; + asset1.modifyTime = "1"; + assets.push_back(asset1); + + Asset asset2; + asset2.name = "assetName"; + asset2.assetId = ""; + asset2.modifyTime = "3"; + assets.push_back(asset2); + + Asset asset3; + asset3.name = "assetName"; + asset3.assetId = ""; + asset3.modifyTime = "2"; + assets.push_back(asset3); + + /** + * @tc.steps: step2. Remove duplicate assets and check data + * @tc.expected: step2. E_OK + */ + DBCommon::RemoveDuplicateAssetsData(assets); + ASSERT_EQ(assets.size(), 1u); + EXPECT_EQ(assets[0].modifyTime, "3"); +} + /** * @tc.name: CloudSyncQueue001 * @tc.desc: Verify sync task count decrease after sync finished. @@ -835,11 +878,12 @@ HWTEST_F(DistributedDBCloudDBProxyTest, CloudDBProxyTest013, TestSize.Level0) ret = proxy.Query(tableName, extend, record); EXPECT_EQ(ret, -E_CLOUD_ERROR); Info info; - ret = proxy.BatchInsert(tableName, record, record, info); + uint32_t retryCount = 0; + ret = proxy.BatchInsert(tableName, record, record, info, retryCount); EXPECT_EQ(ret, -E_CLOUD_ERROR); - ret = proxy.BatchUpdate(tableName, record, record, info); + ret = proxy.BatchUpdate(tableName, record, record, info, retryCount); EXPECT_EQ(ret, -E_CLOUD_ERROR); - ret = proxy.BatchDelete(tableName, record, record, info); + ret = proxy.BatchDelete(tableName, record, record, info, retryCount); EXPECT_EQ(ret, -E_CLOUD_ERROR); std::pair res = proxy.Lock(); EXPECT_EQ(res.first, -E_CLOUD_ERROR); diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_kv_syncer_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_kv_syncer_test.cpp index c191f6b85bc432847b8513c974771ed6d679af61..69293d253c8426b080cdcf3d15569ce1a0e826c6 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_kv_syncer_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_kv_syncer_test.cpp @@ -55,6 +55,7 @@ protected: void BlockSync(KvStoreNbDelegate *delegate, DBStatus expectDBStatus, CloudSyncOption option, DBStatus expectSyncResult = OK); static DataBaseSchema GetDataBaseSchema(bool invalidSchema); + void PutKvBatchDataAndSyncCloud(CloudSyncOption &syncOption); void GetSingleStore(); void ReleaseSingleStore(); void BlockCompensatedSync(int &actSyncCnt, int expSyncCnt); @@ -484,7 +485,7 @@ HWTEST_F(DistributedDBCloudKvSyncerTest, UploadAbnormalSync004, TestSize.Level0) * @tc.steps:step1. Device A inserts data and synchronizes * @tc.expected: step1 errCode outside DBStatus should be kept. */ - int errCode = 27394048; + int errCode = 27394048; // an error not in [27328512, 27394048) virtualCloudDb_->SetActionStatus(static_cast(errCode)); Key key = {'k'}; Value value = {'v'}; @@ -502,7 +503,7 @@ HWTEST_F(DistributedDBCloudKvSyncerTest, UploadAbnormalSync004, TestSize.Level0) */ HWTEST_F(DistributedDBCloudKvSyncerTest, QueryParsingProcessTest001, TestSize.Level0) { - auto cloudHook = (ICloudSyncStorageHook *) singleStore_->GetCloudKvStore(); + auto cloudHook = (ICloudSyncStorageHook *)singleStore_->GetCloudKvStore(); ASSERT_NE(cloudHook, nullptr); /** @@ -595,11 +596,10 @@ HWTEST_F(DistributedDBCloudKvSyncerTest, SyncWithMultipleUsers001, TestSize.Leve EXPECT_EQ(actualValue, value); } -#define TEST_SYNCWITHMULTIPLEUSER002_ENTRISE_NUM 200 -#define TEST_SYNCWITHMULTIPLEUSER002_KEY_NUM 100 -static void SetEntryDataForSyncWithMultipleUsers002(std::vector &entries, std::vector &keys) +void DistributedDBCloudKvSyncerTest::PutKvBatchDataAndSyncCloud(CloudSyncOption &syncOption) { - for (int i = 0; i < TEST_SYNCWITHMULTIPLEUSER002_ENTRISE_NUM; i++) { + std::vector entries; + for (int i = 0; i < 200; i++) { // 200 is number of data std::string keyStr = "k_" + std::to_string(i); std::string valueStr = "v_" + std::to_string(i); Key key(keyStr.begin(), keyStr.end()); @@ -610,11 +610,12 @@ static void SetEntryDataForSyncWithMultipleUsers002(std::vector &entries, entries.push_back(entry); } - for (int i = 0; i < TEST_SYNCWITHMULTIPLEUSER002_KEY_NUM; i++) { - std::string keyStr = "k_" + std::to_string(i); - Key key(keyStr.begin(), keyStr.end()); - keys.push_back(key); - } + ASSERT_EQ(kvDelegatePtrS1_->PutBatch(entries), OK); + syncOption.mode = SyncMode::SYNC_MODE_CLOUD_MERGE; + syncOption.users.push_back(USER_ID); + syncOption.users.push_back(USER_ID_2); + syncOption.devices.push_back("cloud"); + BlockSync(kvDelegatePtrS1_, OK, syncOption); } /** @@ -630,17 +631,8 @@ HWTEST_F(DistributedDBCloudKvSyncerTest, SyncWithMultipleUsers002, TestSize.Leve * @tc.steps: step1. kvDelegatePtrS1_ put 200 data and sync to cloud. * @tc.expected: step1. return ok. */ - std::vector entries; - std::vector keys; - SetEntryDataForSyncWithMultipleUsers002(entries, keys); - - ASSERT_EQ(kvDelegatePtrS1_->PutBatch(entries), OK); CloudSyncOption syncOption; - syncOption.mode = SyncMode::SYNC_MODE_CLOUD_MERGE; - syncOption.users.push_back(USER_ID); - syncOption.users.push_back(USER_ID_2); - syncOption.devices.push_back("cloud"); - BlockSync(kvDelegatePtrS1_, OK, syncOption); + PutKvBatchDataAndSyncCloud(syncOption); /** * @tc.steps: step2. kvDelegatePtrS2_ only sync user0 from cloud. @@ -654,6 +646,12 @@ HWTEST_F(DistributedDBCloudKvSyncerTest, SyncWithMultipleUsers002, TestSize.Leve * @tc.steps: step3. kvDelegatePtrS2_ delete 100 data. * @tc.expected: step3. return ok. */ + std::vector keys; + for (int i = 0; i < 100; i++) { + std::string keyStr = "k_" + std::to_string(i); + Key key(keyStr.begin(), keyStr.end()); + keys.push_back(key); + } ASSERT_EQ(kvDelegatePtrS2_->DeleteBatch(keys), OK); /** @@ -668,9 +666,11 @@ HWTEST_F(DistributedDBCloudKvSyncerTest, SyncWithMultipleUsers002, TestSize.Leve std::condition_variable cv; bool finish = false; uint32_t insertCount = 0; - auto callback = [&](const std::map &process) { + auto callback = [&dataMutex, &syncOption, &finish, &insertCount, &cv](const std::map &process) { size_t notifyCnt = 0; for (const auto &item : process) { + LOGD("user = %s, status = %d, errCode=%d", item.first.c_str(), item.second.process, item.second.errCode); if (item.second.process != DistributedDB::FINISHED) { continue; } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_kv_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_kv_test.cpp index 2a393566ba116ef9656473291e0c6956e9fee782..53a821da49c9933009943a2008ce12d0ddc76026 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_kv_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_kv_test.cpp @@ -218,7 +218,6 @@ DataBaseSchema DistributedDBCloudKvTest::GetDataBaseSchema(bool invalidSchema) return schema; } - DBStatus DistributedDBCloudKvTest::GetKvStore(KvStoreNbDelegate *&delegate, const std::string &storeId, KvStoreNbDelegate::Option option, bool invalidSchema) { @@ -810,6 +809,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync014, TestSize.Level1) BlockSync(kvDelegatePtrS3_, USER_CHANGED, g_CloudSyncoption); thread.join(); CloseKvStore(kvDelegatePtrS3_, STORE_ID_3); + g_mgr.SetSyncActivationCheckCallback(nullptr); } /** @@ -1351,7 +1351,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync030, TestSize.Level0) ASSERT_EQ(kvDelegatePtrS3_->Put(key, value), OK); /** * @tc.steps:step3. Set null cloudDB. - * @tc.expected: step3 CLOUD_ERROR. + * @tc.expected: step3 INVALID_ARGS. */ BlockSync(kvDelegatePtrS3_, OK, g_CloudSyncoption, CLOUD_ERROR); std::map> cloudDbs; @@ -1561,7 +1561,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync035, TestSize.Level0) EXPECT_EQ(actualValue1, value1); auto result = kvDelegatePtrS1_->GetCloudVersion(""); EXPECT_EQ(result.first, OK); - for (auto item : result.second) { + for (const auto &item : result.second) { EXPECT_EQ(item.second, "1"); } /** @@ -1584,7 +1584,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync035, TestSize.Level0) EXPECT_EQ(actualValue2, value2); result = kvDelegatePtrS1_->GetCloudVersion(""); EXPECT_EQ(result.first, OK); - for (auto item : result.second) { + for (const auto &item : result.second) { EXPECT_EQ(item.second, "11"); } kvDelegatePtrS1_->SetGenCloudVersionCallback(nullptr); @@ -1601,7 +1601,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync036, TestSize.Level0) { /** * @tc.steps:step1. put data and SetCloudSyncConfig. - * @tc.expected: step1 ok. + * @tc.expected: step1. ok. */ CloudSyncConfig config; int maxUploadCount = 40; @@ -1612,7 +1612,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync036, TestSize.Level0) kvDelegatePtrS1_->Put(key, value); /** * @tc.steps:step2. sync. - * @tc.expected: step2 ok. + * @tc.expected: step2. ok. */ BlockSync(kvDelegatePtrS1_, OK, g_CloudSyncoption); } @@ -1907,7 +1907,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync042, TestSize.Level0) */ auto result = kvDelegatePtrS1_->GetCloudVersion(""); EXPECT_EQ(result.first, OK); - for (auto item : result.second) { + for (const auto &item : result.second) { EXPECT_EQ(item.second, "1"); } kvDelegatePtrS1_->SetGenCloudVersionCallback(nullptr); @@ -1963,7 +1963,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync043, TestSize.Level0) */ auto result = kvDelegatePtrS1_->GetCloudVersion(""); EXPECT_EQ(result.first, NOT_FOUND); - for (auto item : result.second) { + for (const auto &item : result.second) { EXPECT_EQ(item.second, ""); } kvDelegatePtrS1_->SetGenCloudVersionCallback(nullptr); @@ -1980,7 +1980,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync043, TestSize.Level0) HWTEST_F(DistributedDBCloudKvTest, NormalSync044, TestSize.Level0) { /** - * @tc.steps:step1. store1 put (k1,v1) and (k2,v2) + * @tc.steps: step1. store1 put (k1,v1) and (k2,v2) * @tc.expected: step1. both put ok */ communicatorAggregator_->SetLocalDeviceId("DEVICES_A"); @@ -2075,7 +2075,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync045, TestSize.Level0) HWTEST_F(DistributedDBCloudKvTest, NormalSync046, TestSize.Level0) { /** - * @tc.steps:step1. store1 put (k1,v1) and (k2,v2) + * @tc.steps: step1. store1 put (k1,v1) and (k2,v2) * @tc.expected: step1. both put ok */ communicatorAggregator_->SetLocalDeviceId("DEVICES_A"); @@ -2273,4 +2273,217 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync049, TestSize.Level0) EXPECT_EQ(actualValue, newValue); } } + +/** + * @tc.name: NormalSync050 + * @tc.desc: test upload with conflic error and chekck upload info + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(DistributedDBCloudKvTest, NormalSync050, TestSize.Level0) +{ + /** + * @tc.steps: step1. Set the retry count to 1 + * @tc.expected: step1. ok. + */ + CloudSyncConfig config; + config.maxRetryConflictTimes = 1; + kvDelegatePtrS1_->SetCloudSyncConfig(config); + /** + * @tc.steps: step2. Put {k1, v1} {k2, v2} locally + * @tc.expected: step2. ok. + */ + kvDelegatePtrS1_->Put(KEY_1, VALUE_1); + kvDelegatePtrS1_->Put(KEY_2, VALUE_2); + /** + * @tc.steps: step3. Set CLOUD_VERSION_CONFLICT when upload 2nd record, and do sync + * @tc.expected: step3. ok. + */ + int recordIndex = 0; + virtualCloudDb_->ForkInsertConflict([&recordIndex](const std::string &tableName, VBucket &extend, VBucket &record, + vector &cloudDataVec) { + recordIndex++; + if (recordIndex == 2) { // set 2nd record return CLOUD_RECORD_EXIST_CONFLICT + extend[CloudDbConstant::ERROR_FIELD] = static_cast(DBStatus::CLOUD_VERSION_CONFLICT); + return CLOUD_VERSION_CONFLICT; + } + return OK; + }); + BlockSync(kvDelegatePtrS1_, OK, g_CloudSyncoption); + /** + * @tc.steps: step4. Check last process + * @tc.expected: step4. ok. + */ + for (const auto &table : lastProcess_.tableProcess) { + EXPECT_EQ(table.second.upLoadInfo.total, 2u); + EXPECT_EQ(table.second.upLoadInfo.successCount, 2u); + EXPECT_EQ(table.second.upLoadInfo.failCount, 0u); + EXPECT_EQ(table.second.upLoadInfo.insertCount, 2u); + } + virtualCloudDb_->ForkInsertConflict(nullptr); +} + +/** + * @tc.name: NormalSync051 + * @tc.desc: test upload with conflict error and exceeds retry limit + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyuchen + */ +HWTEST_F(DistributedDBCloudKvTest, NormalSync051, TestSize.Level0) +{ + /** + * @tc.steps: step1. Set the retry count to 0 + * @tc.expected: step1. ok. + */ + CloudSyncConfig config; + config.maxRetryConflictTimes = 0; + kvDelegatePtrS1_->SetCloudSyncConfig(config); + /** + * @tc.steps: step2. Put {k1, v1} {k2, v2} locally + * @tc.expected: step2. ok. + */ + kvDelegatePtrS1_->Put(KEY_1, VALUE_1); + kvDelegatePtrS1_->Put(KEY_2, VALUE_2); + /** + * @tc.steps: step3. Set CLOUD_VERSION_CONFLICT when upload 2nd record, and do sync + * @tc.expected: step3. CLOUD_VERSION_CONFLICT. + */ + int recordIndex = 0; + virtualCloudDb_->ForkInsertConflict([&recordIndex](const std::string &tableName, VBucket &extend, VBucket &record, + vector &cloudDataVec) { + recordIndex++; + if (recordIndex == 2) { // set 2nd record return CLOUD_VERSION_CONFLICT + extend[CloudDbConstant::ERROR_FIELD] = static_cast(DBStatus::CLOUD_VERSION_CONFLICT); + return CLOUD_VERSION_CONFLICT; + } + return OK; + }); + BlockSync(kvDelegatePtrS1_, CLOUD_VERSION_CONFLICT, g_CloudSyncoption); + /** + * @tc.steps: step4. Check last process + * @tc.expected: step4. ok. + */ + for (const auto &table : lastProcess_.tableProcess) { + EXPECT_EQ(table.second.upLoadInfo.total, 2u); + EXPECT_EQ(table.second.upLoadInfo.successCount, 1u); + EXPECT_EQ(table.second.upLoadInfo.failCount, 1u); + EXPECT_EQ(table.second.upLoadInfo.insertCount, 1u); + } + virtualCloudDb_->ForkInsertConflict(nullptr); +} + +/** + * @tc.name: NormalSync052 + * @tc.desc: test upload with version conflict error under force push mode + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyuchen + */ +HWTEST_F(DistributedDBCloudKvTest, NormalSync052, TestSize.Level0) +{ + /** + * @tc.steps: step1. Set the retry count to 2 + * @tc.expected: step1. ok. + */ + CloudSyncConfig config; + config.maxRetryConflictTimes = 2; + kvDelegatePtrS1_->SetCloudSyncConfig(config); + /** + * @tc.steps: step2. Put {k1, v1} {k2, v2} locally, then sync to cloud + * @tc.expected: step2. ok. + */ + kvDelegatePtrS1_->Put(KEY_1, VALUE_1); + kvDelegatePtrS1_->Put(KEY_2, VALUE_2); + /** + * @tc.steps: step3. Set CLOUD_VERSION_CONFLICT when upload 2nd record, and do sync + * @tc.expected: step3. OK. + */ + int recordIndex = 0; + virtualCloudDb_->ForkInsertConflict([&recordIndex](const std::string &tableName, VBucket &extend, VBucket &record, + vector &cloudDataVec) { + recordIndex++; + if (recordIndex == 2) { // set 2nd record return CLOUD_VERSION_CONFLICT + extend[CloudDbConstant::ERROR_FIELD] = static_cast(DBStatus::CLOUD_VERSION_CONFLICT); + return CLOUD_VERSION_CONFLICT; + } + return OK; + }); + g_CloudSyncoption.mode = SyncMode::SYNC_MODE_CLOUD_FORCE_PUSH; + BlockSync(kvDelegatePtrS1_, OK, g_CloudSyncoption); + g_CloudSyncoption.mode = SyncMode::SYNC_MODE_CLOUD_MERGE; + /** + * @tc.steps: step4. Check last process + * @tc.expected: step4. ok. + */ + for (const auto &table : lastProcess_.tableProcess) { + EXPECT_EQ(table.second.upLoadInfo.total, 3u); + EXPECT_EQ(table.second.upLoadInfo.successCount, 3u); + EXPECT_EQ(table.second.upLoadInfo.failCount, 0u); + EXPECT_EQ(table.second.upLoadInfo.insertCount, 2u); + } + virtualCloudDb_->ForkInsertConflict(nullptr); +} + +/** + * @tc.name: NormalSync053 + * @tc.desc: test upload with version conflict error under force push mode, which has both update and insert + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyuchen + */ +HWTEST_F(DistributedDBCloudKvTest, NormalSync053, TestSize.Level0) +{ + /** + * @tc.steps: step1. Set the retry count to 0 + * @tc.expected: step1. ok. + */ + CloudSyncConfig config; + config.maxRetryConflictTimes = 0; + kvDelegatePtrS1_->SetCloudSyncConfig(config); + /** + * @tc.steps: step2. Put {k1, v1} {k2, v2} locally, then sync to cloud + * @tc.expected: step2. ok. + */ + kvDelegatePtrS1_->Put(KEY_1, VALUE_1); + kvDelegatePtrS1_->Put(KEY_2, VALUE_2); + BlockSync(kvDelegatePtrS1_, OK, g_CloudSyncoption); + /** + * @tc.steps: step3. Put {k3, v3} locally, and update k1 k2 + * @tc.expected: step3. ok. + */ + kvDelegatePtrS1_->Put(KEY_1, VALUE_2); + kvDelegatePtrS1_->Put(KEY_2, VALUE_3); + kvDelegatePtrS1_->Put(KEY_3, VALUE_3); + /** + * @tc.steps: step4. Set CLOUD_VERSION_CONFLICT when upload 2nd record, and do sync + * @tc.expected: step4. CLOUD_VERSION_CONFLICT. + */ + int recordIndex = 0; + virtualCloudDb_->ForkInsertConflict([&recordIndex](const std::string &tableName, VBucket &extend, VBucket &record, + vector &cloudDataVec) { + recordIndex++; + if (recordIndex == 2) { // set 2nd record return CLOUD_VERSION_CONFLICT + extend[CloudDbConstant::ERROR_FIELD] = static_cast(DBStatus::CLOUD_VERSION_CONFLICT); + return CLOUD_VERSION_CONFLICT; + } + return OK; + }); + g_CloudSyncoption.mode = SyncMode::SYNC_MODE_CLOUD_FORCE_PUSH; + BlockSync(kvDelegatePtrS1_, CLOUD_VERSION_CONFLICT, g_CloudSyncoption); + g_CloudSyncoption.mode = SyncMode::SYNC_MODE_CLOUD_MERGE; + /** + * @tc.steps: step5. Check last process + * @tc.expected: step5. ok. + */ + for (const auto &table : lastProcess_.tableProcess) { + EXPECT_EQ(table.second.upLoadInfo.total, 3u); + EXPECT_EQ(table.second.upLoadInfo.successCount, 1u); + EXPECT_EQ(table.second.upLoadInfo.failCount, 2u); + EXPECT_EQ(table.second.upLoadInfo.updateCount, 1u); + EXPECT_EQ(table.second.upLoadInfo.insertCount, 0u); + } + virtualCloudDb_->ForkInsertConflict(nullptr); +} } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_strategy_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_strategy_test.cpp index 6560ded5e9c710fbc8031bfcc2c0282c27bd0e99..c939121a71f42acdda37185ca630c9fc82989732 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_strategy_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_strategy_test.cpp @@ -368,4 +368,55 @@ HWTEST_F(DistributedDBCloudStrategyTest, TagOpTyeTest006, TestSize.Level0) cloudInfo.timestamp = cloudInfo.timestamp + CloudDbConstant::ONE_SECOND; EXPECT_EQ(strategy->TagSyncDataStatus(true, false, localInfo, cloudInfo), OpType::UPDATE); } + +/** + * @tc.name: TagOpTyeTest007 + * @tc.desc: Verify cloud merge strategy for KV and RDB scene when local time is larger and local flag different. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBCloudStrategyTest, TagOpTyeTest007, TestSize.Level0) +{ + /** + * @tc.steps: step1. create merge strategy, init localInfo/cloudInfo and local time is larger + * @tc.expected: step1. create ok + */ + auto strategy = StrategyFactory::BuildSyncStrategy(SyncMode::SYNC_MODE_CLOUD_MERGE); + ASSERT_NE(strategy, nullptr); + LogInfo localInfo; + LogInfo cloudInfo; + localInfo.cloudGid = "gid"; + localInfo.timestamp = 1u; + + /** + * @tc.steps: step2. local record is newer when flag is FLAG_LOCAL for RDB scene + * @tc.expected: step2. no need handle this record + */ + localInfo.flag = static_cast(LogInfoFlag::FLAG_LOCAL); + EXPECT_EQ(strategy->TagSyncDataStatus(true, false, localInfo, cloudInfo), OpType::NOT_HANDLE); + + /** + * @tc.steps: step3. local data need update when flag is not FLAG_LOCAL for RDB scene + * @tc.expected: step3. need UPDATE this record + */ + localInfo.flag = 0x00; + EXPECT_EQ(strategy->TagSyncDataStatus(true, false, localInfo, cloudInfo), OpType::UPDATE); + + /** + * @tc.steps: step4. local record is newer when flag is not FLAG_CLOUD_WRITE for KV scene + * @tc.expected: step4. no need handle this record + */ + strategy->SetIsKvScene(true); + EXPECT_EQ(strategy->TagSyncDataStatus(true, false, localInfo, cloudInfo), OpType::NOT_HANDLE); + localInfo.flag = 0x00; + EXPECT_EQ(strategy->TagSyncDataStatus(true, false, localInfo, cloudInfo), OpType::NOT_HANDLE); + + /** + * @tc.steps: step5. local data need update when flag is FLAG_CLOUD_WRITE for KV scene + * @tc.expected: step5. need UPDATE this record + */ + localInfo.flag = static_cast(LogInfoFlag::FLAG_CLOUD_WRITE); + EXPECT_EQ(strategy->TagSyncDataStatus(true, false, localInfo, cloudInfo), OpType::UPDATE); +} } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_download_assets_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_download_assets_test.cpp index 06fe29202b63de79726d0c930cf1a362f4b0e5b5..95d6edf7c7f226944d56fe4e0400c14419c98907 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_download_assets_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_download_assets_test.cpp @@ -96,10 +96,8 @@ const Asset ASSET_COPY2 = {.version = 1, .size = "256", .hash = "ASE"}; const Assets ASSETS_COPY1 = { ASSET_COPY, ASSET_COPY2 }; -const std::string QUERY_CONSISTENT_SQL = "select count(*) from " + DBCommon::GetLogTableName(ASSETS_TABLE_NAME) + - " where flag&0x20=0;"; -const std::string QUERY_COMPENSATED_SQL = "select count(*) from " + DBCommon::GetLogTableName(ASSETS_TABLE_NAME) + - " where flag&0x10!=0;"; +const std::string QUERY_CONSISTENT_SQL = "select count(*) from naturalbase_rdb_aux_student_log where flag&0x20=0;"; +const std::string QUERY_COMPENSATED_SQL = "select count(*) from naturalbase_rdb_aux_student_log where flag&0x10!=0;"; string g_storePath; string g_testDir; @@ -308,7 +306,8 @@ void CallSync(const std::vector &tableNames, SyncMode mode, DBStatu std::vector expectProcess; CloudSyncStatusCallback callback = [&errCode](const std::map &process) { ASSERT_EQ(process.begin()->first, DEVICE_CLOUD); - g_syncProcess = std::move(process.begin()->second); + std::unique_lock lock(g_processMutex); + g_syncProcess = process.begin()->second; if (g_syncProcess.process == FINISHED) { g_processCondition.notify_one(); ASSERT_EQ(g_syncProcess.errCode, errCode); @@ -444,6 +443,7 @@ void DistributedDBCloudSyncerDownloadAssetsTest::TearDownTestCase(void) {} void DistributedDBCloudSyncerDownloadAssetsTest::SetUp(void) { + RuntimeContext::GetInstance()->SetBatchDownloadAssets(false); if (DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir) != 0) { LOGE("rm test db files error."); } @@ -1609,7 +1609,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId020, TestSize.Le CloudSyncConfig config; config.maxUploadCount = 200; // max upload 200 g_delegate->SetCloudSyncConfig(config); - + /** * @tc.steps:step1. local insert assets and erase assets extends * @tc.expected: step1. return OK. @@ -1621,7 +1621,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId020, TestSize.Le }); CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, DBStatus::OK); CheckLocaLAssets(ASSETS_TABLE_NAME, "0", {}); - + /** * @tc.steps:step2. local insert assets and modify assetId to empty * @tc.expected: step2. return OK. @@ -1643,7 +1643,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId020, TestSize.Le index.insert(i); } CheckLocaLAssets(ASSETS_TABLE_NAME, "10", index); - + /** * @tc.steps:step3. local insert assets and modify assetId info such as asset.name * @tc.expected: step3. return OK. @@ -1664,7 +1664,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId020, TestSize.Le newIndex.insert(i); } CheckLocaLAssets(ASSETS_TABLE_NAME, "10", newIndex); - + /** * @tc.steps:step4. local update assets and sync, check the local assetId. * @tc.expected: step4. sync success. @@ -1686,14 +1686,14 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId021, TestSize.Le CloudSyncConfig config; config.maxUploadCount = 200; // max upload 200 g_delegate->SetCloudSyncConfig(config); - + /** * @tc.steps:step1. local insert assets and erase assets extends * @tc.expected: step1. return OK. */ int localCount = 50; InsertLocalData(db, 0, localCount, ASSETS_TABLE_NAME); - + /** * @tc.steps:step2. ForkInsertConflict, make one record assets missing during batch insert * @tc.expected: step2. SyncProgress return OK. One record's assets missing will not block other progress. @@ -1708,7 +1708,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId021, TestSize.Le } return OK; }); - + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, DBStatus::OK); int beginFailFillNum = 49; int endFailFillNum = 50; @@ -1719,7 +1719,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId021, TestSize.Le CheckLocaLAssets(ASSETS_TABLE_NAME, "10", index); g_virtualCloudDb->ForkUpload(nullptr); } - + /** * @tc.name: FillAssetId022 * @tc.desc: Test if local assets missing, many records's assets missing will not mark the whole sync progress failure @@ -1732,14 +1732,14 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId022, TestSize.Le CloudSyncConfig config; config.maxUploadCount = 200; // max upload 200 g_delegate->SetCloudSyncConfig(config); - + /** * @tc.steps:step1. local insert assets and erase assets extends * @tc.expected: step1. return OK. */ int localCount = 50; InsertLocalData(db, 0, localCount, ASSETS_TABLE_NAME); - + /** * @tc.steps:step2. ForkInsertConflict, make one record assets missing during batch insert * @tc.expected: step2. SyncProgress return OK. One record's assets missing will not block other progress. @@ -1754,7 +1754,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId022, TestSize.Le } return OK; }); - + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, DBStatus::OK); int beginFailFillNum = 49; int endFailFillNum = 54; @@ -2082,7 +2082,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, ConsistentFlagTest004, Test InsertCloudDBData(0, cloudCount, 0, ASSETS_TABLE_NAME); /** - * @tc.steps:step2. fork upload, not return error filed of CLOUD_NETWORK_ERROR + * @tc.steps:step2. fork upload, return error filed of CLOUD_NETWORK_ERROR * @tc.expected: step2. return OK. */ int upIdx = 0; @@ -2390,6 +2390,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, SyncDataStatusTest008, Test */ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetTest001, TestSize.Level0) { + RuntimeContext::GetInstance()->SetBatchDownloadAssets(true); /** * @tc.steps:step1. init data and sync * @tc.expected: step1. return OK. @@ -2414,6 +2415,8 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetTest001, TestS EXPECT_EQ(asset.status, AssetStatus::NORMAL); } } + EXPECT_EQ(g_virtualAssetLoader->GetBatchDownloadCount(), 0); + RuntimeContext::GetInstance()->SetBatchDownloadAssets(false); } /** @@ -2515,13 +2518,13 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, RecordLockFuncTest001, Test std::mutex mtx; std::condition_variable cv; int queryIdx = 0; + bool ready = false; g_virtualCloudDb->ForkQuery([&](const std::string &, VBucket &) { LOGD("query index:%d", ++queryIdx); if (queryIdx == 2) { // 2 is compensated sync - mtx.lock(); + std::unique_lock lock(mtx); + ready = true; cv.notify_one(); - mtx.unlock(); - std::this_thread::sleep_for(std::chrono::seconds(2)); // block notify 2s } }); g_virtualAssetLoader->SetDownloadStatus(DBStatus::CLOUD_ERROR); @@ -2529,21 +2532,14 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, RecordLockFuncTest001, Test { std::unique_lock lock(mtx); - cv.wait(lock); + cv.wait(lock, [&]{ return ready; }); } g_virtualAssetLoader->SetDownloadStatus(DBStatus::OK); + std::this_thread::sleep_for(std::chrono::seconds(6)); /** - * @tc.steps:step3. check before compensated sync - * @tc.expected: 70-99 is UNLOCKING. - */ - CheckLockStatus(db, 0, 69, LockStatus::UNLOCK); - CheckLockStatus(db, 70, 99, LockStatus::UNLOCKING); - - std::this_thread::sleep_for(std::chrono::seconds(3)); - /** - * @tc.steps:step4. check after compensated sync - * @tc.expected: all is UNLOCKING. + * @tc.steps:step3. check after compensated sync + * @tc.expected: step3. all is UNLOCKING. */ CheckLockStatus(db, 0, 99, LockStatus::UNLOCK); } @@ -2617,6 +2613,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, RecordLockFuncTest002, Test * @tc.expected: step7.100-119 is UNLOCKING. */ EXPECT_EQ(UnLock(ASSETS_TABLE_NAME, hashKey, db), WAIT_COMPENSATED_SYNC); + CheckLockStatus(db, 0, 99, LockStatus::UNLOCK); CheckLockStatus(db, 100, 119, LockStatus::UNLOCKING); /** @@ -2626,32 +2623,25 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, RecordLockFuncTest002, Test std::mutex mtx; std::condition_variable cv; int queryIdx = 0; + bool ready = false; g_virtualCloudDb->ForkQuery([&](const std::string &, VBucket &) { LOGD("query index:%d", ++queryIdx); if (queryIdx == 5) { // 5 is compensated sync - mtx.lock(); + std::unique_lock lock(mtx); + ready = true; cv.notify_one(); - mtx.unlock(); - std::this_thread::sleep_for(std::chrono::seconds(2)); // block notify 2s } }); CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_FORCE_PUSH, DBStatus::OK); { std::unique_lock lock(mtx); - cv.wait(lock); + cv.wait(lock, [&]{ return ready; }); } + std::this_thread::sleep_for(std::chrono::seconds(6)); /** - * @tc.steps:step9. check before compensated sync - * @tc.expected: 100-119 is UNLOCKING. - */ - CheckLockStatus(db, 0, 99, LockStatus::UNLOCK); - CheckLockStatus(db, 100, 119, LockStatus::UNLOCKING); - - std::this_thread::sleep_for(std::chrono::seconds(3)); - /** - * @tc.steps:step10. check after compensated sync - * @tc.expected: all is UNLOCK. + * @tc.steps:step9. check after compensated sync + * @tc.expected: step9. all is UNLOCK. */ CheckLockStatus(db, 0, 119, LockStatus::UNLOCK); } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_lock_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_lock_test.cpp index 74b51338722f54342a699f5257e8506a56c7b800..cff414d05f360356ea05aa7056762749977b06a4 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_lock_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_lock_test.cpp @@ -141,6 +141,7 @@ void DistributedDBCloudSyncerLockTest::TearDownTestCase(void) {} void DistributedDBCloudSyncerLockTest::SetUp(void) { + RuntimeContext::GetInstance()->SetBatchDownloadAssets(false); if (DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir) != 0) { LOGE("rm test db files error."); } @@ -757,17 +758,18 @@ HWTEST_F(DistributedDBCloudSyncerLockTest, DownloadAssetStatusTest002, TestSize. }); g_virtualAssetLoader->SetRemoveLocalAssetsCallback([&b2](std::map &assets) { auto it = assets.find(COL_ASSET); - ASSERT_EQ(it != assets.end(), true); - ASSERT_EQ(it->second.size(), 1u); + EXPECT_EQ(it != assets.end(), true); + EXPECT_EQ(it->second.size(), 1u); EXPECT_EQ(it->second[0].status, static_cast(AssetStatus::DELETE)); it = assets.find(COL_ASSETS); - ASSERT_EQ(it != assets.end(), true); - ASSERT_EQ(it->second.size(), 1u); // 1 is remove size + EXPECT_EQ(it != assets.end(), true); + EXPECT_EQ(it->second.size(), 1u); // 1 is remove size for (const auto &b: it->second) { if (b.name == b2.name) { EXPECT_EQ(b.status, static_cast(AssetStatus::DELETE)); } } + return DBStatus::OK; }); CallSync(option); g_virtualAssetLoader->ForkDownload(nullptr); diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/mock_icloud_sync_storage_interface.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/mock_icloud_sync_storage_interface.h index ec34ffe9f53864bbaf02b593328a88a84d858b33..76e7912a7ebb73f46869d9d55183f99101d4d4ad 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/mock_icloud_sync_storage_interface.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/mock_icloud_sync_storage_interface.h @@ -51,6 +51,7 @@ public: MOCK_METHOD1(CheckQueryValid, int(const QuerySyncObject &)); MOCK_METHOD1(IsSharedTable, bool(const std::string &)); MOCK_CONST_METHOD0(GetCloudSyncConfig, CloudSyncConfig()); + MOCK_METHOD3(GetLocalDataCount, int(const std::string &, int &, int &)); }; } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_asset_loader.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_asset_loader.cpp index edfb3ae852340f6fe507de331bc981e9d9d5dcfa..365ca9b17da3b4f6bd9d9f2d0b553c752506660d 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_asset_loader.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_asset_loader.cpp @@ -55,8 +55,12 @@ DBStatus VirtualAssetLoader::RemoveLocalAssets(const std::string &tableName, con return removeStatus_; } } + DBStatus errCode = DBStatus::OK; if (removeLocalAssetsCallBack_) { - removeLocalAssetsCallBack_(assets); + errCode = removeLocalAssetsCallBack_(assets); + } + if (errCode != DBStatus::OK) { + return errCode; } LOGD("RemoveLocalAssets GID:%s", gid.c_str()); for (auto &item: assets) { diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_asset_loader.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_asset_loader.h index 3ee2b4b042b096c12c6f74860b19c163f05e2d2f..f30f39a37ba13ed7f748837e9f6f801a2453001e 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_asset_loader.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_asset_loader.h @@ -21,7 +21,7 @@ namespace DistributedDB { using DownloadCallBack = std::function &assets)>; using RemoveAssetsCallBack = std::function &assets)>; -using RemoveLocalAssetsCallBack = std::function &assets)>; +using RemoveLocalAssetsCallBack = std::function &assets)>; class VirtualAssetLoader : public IAssetLoader { public: VirtualAssetLoader() = default; diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_cloud_db.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_cloud_db.cpp index fb69bc6adab140cbc585f70ad14e4175b3068ca0..8ffb2ac7bee623f44041825e713c91fa20654e8e 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_cloud_db.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_cloud_db.cpp @@ -50,7 +50,7 @@ DBStatus VirtualCloudDb::BatchInsert(const std::string &tableName, std::vector 0) { - extend.erase(extend.end()); + extend.pop_back(); } else if (missingExtendCount_ < 0) { VBucket vBucket; extend.push_back(vBucket); @@ -140,7 +140,7 @@ DBStatus VirtualCloudDb::BatchInsertWithGid(const std::string &tableName, std::v cloudData_[tableName].push_back(cloudData); } if (missingExtendCount_ > 0) { - extend.erase(extend.end()); + extend.pop_back(); } else if (missingExtendCount_ < 0) { VBucket vBucket; extend.push_back(vBucket); @@ -409,13 +409,16 @@ DBStatus VirtualCloudDb::InnerUpdate(const std::string &tableName, std::vector autoLock(cloudDataMutex_); DBStatus res = InnerUpdateWithoutLock(tableName, std::move(record), extend, isDelete); if (res != OK) { return res; } if (missingExtendCount_ > 0) { - extend.erase(extend.end()); + extend.pop_back(); } else if (missingExtendCount_ < 0) { VBucket vBucket; extend.push_back(vBucket); @@ -607,6 +610,12 @@ void VirtualCloudDb::ForkUpload(const std::function &, + std::vector &, bool isDelete)> &forkBeforeBatchUpdateFunc) +{ + forkBeforeBatchUpdateFunc_ = forkBeforeBatchUpdateFunc; +} + int32_t VirtualCloudDb::GetLockCount() const { return lockCount_; diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_cloud_db.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_cloud_db.h index 6232bb0a1761600549e2df0c4d4d5061b516e422..6c90e2b13d407a7ca77bc9608efad2ab757450f0 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_cloud_db.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_cloud_db.h @@ -79,6 +79,9 @@ public: void ForkUpload(const std::function &forkUploadFunc); + void ForkBeforeBatchUpdate(const std::function &, + std::vector &, bool isDelete)> &forkBeforeBatchUpdateFunc); + void ForkInsertConflict(const std::function &)> &forkUploadFunc); @@ -148,6 +151,8 @@ private: DBStatus actionStatus_ = OK; std::function forkFunc_; std::function forkUploadFunc_; + std::function &, std::vector &, + bool isDelete)> forkBeforeBatchUpdateFunc_; std::function &)> forkUploadConflictFunc_; std::function insertCheckFunc_; diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_multi_user_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_multi_user_test.cpp index 9e5bfb679d556c8fef696d4b66e35c955c14266f..88063699bb70d5eb27837d5c299ad2ce4212c09a 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_multi_user_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_multi_user_test.cpp @@ -1301,4 +1301,4 @@ HWTEST_F(DistributedDBRelationalMultiUserTest, DropDistributedTableTest001, Test CheckDataInRealDevice(); g_currentStatus = 0; CloseStore(); -} +} \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_ver_p2p_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_ver_p2p_sync_test.cpp index 4aabf268caef0b372c4cf2537ed7f6bebc473032..0c7d7d2542efb1df74d50e37fdcc3b9ab1fca686 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_ver_p2p_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_ver_p2p_sync_test.cpp @@ -797,6 +797,17 @@ namespace { observer = nullptr; } + void SetOption(StoreObserver *observer, RelationalStoreDelegate::Option &option) + { + option.observer = observer; +#ifndef OMIT_ENCRYPT + option.isEncryptedDb = true; + option.iterateTimes = DEFAULT_ITER; + option.passwd = g_isAfterRekey ? g_rekeyPasswd : g_correctPasswd; + option.cipher = CipherType::DEFAULT; +#endif + } + class DistributedDBRelationalVerP2PSyncTest : public testing::Test { public: static void SetUpTestCase(); @@ -1265,7 +1276,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, AutoLaunchSync002, TestSize.Leve Query query = Query::Select(g_tableName); SyncOperation::UserCallback callBack = [](const std::map &statusMap) { for (const auto &entry : statusMap) { - EXPECT_EQ(entry.second, static_cast(SyncOperation::OP_COMM_ABNORMAL)); + EXPECT_EQ(entry.second, -E_NOT_FOUND); } }; EXPECT_EQ(g_deviceB->GenericVirtualDevice::Sync(SYNC_MODE_PUSH_ONLY, query, callBack, true), E_OK); @@ -1307,7 +1318,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, AutoLaunchSync003, TestSize.Leve Query query = Query::Select(g_tableName); SyncOperation::UserCallback callBack = [](const std::map &statusMap) { for (const auto &entry : statusMap) { - EXPECT_EQ(entry.second, static_cast(SyncOperation::OP_COMM_ABNORMAL)); + EXPECT_EQ(entry.second, -E_NOT_FOUND); } }; EXPECT_EQ(g_deviceB->GenericVirtualDevice::Sync(SYNC_MODE_PUSH_ONLY, query, callBack, true), E_OK); @@ -1502,6 +1513,23 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, AbilitySync004, TestSize.Level1) EXPECT_EQ(res, static_cast(SyncOperation::Status::OP_SCHEMA_INCOMPATIBLE)); } +/** +* @tc.name: Ability Sync 005 +* @tc.desc: Test ability sync fail when SendMessage err. +* @tc.type: FUNC +* @tc.require: +* @tc.author: suyue +*/ +HWTEST_F(DistributedDBRelationalVerP2PSyncTest, AbilitySync005, TestSize.Level1) +{ + std::map dataMap; + std::vector localFieldInfo; + GetFieldInfo(localFieldInfo, g_storageType); + g_communicatorAggregator->DisableCommunicator(); + PrepareEnvironment(dataMap, localFieldInfo, localFieldInfo, {g_deviceB}); + BlockSync(SyncMode::SYNC_MODE_PUSH_ONLY, DB_ERROR, {DEVICE_B}); +} + /** * @tc.name: WaterMark 001 * @tc.desc: Test sync success after erase waterMark. @@ -1957,20 +1985,6 @@ void RegisterNewObserver(RelationalStoreDelegate *rdb1, RelationalStoreObserverU rdb1 = nullptr; } -static void SetAutoLaunchParamForObserver008(AutoLaunchParam ¶m) -{ - param.path = g_dbDir; - param.appId = APP_ID; - param.userId = USER_ID; - param.storeId = STORE_ID_1; -#ifndef OMIT_ENCRYPT - param.option.isEncryptedDb = true; - param.option.cipher = CipherType::DEFAULT; - param.option.passwd = g_correctPasswd; - param.option.iterateTimes = DEFAULT_ITER; -#endif -} - /** * @tc.name: relation observer 008 * @tc.desc: Test multi rdb observer @@ -1995,8 +2009,17 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, Observer008, TestSize.Level3) if (g_id != identifier) { return false; } - SetAutoLaunchParamForObserver008(param); + param.path = g_dbDir; + param.appId = APP_ID; + param.userId = USER_ID; + param.storeId = STORE_ID_1; param.option.storeObserver = autoObserver; +#ifndef OMIT_ENCRYPT + param.option.isEncryptedDb = true; + param.option.cipher = CipherType::DEFAULT; + param.option.passwd = g_correctPasswd; + param.option.iterateTimes = DEFAULT_ITER; +#endif return true; }; g_mgr.SetAutoLaunchRequestCallback(callback); @@ -2017,13 +2040,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, Observer008, TestSize.Level3) auto observer1 = new (std::nothrow) RelationalStoreObserverUnitTest(); ASSERT_NE(observer1, nullptr); RelationalStoreDelegate::Option option; - option.observer = observer1; -#ifndef OMIT_ENCRYPT - option.isEncryptedDb = true; - option.iterateTimes = DEFAULT_ITER; - option.passwd = g_isAfterRekey ? g_rekeyPasswd : g_correctPasswd; - option.cipher = CipherType::DEFAULT; -#endif + SetOption(observer1, option); RelationalStoreDelegate *rdb1 = nullptr; g_mgr.OpenStore(g_dbDir, STORE_ID_1, option, rdb1); ASSERT_TRUE(rdb1 != nullptr); @@ -2039,8 +2056,8 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, Observer008, TestSize.Level3) EXPECT_EQ(autoObserver->GetCallCount(), 1u); int reTry = 5; while (observer1->GetCallCount() != 1u && reTry > 0) { - std::this_thread::sleep_for(std::chrono::seconds(1)); reTry--; + std::this_thread::sleep_for(std::chrono::seconds(1)); } EXPECT_EQ(observer1->GetCallCount(), 1u); EXPECT_EQ(autoObserver->GetDataChangeDevice(), DEVICE_B); diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_complex_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_complex_sync_test.cpp index a8dd4d825345efcc97cad1890c3f3af0e250c41b..4b2106fa28a1737990d397e8dea3a12ce09799f8 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_complex_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_complex_sync_test.cpp @@ -729,9 +729,13 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DeviceOfflineSync001, TestSiz for (const auto &pair : result) { LOGD("dev %s, status %d", pair.first.c_str(), pair.second); if (pair.first == DEVICE_B) { - EXPECT_TRUE(pair.second == COMM_FAILURE); + // If syncTaskContext of deviceB is scheduled to be executed first, ClearAllSyncTask is + // invoked when OfflineHandleByDevice is triggered, and SyncOperation::Finished() is triggered in advance. + // The returned status is COMM_FAILURE + EXPECT_TRUE((pair.second == static_cast(-E_PERIPHERAL_INTERFACE_FAIL)) || + (pair.second == COMM_FAILURE)); } else { - EXPECT_TRUE(pair.second == OK); + EXPECT_EQ(pair.second, OK); } } VirtualDataItem item; @@ -804,9 +808,13 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DeviceOfflineSync002, TestSiz for (const auto &pair : result) { LOGD("dev %s, status %d", pair.first.c_str(), pair.second); if (pair.first == DEVICE_B) { - EXPECT_TRUE(pair.second == COMM_FAILURE); + // If syncTaskContext of deviceB is scheduled to be executed first, ClearAllSyncTask is + // invoked when OfflineHandleByDevice is triggered, and SyncOperation::Finished() is triggered in advance. + // The returned status is COMM_FAILURE + EXPECT_TRUE((pair.second == static_cast(-E_PERIPHERAL_INTERFACE_FAIL)) || + (pair.second == COMM_FAILURE)); } else { - EXPECT_TRUE(pair.second == OK); + EXPECT_EQ(pair.second, OK); } } @@ -819,6 +827,77 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DeviceOfflineSync002, TestSiz EXPECT_EQ(value5, value4); } +/** + * @tc.name: Device Offline Sync 003 + * @tc.desc: Test sync statuses when device offline and sendMessage return different errCode + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DeviceOfflineSync003, TestSize.Level1) +{ + /** + * @tc.steps: step1. device put data. + * @tc.expected: step1. sync return OK. + */ + std::vector devices; + devices.push_back(g_deviceB->GetDeviceId()); + devices.push_back(g_deviceC->GetDeviceId()); + Key key1 = {'1'}; + Value value1 = {'1'}; + ASSERT_EQ(g_kvDelegatePtr->Put(key1, value1), OK); + + /** + * @tc.steps: step2. call sync when device offline and mock commErrCode is E_BASE(positive number). + * @tc.expected: step2. return COMM_FAILURE. + */ + g_communicatorAggregator->MockCommErrCode(E_BASE); + std::map result; + DBStatus status = g_tool.SyncTest(g_kvDelegatePtr, devices, SYNC_MODE_PUSH_ONLY, result); + ASSERT_EQ(status, OK); + for (const auto &pair : result) { + LOGD("dev %s, status %d, expectStatus %d", pair.first.c_str(), pair.second, E_BASE); + EXPECT_EQ(pair.second, COMM_FAILURE); + } + + /** + * @tc.steps: step3. call sync when device offline and mock commErrCode is -E_BASE(negative number). + * @tc.expected: step3. return -E_BASE. + */ + g_communicatorAggregator->MockCommErrCode(-E_BASE); + status = g_tool.SyncTest(g_kvDelegatePtr, devices, SYNC_MODE_PUSH_ONLY, result); + ASSERT_EQ(status, OK); + for (const auto &pair : result) { + LOGD("dev %s, status %d, expectStatus %d", pair.first.c_str(), pair.second, COMM_FAILURE); + EXPECT_EQ(pair.second, static_cast(-E_BASE)); + } + + /** + * @tc.steps: step4. call sync when device offline and mock commErrCode is INT_MAX. + * @tc.expected: step4. return COMM_FAILURE. + */ + g_communicatorAggregator->MockCommErrCode(INT_MAX); + status = g_tool.SyncTest(g_kvDelegatePtr, devices, SYNC_MODE_PUSH_ONLY, result); + ASSERT_EQ(status, OK); + for (const auto &pair : result) { + LOGD("dev %s, status %d, expectStatus %d", pair.first.c_str(), pair.second, INT_MAX); + EXPECT_EQ(pair.second, COMM_FAILURE); + } + + /** + * @tc.steps: step5. call sync when device offline and mock commErrCode is -INT_MAX. + * @tc.expected: step5. return -INT_MAX. + */ + g_communicatorAggregator->MockCommErrCode(-INT_MAX); + status = g_tool.SyncTest(g_kvDelegatePtr, devices, SYNC_MODE_PUSH_ONLY, result); + ASSERT_EQ(status, OK); + for (const auto &pair : result) { + LOGD("dev %s, status %d, expectStatus %d", pair.first.c_str(), pair.second, -INT_MAX); + EXPECT_EQ(pair.second, -INT_MAX); + } + g_communicatorAggregator->MockCommErrCode(E_OK); +} + /** * @tc.name: EncryptedAlgoUpgrade001 * @tc.desc: Test upgrade encrypted db can sync normally @@ -1570,6 +1649,75 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, RebuildSync003, TestSize.Leve g_communicatorAggregator->ResetSendDelayInfo(); } +/** + * @tc.name: RebuildSync004 + * @tc.desc: test WIPE_STALE_DATA mode when peers rebuilt db + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangtao + */ +HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, RebuildSync004, TestSize.Level1) +{ + ASSERT_TRUE(g_kvDelegatePtr != nullptr); + /** + * @tc.steps: step1. sync deviceB data to A and check data + * * @tc.expected: step1. interface return ok + */ + Key key1 = {'1'}; + Key key2 = {'2'}; + Key key3 = {'3'}; + Key key4 = {'4'}; + Value value = {'1'}; + EXPECT_EQ(g_kvDelegatePtr->Put(key1, value), OK); + EXPECT_EQ(g_kvDelegatePtr->Put(key2, value), OK); + EXPECT_EQ(g_kvDelegatePtr->Put(key3, value), OK); + EXPECT_EQ(g_deviceB->Sync(DistributedDB::SYNC_MODE_PUSH_PULL, true), E_OK); + Value actualValue; + EXPECT_EQ(g_kvDelegatePtr->Get(key1, actualValue), OK); + EXPECT_EQ(actualValue, value); + EXPECT_EQ(g_kvDelegatePtr->Get(key2, actualValue), OK); + EXPECT_EQ(actualValue, value); + EXPECT_EQ(g_kvDelegatePtr->Get(key3, actualValue), OK); + EXPECT_EQ(actualValue, value); + VirtualDataItem item; + EXPECT_EQ(g_deviceB->GetData(key1, item), E_OK); + EXPECT_EQ(item.value, value); + EXPECT_EQ(g_deviceB->GetData(key2, item), E_OK); + EXPECT_EQ(item.value, value); + EXPECT_EQ(g_deviceB->GetData(key3, item), E_OK); + EXPECT_EQ(item.value, value); + + /** + * @tc.steps: step2. device A rebuilt, device B push data to A and set clear remote data mark into context after 1s + * * @tc.expected: step2. interface return ok + */ + g_deviceB->SetClearRemoteStaleData(true); + EXPECT_EQ(g_deviceB->PutData(key4, value, 3u, 2), E_OK); // 3: timestamp + + VirtualDataItem item2; + EXPECT_EQ(g_deviceB->GetData(key4, item2), E_OK); + EXPECT_EQ(item2.value, value); + g_mgr.CloseKvStore(g_kvDelegatePtr); + g_kvDelegatePtr = nullptr; + ASSERT_TRUE(g_mgr.DeleteKvStore(STORE_ID) == OK); + KvStoreNbDelegate::Option option; + g_mgr.GetKvStore(STORE_ID, option, g_kvDelegateCallback); + ASSERT_TRUE(g_kvDelegateStatus == OK); + ASSERT_TRUE(g_kvDelegatePtr != nullptr); + + /** + * @tc.steps: step3. device B sync to A, make it clear history data and check data + * * @tc.expected: step3. interface return ok + */ + EXPECT_EQ(g_deviceB->Sync(DistributedDB::SYNC_MODE_PUSH_ONLY, true), E_OK); + EXPECT_EQ(g_deviceB->GetData(key2, item), -E_NOT_FOUND); + EXPECT_EQ(g_deviceB->GetData(key3, item), -E_NOT_FOUND); + EXPECT_EQ(g_deviceB->GetData(key4, item2), E_OK); + EXPECT_EQ(item2.value, value); + EXPECT_EQ(g_kvDelegatePtr->Get(key4, actualValue), OK); + EXPECT_EQ(actualValue, value); +} + /** * @tc.name: RemoveDeviceData001 * @tc.desc: call rekey and removeDeviceData Concurrently @@ -1741,75 +1889,6 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, DeviceOfflineSyncTask003, Tes g_deviceB->Offline(); } -/** - * @tc.name: RebuildSync004 - * @tc.desc: test WIPE_STALE_DATA mode when peers rebuilt db - * @tc.type: FUNC - * @tc.require: - * @tc.author: zhangtao - */ -HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, RebuildSync004, TestSize.Level1) -{ - ASSERT_TRUE(g_kvDelegatePtr != nullptr); - /** - * @tc.steps: step1. sync deviceB data to A and check data - * * @tc.expected: step1. interface return ok - */ - Key key1 = {'1'}; - Key key2 = {'2'}; - Key key3 = {'3'}; - Key key4 = {'4'}; - Value value = {'1'}; - EXPECT_EQ(g_kvDelegatePtr->Put(key1, value), OK); - EXPECT_EQ(g_kvDelegatePtr->Put(key2, value), OK); - EXPECT_EQ(g_kvDelegatePtr->Put(key3, value), OK); - EXPECT_EQ(g_deviceB->Sync(DistributedDB::SYNC_MODE_PUSH_PULL, true), E_OK); - Value actualValue; - EXPECT_EQ(g_kvDelegatePtr->Get(key1, actualValue), OK); - EXPECT_EQ(actualValue, value); - EXPECT_EQ(g_kvDelegatePtr->Get(key2, actualValue), OK); - EXPECT_EQ(actualValue, value); - EXPECT_EQ(g_kvDelegatePtr->Get(key3, actualValue), OK); - EXPECT_EQ(actualValue, value); - VirtualDataItem item; - EXPECT_EQ(g_deviceB->GetData(key1, item), E_OK); - EXPECT_EQ(item.value, value); - EXPECT_EQ(g_deviceB->GetData(key2, item), E_OK); - EXPECT_EQ(item.value, value); - EXPECT_EQ(g_deviceB->GetData(key3, item), E_OK); - EXPECT_EQ(item.value, value); - - /** - * @tc.steps: step2. device A rebuilt, device B push data to A and set clear remote data mark into context after 1s - * * @tc.expected: step2. interface return ok - */ - g_deviceB->SetClearRemoteStaleData(true); - EXPECT_EQ(g_deviceB->PutData(key4, value, 3u, 2), E_OK); // 3: timestamp - - VirtualDataItem item2; - EXPECT_EQ(g_deviceB->GetData(key4, item2), E_OK); - EXPECT_EQ(item2.value, value); - g_mgr.CloseKvStore(g_kvDelegatePtr); - g_kvDelegatePtr = nullptr; - ASSERT_TRUE(g_mgr.DeleteKvStore(STORE_ID) == OK); - KvStoreNbDelegate::Option option; - g_mgr.GetKvStore(STORE_ID, option, g_kvDelegateCallback); - ASSERT_TRUE(g_kvDelegateStatus == OK); - ASSERT_TRUE(g_kvDelegatePtr != nullptr); - - /** - * @tc.steps: step3. device B sync to A, make it clear history data and check data - * * @tc.expected: step3. interface return ok - */ - EXPECT_EQ(g_deviceB->Sync(DistributedDB::SYNC_MODE_PUSH_ONLY, true), E_OK); - EXPECT_EQ(g_deviceB->GetData(key2, item), -E_NOT_FOUND); - EXPECT_EQ(g_deviceB->GetData(key3, item), -E_NOT_FOUND); - EXPECT_EQ(g_deviceB->GetData(key4, item2), E_OK); - EXPECT_EQ(item2.value, value); - EXPECT_EQ(g_kvDelegatePtr->Get(key4, actualValue), OK); - EXPECT_EQ(actualValue, value); -} - /** * @tc.name: GetSyncDataFail001 * @tc.desc: test get sync data failed when sync @@ -2200,4 +2279,4 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, MetaBusy001, TestSize.Level1) } g_deviceB->SetSaveDataCallback(nullptr); RuntimeContext::GetInstance()->StopTaskPool(); -} \ No newline at end of file +} diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_simple_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_simple_sync_test.cpp index 2e4f73bdff734cf118e77c8fc1cb9a433b94b08d..24e96e430c3b6fe97a928c9c7d23781491be4ba1 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_simple_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_simple_sync_test.cpp @@ -1219,7 +1219,11 @@ HWTEST_F(DistributedDBSingleVerP2PSimpleSyncTest, BlockSync004, TestSize.Level2) ASSERT_TRUE(result.size() == devices.size()); for (const auto &pair : result) { LOGD("dev %s, status %d", pair.first.c_str(), pair.second); - EXPECT_TRUE(pair.second == COMM_FAILURE); + // If syncTaskContext of deviceB is scheduled to be executed first, ClearAllSyncTask is + // invoked when OfflineHandleByDevice is triggered, and SyncOperation::Finished() is triggered in advance. + // The returned status is COMM_FAILURE + EXPECT_TRUE((pair.second == static_cast(-E_PERIPHERAL_INTERFACE_FAIL)) || + (pair.second == COMM_FAILURE)); } } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_sync_check_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_sync_check_test.cpp index 2229a0b303c80c9466a03f5bce05136310b41877..78941c21f2d88315317257cd2429602bf93724b3 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_sync_check_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_sync_check_test.cpp @@ -532,7 +532,7 @@ HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, SyncProcess001, TestSize.Level1 * @tc.steps: step1. deviceB deviceC put bigData */ std::vector entries; - const uint32_t dataCount = 10; + const int dataCount = 10; DistributedDBUnitTest::GenerateNumberEntryVector(dataCount, entries); for (uint32_t i = 0; i < entries.size(); i++) { @@ -570,8 +570,8 @@ HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, SyncProcess001, TestSize.Level1 entry.second.errCode, entry.second.pullInfo.total, entry.second.pullInfo.finishedCount); EXPECT_EQ(entry.second.errCode, OK); EXPECT_EQ(entry.second.process, ProcessStatus::FINISHED); - EXPECT_EQ(entry.second.pullInfo.total, dataCount/2); - EXPECT_EQ(entry.second.pullInfo.finishedCount, dataCount/2); + EXPECT_EQ(entry.second.pullInfo.total, static_cast(dataCount / 2)); + EXPECT_EQ(entry.second.pullInfo.finishedCount, static_cast(dataCount / 2)); ASSERT_TRUE(entry.second.syncId > 0); } } @@ -589,7 +589,7 @@ HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, SyncProcess002, TestSize.Level1 * @tc.steps: step1. deviceA put bigData */ std::vector entries; - const uint32_t dataCount = 10; + const int dataCount = 10; DistributedDBUnitTest::GenerateNumberEntryVector(dataCount, entries); for (uint32_t i = 0; i < entries.size(); i++) { @@ -640,8 +640,8 @@ HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, SyncProcess002, TestSize.Level1 entry.second.errCode, entry.second.pullInfo.total, entry.second.pullInfo.finishedCount); EXPECT_EQ(entry.second.errCode, DBStatus::OK); EXPECT_EQ(entry.second.process, ProcessStatus::FINISHED); - EXPECT_EQ(entry.second.pullInfo.total, dataCount); - EXPECT_EQ(entry.second.pullInfo.finishedCount, dataCount); + EXPECT_EQ(entry.second.pullInfo.total, static_cast(dataCount)); + EXPECT_EQ(entry.second.pullInfo.finishedCount, static_cast(dataCount)); ASSERT_TRUE(entry.second.syncId > 0); } } @@ -659,7 +659,7 @@ HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, SyncProcess003, TestSize.Level1 * @tc.steps: step1. deviceA put bigData */ std::vector entries; - const uint32_t dataCount = 10; + const int dataCount = 10; DistributedDBUnitTest::GenerateNumberEntryVector(dataCount, entries); for (uint32_t i = 0; i < entries.size(); i++) { diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_communicator_aggregator.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_communicator_aggregator.cpp index 7829c53e797fde0914734428836da1300dc27cad..2b7b4d4a0da0459b38bca90e7110a1bb4899a63d 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_communicator_aggregator.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_communicator_aggregator.cpp @@ -255,6 +255,9 @@ void VirtualCommunicatorAggregator::Enable() void VirtualCommunicatorAggregator::CallSendEnd(int errCode, const OnSendEnd &onEnd) { + if (commErrCodeMock_ != E_OK) { + errCode = commErrCodeMock_; + } if (onEnd) { (void)RuntimeContext::GetInstance()->ScheduleTask([errCode, onEnd]() { onEnd(errCode); @@ -371,4 +374,10 @@ void VirtualCommunicatorAggregator::MockGetLocalDeviceRes(int mockRes) std::lock_guard lock(localDeviceIdMutex_); getLocalDeviceRet_ = mockRes; } + +void VirtualCommunicatorAggregator::MockCommErrCode(int mockErrCode) +{ + std::lock_guard lock(localDeviceIdMutex_); + commErrCodeMock_ = mockErrCode; +} } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_communicator_aggregator.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_communicator_aggregator.h index 0ad60442faa20cb9f38b353cbdc40d46a9542db8..8a3ae4fcf61bcba231e47cfdd2d4264c1e9af108 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_communicator_aggregator.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_communicator_aggregator.h @@ -93,6 +93,8 @@ public: void MockGetLocalDeviceRes(int mockRes); + void MockCommErrCode(int mockErrCode); + ~VirtualCommunicatorAggregator() override = default; VirtualCommunicatorAggregator() = default; @@ -124,6 +126,7 @@ private: mutable std::mutex localDeviceIdMutex_; std::string localDeviceId_; int getLocalDeviceRet_ = E_OK; + int commErrCodeMock_ = E_OK; }; } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_relational_ver_sync_db_interface.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_relational_ver_sync_db_interface.cpp index 9dffa54a210bb528a68f578a1f7f4e622db644a2..8ba5145cb18f8fd7c60fb446a5388abaf73269dd 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_relational_ver_sync_db_interface.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_relational_ver_sync_db_interface.cpp @@ -344,7 +344,7 @@ int VirtualRelationalVerSyncDBInterface::SaveRemoteDeviceSchema(const std::strin int VirtualRelationalVerSyncDBInterface::GetSchemaFromDB(RelationalSchemaObject &schema) { return E_OK; -}; +} int VirtualRelationalVerSyncDBInterface::GetRemoteDeviceSchema(const std::string &deviceId, RelationalSchemaObject &schemaObj) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_single_ver_sync_db_Interface.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_single_ver_sync_db_Interface.cpp index 282e0d228ed04b2d1fabefb9ee2d8ab6279855bb..8ca7d89a1c7300f6a2f29382724a1a02fe0b67a6 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_single_ver_sync_db_Interface.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_single_ver_sync_db_Interface.cpp @@ -154,7 +154,7 @@ int VirtualSingleVerSyncDBInterface::GetUnSyncTotal(QueryObject &query, const Sy if (getDataDelayTime_ > 0) { std::this_thread::sleep_for(std::chrono::milliseconds(getDataDelayTime_)); } - int errCode = DataControl(); + int errCode = DataControl(); if (errCode != E_OK) { return errCode; } @@ -177,7 +177,7 @@ int VirtualSingleVerSyncDBInterface::GetUnSyncTotal(QueryObject &query, const Sy } else { if (data.timestamp >= timeRange.beginTime && data.timestamp < timeRange.endTime && data.key >= startKey && data.key <= endKey) { - total++; + total++; } } } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_single_ver_sync_db_Interface.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_single_ver_sync_db_Interface.h index 415750056f868bf830d89e831003205759ac4ec9..20927700b98710b3f8eaae457c543747391c1b72 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_single_ver_sync_db_Interface.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_single_ver_sync_db_Interface.h @@ -85,7 +85,7 @@ public: int GetSyncData(QueryObject &query, const SyncTimeRange &timeRange, const DataSizeSpecInfo &dataSizeInfo, ContinueToken &continueStmtToken, std::vector &entries) const override; - + int GetUnSyncTotal(Timestamp begin, Timestamp end, uint32_t &total) const override; int GetUnSyncTotal(QueryObject &query, const SyncTimeRange &timeRange, uint32_t &total) const override; diff --git a/kv_store/interfaces/innerkits/distributeddata/include/active_boottime.h b/kv_store/interfaces/innerkits/distributeddata/include/active_boottime.h new file mode 100644 index 0000000000000000000000000000000000000000..2e52e8bc1419d0f09427759fabd2ea6edd91cc0f --- /dev/null +++ b/kv_store/interfaces/innerkits/distributeddata/include/active_boottime.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DISTRIBUTED_DATA_FRAMEWORKS_COMMON_ACTIVE_BOOTTIME_H +#define OHOS_DISTRIBUTED_DATA_FRAMEWORKS_COMMON_ACTIVE_BOOTTIME_H + +#if __linux__ +#include +#endif +#include + +namespace OHOS { +class Boottime final { +public: + static constexpr int64_t SECONDS_TO_NANO = 1000000000; + + using NanoSec = std::chrono::nanoseconds; + using TimePoint = std::chrono::steady_clock::time_point; + + static TimePoint Now() + { + #if __linux__ + struct timespec tv {}; + if (clock_gettime(CLOCK_BOOTTIME, &tv) < 0) { + return TimePoint(NanoSec(0)); + } + auto time = NanoSec(tv.tv_sec * SECONDS_TO_NANO + tv.tv_nsec); + return TimePoint(time); + #else + return std::chrono::steady_clock::now(); + #endif + } +}; +} // namespace OHOS +#endif //OHOS_DISTRIBUTED_DATA_FRAMEWORKS_COMMON_ACTIVE_BOOTTIME_H diff --git a/kv_store/interfaces/innerkits/distributeddata/include/executor.h b/kv_store/interfaces/innerkits/distributeddata/include/executor.h index 3d2c49bc5b432b7fee287323302a843108402fa0..29217ccc4d26f23b1cf92da5db05ff6abd4d60ad 100644 --- a/kv_store/interfaces/innerkits/distributeddata/include/executor.h +++ b/kv_store/interfaces/innerkits/distributeddata/include/executor.h @@ -20,6 +20,7 @@ #include #include #include "priority_queue.h" +#include "active_boottime.h" namespace OHOS { class Executor : public std::enable_shared_from_this { @@ -103,7 +104,7 @@ private: } waits_ = nullptr; } while (running_ == RUNNING && - condition_.wait_until(lock, std::chrono::steady_clock::now() + TIME_OUT, [this]() { + condition_.wait_until(lock, Boottime::Now() + TIME_OUT, [this]() { return waits_ != nullptr; })); } while (!release_(self_, running_ == IS_STOPPING)); diff --git a/kv_store/interfaces/innerkits/distributeddata/include/executor_pool.h b/kv_store/interfaces/innerkits/distributeddata/include/executor_pool.h index 8357b84c5102e8c334d7b32e9d6028233459c7db..0c9d0608e302d220f308478ffbacfb599ed82db9 100644 --- a/kv_store/interfaces/innerkits/distributeddata/include/executor_pool.h +++ b/kv_store/interfaces/innerkits/distributeddata/include/executor_pool.h @@ -24,6 +24,7 @@ #include "executor.h" #include "pool.h" #include "priority_queue.h" +#include "active_boottime.h" namespace OHOS { class ExecutorPool { public: @@ -106,7 +107,7 @@ public: innerTask.interval = interval; innerTask.times = times; innerTask.taskId = GenTaskId(); - return Schedule(std::move(innerTask), std::chrono::steady_clock::now() + delay); + return Schedule(std::move(innerTask), Boottime::Now() + delay); } bool Remove(TaskId taskId, bool wait = false) @@ -129,7 +130,7 @@ public: if (task.interval != INVALID_INTERVAL) { task.interval = interval; } - auto time = std::chrono::steady_clock::now() + interval; + auto time = Boottime::Now() + interval; return std::pair{ task.interval != INVALID_INTERVAL, time }; }); return updated ? taskId : INVALID_TASK_ID; @@ -202,7 +203,7 @@ private: static std::pair NextTimer(InnerTask &task) { if (task.interval != INVALID_INTERVAL && --task.times > 0) { - auto time = std::chrono::steady_clock::now() + task.interval; + auto time = Boottime::Now() + task.interval; return { true, time }; } return { false, INVALID_TIME }; diff --git a/kv_store/interfaces/innerkits/distributeddata/include/priority_queue.h b/kv_store/interfaces/innerkits/distributeddata/include/priority_queue.h index f10bca3a06ee37911c5f615a5866803af32d24b7..36fb68bd6aaddf390dd27310fa4311ddc83506b2 100644 --- a/kv_store/interfaces/innerkits/distributeddata/include/priority_queue.h +++ b/kv_store/interfaces/innerkits/distributeddata/include/priority_queue.h @@ -23,6 +23,7 @@ #include #include #include +#include "active_boottime.h" namespace OHOS { template class PriorityQueue { @@ -48,7 +49,7 @@ public: std::unique_lock lock(pqMtx_); while (!tasks_.empty()) { auto waitTme = tasks_.begin()->first; - if (waitTme > std::chrono::steady_clock::now()) { + if (waitTme > Boottime::Now()) { popCv_.wait_until(lock, waitTme); continue; } diff --git a/kv_store/interfaces/innerkits/distributeddata/include/store_errno.h b/kv_store/interfaces/innerkits/distributeddata/include/store_errno.h index a7438e534e38f3a3144beae9f4d1025894000f18..5065b787a43ea036f999fd5a01e627fea133cb10 100644 --- a/kv_store/interfaces/innerkits/distributeddata/include/store_errno.h +++ b/kv_store/interfaces/innerkits/distributeddata/include/store_errno.h @@ -203,7 +203,12 @@ enum Status : int32_t { /** * Cloud disabled. */ - CLOUD_DISABLED = DISTRIBUTEDDATAMGR_ERR_OFFSET + 41 + CLOUD_DISABLED = DISTRIBUTEDDATAMGR_ERR_OFFSET + 41, + + /** + * database can not open. + */ + DB_CANT_OPEN = DISTRIBUTEDDATAMGR_ERR_OFFSET + 42 }; } // namespace OHOS::DistributedKv #endif // OHOS_DISTRIBUTED_DATA_INTERFACES_DISTRIBUTEDDATA_STORE_ERRNO_H diff --git a/kv_store/kvstoremock/frameworks/innerkitsimpl/kvdb/src/store_util.cpp b/kv_store/kvstoremock/frameworks/innerkitsimpl/kvdb/src/store_util.cpp index b968707d6f6ea7e24e075bb07b12059803523e3b..e774099f1479c8a0fd46b43413e3db6816077bf4 100644 --- a/kv_store/kvstoremock/frameworks/innerkitsimpl/kvdb/src/store_util.cpp +++ b/kv_store/kvstoremock/frameworks/innerkitsimpl/kvdb/src/store_util.cpp @@ -148,7 +148,7 @@ Status StoreUtil::ConvertStatus(DBStatus status) case DBStatus::OVER_MAX_LIMITS: return Status::OVER_MAX_LIMITS; case DBStatus::INVALID_PASSWD_OR_CORRUPTED_DB: - return Status::CRYPT_ERROR; + return Status::DATA_CORRUPTED; case DBStatus::SCHEMA_MISMATCH: return Status::SCHEMA_MISMATCH; case DBStatus::INVALID_SCHEMA: diff --git a/kv_store/kvstoremock/frameworks/jskitsimpl/distributedkvstore/src/js_util_mock.cpp b/kv_store/kvstoremock/frameworks/jskitsimpl/distributedkvstore/src/js_util_mock.cpp index 71c67fde8334925b192b30667f614fddf4ba66e8..0999f1ac55470f34a7a3c516bfa7a520ff57b8ef 100644 --- a/kv_store/kvstoremock/frameworks/jskitsimpl/distributedkvstore/src/js_util_mock.cpp +++ b/kv_store/kvstoremock/frameworks/jskitsimpl/distributedkvstore/src/js_util_mock.cpp @@ -29,8 +29,6 @@ #define htobe32(data) data #define htobe64(data) data -#define GetCurrentAbility(env) GetAbility() - #ifdef _WIN32 #define mkdir(dir, mode) mkdir(dir) #endif @@ -40,6 +38,7 @@ #endif constexpr mode_t MODE = 0755; +constexpr int32_t API_VERSION = 9; class AbilityMock { public: @@ -54,6 +53,7 @@ public: struct ApplicationInfo { bool isSystemApp = true; + int32_t apiTargetVersion = API_VERSION; }; class ContextMock { @@ -94,10 +94,16 @@ public: }; namespace AbilityRuntime { - std::shared_ptr GetAbility() + std::shared_ptr GetCurrentAbility(napi_env env) { return std::make_shared(); } + + std::shared_ptr GetStageModeContext(napi_env env, napi_value value) + { + auto ability = std::make_shared(); + return ability->GetAbilityContext(); + } } #include "frameworks/jskitsimpl/distributedkvstore/src/js_util.cpp" diff --git a/mock/src/mock_access_token.cpp b/mock/src/mock_access_token.cpp index 88e283f4ad29acbce735697a645a56454e4096ee..a000e2af66af4a28f412453503e1d934d2d79967 100644 --- a/mock/src/mock_access_token.cpp +++ b/mock/src/mock_access_token.cpp @@ -121,6 +121,10 @@ AccessTokenIDEx AccessTokenKit::GetHapTokenIDEx(int32_t userID, const std::strin AccessTokenIDEx result; return result; } +ATokenTypeEnum AccessTokenKit::GetTokenType(AccessTokenID tokenID) +{ + return TOKEN_HAP; +} } // namespace OHOS::Security::AccessToken uint64_t GetAccessTokenId(NativeTokenInfoParams *params) diff --git a/preferences/frameworks/native/src/preferences_helper.cpp b/preferences/frameworks/native/src/preferences_helper.cpp index 1aa8a1b8535c88d716dd7c9e7667fef6ea5b2b21..c59c60b846a9c8fd30aead7fab12eda5b1c36bec 100644 --- a/preferences/frameworks/native/src/preferences_helper.cpp +++ b/preferences/frameworks/native/src/preferences_helper.cpp @@ -156,13 +156,6 @@ std::shared_ptr PreferencesHelper::GetPreferences(const Options &op } const_cast(options).filePath = realPath; - std::string::size_type pos = realPath.find_last_of('/'); - std::string filePath = realPath.substr(0, pos); - if (access(filePath.c_str(), F_OK) != 0) { - LOG_ERROR("The path is invalid, prefName is %{public}s.", ExtractFileName(realPath).c_str()); - errCode = E_INVALID_FILE_PATH; - return nullptr; - } std::shared_ptr pref = nullptr; bool isEnhancePreferences = false; #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) &&!defined(IOS_PLATFORM) diff --git a/preferences/test/native/unittest/preferences_helper_test.cpp b/preferences/test/native/unittest/preferences_helper_test.cpp index 4c68e22afc8a82a10e714b68e4d5ac68bf84bec7..b930532e3cd7ace79e63dcc68025cd9c726601a3 100644 --- a/preferences/test/native/unittest/preferences_helper_test.cpp +++ b/preferences/test/native/unittest/preferences_helper_test.cpp @@ -148,18 +148,4 @@ HWTEST_F(PreferencesHelperTest, NativePreferencesHelperTest_005, TestSize.Level1 EXPECT_EQ(preferences, nullptr); preferences = nullptr; } - -/** - * @tc.name: NativePreferencesHelperTest_006 - * @tc.desc: error testcase of GetRealPath - * @tc.type: FUNC - */ -HWTEST_F(PreferencesHelperTest, NativePreferencesHelperTest_006, TestSize.Level1) -{ - Options option = Options("/data/test/preferences/test01", "", ""); - int errCode = E_OK; - std::shared_ptr preferences = PreferencesHelper::GetPreferences(option, errCode); - EXPECT_EQ(preferences, nullptr); - preferences = nullptr; -} } diff --git a/relational_store/frameworks/js/napi/cloud_data/include/js_error_utils.h b/relational_store/frameworks/js/napi/cloud_data/include/js_error_utils.h index ca36f5dfd8848c1d4a4a716737a1f2fb841bddbd..b2cb6d13911222ad438d5843a82f109daf5e9f04 100644 --- a/relational_store/frameworks/js/napi/cloud_data/include/js_error_utils.h +++ b/relational_store/frameworks/js/napi/cloud_data/include/js_error_utils.h @@ -33,8 +33,6 @@ struct JsErrorCode { const char *message = nullptr; }; - - const std::optional GetJsErrorCode(int32_t errorCode); Status GenerateNapiError(int32_t status, int32_t &errCode, std::string &errMessage); void ThrowNapiError(napi_env env, int32_t errCode, const std::string &errMessage); diff --git a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_store.cpp b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_store.cpp index 455295fa6c6ea76c579af9b1e24c2500cd8f535e..3980c9b38957c67e2ebcbae221456b33a7329116 100644 --- a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_store.cpp +++ b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_store.cpp @@ -472,8 +472,8 @@ int ParseBindArgs(const napi_env env, const napi_value arg, std::shared_ptr(std::to_string(i), "ValueObject")); // The blob is an empty vector. - // If the API version is less than 12, and insert null. Otherwise, insert an empty vector. - if (valueObject.GetType() == ValueObject::TYPE_BLOB && JSUtils::GetHapVersion() < 12) { + // If the API version is less than 14, and insert null. Otherwise, insert an empty vector. + if (valueObject.GetType() == ValueObject::TYPE_BLOB && JSUtils::GetHapVersion() < 14) { std::vector tmpValue; valueObject.GetBlob(tmpValue); if (tmpValue.empty()) { @@ -561,8 +561,8 @@ int ParseValuesBucket(const napi_env env, const napi_value arg, std::shared_ptr< ValueObject valueObject; int32_t ret = JSUtils::Convert2Value(env, value, valueObject.value); // The blob is an empty vector. - // If the API version is less than 12, and insert null. Otherwise, insert an empty vector. - if (ret == napi_ok && valueObject.GetType() == ValueObject::TYPE_BLOB && JSUtils::GetHapVersion() < 12) { + // If the API version is less than 14, and insert null. Otherwise, insert an empty vector. + if (ret == napi_ok && valueObject.GetType() == ValueObject::TYPE_BLOB && JSUtils::GetHapVersion() < 14) { std::vector tmpValue; valueObject.GetBlob(tmpValue); if (tmpValue.empty()) { diff --git a/relational_store/frameworks/native/rdb/include/grd_api_manager.h b/relational_store/frameworks/native/rdb/include/grd_api_manager.h index 6f6d989750109db838b0f868f366f70fb0da2898..8fcb4c071fd3c41831b19ebf468c66185ee6879a 100644 --- a/relational_store/frameworks/native/rdb/include/grd_api_manager.h +++ b/relational_store/frameworks/native/rdb/include/grd_api_manager.h @@ -54,7 +54,7 @@ typedef int64_t (*DBSqlColInt64)(GRD_SqlStmt *stmt, uint32_t idx); typedef double (*DBSqlColDouble)(GRD_SqlStmt *stmt, uint32_t idx); typedef const float *(*DBSqlColumnFloatVector)(GRD_SqlStmt *stmt, uint32_t idx, uint32_t *dim); typedef int32_t (*DBBackup) (GRD_DB *db, const char *backupDbFile, GRD_CipherInfoT *cipherInfo); -typedef int32_t (*DBRestore) (GRD_DB *db, const char *backupDbFile, GRD_CipherInfoT *cipherInfo); +typedef int32_t (*DBRestore) (const char *dbFile, const char *backupDbFile, GRD_CipherInfoT *cipherInfo); typedef int32_t (*DBReKey) (const char *dbFile, const char *configStr, GRD_CipherInfoT *cipherInfo); typedef GRD_DbValueT (*DBGetConfig) (GRD_DB *db, GRD_ConfigTypeE type); typedef int32_t (*DBSetConfig) (GRD_DB *db, GRD_ConfigTypeE type, GRD_DbValueT value); diff --git a/relational_store/frameworks/native/rdb/include/rd_utils.h b/relational_store/frameworks/native/rdb/include/rd_utils.h index 7f471fe0406f66486d1db4f0599693f45f292e69..a31d54c4911da780b796a7ed75446e6248afdc7c 100644 --- a/relational_store/frameworks/native/rdb/include/rd_utils.h +++ b/relational_store/frameworks/native/rdb/include/rd_utils.h @@ -63,7 +63,7 @@ public: static void ClearAndZeroString(std::string &str); static const char *GetEncryptKey(const std::vector &encryptedKey, char outBuff[], size_t outBufSize); static int RdDbBackup(GRD_DB *db, const char *backupDbFile, const std::vector &encryptedKey); - static int RdDbRestore(GRD_DB *db, const char *backupDbFile, const std::vector &encryptedKey); + static int RdDbRestore(const char *dbFile, const char *backupDbFile, const std::vector &encryptedKey); static int RdDbRekey(const char *dbFile, const char *configStr, const std::vector &encryptedKey); static int RdDbGetVersion(GRD_DB *db, GRD_ConfigTypeE type, int &version); diff --git a/relational_store/frameworks/native/rdb/include/rdb_security_manager.h b/relational_store/frameworks/native/rdb/include/rdb_security_manager.h index 375fc497d3d2bb20c9a14e1d56ded84c2631c7eb..0bdad7d9d246b8ec51d44db17777d407e32f36fd 100644 --- a/relational_store/frameworks/native/rdb/include/rdb_security_manager.h +++ b/relational_store/frameworks/native/rdb/include/rdb_security_manager.h @@ -73,6 +73,7 @@ public: KeyFiles(const std::string &dbPath, bool openFile = true); ~KeyFiles(); const std::string &GetKeyFile(KeyFileType type); + int32_t InitKeyPath(); int32_t DestroyLock(); int32_t Lock(); int32_t Unlock(); diff --git a/relational_store/frameworks/native/rdb/include/rdb_service_proxy.h b/relational_store/frameworks/native/rdb/include/rdb_service_proxy.h index d031450910d12dcfe5769af527899d341928d632..c6080aa1007829a6a94e21958a6ba3d044227922 100644 --- a/relational_store/frameworks/native/rdb/include/rdb_service_proxy.h +++ b/relational_store/frameworks/native/rdb/include/rdb_service_proxy.h @@ -88,6 +88,8 @@ public: int32_t GetDebugInfo(const RdbSyncerParam ¶m, std::map &debugInfo) override; + int32_t VerifyPromiseInfo(const RdbSyncerParam ¶m) override; + private: using ChangeInfo = RdbStoreObserver::ChangeInfo; using PrimaryFields = RdbStoreObserver::PrimaryFields; diff --git a/relational_store/frameworks/native/rdb/include/rdb_store_manager.h b/relational_store/frameworks/native/rdb/include/rdb_store_manager.h index ac06f7914aed16649c60bab3457632ea055c59ef..b49aeb10272b5e112ce2a9747714a31349ab018a 100644 --- a/relational_store/frameworks/native/rdb/include/rdb_store_manager.h +++ b/relational_store/frameworks/native/rdb/include/rdb_store_manager.h @@ -46,8 +46,9 @@ private: using Info = DistributedRdb::RdbDebugInfo; int ProcessOpenCallback(RdbStore &rdbStore, const RdbStoreConfig &config, int version, RdbOpenCallback &openCallback); - bool IsConfigInvalidChanged(const std::string &path, const RdbStoreConfig &config); + bool IsConfigInvalidChanged(const std::string &path, RdbStoreConfig &config); int32_t GetParamFromService(DistributedRdb::RdbSyncerParam ¶m); + int32_t GetPromiseFromService(DistributedRdb::RdbSyncerParam ¶m); static Param GetSyncParam(const RdbStoreConfig &config); static std::map Collector(const RdbStoreConfig &config); std::shared_ptr GetStoreFromCache(const RdbStoreConfig &config, const std::string &path); diff --git a/relational_store/frameworks/native/rdb/include/sqlite_connection.h b/relational_store/frameworks/native/rdb/include/sqlite_connection.h index a255521a67c789e695356067e7ec962b1728b043..785ff1c098c48b22bfe345bcc86a7a9507a2055f 100644 --- a/relational_store/frameworks/native/rdb/include/sqlite_connection.h +++ b/relational_store/frameworks/native/rdb/include/sqlite_connection.h @@ -42,6 +42,7 @@ class SqliteConnection : public Connection { public: static std::pair> Create(const RdbStoreConfig &config, bool isWrite); static int32_t Delete(const RdbStoreConfig &config); + static int32_t Delete(const std::string &path); static int32_t Repair(const RdbStoreConfig &config); static std::map Collect(const RdbStoreConfig &config); SqliteConnection(const RdbStoreConfig &config, bool isWriteConnection); @@ -80,6 +81,11 @@ private: const char *debug_ = nullptr; }; + enum SlaveOpenPolicy : int32_t { + FORCE_OPEN = 0, + OPEN_IF_DB_VALID // DB exists and there are no -slaveFailure and -syncInterrupt files + }; + int InnerOpen(const RdbStoreConfig &config); int Configure(const RdbStoreConfig &config, std::string &dbPath); int SetPageSize(const RdbStoreConfig &config); @@ -112,10 +118,13 @@ private: int32_t OpenDatabase(const std::string &dbPath, int openFileFlags); int LoadExtension(const RdbStoreConfig &config, sqlite3 *dbHandle); RdbStoreConfig GetSlaveRdbStoreConfig(const RdbStoreConfig &rdbConfig); - int CreateSlaveConnection(const RdbStoreConfig &config, bool checkSlaveExist = true); - int ExchangeSlaverToMaster(bool isRestore, SlaveStatus &status); - int IsRepairable(); + std::pair> CreateSlaveConnection(const RdbStoreConfig &config, + SlaveOpenPolicy slaveOpenPolicy); + int ExchangeSlaverToMaster(bool isRestore, bool verifyDb, SlaveStatus &status); int ExchangeVerify(bool isRestore); + int SqliteNativeBackup(bool isRestore, SlaveStatus &curStatus); + int VeritySlaveIntegrity(); + bool IsDbVersionBelowSlave(); static std::pair> InnerCreate(const RdbStoreConfig &config, bool isWrite); static constexpr SqliteConnection::Suffix FILE_SUFFIXES[] = { @@ -133,7 +142,9 @@ private: static constexpr int BACKUP_PAGES_PRE_STEP = 12800; // 1024 * 4 * 12800 == 50m static constexpr int BACKUP_PRE_WAIT_TIME = 10; static constexpr ssize_t SLAVE_WAL_SIZE_LIMIT = 2147483647; // 2147483647 = 2g - 1 + static constexpr ssize_t SLAVE_INTEGRITY_CHECK_LIMIT = 524288000; // 524288000 == 1024 * 1024 * 500 static constexpr uint32_t NO_ITER = 0; + static constexpr uint32_t DB_INDEX = 0; static constexpr uint32_t WAL_INDEX = 2; static const int32_t regCreator_; static const int32_t regRepairer_; diff --git a/relational_store/frameworks/native/rdb/include/sqlite_utils.h b/relational_store/frameworks/native/rdb/include/sqlite_utils.h index e8b1563f2d99d489965516b026dbddd509585735..3db62bd5ae8ac57ae9e8ed89d4faaa95d964264f 100644 --- a/relational_store/frameworks/native/rdb/include/sqlite_utils.h +++ b/relational_store/frameworks/native/rdb/include/sqlite_utils.h @@ -43,6 +43,8 @@ public: static constexpr int ENABLE_LOAD_EXTENSION = 1; static constexpr int MAX_LOAD_EXTENSION_COUNT = 16; static constexpr const char* REP = "#_"; + static constexpr const char* SLAVE_FAILURE = "-slaveFailure"; + static constexpr const char* SLAVE_INTERRUPT = "-syncInterrupt"; static int GetSqlStatementType(const std::string &sql); static bool IsSupportSqlForExecute(int sqlType); @@ -58,8 +60,11 @@ public: static ssize_t GetFileSize(const std::string &fileName); static bool IsSlaveDbName(const std::string &fileName); static std::string GetSlavePath(const std::string& name); - static bool TryAccessSlaveLock(const std::string &dbPath, bool isDelete, bool needCreate, - bool isSlaveFailure = false); + static int SetSlaveInvalid(const std::string &dbPath); + static int SetSlaveInterrupted(const std::string &dbPath); + static bool IsSlaveInvalid(const std::string &dbPath); + static bool IsSlaveInterrupted(const std::string &dbPath); + static void SetSlaveValid(const std::string &dbPath); static const char *HmacAlgoDescription(int32_t hmacAlgo); static const char *KdfAlgoDescription(int32_t kdfAlgo); static const char *EncryptAlgoDescription(int32_t encryptAlgo); diff --git a/relational_store/frameworks/native/rdb/src/connection_pool.cpp b/relational_store/frameworks/native/rdb/src/connection_pool.cpp index bd4341a24519f8b84e660123fe8df3efa6f3aac8..b410f653e306efcf1f3935c64fc7d474d18896fc 100644 --- a/relational_store/frameworks/native/rdb/src/connection_pool.cpp +++ b/relational_store/frameworks/native/rdb/src/connection_pool.cpp @@ -81,9 +81,12 @@ std::pair> ConnPool::HandleDataCorr errCode = Connection::Repair(storeConfig); if (errCode == E_OK) { rebuiltType = RebuiltType::REPAIRED; - } else { + } else if (storeConfig.GetAllowRebuild()) { Connection::Delete(storeConfig); rebuiltType = RebuiltType::REBUILT; + } else { + errCode = E_SQLITE_CORRUPT; + return result; } pool = Create(storeConfig, errCode); if (errCode != E_OK) { @@ -114,7 +117,7 @@ std::pair> ConnPool::Init(bool isAttach, bo return result; } - if (config.GetRoleType() == OWNER && !config.IsReadOnly()) { + if ((config.GetRoleType() == OWNER || config.GetRoleType() == VISITOR_WRITE) && !config.IsReadOnly()) { // write connect count is 1 std::shared_ptr node; std::tie(errCode, node) = writers_.Initialize( @@ -366,20 +369,25 @@ int ConnPool::ChangeDbFileForRestore(const std::string &newPath, const std::stri } if (config_.GetDBType() == DB_VECTOR) { CloseAllConnections(); - auto [retVal, connection] = CreateTransConn(); - - if (connection == nullptr) { - LOG_ERROR("Get null connection."); + auto [retVal, conn] = Connection::Create(config_, false); + if (retVal != E_OK) { + LOG_ERROR("create connection fail, erroce:%{public}d", retVal); return retVal; } - retVal = connection->Restore(backupPath, newKey, slaveStatus); + + retVal = conn->Restore(backupPath, newKey, slaveStatus); if (retVal != E_OK) { - LOG_ERROR("RdDbRestore error."); + LOG_ERROR("Restore failed, errCode:0x%{public}x", retVal); return retVal; } - CloseAllConnections(); - auto [errCode, node] = Init(); - return errCode; + + conn = nullptr; + auto initRes = Init(); + if (initRes.first != E_OK) { + LOG_ERROR("init fail, errCode:%{public}d", initRes.first); + return initRes.first; + } + return retVal; } return RestoreByDbSqliteType(newPath, backupPath, slaveStatus); } diff --git a/relational_store/frameworks/native/rdb/src/rd_connection.cpp b/relational_store/frameworks/native/rdb/src/rd_connection.cpp index be1f69e5a63f0eebf64d67a37a3f127306fb6a67..659915aa6ebb63c0405196d353291c9eeef3dd18 100644 --- a/relational_store/frameworks/native/rdb/src/rd_connection.cpp +++ b/relational_store/frameworks/native/rdb/src/rd_connection.cpp @@ -303,13 +303,32 @@ int32_t RdConnection::Backup(const std::string &databasePath, const std::vector< int32_t RdConnection::Restore(const std::string &databasePath, const std::vector &destEncryptKey, SlaveStatus &slaveStatus) { + auto ret = RdUtils::RdDbClose(dbHandle_, 0); + if (ret != E_OK) { + LOG_ERROR("close db failed"); + return ret; + } + if (destEncryptKey.empty()) { std::vector key = config_.GetEncryptKey(); - int32_t ret = RdUtils::RdDbRestore(dbHandle_, databasePath.c_str(), key); + ret = RdUtils::RdDbRestore(config_.GetPath().c_str(), databasePath.c_str(), key); key.assign(key.size(), 0); + } else { + ret = RdUtils::RdDbRestore(config_.GetPath().c_str(), databasePath.c_str(), destEncryptKey); + } + + if (ret != E_OK) { + LOG_ERROR("restore failed, original datapath:%{public}s, restorepath:%{public}s, errcode:%{public}d", + config_.GetPath().c_str(), databasePath.c_str(), ret); + return ret; + } + + ret = InnerOpen(config_); + if (ret != E_OK) { + LOG_ERROR("reopen db failed:%{public}d", ret); return ret; } - return RdUtils::RdDbRestore(dbHandle_, databasePath.c_str(), destEncryptKey); + return ret; } ExchangeStrategy RdConnection::GenerateExchangeStrategy(const SlaveStatus &status) diff --git a/relational_store/frameworks/native/rdb/src/rd_utils.cpp b/relational_store/frameworks/native/rdb/src/rd_utils.cpp index 6a5042b24f39d6f10888a89b4590c2d1547e476e..66d1fc16abec156c5df29080b396250dbda8770f 100644 --- a/relational_store/frameworks/native/rdb/src/rd_utils.cpp +++ b/relational_store/frameworks/native/rdb/src/rd_utils.cpp @@ -494,7 +494,7 @@ int RdUtils::RdDbBackup(GRD_DB *db, const char *backupDbFile, const std::vector< return ret; } -int RdUtils::RdDbRestore(GRD_DB *db, const char *backupDbFile, const std::vector &encryptedKey) +int RdUtils::RdDbRestore(const char *dbFile, const char *backupDbFile, const std::vector &encryptedKey) { if (GRD_KVApiInfo.DBRestoreApi == nullptr) { GRD_KVApiInfo = GetApiInfoInstance(); @@ -506,7 +506,7 @@ int RdUtils::RdDbRestore(GRD_DB *db, const char *backupDbFile, const std::vector char key[keySize]; GRD_CipherInfoT info = { 0 }; info.hexPassword = (encryptedKey.size() > 0) ? GetEncryptKey(encryptedKey, key, keySize) : nullptr; - int ret = TransferGrdErrno(GRD_KVApiInfo.DBRestoreApi(db, backupDbFile, &info)); + int ret = TransferGrdErrno(GRD_KVApiInfo.DBRestoreApi(dbFile, backupDbFile, &info)); errno_t err = memset_s(key, keySize, 0, keySize); if (err != E_OK) { LOG_ERROR("can not memset 0, size %{public}zu", keySize); diff --git a/relational_store/frameworks/native/rdb/src/rdb_helper.cpp b/relational_store/frameworks/native/rdb/src/rdb_helper.cpp index 55f34bef657459ae703c3f5f3fbb2763376fb0ce..bb49518ccfdc6ac4ca711b30af0fece55d00f8f4 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_helper.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_helper.cpp @@ -75,31 +75,13 @@ int DeleteRdFiles(const std::string &dbFileName) int RdbHelper::DeleteRdbStore(const std::string &dbFileName) { - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - if (dbFileName.empty()) { - return E_INVALID_FILE_PATH; - } - if (access(dbFileName.c_str(), F_OK) != 0) { - LOG_ERROR("Store to delete doesn't exist, path %{public}s", SqliteUtils::Anonymous(dbFileName).c_str()); - return E_OK; // not not exist - } RdbStoreConfig config(dbFileName); - Reportor::ReportRestore(Reportor::Create(config, E_OK, "RestoreType:Restore")); - - RdbStoreManager::GetInstance().Delete(dbFileName); - RdbSecurityManager::GetInstance().DelAllKeyFiles(dbFileName); - DeleteRdbStore(SqliteUtils::GetSlavePath(dbFileName)); - config.SetDBType(DB_SQLITE); - int errCodeSqlite = Connection::Delete(config); + int errCodeSqlite = DeleteRdbStore(config); config.SetDBType(DB_VECTOR); - int errCodeVector = Connection::Delete(config); - - int errCode = (errCodeSqlite == E_OK && errCodeVector == E_OK) ? E_OK : E_REMOVE_FILE; - LOG_INFO("Delete rdb store ret sqlite=%{public}d, vector=%{public}d, path %{public}s", - errCodeSqlite, errCodeVector, SqliteUtils::Anonymous(dbFileName).c_str()); - return errCode; + int errCodeVector = DeleteRdbStore(config); + return (errCodeSqlite == E_OK && errCodeVector == E_OK) ? E_OK : E_REMOVE_FILE; } int RdbHelper::DeleteRdbStore(const RdbStoreConfig &config) @@ -109,15 +91,16 @@ int RdbHelper::DeleteRdbStore(const RdbStoreConfig &config) if (dbFile.empty()) { return E_INVALID_FILE_PATH; } - if (access(dbFile.c_str(), F_OK) != 0) { - LOG_ERROR("not exist, path %{public}s", SqliteUtils::Anonymous(dbFile).c_str()); - return E_OK; // not not exist + if (access(dbFile.c_str(), F_OK) == 0) { + RdbStoreManager::GetInstance().Delete(dbFile); } - Reportor::ReportRestore(Reportor::Create(config, E_OK, "RestoreType:Restore")); - RdbStoreManager::GetInstance().Delete(dbFile); Connection::Delete(config); + RdbSecurityManager::GetInstance().DelAllKeyFiles(dbFile); - LOG_INFO("Delete rdb store, path %{public}s", SqliteUtils::Anonymous(dbFile).c_str()); + + Reportor::ReportRestore(Reportor::Create(config, E_OK, "RestoreType:Restore")); + LOG_INFO("Delete rdb store, dbType:%{public}d, path %{public}s", config.GetDBType(), + SqliteUtils::Anonymous(dbFile).c_str()); return E_OK; } } // namespace NativeRdb diff --git a/relational_store/frameworks/native/rdb/src/rdb_security_manager.cpp b/relational_store/frameworks/native/rdb/src/rdb_security_manager.cpp index f57884e0aa784015b77eb80912879d2d2e5e1607..c3e2f5c47ce91409cc7578876cfd5e452c135817 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_security_manager.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_security_manager.cpp @@ -520,6 +520,7 @@ RdbPassword RdbSecurityManager::GetRdbPassword(const std::string &dbPath, KeyFil keyFiles.Lock(); auto &keyFile = keyFiles.GetKeyFile(keyFileType); if (IsKeyFileEmpty(keyFile)) { + keyFiles.InitKeyPath(); if (!SaveSecretKeyToFile(keyFile)) { keyFiles.Unlock(); LOG_ERROR("Failed to save key type:%{public}d err:%{public}d.", keyFileType, errno); @@ -641,10 +642,6 @@ int32_t RdbSecurityManager::RestoreKeyFile(const std::string &dbPath, const std: RdbSecurityManager::KeyFiles::KeyFiles(const std::string &dbPath, bool openFile) { const std::string dbKeyDir = StringUtils::ExtractFilePath(dbPath) + "key/"; - if (!InitPath(dbKeyDir)) { - LOG_ERROR( - "dbKeyDir failed, errno:%{public}d, dir:%{public}s.", errno, SqliteUtils::Anonymous(dbKeyDir).c_str()); - } const std::string lockDir = StringUtils::ExtractFilePath(dbPath) + "lock/"; if (!InitPath(lockDir)) { LOG_ERROR("lockDir failed, errno:%{public}d, dir:%{public}s.", errno, SqliteUtils::Anonymous(lockDir).c_str()); @@ -679,6 +676,15 @@ const std::string &RdbSecurityManager::KeyFiles::GetKeyFile(KeyFileType type) return keys_[PUB_KEY_FILE_NEW_KEY]; } +int32_t RdbSecurityManager::KeyFiles::InitKeyPath() +{ + const std::string keyDir = StringUtils::ExtractFilePath(keys_[PUB_KEY_FILE]); + if (!InitPath(keyDir)) { + LOG_ERROR("keyDir failed, errno:%{public}d, dir:%{public}s.", errno, SqliteUtils::Anonymous(keyDir).c_str()); + } + return E_OK; +} + int32_t RdbSecurityManager::KeyFiles::Lock() { if (lockFd_ < 0) { diff --git a/relational_store/frameworks/native/rdb/src/rdb_service_proxy.cpp b/relational_store/frameworks/native/rdb/src/rdb_service_proxy.cpp index 17ce49cdb682531fd587207b30b79f1849906f84..d268a394696627d84575fdd1aaeb2997d8b753ee 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_service_proxy.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_service_proxy.cpp @@ -608,4 +608,15 @@ int32_t RdbServiceProxy::GetDebugInfo(const RdbSyncerParam ¶m, std::map(RdbServiceCode::RDB_SERVICE_CMD_VERIFY_PROMISE_INFO), reply, param); + if (status != RDB_OK) { + LOG_ERROR("fail, status:%{public}d, bundleName:%{public}s, storeName:%{public}s", status, + param.bundleName_.c_str(), SqliteUtils::Anonymous(param.storeName_).c_str()); + } + return status; +} } // namespace OHOS::DistributedRdb \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb/src/rdb_store_config.cpp b/relational_store/frameworks/native/rdb/src/rdb_store_config.cpp index 0df7ad3424c9dbe612dc3ec68391456243d7492d..01b0b2ba8169b0fe8b9e873205b7ea6ebbe536a7 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_store_config.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_store_config.cpp @@ -15,6 +15,8 @@ #define LOG_TAG "RdbStoreConfig" #include "rdb_store_config.h" +#include + #include "logger.h" #include "rdb_errno.h" #include "rdb_security_manager.h" @@ -346,11 +348,6 @@ void RdbStoreConfig::RestoreEncryptKey(const std::vector &encryptKey) c cryptoParam_.encryptKey_ = encryptKey; } -void RdbStoreConfig::SetNewEncryptKey(const std::vector newEncryptKey) -{ - newEncryptKey_ = newEncryptKey; -} - std::vector RdbStoreConfig::GetEncryptKey() const { return cryptoParam_.encryptKey_; @@ -585,6 +582,16 @@ void RdbStoreConfig::SetHaMode(int32_t haMode) haMode_ = haMode; } +PromiseInfo RdbStoreConfig::GetPromiseInfo() const +{ + return promiseInfo_; +} + +void RdbStoreConfig::SetPromiseInfo(PromiseInfo promiseInfo) +{ + promiseInfo_ = promiseInfo; +} + void RdbStoreConfig::EnableRekey(bool enable) { autoRekey_ = enable; @@ -630,4 +637,25 @@ bool RdbStoreConfig::CryptoParam::IsValid() const (cryptoPageSize & (cryptoPageSize - 1)) == 0; } +std::string RdbStoreConfig::Format(const RdbStoreConfig &cacheConfig, const RdbStoreConfig &incomingConfig) +{ + std::stringstream oss; + oss << " isEncrypt:" << static_cast(cacheConfig.IsEncrypt()) << "->" + << static_cast(incomingConfig.IsEncrypt()) << ","; + oss << " securityLevel:" << static_cast(cacheConfig.securityLevel_) << "->" + << static_cast(incomingConfig.securityLevel_) << ","; + oss << " area:" << cacheConfig.area_ << "->" << incomingConfig.area_ << ","; + oss << " storageMode:" << static_cast(cacheConfig.storageMode_) << "->" + << static_cast(incomingConfig.storageMode_) << ","; + oss << " journalMode:" << cacheConfig.journalMode_ << "->" << incomingConfig.journalMode_ << ","; + oss << " syncMode:" << cacheConfig.syncMode_ << "->" << incomingConfig.syncMode_ << ","; + oss << " databaseFileType:" << cacheConfig.databaseFileType << "->" << incomingConfig.databaseFileType << ","; + oss << " journalSize:" << cacheConfig.journalSize_ << "->" << incomingConfig.journalSize_ << ","; + oss << " pageSize:" << cacheConfig.pageSize_ << "->" << incomingConfig.pageSize_ << ","; + oss << " customDir:" << cacheConfig.customDir_ << "->" << incomingConfig.customDir_ << ","; + oss << " haMode:" << cacheConfig.haMode_ << "->" << incomingConfig.haMode_ << ","; + oss << " dbType:" << cacheConfig.dbType_ << "->" << incomingConfig.dbType_ << ","; + + return oss.str(); +} } // namespace OHOS::NativeRdb diff --git a/relational_store/frameworks/native/rdb/src/rdb_store_impl.cpp b/relational_store/frameworks/native/rdb/src/rdb_store_impl.cpp index 14b81a2a995d11108dbf49f0a4c7b20c10f317bc..d91403e17ba29c923512de46e27cf91885fb713b 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_store_impl.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_store_impl.cpp @@ -94,6 +94,10 @@ void RdbStoreImpl::InitSyncerParam(const RdbStoreConfig &config, bool created) syncerParam_.password_ = config.GetEncryptKey(); syncerParam_.haMode_ = config.GetHaMode(); syncerParam_.roleType_ = config.GetRoleType(); + syncerParam_.tokenIds_ = config.GetPromiseInfo().tokenIds_; + syncerParam_.uids_ = config.GetPromiseInfo().uids_; + syncerParam_.user_ = config.GetPromiseInfo().user_; + syncerParam_.permissionNames_ = config.GetPromiseInfo().permissionNames_; if (created) { syncerParam_.infos_ = Connection::Collect(config); } @@ -873,7 +877,7 @@ RdbStoreImpl::RdbStoreImpl(const RdbStoreConfig &config) : isMemoryRdb_(config.IsMemoryRdb()), config_(config), name_(config.GetName()), fileType_(config.GetDatabaseFileType()) { - path_ = (config.GetRoleType() == VISITOR) ? config.GetVisitorDir() : config.GetPath(); + path_ = (config.GetRoleType() != OWNER) ? config.GetVisitorDir() : config.GetPath(); isReadOnly_ = config.IsReadOnly() || config.GetRoleType() == VISITOR; } @@ -882,11 +886,12 @@ RdbStoreImpl::RdbStoreImpl(const RdbStoreConfig &config, int &errCode) fileType_(config.GetDatabaseFileType()) { isReadOnly_ = config.IsReadOnly() || config.GetRoleType() == VISITOR; - path_ = (config.GetRoleType() == VISITOR) ? config.GetVisitorDir() : config.GetPath(); + path_ = (config.GetRoleType() != OWNER) ? config.GetVisitorDir() : config.GetPath(); bool created = access(path_.c_str(), F_OK) != 0; connectionPool_ = ConnectionPool::Create(config_, errCode); - if (connectionPool_ == nullptr && errCode == E_SQLITE_CORRUPT && config.GetAllowRebuild() && !isReadOnly_) { - LOG_ERROR("database corrupt, rebuild database %{public}s", SqliteUtils::Anonymous(name_).c_str()); + if (connectionPool_ == nullptr && errCode == E_SQLITE_CORRUPT && !isReadOnly_) { + LOG_ERROR("database corrupt, %{public}s, %{public}s", SqliteUtils::Anonymous(name_).c_str(), + Reportor::FormatBrief(Connection::Collect(config_), "master").c_str()); #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) RdbParam param; param.bundleName_ = config_.GetBundleName(); @@ -897,6 +902,11 @@ RdbStoreImpl::RdbStoreImpl(const RdbStoreConfig &config, int &errCode) } #endif config_.SetIter(0); + if (config_.IsEncrypt()) { + auto key = config_.GetEncryptKey(); + RdbSecurityManager::GetInstance().RestoreKeyFile(path_, key); + key.assign(key.size(), 0); + } std::tie(rebuild_, connectionPool_) = ConnectionPool::HandleDataCorruption(config_, errCode); created = true; #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) @@ -2303,14 +2313,13 @@ bool RdbStoreImpl::TryGetMasterSlaveBackupPath(const std::string &srcPath, std:: bool RdbStoreImpl::IsSlaveDiffFromMaster() const { - std::string failureFlagFile = config_.GetPath() + "-slaveFailure"; std::string slaveDbPath = SqliteUtils::GetSlavePath(config_.GetPath()); - return access(failureFlagFile.c_str(), F_OK) == 0 || access(slaveDbPath.c_str(), F_OK) != 0; + return SqliteUtils::IsSlaveInvalid(config_.GetPath()) || (access(slaveDbPath.c_str(), F_OK) != 0); } int32_t RdbStoreImpl::ExchangeSlaverToMaster() { - if (isReadOnly_) { + if (isReadOnly_ || rebuild_ != RebuiltType::NONE) { return E_OK; } auto conn = connectionPool_->AcquireConnection(false); @@ -2343,6 +2352,7 @@ std::pair> RdbStoreImpl::CreateTransaction if (isReadOnly_) { return { E_NOT_SUPPORT, nullptr }; } + auto [errCode, conn] = connectionPool_->CreateTransConn(); if (conn == nullptr) { return { errCode, nullptr }; diff --git a/relational_store/frameworks/native/rdb/src/rdb_store_manager.cpp b/relational_store/frameworks/native/rdb/src/rdb_store_manager.cpp index 923012d1693f221b3c0cb0594d081a6090df938c..b204617a1b4d00127795a47c2ca60965cf29f467 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_store_manager.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_store_manager.cpp @@ -61,68 +61,83 @@ RdbStoreManager::RdbStoreManager() : configCache_(BUCKET_MAX_SIZE) std::shared_ptr RdbStoreManager::GetStoreFromCache(const RdbStoreConfig &config, const std::string &path) { - if (storeCache_.find(path) != storeCache_.end()) { - std::shared_ptr rdbStore = storeCache_[path].lock(); - if (rdbStore != nullptr && rdbStore->GetConfig() == config) { - return rdbStore; - } - // TOD reconfigure store should be repeated this + auto it = storeCache_.find(path); + if (it == storeCache_.end()) { + return nullptr; + } + std::shared_ptr rdbStore = it->second.lock(); + if (rdbStore == nullptr) { storeCache_.erase(path); - // If rdbStore is not null, it means that the config has changed. - if (rdbStore != nullptr) { - LOG_INFO("app[%{public}s:%{public}s] path[%{public}s]" - " cfg[%{public}d,%{public}d,%{public}d,%{public}d,%{public}d,%{public}d,%{public}d,%{public}s]" - " %{public}s", - config.GetBundleName().c_str(), config.GetModuleName().c_str(), SqliteUtils::Anonymous(path).c_str(), - config.GetDBType(), config.GetHaMode(), config.IsEncrypt(), config.GetArea(), - config.GetSecurityLevel(), config.GetRoleType(), config.IsReadOnly(), config.GetCustomDir().c_str(), - RdbFaultHiViewReporter::FormatBrief( - Connection::Collect(config), SqliteUtils::Anonymous(config.GetName())) - .c_str()); + return nullptr; + } + if (!(rdbStore->GetConfig() == config)) { + storeCache_.erase(path); + auto pool = TaskExecutor::GetInstance().GetExecutor(); + if (pool != nullptr) { + pool->Schedule(std::chrono::seconds(RETRY_INTERVAL), [config, rdbStore]() { + Reportor::Report(Reportor::Create(config, E_CONFIG_INVALID_CHANGE, + "ErrorType:Config diff!" + RdbStoreConfig::Format(rdbStore->GetConfig(), config))); + }); } + LOG_INFO("app[%{public}s:%{public}s] path[%{public}s]" + " cfg[%{public}d,%{public}d,%{public}d,%{public}d,%{public}d,%{public}d,%{public}d,%{public}s]" + " %{public}s", + config.GetBundleName().c_str(), config.GetModuleName().c_str(), SqliteUtils::Anonymous(path).c_str(), + config.GetDBType(), config.GetHaMode(), config.IsEncrypt(), config.GetArea(), config.GetSecurityLevel(), + config.GetRoleType(), config.IsReadOnly(), config.GetCustomDir().c_str(), + Reportor::FormatBrief(Connection::Collect(config), SqliteUtils::Anonymous(config.GetName())).c_str()); + return nullptr; } - return nullptr; + return rdbStore; } std::shared_ptr RdbStoreManager::GetRdbStore( const RdbStoreConfig &config, int &errCode, int version, RdbOpenCallback &openCallback) { + RdbStoreConfig modifyConfig = config; // TOD this lock should only work on storeCache_, add one more lock for connectionpool std::lock_guard lock(mutex_); - auto path = config.GetRoleType() == VISITOR ? config.GetVisitorDir() : config.GetPath(); - auto pool = TaskExecutor::GetInstance().GetExecutor(); - pool->Schedule(std::chrono::seconds(RETRY_INTERVAL), [path, config, this]() { - if (IsConfigInvalidChanged(path, config)) { - Reportor::Report(Reportor::Create(config, E_CONFIG_INVALID_CHANGE, "ErrorType:Encrypt diff")); - } - }); - std::shared_ptr rdbStore = GetStoreFromCache(config, path); + auto path = modifyConfig.GetRoleType() != OWNER ? modifyConfig.GetVisitorDir() : modifyConfig.GetPath(); + bundleName_ = modifyConfig.GetBundleName(); + std::shared_ptr rdbStore = GetStoreFromCache(modifyConfig, path); if (rdbStore != nullptr) { return rdbStore; } - rdbStore = std::make_shared(config, errCode); + if (modifyConfig.GetRoleType() == OWNER && IsConfigInvalidChanged(path, modifyConfig)) { + errCode = E_CONFIG_INVALID_CHANGE; + return nullptr; + } + if (modifyConfig.GetRoleType() == VISITOR_WRITE) { + Param param = GetSyncParam(config); + int32_t status = GetPromiseFromService(param); + if (status != E_OK) { + LOG_ERROR("failed, storeName:%{public}s, status:%{public}d", config.GetName().c_str(), status); + return nullptr; + } + } + rdbStore = std::make_shared(modifyConfig, errCode); if (errCode != E_OK) { - LOG_ERROR("RdbStoreManager GetRdbStore fail to open RdbStore as memory issue, rc=%{public}d", errCode); + LOG_ERROR("GetRdbStore fail path:%{public}s, rc=%{public}d", SqliteUtils::Anonymous(path).c_str(), errCode); return nullptr; } - if (config.GetRoleType() == OWNER && !config.IsReadOnly()) { - errCode = SetSecurityLabel(config); + if (modifyConfig.GetRoleType() == OWNER && !modifyConfig.IsReadOnly()) { + errCode = SetSecurityLabel(modifyConfig); if (errCode != E_OK) { LOG_ERROR("fail, storeName:%{public}s security %{public}d errCode:%{public}d", - SqliteUtils::Anonymous(config.GetName()).c_str(), config.GetSecurityLevel(), errCode); + SqliteUtils::Anonymous(modifyConfig.GetName()).c_str(), modifyConfig.GetSecurityLevel(), errCode); return nullptr; } - if (config.IsVector()) { + if (modifyConfig.IsVector()) { storeCache_[path] = rdbStore; return rdbStore; } (void)rdbStore->ExchangeSlaverToMaster(); - errCode = ProcessOpenCallback(*rdbStore, config, version, openCallback); + errCode = ProcessOpenCallback(*rdbStore, modifyConfig, version, openCallback); if (errCode != E_OK) { LOG_ERROR("fail, storeName:%{public}s path:%{public}s ProcessOpenCallback errCode:%{public}d", - SqliteUtils::Anonymous(config.GetName()).c_str(), SqliteUtils::Anonymous(config.GetPath()).c_str(), - errCode); + SqliteUtils::Anonymous(modifyConfig.GetName()).c_str(), + SqliteUtils::Anonymous(modifyConfig.GetPath()).c_str(), errCode); return nullptr; } } @@ -131,11 +146,11 @@ std::shared_ptr RdbStoreManager::GetRdbStore( return rdbStore; } -bool RdbStoreManager::IsConfigInvalidChanged(const std::string &path, const RdbStoreConfig &config) +bool RdbStoreManager::IsConfigInvalidChanged(const std::string &path, RdbStoreConfig &config) { Param param = GetSyncParam(config); Param tempParam; - if (bundleName_.empty()) { + if (config.GetBundleName().empty()) { LOG_WARN("Config has no bundleName, path: %{public}s", SqliteUtils::Anonymous(path).c_str()); return false; } @@ -148,14 +163,17 @@ bool RdbStoreManager::IsConfigInvalidChanged(const std::string &path, const RdbS return false; }; }; - - if (tempParam.level_ != param.level_ || tempParam.area_ != param.area_ || - tempParam.isEncrypt_ != param.isEncrypt_) { - LOG_ERROR("Store config invalid change, storeName %{public}s, securitylevel: %{public}d -> %{public}d, " - "area: %{public}d -> %{public}d, isEncrypt: %{public}d -> %{public}d", + bool isLevelInvalidChange = (tempParam.level_ > param.level_); + bool isEncryptInvalidChange = (tempParam.isEncrypt_ != param.isEncrypt_); + bool isAreaInvalidChange = (tempParam.area_ != param.area_); + if (isLevelInvalidChange || isEncryptInvalidChange || isAreaInvalidChange) { + LOG_WARN("Store config invalid change, storePath %{public}s, securitylevel: %{public}d -> %{public}d, " + "area: %{public}d -> %{public}d, isEncrypt: %{public}d -> %{public}d", SqliteUtils::Anonymous(path).c_str(), tempParam.level_, param.level_, tempParam.area_, param.area_, tempParam.isEncrypt_, param.isEncrypt_); - return true; + if (isEncryptInvalidChange) { + config.SetEncryptStatus(tempParam.isEncrypt_); + } } return false; } @@ -174,6 +192,10 @@ DistributedRdb::RdbSyncerParam RdbStoreManager::GetSyncParam(const RdbStoreConfi syncerParam.isSearchable_ = config.IsSearchable(); syncerParam.roleType_ = config.GetRoleType(); syncerParam.haMode_ = config.GetHaMode(); + syncerParam.tokenIds_ = config.GetPromiseInfo().tokenIds_; + syncerParam.uids_ = config.GetPromiseInfo().uids_; + syncerParam.user_ = config.GetPromiseInfo().user_; + syncerParam.permissionNames_ = config.GetPromiseInfo().permissionNames_; return syncerParam; } @@ -198,6 +220,27 @@ int32_t RdbStoreManager::GetParamFromService(DistributedRdb::RdbSyncerParam &par return E_ERROR; } +int32_t RdbStoreManager::GetPromiseFromService(DistributedRdb::RdbSyncerParam ¶m) +{ +#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) + auto [err, service] = DistributedRdb::RdbManagerImpl::GetInstance().GetRdbService(param); + if (err == E_NOT_SUPPORT) { + return E_ERROR; + } + if (err != E_OK || service == nullptr) { + LOG_ERROR("GetRdbService failed, err is %{public}d.", err); + return E_ERROR; + } + err = service->VerifyPromiseInfo(param); + if (err != DistributedRdb::RDB_OK) { + LOG_ERROR("failed, err is %{public}d.", err); + return E_ERROR; + } + return E_OK; +#endif + return E_ERROR; +} + void RdbStoreManager::Clear() { std::lock_guard lock(mutex_); diff --git a/relational_store/frameworks/native/rdb/src/rdb_types_util.cpp b/relational_store/frameworks/native/rdb/src/rdb_types_util.cpp index b974052b88951287375a304584e942deb52e5ce7..a4ab7de3df5a078579ca3b6d03559c3800402cd4 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_types_util.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_types_util.cpp @@ -20,14 +20,16 @@ bool Marshalling(const SyncerParam &input, MessageParcel &data) { return ITypesUtil::Marshal(data, input.bundleName_, input.hapName_, input.storeName_, input.area_, input.level_, input.type_, input.isEncrypt_, input.password_, input.customDir_, input.isAutoClean_, - input.isSearchable_, input.haMode_, input.infos_); + input.isSearchable_, input.haMode_, input.infos_, input.tokenIds_, input.uids_, input.user_, + input.permissionNames_); } template<> bool Unmarshalling(SyncerParam &output, MessageParcel &data) { return ITypesUtil::Unmarshal(data, output.bundleName_, output.hapName_, output.storeName_, output.area_, output.level_, output.type_, output.isEncrypt_, output.password_, output.customDir_, output.isAutoClean_, - output.isSearchable_, output.haMode_, output.infos_); + output.isSearchable_, output.haMode_, output.infos_, output.tokenIds_, output.uids_, output.user_, + output.permissionNames_); } template<> diff --git a/relational_store/frameworks/native/rdb/src/sqlite_connection.cpp b/relational_store/frameworks/native/rdb/src/sqlite_connection.cpp index 39b3c84a99f404ee450ac14febc4766860d4fea8..dbf7f28c9bc743b3b5192d0c379d8437fc1b6bb7 100644 --- a/relational_store/frameworks/native/rdb/src/sqlite_connection.cpp +++ b/relational_store/frameworks/native/rdb/src/sqlite_connection.cpp @@ -63,7 +63,9 @@ constexpr int SqliteConnection::DEFAULT_BUSY_TIMEOUT_MS; constexpr int SqliteConnection::BACKUP_PAGES_PRE_STEP; // 1024 * 4 * 12800 == 50m constexpr int SqliteConnection::BACKUP_PRE_WAIT_TIME; constexpr ssize_t SqliteConnection::SLAVE_WAL_SIZE_LIMIT; +constexpr ssize_t SqliteConnection::SLAVE_INTEGRITY_CHECK_LIMIT; constexpr uint32_t SqliteConnection::NO_ITER; +constexpr uint32_t SqliteConnection::DB_INDEX; constexpr uint32_t SqliteConnection::WAL_INDEX; __attribute__((used)) const int32_t SqliteConnection::regCreator_ = Connection::RegisterCreator(DB_SQLITE, SqliteConnection::Create); @@ -85,7 +87,15 @@ std::pair> SqliteConnection::Create(const R int32_t SqliteConnection::Delete(const RdbStoreConfig &config) { auto path = config.GetPath(); - for (auto &suffix : FILE_SUFFIXES) { + auto slavePath = SqliteUtils::GetSlavePath(path); + Delete(path); + Delete(slavePath); + return E_OK; +} + +int32_t SqliteConnection::Delete(const std::string &path) +{ + for (const auto &suffix : FILE_SUFFIXES) { SqliteUtils::DeleteFile(path + suffix.suffix_); } return E_OK; @@ -133,15 +143,15 @@ SqliteConnection::SqliteConnection(const RdbStoreConfig &config, bool isWriteCon backupId_ = TaskExecutor::INVALID_TASK_ID; } -int SqliteConnection::CreateSlaveConnection(const RdbStoreConfig &config, bool checkSlaveExist) +std::pair> SqliteConnection::CreateSlaveConnection( + const RdbStoreConfig &config, SlaveOpenPolicy slaveOpenPolicy) { - if (config.GetHaMode() != HAMode::MAIN_REPLICA && config.GetHaMode() != HAMode::MANUAL_TRIGGER) { - return E_OK; - } + std::pair> result = { E_ERROR, nullptr }; + auto &[errCode, conn] = result; std::map bugInfo = Connection::Collect(config); bool isSlaveExist = access(config.GetPath().c_str(), F_OK) == 0; - bool isSlaveLockExist = SqliteUtils::TryAccessSlaveLock(config_.GetPath(), false, false); - bool hasFailure = SqliteUtils::TryAccessSlaveLock(config_.GetPath(), false, false, true); + bool isSlaveLockExist = SqliteUtils::IsSlaveInterrupted(config_.GetPath()); + bool hasFailure = SqliteUtils::IsSlaveInvalid(config_.GetPath()); bool walOverLimit = bugInfo.find(FILE_SUFFIXES[WAL_INDEX].debug_) != bugInfo.end() && bugInfo[FILE_SUFFIXES[WAL_INDEX].debug_].size_ > SLAVE_WAL_SIZE_LIMIT; LOG_INFO("slave cfg:[%{public}d,%{public}d,%{public}d,%{public}d,%{public}d,%{public}d,%{public}d]%{public}s " @@ -151,34 +161,38 @@ int SqliteConnection::CreateSlaveConnection(const RdbStoreConfig &config, bool c Reportor::FormatBrief(bugInfo, SqliteUtils::Anonymous(config.GetName())).c_str(), Reportor::FormatBrief(Connection::Collect(config_), "master").c_str(), isSlaveExist, isSlaveLockExist, hasFailure, walOverLimit); - if (config.GetHaMode() == HAMode::MANUAL_TRIGGER && - (checkSlaveExist && (!isSlaveExist || isSlaveLockExist || hasFailure || walOverLimit))) { + if (config.GetHaMode() == HAMode::MANUAL_TRIGGER && (slaveOpenPolicy == SlaveOpenPolicy::OPEN_IF_DB_VALID && + (!isSlaveExist || isSlaveLockExist || hasFailure || walOverLimit))) { if (walOverLimit) { - SqliteUtils::TryAccessSlaveLock(config_.GetPath(), false, true, true); + SqliteUtils::SetSlaveInvalid(config_.GetPath()); } - return E_OK; + return result; } std::shared_ptr connection = std::make_shared(config, true); - int errCode = connection->InnerOpen(config); + errCode = connection->InnerOpen(config); if (errCode != E_OK) { - SqliteUtils::TryAccessSlaveLock(config_.GetPath(), false, true, true); + SqliteUtils::SetSlaveInvalid(config_.GetPath()); if (errCode == E_SQLITE_CORRUPT) { LOG_WARN("slave corrupt, rebuild:%{public}s", SqliteUtils::Anonymous(config.GetPath()).c_str()); - (void)Delete(config); + (void)Delete(config.GetPath()); + // trigger mode does not require rebuild the slave + if (config.GetHaMode() == HAMode::MANUAL_TRIGGER) { + return result; + } errCode = connection->InnerOpen(config); if (errCode != E_OK) { LOG_ERROR("reopen slave failed:%{public}d", errCode); - return errCode; + return result; } } else { LOG_WARN("open slave failed:%{public}d, %{public}s", errCode, SqliteUtils::Anonymous(config.GetPath()).c_str()); - return errCode; + return result; } } - slaveConnection_ = connection; - return errCode; + conn = connection; + return result; } RdbStoreConfig SqliteConnection::GetSlaveRdbStoreConfig(const RdbStoreConfig &rdbConfig) @@ -443,7 +457,7 @@ std::pair> SqliteConnection::CreateStatement( errCode = slaveStmt->Prepare(slaveConnection_->dbHandle_, sql); if (errCode != E_OK) { LOG_WARN("prepare slave stmt failed:%{public}d, sql:%{public}s", errCode, sql.c_str()); - SqliteUtils::TryAccessSlaveLock(config_.GetPath(), false, true, true); + SqliteUtils::SetSlaveInvalid(config_.GetPath()); return { E_OK, statement }; } statement->slave_ = slaveStmt; @@ -1221,14 +1235,15 @@ int32_t SqliteConnection::Backup(const std::string &databasePath, const std::vec if (!isAsync) { if (slaveConnection_ == nullptr) { RdbStoreConfig rdbSlaveStoreConfig = GetSlaveRdbStoreConfig(config_); - int errCode = CreateSlaveConnection(rdbSlaveStoreConfig, false); + auto [errCode, conn] = CreateSlaveConnection(rdbSlaveStoreConfig, SlaveOpenPolicy::FORCE_OPEN); if (errCode != E_OK) { - LOG_ERROR("manual slave conn failed:%{public}d", errCode); return errCode; } + slaveConnection_ = conn; } - return ExchangeSlaverToMaster(false, slaveStatus); + return ExchangeSlaverToMaster(false, true, slaveStatus); } + if (backupId_ == TaskExecutor::INVALID_TASK_ID) { auto pool = TaskExecutor::GetInstance().GetExecutor(); if (pool == nullptr) { @@ -1240,7 +1255,7 @@ int32_t SqliteConnection::Backup(const std::string &databasePath, const std::vec if (err != E_OK) { return; } - err = conn->ExchangeSlaverToMaster(false, slaveStatus); + err = conn->ExchangeSlaverToMaster(false, true, slaveStatus); if (err != E_OK) { LOG_WARN("master backup to slave failed:%{public}d", err); } @@ -1253,8 +1268,7 @@ int32_t SqliteConnection::Backup(const std::string &databasePath, const std::vec int32_t SqliteConnection::Restore(const std::string &databasePath, const std::vector &destEncryptKey, SlaveStatus &slaveStatus) { - LOG_INFO("begin to restore from slave:%{public}s", SqliteUtils::Anonymous(databasePath).c_str()); - return ExchangeSlaverToMaster(true, slaveStatus); + return ExchangeSlaverToMaster(true, true, slaveStatus); }; int SqliteConnection::LoadExtension(const RdbStoreConfig &config, sqlite3 *dbHandle) @@ -1330,15 +1344,19 @@ int SqliteConnection::SetServiceKey(const RdbStoreConfig &config, int32_t errCod return errCode; } -int SqliteConnection::ExchangeSlaverToMaster(bool isRestore, SlaveStatus &curStatus) +int SqliteConnection::ExchangeSlaverToMaster(bool isRestore, bool verifyDb, SlaveStatus &curStatus) { curStatus = SlaveStatus::BACKING_UP; - auto err = ExchangeVerify(isRestore); + int err = verifyDb ? ExchangeVerify(isRestore) : E_OK; if (err != E_OK) { curStatus = SlaveStatus::UNDEFINED; return err; } + return SqliteNativeBackup(isRestore, curStatus); +} +int SqliteConnection::SqliteNativeBackup(bool isRestore, SlaveStatus &curStatus) +{ sqlite3 *dbFrom = isRestore ? dbHandle_ : slaveConnection_->dbHandle_; sqlite3 *dbTo = isRestore ? slaveConnection_->dbHandle_ : dbHandle_; sqlite3_backup *pBackup = sqlite3_backup_init(dbFrom, "main", dbTo, "main"); @@ -1350,7 +1368,6 @@ int SqliteConnection::ExchangeSlaverToMaster(bool isRestore, SlaveStatus &curSta int rc = SQLITE_OK; do { if (!isRestore && curStatus == SlaveStatus::BACKUP_INTERRUPT) { - LOG_INFO("backup slave was interrupt!"); rc = E_CANCEL; break; } @@ -1369,7 +1386,7 @@ int SqliteConnection::ExchangeSlaverToMaster(bool isRestore, SlaveStatus &curSta RdbStoreConfig slaveConfig(slaveConnection_->config_.GetPath()); if (rc != SQLITE_BUSY && rc != SQLITE_LOCKED) { slaveConnection_ = nullptr; - (void)SqliteConnection::Delete(slaveConfig); + (void)SqliteConnection::Delete(slaveConfig.GetPath()); } curStatus = SlaveStatus::BACKUP_INTERRUPT; } @@ -1384,8 +1401,7 @@ int SqliteConnection::ExchangeSlaverToMaster(bool isRestore, SlaveStatus &curSta return E_OK; } curStatus = SlaveStatus::BACKUP_FINISHED; - SqliteUtils::TryAccessSlaveLock(config_.GetPath(), true, false); - SqliteUtils::TryAccessSlaveLock(config_.GetPath(), true, false, true); + SqliteUtils::SetSlaveValid(config_.GetPath()); LOG_INFO("backup slave success, isRestore:%{public}d", isRestore); return E_OK; } @@ -1416,8 +1432,7 @@ ExchangeStrategy SqliteConnection::GenerateExchangeStrategy(const SlaveStatus &s return ExchangeStrategy::BACKUP; } int64_t sCount = static_cast(sObj); - std::string failureFlagFile = config_.GetPath() + "-slaveFailure"; - if (mCount == sCount && access(failureFlagFile.c_str(), F_OK) != 0) { + if ((mCount == sCount) && !SqliteUtils::IsSlaveInvalid(config_.GetPath())) { LOG_INFO("equal, main:%{public}" PRId64 ",slave:%{public}" PRId64, mCount, sCount); return ExchangeStrategy::NOT_HANDLE; } @@ -1431,102 +1446,70 @@ ExchangeStrategy SqliteConnection::GenerateExchangeStrategy(const SlaveStatus &s int32_t SqliteConnection::Repair(const RdbStoreConfig &config) { - if (config.GetHaMode() != MAIN_REPLICA && config.GetHaMode() != MANUAL_TRIGGER) { - return E_NOT_SUPPORT; - } std::shared_ptr connection = std::make_shared(config, true); if (connection == nullptr) { - return E_NOT_SUPPORT; + return E_ERROR; } RdbStoreConfig rdbSlaveStoreConfig = connection->GetSlaveRdbStoreConfig(config); - int ret = connection->CreateSlaveConnection(rdbSlaveStoreConfig); + if (access(rdbSlaveStoreConfig.GetPath().c_str(), F_OK) != 0) { + return E_NOT_SUPPORT; + } + auto [ret, conn] = connection->CreateSlaveConnection(rdbSlaveStoreConfig, SlaveOpenPolicy::FORCE_OPEN); if (ret != E_OK) { return ret; } - ret = connection->IsRepairable(); + connection->slaveConnection_ = conn; + ret = connection->VeritySlaveIntegrity(); if (ret != E_OK) { return ret; } - LOG_WARN("begin repair main:%{public}s", SqliteUtils::Anonymous(config.GetPath()).c_str()); - (void)SqliteConnection::Delete(config); + (void)SqliteConnection::Delete(config.GetPath()); ret = connection->InnerOpen(config); if (ret != E_OK) { LOG_ERROR("reopen db failed, err:%{public}d", ret); return ret; } SlaveStatus curStatus; - ret = connection->ExchangeSlaverToMaster(true, curStatus); + ret = connection->ExchangeSlaverToMaster(true, false, curStatus); if (ret != E_OK) { LOG_ERROR("repair failed, [%{public}s]->[%{public}s], err:%{public}d", rdbSlaveStoreConfig.GetName().c_str(), SqliteUtils::Anonymous(config.GetName()).c_str(), ret); } else { LOG_INFO("repair main success:%{public}s", SqliteUtils::Anonymous(config.GetPath()).c_str()); } - connection->slaveConnection_ = nullptr; - connection = nullptr; return ret; } -int SqliteConnection::IsRepairable() -{ - if (slaveConnection_ == nullptr || slaveConnection_->dbHandle_ == nullptr) { - return E_STORE_CLOSED; - } - if (SqliteUtils::TryAccessSlaveLock(config_.GetPath(), false, false, false)) { - LOG_ERROR("unavailable slave, %{public}s", config_.GetName().c_str()); - return E_SQLITE_CORRUPT; - } - std::string querySql = "SELECT COUNT(*) FROM sqlite_master WHERE type='table';"; - auto [qRet, qObj] = slaveConnection_->ExecuteForValue(querySql); - if (qRet == E_SQLITE_CORRUPT || (static_cast(qObj) == 0L)) { - LOG_INFO("cancel repair, ret:%{public}d", qRet); - return E_SQLITE_CORRUPT; - } - return E_OK; -} - int SqliteConnection::ExchangeVerify(bool isRestore) { - if (dbHandle_ == nullptr || slaveConnection_ == nullptr || slaveConnection_->dbHandle_ == nullptr) { - LOG_WARN("slave conn invalid"); - return E_STORE_CLOSED; - } - if (access(config_.GetPath().c_str(), F_OK) != 0) { - LOG_WARN("main no exist, isR:%{public}d, %{public}s", isRestore, config_.GetName().c_str()); - return E_DB_NOT_EXIST; - } if (isRestore) { - int err = IsRepairable(); + int err = VeritySlaveIntegrity(); if (err != E_OK) { return err; } - auto [cRet, cObj] = slaveConnection_->ExecuteForValue(INTEGRITIES[2]); // 2 is integrity_check - if (cRet != E_OK || (static_cast(cObj) != "ok")) { - LOG_ERROR("slave may corrupt, cancel, ret:%{public}s, cRet:%{public}d", - static_cast(cObj).c_str(), cRet); - return E_SQLITE_CORRUPT; - } - std::string querySql = "SELECT COUNT(*) FROM sqlite_master WHERE type='table';"; - std::tie(cRet, cObj) = ExecuteForValue(querySql); - if (cRet == E_OK && (static_cast(cObj) == 0L)) { - LOG_INFO("main empty, need restore, %{public}s", config_.GetName().c_str()); + if (IsDbVersionBelowSlave()) { return E_OK; } - if (SqliteUtils::TryAccessSlaveLock(config_.GetPath(), false, false, true)) { + if (SqliteUtils::IsSlaveInvalid(config_.GetPath())) { LOG_ERROR("incomplete slave, %{public}s", config_.GetName().c_str()); - return E_NOT_SUPPORTED; - } - } else { - auto [cRet, cObj] = ExecuteForValue(INTEGRITIES[1]); // 1 is quick_check - if (cRet != E_OK || (static_cast(cObj) != "ok")) { - LOG_ERROR("main corrupt, cancel, ret:%{public}s, qRet:%{public}d", - static_cast(cObj).c_str(), cRet); return E_SQLITE_CORRUPT; } - if (!SqliteUtils::TryAccessSlaveLock(config_.GetPath(), false, true)) { - LOG_WARN("try create slave lock failed! isRestore:%{public}d", isRestore); - } + return E_OK; + } + if (slaveConnection_ == nullptr) { + return E_ALREADY_CLOSED; } + if (access(config_.GetPath().c_str(), F_OK) != 0) { + LOG_WARN("main no exist, isR:%{public}d, %{public}s", isRestore, config_.GetName().c_str()); + return E_DB_NOT_EXIST; + } + auto [cRet, cObj] = ExecuteForValue(INTEGRITIES[1]); // 1 is quick_check + if (cRet == E_OK && (static_cast(cObj) != "ok")) { + LOG_ERROR("main corrupt, cancel, %{public}s, ret:%{public}s, qRet:%{public}d", + SqliteUtils::Anonymous(config_.GetName()).c_str(), static_cast(cObj).c_str(), cRet); + return E_SQLITE_CORRUPT; + } + SqliteUtils::SetSlaveInterrupted(config_.GetPath()); return E_OK; } @@ -1547,10 +1530,84 @@ std::pair> SqliteConnection::InnerCre return result; } conn = connection; - if (isWrite) { - (void)connection->CreateSlaveConnection(slaveCfg, isWrite); + if (isWrite && config.GetHaMode() != HAMode::SINGLE) { + auto [err, slaveConn] = connection->CreateSlaveConnection(slaveCfg, SlaveOpenPolicy::OPEN_IF_DB_VALID); + if (err == E_OK) { + conn->slaveConnection_ = slaveConn; + } } return result; } + +int SqliteConnection::VeritySlaveIntegrity() +{ + if (slaveConnection_ == nullptr) { + return E_ALREADY_CLOSED; + } + + RdbStoreConfig slaveCfg = GetSlaveRdbStoreConfig(config_); + std::map bugInfo = Connection::Collect(slaveCfg); + LOG_INFO("%{public}s", Reportor::FormatBrief(bugInfo, SqliteUtils::Anonymous(slaveCfg.GetName())).c_str()); + + if (SqliteUtils::IsSlaveInterrupted(config_.GetPath())) { + return E_SQLITE_CORRUPT; + } + + std::string sql = "SELECT COUNT(*) FROM sqlite_master WHERE type='table';"; + auto [err, obj] = slaveConnection_->ExecuteForValue(sql); + auto val = std::get_if(&obj.value); + if (err == E_SQLITE_CORRUPT || (val != nullptr && static_cast(*val) == 0L)) { + LOG_ERROR("slave %{public}d", err); + return E_SQLITE_CORRUPT; + } + + int64_t mCount = 0L; + if (dbHandle_ != nullptr) { + std::tie(err, obj) = ExecuteForValue(sql); + val = std::get_if(&obj.value); + if (val != nullptr) { + mCount = static_cast(*val); + } + } + bool isSlaveDbOverLimit = bugInfo.find(FILE_SUFFIXES[DB_INDEX].debug_) != bugInfo.end() && + bugInfo[FILE_SUFFIXES[DB_INDEX].debug_].size_ > SLAVE_INTEGRITY_CHECK_LIMIT; + if (isSlaveDbOverLimit && mCount == 0L) { + return SqliteUtils::IsSlaveInvalid(config_.GetPath()) ? E_SQLITE_CORRUPT : E_OK; + } + + std::tie(err, obj) = slaveConnection_->ExecuteForValue(INTEGRITIES[2]); // 2 is integrity_check + if (err == E_OK && (static_cast(obj) != "ok")) { + LOG_ERROR("slave corrupt, ret:%{public}s, cRet:%{public}d, %{public}d", + static_cast(obj).c_str(), err, errno); + SqliteUtils::SetSlaveInvalid(config_.GetPath()); + return E_SQLITE_CORRUPT; + } + return E_OK; +} + +bool SqliteConnection::IsDbVersionBelowSlave() +{ + if (slaveConnection_ == nullptr) { + return false; + } + + auto[cRet, cObj] = ExecuteForValue("SELECT COUNT(*) FROM sqlite_master WHERE type='table';"); + auto cVal = std::get_if(&cObj.value); + if (cRet == E_SQLITE_CORRUPT || (cVal != nullptr && (static_cast(*cVal) == 0L))) { + LOG_INFO("main empty, %{public}d, %{public}s", cRet, config_.GetName().c_str()); + return true; + } + + std::tie(cRet, cObj) = ExecuteForValue(GlobalExpr::PRAGMA_VERSION); + if (cVal == nullptr || (cVal != nullptr && static_cast(*cVal) == 0L)) { + std::tie(cRet, cObj) = slaveConnection_->ExecuteForValue(GlobalExpr::PRAGMA_VERSION); + cVal = std::get_if(&cObj.value); + if (cVal != nullptr && static_cast(*cVal) > 0L) { + LOG_INFO("version, %{public}" PRId64, static_cast(*cVal)); + return true; + } + } + return false; +} } // namespace NativeRdb } // namespace OHOS \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb/src/sqlite_sql_builder.cpp b/relational_store/frameworks/native/rdb/src/sqlite_sql_builder.cpp index 2fa7e9bd8f1dc48d6efe9275938b16b40ebe6b9e..25da02f6566856d533e17aaa45aaa9a0d2f0fb6b 100644 --- a/relational_store/frameworks/native/rdb/src/sqlite_sql_builder.cpp +++ b/relational_store/frameworks/native/rdb/src/sqlite_sql_builder.cpp @@ -304,7 +304,6 @@ SqliteSqlBuilder::BatchRefSqls SqliteSqlBuilder::GenerateSqls(const std::string auto [fields, values] = buckets.GetFieldsAndValues(); auto columnSize = fields->size(); auto rowSize = buckets.RowSize(); - LOG_INFO("columnSize=%{public}zu, rowSize=%{public}zu", columnSize, rowSize); std::vector> args(columnSize * rowSize, nullRef_); std::string sql = "INSERT OR REPLACE INTO " + table + " ("; size_t columnIndex = 0; @@ -312,7 +311,6 @@ SqliteSqlBuilder::BatchRefSqls SqliteSqlBuilder::GenerateSqls(const std::string for (size_t row = 0; row < rowSize; ++row) { auto [errorCode, value] = buckets.Get(row, std::ref(field)); if (errorCode != E_OK) { - LOG_ERROR("not found %{public}s in row=%{public}zu", field.c_str(), row); continue; } SqliteSqlBuilder::UpdateAssetStatus(value.get(), AssetValue::STATUS_INSERT); diff --git a/relational_store/frameworks/native/rdb/src/sqlite_statement.cpp b/relational_store/frameworks/native/rdb/src/sqlite_statement.cpp index bd08afbeee355dc0b9a9729c88598a933e670186..bb03940e6445d7b46e37b43fec15954694f0604e 100644 --- a/relational_store/frameworks/native/rdb/src/sqlite_statement.cpp +++ b/relational_store/frameworks/native/rdb/src/sqlite_statement.cpp @@ -205,7 +205,7 @@ int SqliteStatement::Prepare(const std::string &sql) int errCode = slave_->Prepare(sql); if (errCode != E_OK) { LOG_WARN("slave prepare Error:%{public}d", errCode); - SqliteUtils::TryAccessSlaveLock(config_->GetPath(), false, true, true); + SqliteUtils::SetSlaveInvalid(config_->GetPath()); } } return E_OK; @@ -246,7 +246,7 @@ int SqliteStatement::Bind(const std::vector &args) int errCode = slave_->Bind(args); if (errCode != E_OK) { LOG_ERROR("slave bind error:%{public}d", errCode); - SqliteUtils::TryAccessSlaveLock(config_->GetPath(), false, true, true); + SqliteUtils::SetSlaveInvalid(config_->GetPath()); } } return E_OK; @@ -384,8 +384,9 @@ int32_t SqliteStatement::Execute(const std::vectorExecute(args); if (errCode != E_OK) { - LOG_ERROR("slave execute error:%{public}d", errCode); - SqliteUtils::TryAccessSlaveLock(config_->GetPath(), false, true, true); + LOG_ERROR("slave execute error:%{public}d, sql is %{public}s, errno %{public}d", + errCode, sql_.c_str(), errno); + SqliteUtils::SetSlaveInvalid(config_->GetPath()); } } return E_OK; diff --git a/relational_store/frameworks/native/rdb/src/sqlite_utils.cpp b/relational_store/frameworks/native/rdb/src/sqlite_utils.cpp index 4b724ff2b77ed550c0fe849d369a25c39638cd09..d9acdf58013a58d04b0aadc1e64cf6792356d36e 100644 --- a/relational_store/frameworks/native/rdb/src/sqlite_utils.cpp +++ b/relational_store/frameworks/native/rdb/src/sqlite_utils.cpp @@ -260,36 +260,6 @@ bool SqliteUtils::IsSlaveDbName(const std::string &fileName) return (pos != std::string::npos) && (pos == fileName.size() - slaveSuffix.size()); } -bool SqliteUtils::TryAccessSlaveLock(const std::string &dbPath, bool isDelete, bool needCreate, - bool isSlaveFailure) -{ - std::string lockFile = isSlaveFailure ? dbPath + "-slaveFailure" : dbPath + "-syncInterrupt"; - if (isDelete) { - if (std::remove(lockFile.c_str()) != 0) { - return false; - } else { - LOG_INFO("remove %{public}s", Anonymous(lockFile).c_str()); - return true; - } - } else { - if (access(lockFile.c_str(), F_OK) == 0) { - return true; - } - if (needCreate) { - std::ofstream src(lockFile.c_str(), std::ios::binary); - if (src.is_open()) { - LOG_INFO("open %{public}s", Anonymous(lockFile).c_str()); - src.close(); - return true; - } else { - LOG_WARN("open errno %{public}d %{public}s", errno, Anonymous(lockFile).c_str()); - return false; - } - } - return false; - } -} - std::string SqliteUtils::GetSlavePath(const std::string& name) { std::string suffix(".db"); @@ -343,5 +313,40 @@ const char *SqliteUtils::EncryptAlgoDescription(int32_t encryptAlgo) } } +int SqliteUtils::SetSlaveInvalid(const std::string &dbPath) +{ + std::ofstream src((dbPath + SLAVE_FAILURE).c_str(), std::ios::binary); + if (src.is_open()) { + src.close(); + return E_OK; + } + return E_ERROR; +} + +int SqliteUtils::SetSlaveInterrupted(const std::string &dbPath) +{ + std::ofstream src((dbPath + SLAVE_INTERRUPT).c_str(), std::ios::binary); + if (src.is_open()) { + src.close(); + return E_OK; + } + return E_ERROR; +} + +bool SqliteUtils::IsSlaveInvalid(const std::string &dbPath) +{ + return access((dbPath + SLAVE_FAILURE).c_str(), F_OK) == 0; +} + +bool SqliteUtils::IsSlaveInterrupted(const std::string &dbPath) +{ + return access((dbPath + SLAVE_INTERRUPT).c_str(), F_OK) == 0; +} + +void SqliteUtils::SetSlaveValid(const std::string &dbPath) +{ + std::remove((dbPath + SLAVE_INTERRUPT).c_str()); + std::remove((dbPath + SLAVE_FAILURE).c_str()); +} } // namespace NativeRdb } // namespace OHOS diff --git a/relational_store/interfaces/inner_api/rdb/include/distributeddata_relational_store_ipc_interface_code.h b/relational_store/interfaces/inner_api/rdb/include/distributeddata_relational_store_ipc_interface_code.h index 2316e8787f40e9616577c48ca61093c8402978b1..fe1a104037d9bbadff8e176af9d649180f3b31f8 100644 --- a/relational_store/interfaces/inner_api/rdb/include/distributeddata_relational_store_ipc_interface_code.h +++ b/relational_store/interfaces/inner_api/rdb/include/distributeddata_relational_store_ipc_interface_code.h @@ -89,6 +89,7 @@ enum class RdbServiceInterfaceCode { RDB_SERVICE_CMD_LOCK_CLOUD_CONTAINER, RDB_SERVICE_CMD_UNLOCK_CLOUD_CONTAINER, RDB_SERVICE_CMD_GET_DEBUG_INFO, + RDB_SERVICE_CMD_VERIFY_PROMISE_INFO, RDB_SERVICE_CMD_MAX }; } // namespace RelationalStore diff --git a/relational_store/interfaces/inner_api/rdb/include/rdb_service.h b/relational_store/interfaces/inner_api/rdb/include/rdb_service.h index 9cd34fadd4d55e3fda0f4ab99a25565f8db27b8c..4a6ed38e19e8fdc060acda6723b88e21d0827f67 100644 --- a/relational_store/interfaces/inner_api/rdb/include/rdb_service.h +++ b/relational_store/interfaces/inner_api/rdb/include/rdb_service.h @@ -90,6 +90,8 @@ public: virtual int32_t UnlockCloudContainer(const RdbSyncerParam ¶m) = 0; virtual int32_t GetDebugInfo(const RdbSyncerParam ¶m, std::map &debugInfo) = 0; + + virtual int32_t VerifyPromiseInfo(const RdbSyncerParam ¶m) = 0; }; } } // namespace OHOS::DistributedRdb diff --git a/relational_store/interfaces/inner_api/rdb/include/rdb_store_config.h b/relational_store/interfaces/inner_api/rdb/include/rdb_store_config.h index df2b92e310b775009854f227f5d088d4e8a4d418..725a9d7326cc9c588e88904ac1c4319370d61312 100644 --- a/relational_store/interfaces/inner_api/rdb/include/rdb_store_config.h +++ b/relational_store/interfaces/inner_api/rdb/include/rdb_store_config.h @@ -143,6 +143,10 @@ enum RoleType : uint32_t { * The user has read-only permission. */ VISITOR, + /** + * The user has specific administrative rights. + */ + VISITOR_WRITE, }; enum DBType : uint32_t { @@ -201,6 +205,14 @@ struct ScalarFunctionInfo { ScalarFunction function_; int argc_; }; + +struct PromiseInfo { + std::string user_ = ""; + std::vector tokenIds_ = {}; + std::vector uids_ = {}; + std::vector permissionNames_ = {}; +}; + /** * Manages relational database configurations. */ @@ -656,12 +668,14 @@ public: int32_t GetIter() const; + PromiseInfo GetPromiseInfo() const; + + void SetPromiseInfo(PromiseInfo promiseInfo); + int32_t GetHaMode() const; void SetHaMode(int32_t haMode); - void SetNewEncryptKey(const std::vector newEncryptKey); - void SetScalarFunctions(const std::map functions); void SetCryptoParam(CryptoParam cryptoParam); @@ -672,6 +686,8 @@ public: void EnableRekey(bool enable); + static std::string Format(const RdbStoreConfig &cacheConfig, const RdbStoreConfig &incomingConfig); + private: void ClearEncryptKey(); int32_t GenerateEncryptedKey() const; @@ -703,6 +719,7 @@ private: std::string journalMode_; std::string syncMode_; std::string databaseFileType; + PromiseInfo promiseInfo_; // distributed rdb std::string bundleName_; std::string moduleName_; diff --git a/relational_store/interfaces/inner_api/rdb/include/rdb_types.h b/relational_store/interfaces/inner_api/rdb/include/rdb_types.h index 7d0d9fc16c535b0b8970d706215b02c966b61bbf..c577b8ceb20a25340c465ee01371a0cb318a1b18 100644 --- a/relational_store/interfaces/inner_api/rdb/include/rdb_types.h +++ b/relational_store/interfaces/inner_api/rdb/include/rdb_types.h @@ -68,6 +68,10 @@ struct RdbSyncerParam { bool isSearchable_ = false; std::vector password_; std::map infos_; + std::vector tokenIds_; + std::vector uids_; + std::string user_; + std::vector permissionNames_ = {}; ~RdbSyncerParam() { password_.assign(password_.size(), 0); diff --git a/relational_store/interfaces/inner_api/rdb/mock/include/rdb_store_config.h b/relational_store/interfaces/inner_api/rdb/mock/include/rdb_store_config.h index 66b4b060f697bc9252ebcc70aa219b979100374d..d65faef65db8ea7937e89756787e04c70da53b71 100644 --- a/relational_store/interfaces/inner_api/rdb/mock/include/rdb_store_config.h +++ b/relational_store/interfaces/inner_api/rdb/mock/include/rdb_store_config.h @@ -73,6 +73,7 @@ enum HAMode : int32_t { enum RoleType : uint32_t { OWNER = 0, VISITOR, + VISITOR_WRITE, }; enum DBType : uint32_t { @@ -112,6 +113,13 @@ struct ScalarFunctionInfo { int argc_; }; +struct PromiseInfo { + std::string user_ = ""; + std::vector tokenIds_ = {}; + std::vector uids_ = {}; + std::vector permissionNames_ = {}; +}; + class RdbStoreConfig { public: struct CryptoParam { @@ -245,13 +253,15 @@ public: void SetIter(int32_t iter) const; int32_t GetIter() const; int32_t GetHaMode() const; + PromiseInfo GetPromiseInfo() const; + void SetPromiseInfo(PromiseInfo promiseInfo); void SetHaMode(int32_t haMode); - void SetNewEncryptKey(const std::vector newEncryptKey); void SetScalarFunctions(const std::map functions); void SetCryptoParam(CryptoParam cryptoParam); CryptoParam GetCryptoParam() const; void SetJournalMode(const std::string &journalMode); void EnableRekey(bool enable); + static std::string Format(const RdbStoreConfig &cacheConfig, const RdbStoreConfig &incomingConfig); private: void ClearEncryptKey(); @@ -284,6 +294,7 @@ private: std::string journalMode_; std::string syncMode_; std::string databaseFileType; + PromiseInfo promiseInfo_; // distributed rdb std::string bundleName_; std::string moduleName_; diff --git a/relational_store/test/js/rdb/unittest/src/RdbstoreEncryptionJsunit.test.js b/relational_store/test/js/rdb/unittest/src/RdbstoreEncryptionJsunit.test.js index 186a8948cd4e6a53553c4487173da587678480a3..247ebcdd38ec06b603257ab172e2d4ed4da10107 100644 --- a/relational_store/test/js/rdb/unittest/src/RdbstoreEncryptionJsunit.test.js +++ b/relational_store/test/js/rdb/unittest/src/RdbstoreEncryptionJsunit.test.js @@ -167,21 +167,43 @@ describe('rdbEncryptTest', function () { * @tc.number SUB_DDM_RDB_JS_RdbEncryptTest_0040 * @tc.desc RDB encrypt function test */ - it('RdbEncryptTest_0040', 0, async function () { - await console.log(TAG + "************* RdbEncryptTest_0040 start *************") - context = ability_featureAbility.getContext() - - await CreateRdbStore(context, STORE_CONFIG_ENCRYPT) + it('RdbEncryptTest_0040', 0, async function (done) { + console.log(TAG + "************* RdbEncryptTest_0040 start *************"); + context = ability_featureAbility.getContext(); + await CreateRdbStore(context, STORE_CONFIG_ENCRYPT); try { - await CreateRdbStore(context, STORE_CONFIG_WRONG) - expect().assertFail() + let rdbStore = await CreateRdbStore(context, STORE_CONFIG_WRONG); + expect(rdbStore !== null).assertTrue(); } catch (err) { - console.log(TAG + `failed, errcode:${JSON.stringify(err)}.`); + console.log(TAG + `failed, errcode:${JSON.stringify(err)}.`); + expect().assertFail(); } - - await console.log(TAG + "************* RdbEncryptTest_0040 end *************") + done(); + console.log(TAG + "************* RdbEncryptTest_0040 end *************"); }) + /** + * @tc.name RdbEncryptTest_0041 + * @tc.number SUB_DDM_RDB_JS_RdbEncryptTest_0041 + * @tc.desc RDB Encrypt function test + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 1 + */ + it('RdbEncryptTest_0041', 0, async function (done) { + console.log(TAG + "************* RdbEncryptTest_0041 start *************"); + context = ability_featureAbility.getContext(); + await CreateRdbStore(context, STORE_CONFIG_WRONG); + try { + let rdbStore = await CreateRdbStore(context, STORE_CONFIG_ENCRYPT); + expect(rdbStore !== null).assertTrue(); + } catch (err) { + console.log(TAG + `failed, errcode:${JSON.stringify(err)}.`); + expect().assertFail(); + } + done(); + console.log(TAG + "************* RdbEncryptTest_0041 end *************"); + }) /** * @tc.name Scenario testcase of RDB, get correct encrypt file when open database * @tc.number SUB_DDM_RDB_JS_RdbEncryptTest_0050 @@ -200,7 +222,7 @@ describe('rdbEncryptTest', function () { rdbStore1 = await CreateRdbStore(context, STORE_CONFIG_ENCRYPT); } catch (err) { expect().assertFail() - console.error(`CreatRdbStore1 failed, error code: ${err.code}, err message: ${err.message}`); + console.error(`CreateRdbStore1 failed, error code: ${err.code}, err message: ${err.message}`); } // query 'rdbstore1' @@ -218,7 +240,7 @@ describe('rdbEncryptTest', function () { rdbStore2 = await CreateRdbStore(context, STORE_CONFIG_ENCRYPT2) } catch (err) { expect().assertFail() - console.error(`CreatRdbStore2 failed, error code: ${err.code}, err message: ${err.message}`); + console.error(`CreateRdbStore2 failed, error code: ${err.code}, err message: ${err.message}`); } // create table and query 'rdbStore1' diff --git a/relational_store/test/js/relationalstore/performance/src/SceneGetValuesBucketPerf.js b/relational_store/test/js/relationalstore/performance/src/SceneGetValuesBucketPerf.js index 9e4711386928925ac5d739b59a01bc17249b07a3..91760e76f2200ddb665b67ebe827828c47986488 100644 --- a/relational_store/test/js/relationalstore/performance/src/SceneGetValuesBucketPerf.js +++ b/relational_store/test/js/relationalstore/performance/src/SceneGetValuesBucketPerf.js @@ -48,7 +48,7 @@ function CREATE_UINT8_ARRAY(len) { const CONST_UINT8_ARRAY = CREATE_UINT8_ARRAY(127); -const DB_NAME = "resultSetPerf.db"; +const DB_NAME = "GetValuesBucketPerf.db"; const STORE_CONFIG = { name: DB_NAME, securityLevel: dataRdb.SecurityLevel.S3 diff --git a/relational_store/test/js/relationalstore/unittest/src/RdbstoreEncryptionJsunit.test.js b/relational_store/test/js/relationalstore/unittest/src/RdbstoreEncryptionJsunit.test.js index ffff620c8ccaa2254170007afce584baa03d9d13..da78089561f1a905af53d184b0c7474c1eda36ac 100644 --- a/relational_store/test/js/relationalstore/unittest/src/RdbstoreEncryptionJsunit.test.js +++ b/relational_store/test/js/relationalstore/unittest/src/RdbstoreEncryptionJsunit.test.js @@ -70,7 +70,7 @@ const STORE_CONFIG_NON_DEFAULT = { } } -async function CreatRdbStore(context, STORE_CONFIG) { +async function CreateRdbStore(context, STORE_CONFIG) { let rdbStore = await data_relationalStore.getRdbStore(context, STORE_CONFIG) await rdbStore.executeSql(CREATE_TABLE_TEST, null) let u8 = new Uint8Array([1, 2, 3]) @@ -211,7 +211,7 @@ describe('rdbEncryptTest', function () { */ it('RdbEncryptTest_0030', 0, async function (done) { await console.log(TAG + "************* RdbEncryptTest_0030 start *************") - let rdbStore = await CreatRdbStore(context, STORE_CONFIG_ENCRYPT) + let rdbStore = await CreateRdbStore(context, STORE_CONFIG_ENCRYPT) let predicates = new data_relationalStore.RdbPredicates("test") predicates.equalTo("name", "zhangsan") let resultSet = await rdbStore.query(predicates) @@ -239,19 +239,42 @@ describe('rdbEncryptTest', function () { * @tc.number SUB_DDM_RDB_JS_RdbEncryptTest_0040 * @tc.desc RDB Encrypt function test */ - it('RdbEncryptTest_0040', 0, async function () { - await console.log(TAG + "************* RdbEncryptTest_0040 start *************") - let rdbStore = await CreatRdbStore(context, STORE_CONFIG_ENCRYPT) - rdbStore = null - + it('RdbEncryptTest_0040', 0, async function (done) { + console.log(TAG + "************* RdbEncryptTest_0040 start *************"); + context = ability_featureAbility.getContext(); + await CreateRdbStore(context, STORE_CONFIG_ENCRYPT); try { - rdbStore = await CreatRdbStore(context, STORE_CONFIG_WRONG) - expect(false).assertTrue() + let rdbStore = await CreateRdbStore(context, STORE_CONFIG_WRONG); + expect(rdbStore !== null).assertTrue(); } catch (err) { - expect(err.code).assertEqual(14800011); + console.log(TAG + `failed, errcode:${JSON.stringify(err)}.`); + expect().assertFail(); } + done(); + console.log(TAG + "************* RdbEncryptTest_0040 end *************"); + }) - await console.log(TAG + "************* RdbEncryptTest_0040 end *************") + /** + * @tc.name RdbEncryptTest_0041 + * @tc.number SUB_DDM_RDB_JS_RdbEncryptTest_0041 + * @tc.desc RDB Encrypt function test + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 1 + */ + it('RdbEncryptTest_0041', 0, async function (done) { + console.log(TAG + "************* RdbEncryptTest_0041 start *************"); + context = ability_featureAbility.getContext(); + await CreateRdbStore(context, STORE_CONFIG_WRONG); + try { + let rdbStore = await CreateRdbStore(context, STORE_CONFIG_ENCRYPT); + expect(rdbStore !== null).assertTrue(); + } catch (err) { + console.log(TAG + `failed, errcode:${JSON.stringify(err)}.`); + expect().assertFail(); + } + done(); + console.log(TAG + "************* RdbEncryptTest_0041 end *************"); }) /** @@ -297,10 +320,10 @@ describe('rdbEncryptTest', function () { let rdbStore2; // create 'rdbstore1' try { - rdbStore1 = await CreatRdbStore(context, STORE_CONFIG_ENCRYPT); + rdbStore1 = await CreateRdbStore(context, STORE_CONFIG_ENCRYPT); } catch (err) { expect().assertFail() - console.error(`CreatRdbStore1 failed, error code: ${err.code}, err message: ${err.message}`); + console.error(`CreateRdbStore1 failed, error code: ${err.code}, err message: ${err.message}`); } // query 'rdbstore1' @@ -315,10 +338,10 @@ describe('rdbEncryptTest', function () { // create 'rdbStore2' try { - rdbStore2 = await CreatRdbStore(context, STORE_CONFIG_ENCRYPT2) + rdbStore2 = await CreateRdbStore(context, STORE_CONFIG_ENCRYPT2) } catch (err) { expect().assertFail() - console.error(`CreatRdbStore2 failed, error code: ${err.code}, err message: ${err.message}`); + console.error(`CreateRdbStore2 failed, error code: ${err.code}, err message: ${err.message}`); } // create table and query 'rdbStore1' diff --git a/relational_store/test/native/rdb/unittest/rdb_double_write_test.cpp b/relational_store/test/native/rdb/unittest/rdb_double_write_test.cpp index ebabdbe9c80c7f2ff74992937ddd8c61cb98711c..3e02914e46417805e2ff3e3cda0485f306caabf7 100644 --- a/relational_store/test/native/rdb/unittest/rdb_double_write_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_double_write_test.cpp @@ -29,11 +29,11 @@ #include "rdb_errno.h" #include "rdb_helper.h" #include "rdb_open_callback.h" - + using namespace testing::ext; using namespace OHOS::NativeRdb; using namespace OHOS::Rdb; - + class RdbDoubleWriteTest : public testing::Test { public: static void SetUpTestCase(void); @@ -65,9 +65,9 @@ public: BACKUP_FINISHED, }; }; - -const std::string RdbDoubleWriteTest::DATABASE_NAME = RDB_TEST_PATH + "insert_test.db"; -const std::string RdbDoubleWriteTest::SLAVE_DATABASE_NAME = RDB_TEST_PATH + "insert_test_slave.db"; + +const std::string RdbDoubleWriteTest::DATABASE_NAME = RDB_TEST_PATH + "dual_write_test.db"; +const std::string RdbDoubleWriteTest::SLAVE_DATABASE_NAME = RDB_TEST_PATH + "dual_write_test_slave.db"; std::shared_ptr RdbDoubleWriteTest::store = nullptr; std::shared_ptr RdbDoubleWriteTest::slaveStore = nullptr; std::shared_ptr RdbDoubleWriteTest::store3 = nullptr; @@ -75,41 +75,41 @@ const int BLOB_SIZE = 3; const uint8_t EXPECTED_BLOB_DATA[] {1, 2, 3}; const int CHECKAGE = 18; const double CHECKCOLUMN = 100.5; - + class DoubleWriteTestOpenCallback : public RdbOpenCallback { public: int OnCreate(RdbStore &store) override; int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override; static const std::string CREATE_TABLE_TEST; }; - + const std::string DoubleWriteTestOpenCallback::CREATE_TABLE_TEST = std::string("CREATE TABLE IF NOT EXISTS test ") + std::string("(id INTEGER PRIMARY KEY AUTOINCREMENT, " "name TEXT NOT NULL, age INTEGER, salary " "REAL, blobType BLOB)"); - + int DoubleWriteTestOpenCallback::OnCreate(RdbStore &store) { return store.ExecuteSql(CREATE_TABLE_TEST); } - + int DoubleWriteTestOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) { return E_OK; } - + void RdbDoubleWriteTest::SetUpTestCase(void) { } - + void RdbDoubleWriteTest::TearDownTestCase(void) { } - + void RdbDoubleWriteTest::SetUp(void) { } - + void RdbDoubleWriteTest::TearDown(void) { store = nullptr; @@ -133,7 +133,7 @@ void RdbDoubleWriteTest::InitDb() store->ExecuteSql("DELETE FROM test"); slaveStore->ExecuteSql("DELETE FROM test"); } - + /** * @tc.name: RdbStore_DoubleWrite_001 * @tc.desc: test RdbStore doubleWrite @@ -144,7 +144,7 @@ HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_001, TestSize.Level1) InitDb(); int64_t id; ValuesBucket values; - + values.PutInt("id", 1); values.PutString("name", std::string("zhangsan")); values.PutInt("age", 18); @@ -153,7 +153,7 @@ HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_001, TestSize.Level1) int ret = store->Insert(id, "test", values); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); - + values.Clear(); values.PutInt("id", 2); values.PutString("name", std::string("lisi")); @@ -163,7 +163,7 @@ HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_001, TestSize.Level1) ret = store->Insert(id, "test", values); EXPECT_EQ(ret, E_OK); EXPECT_EQ(2, id); - + values.Clear(); values.PutInt("id", 3); values.PutString("name", std::string("lisi")); @@ -226,13 +226,13 @@ void RdbDoubleWriteTest::TryInterruptBackup() EXPECT_EQ(err, E_OK); LOG_INFO("----------interrupt backup---------"); } - + void RdbDoubleWriteTest::CheckResultSet(std::shared_ptr &store) { std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test WHERE name = ?", std::vector{ "zhangsan" }); EXPECT_NE(resultSet, nullptr); - + int columnIndex; int intVal; std::string strVal; @@ -241,13 +241,13 @@ void RdbDoubleWriteTest::CheckResultSet(std::shared_ptr &store) int ret = resultSet->GetRowIndex(position); EXPECT_EQ(ret, E_OK); EXPECT_EQ(position, -1); - + ret = resultSet->GetColumnType(0, columnType); EXPECT_EQ(ret, E_ROW_OUT_RANGE); - + ret = resultSet->GoToFirstRow(); EXPECT_EQ(ret, E_OK); - + ret = resultSet->GetColumnIndex("id", columnIndex); EXPECT_EQ(ret, E_OK); EXPECT_EQ(columnIndex, 0); @@ -257,7 +257,7 @@ void RdbDoubleWriteTest::CheckResultSet(std::shared_ptr &store) ret = resultSet->GetInt(columnIndex, intVal); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, intVal); - + ret = resultSet->GetColumnIndex("name", columnIndex); EXPECT_EQ(ret, E_OK); ret = resultSet->GetColumnType(columnIndex, columnType); @@ -266,21 +266,21 @@ void RdbDoubleWriteTest::CheckResultSet(std::shared_ptr &store) ret = resultSet->GetString(columnIndex, strVal); EXPECT_EQ(ret, E_OK); EXPECT_EQ("zhangsan", strVal); - + RdbDoubleWriteTest::CheckAge(resultSet); RdbDoubleWriteTest::CheckSalary(resultSet); RdbDoubleWriteTest::CheckBlob(resultSet); - + ret = resultSet->GoToNextRow(); EXPECT_EQ(ret, E_ROW_OUT_RANGE); - + ret = resultSet->GetColumnType(columnIndex, columnType); EXPECT_EQ(ret, E_ROW_OUT_RANGE); - + ret = resultSet->Close(); EXPECT_EQ(ret, E_OK); } - + void RdbDoubleWriteTest::CheckAge(std::shared_ptr &resultSet) { int columnIndex; @@ -295,7 +295,7 @@ void RdbDoubleWriteTest::CheckAge(std::shared_ptr &resultSet) EXPECT_EQ(ret, E_OK); EXPECT_EQ(CHECKAGE, intVal); } - + void RdbDoubleWriteTest::CheckSalary(std::shared_ptr &resultSet) { int columnIndex; @@ -310,7 +310,7 @@ void RdbDoubleWriteTest::CheckSalary(std::shared_ptr &resultSet) EXPECT_EQ(ret, E_OK); EXPECT_EQ(CHECKCOLUMN, dVal); } - + void RdbDoubleWriteTest::CheckBlob(std::shared_ptr &resultSet) { int columnIndex; @@ -328,7 +328,7 @@ void RdbDoubleWriteTest::CheckBlob(std::shared_ptr &resultSet) EXPECT_EQ(EXPECTED_BLOB_DATA[i], blob[i]); } } - + void RdbDoubleWriteTest::CheckNumber(std::shared_ptr &store, int num, int errCode, const std::string &tableName) { @@ -349,7 +349,7 @@ void RdbDoubleWriteTest::CheckNumber(std::shared_ptr &store, int num, HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_003, TestSize.Level1) { InitDb(); - + int64_t id; ValuesBucket values; values.PutInt("id", 1); @@ -361,10 +361,10 @@ HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_003, TestSize.Level1) EXPECT_EQ(ret, E_OK); auto [ret2, outValue2] = store->Execute("UPDATE test SET age= 18 WHERE id = 1"); EXPECT_EQ(E_OK, ret2); - + RdbDoubleWriteTest::CheckResultSet(slaveStore); } - + /** * @tc.name: RdbStore_DoubleWrite_004 * @tc.desc: test RdbStore updata @@ -373,9 +373,9 @@ HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_003, TestSize.Level1) HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_004, TestSize.Level1) { InitDb(); - + int64_t id; - + ValuesBucket values; values.PutInt("id", 1); values.PutString("name", std::string("zhangsan")); @@ -383,17 +383,17 @@ HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_004, TestSize.Level1) values.PutDouble("salary", 100.5); values.PutBlob("blobType", std::vector{ 1, 2, 3 }); int ret = store->Insert(id, "test", values); - + int changedRows; values.Clear(); values.PutInt("age", 18); ret = store->Update(changedRows, "test", values); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, changedRows); - + RdbDoubleWriteTest::CheckResultSet(slaveStore); } - + /** * @tc.name: RdbStore_DoubleWrite_005 * @tc.desc: test RdbStore delete @@ -402,7 +402,7 @@ HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_004, TestSize.Level1) HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_005, TestSize.Level1) { InitDb(); - + ValuesBucket values; int64_t id; values.PutInt("id", 1); @@ -413,7 +413,7 @@ HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_005, TestSize.Level1) int ret = store->Insert(id, "test", values); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); - + values.Clear(); values.PutInt("id", 2); values.PutString("name", std::string("lisi")); @@ -423,7 +423,7 @@ HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_005, TestSize.Level1) ret = store->Insert(id, "test", values); EXPECT_EQ(ret, E_OK); EXPECT_EQ(2, id); - + values.Clear(); values.PutInt("id", 3); values.PutString("name", std::string("lisi")); @@ -433,13 +433,13 @@ HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_005, TestSize.Level1) ret = store->Insert(id, "test", values); EXPECT_EQ(ret, E_OK); EXPECT_EQ(3, id); - + int deletedRows; ret = store->Delete(deletedRows, "test", "id = 2"); ret = store->Delete(deletedRows, "test", "id = 3"); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, deletedRows); - + RdbDoubleWriteTest::CheckNumber(slaveStore, 1); } @@ -1051,4 +1051,70 @@ HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_030, TestSize.Level1) RdbDoubleWriteTest::CheckNumber(store, count + 1); RdbDoubleWriteTest::CheckNumber(slaveStore, count); +} + +/** + * @tc.name: RdbStore_DoubleWrite_031 + * @tc.desc: open db, delete main.db, deleteRdbStore, check slave db + * @tc.type: FUNC + */ +HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_031, TestSize.Level1) +{ + InitDb(); + remove(RdbDoubleWriteTest::DATABASE_NAME.c_str()); + RdbHelper::DeleteRdbStore(RdbDoubleWriteTest::DATABASE_NAME); + EXPECT_NE(access(RdbDoubleWriteTest::SLAVE_DATABASE_NAME.c_str(), F_OK), 0); +} + +/** + * @tc.name: RdbStore_DoubleWrite_032 + * @tc.desc: open db, delete main.db, deleteRdbStore, check slave db + * @tc.type: FUNC + */ +HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_032, TestSize.Level1) +{ + InitDb(); + remove(RdbDoubleWriteTest::DATABASE_NAME.c_str()); + RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); + RdbHelper::DeleteRdbStore(config); + EXPECT_NE(access(RdbDoubleWriteTest::SLAVE_DATABASE_NAME.c_str(), F_OK), 0); +} + +/** + * @tc.name: RdbStore_DoubleWrite_033 + * @tc.desc: open db, write, close, corrupt, open SINGLE db, check + * @tc.type: FUNC + */ +HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_033, TestSize.Level1) +{ + InitDb(); + int64_t id = 10; + int count = 100; + Insert(id, count); + + store = nullptr; + slaveStore = nullptr; + + std::fstream file(DATABASE_NAME, std::ios::in | std::ios::out | std::ios::binary); + ASSERT_TRUE(file.is_open() == true); + file.seekp(30, std::ios::beg); + ASSERT_TRUE(file.good() == true); + char bytes[2] = {0x6, 0x6}; + file.write(bytes, 2); + ASSERT_TRUE(file.good() == true); + file.close(); + + int errCode = E_OK; + RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); + config.SetHaMode(HAMode::SINGLE); + DoubleWriteTestOpenCallback helper; + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_EQ(errCode, E_OK); + ASSERT_NE(store, nullptr); + + RebuiltType rebuiltType; + store->GetRebuilt(rebuiltType); + EXPECT_EQ(rebuiltType, RebuiltType::REPAIRED); + + RdbDoubleWriteTest::CheckNumber(store, count); } \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/rdb_encrypt_decrypt_test.cpp b/relational_store/test/native/rdb/unittest/rdb_encrypt_decrypt_test.cpp index d2faa3d007daa55ba978b867c5e9f41e8d56a964..a33ed90ac4acef1ea654e8f6644ef15873a26bc2 100644 --- a/relational_store/test/native/rdb/unittest/rdb_encrypt_decrypt_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_encrypt_decrypt_test.cpp @@ -337,6 +337,59 @@ HWTEST_F(RdbEncryptTest, RdbStore_Encrypt_009, TestSize.Level1) EXPECT_EQ(ret, E_OK); } +/** + * @tc.name: RdbStore_Encrypt_010 + * @tc.desc: test create encrypted Rdb and open in non encrypted mode ,then E_OK + * @tc.type: FUNC + */ +HWTEST_F(RdbEncryptTest, RdbStore_Encrypt_010, TestSize.Level1) +{ + RdbStoreConfig config(RdbEncryptTest::ENCRYPTED_DATABASE_NAME); + config.SetEncryptStatus(true); + config.SetBundleName("com.example.TestEncrypt10"); + + EncryptTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + EXPECT_EQ(errCode, E_OK); + + std::string keyPath = RDB_TEST_PATH + "key/encrypted.pub_key"; + int ret = access(keyPath.c_str(), F_OK); + EXPECT_EQ(ret, 0); + + config.SetEncryptStatus(false); + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + EXPECT_EQ(errCode, E_OK); +} + +/** + * @tc.name: RdbStore_Encrypt_011 + * @tc.desc: test create unencrypted Rdb and open in encrypted mode ,then E_OK + * @tc.type: FUNC + */ +HWTEST_F(RdbEncryptTest, RdbStore_Encrypt_011, TestSize.Level1) +{ + RdbStoreConfig config(RdbEncryptTest::UNENCRYPTED_DATABASE_NAME); + config.SetEncryptStatus(false); + config.SetBundleName("com.example.TestEncrypt11"); + EncryptTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + EXPECT_EQ(errCode, E_OK); + + std::string keyPath = RDB_TEST_PATH + "key/unencrypted.pub_key"; + int ret = access(keyPath.c_str(), F_OK); + EXPECT_EQ(ret, -1); + + config.SetEncryptStatus(true); + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + EXPECT_EQ(errCode, E_OK); +} + /** * @tc.name: RdbStore_RdbPassword_001 * @tc.desc: Abnomal test RdbStore RdbPassword class diff --git a/relational_store/test/native/rdb/unittest/rdb_execute_rd_test.cpp b/relational_store/test/native/rdb/unittest/rdb_execute_rd_test.cpp index 5d10b0f9ed98e792ddc1d8a9645b5e3c237d00ab..3339afb6e13ebdf534e5f4be5578ab70ff0e9bda 100644 --- a/relational_store/test/native/rdb/unittest/rdb_execute_rd_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_execute_rd_test.cpp @@ -34,11 +34,15 @@ public: static const std::string databaseName; static std::shared_ptr store; + static const std::string restoreDatabaseName; + static const std::string backupDatabaseName; }; INSTANTIATE_TEST_CASE_P(, RdbExecuteRdTest, testing::Values(false, true)); const std::string RdbExecuteRdTest::databaseName = RDB_TEST_PATH + "execute_test.db"; +const std::string RdbExecuteRdTest::restoreDatabaseName = RDB_TEST_PATH + "execute_test_restore.db"; +const std::string RdbExecuteRdTest::backupDatabaseName = RDB_TEST_PATH + "execute_test_backup.db"; std::shared_ptr RdbExecuteRdTest::store = nullptr; class ExecuteTestOpenRdCallback : public RdbOpenCallback { @@ -919,3 +923,71 @@ HWTEST_P(RdbExecuteRdTest, RdbStore_Execute_018, TestSize.Level1) EXPECT_EQ(store, nullptr); } } + +/* * + * @tc.name: Rdb_BackupRestoreTest_001 + * @tc.desc: backup and restore + * @tc.type: FUNC + */ +HWTEST_P(RdbExecuteRdTest, Rdb_BackupRestoreTest_001, TestSize.Level2) +{ + //create new db instance + int errCode = E_OK; + RdbStoreConfig config(RdbExecuteRdTest::restoreDatabaseName); + config.SetIsVector(true); + config.SetSecurityLevel(SecurityLevel::S4); + config.SetEncryptStatus(GetParam()); + if (GetParam()) { // check if encrypt + config.SetHaMode(HAMode::MAIN_REPLICA); + } + config.SetAllowRebuild(true); + ExecuteTestOpenRdCallback helper; + auto store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_EQ(errCode, E_OK); + EXPECT_NE(store, nullptr); + + std::string sqlCreateTable = "CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY, repr floatvector(8));"; + std::string sqlInsert = "INSERT INTO test VALUES(1, '[1.2, 0.3, 3.2, 1.6, 2.5, 3.1, 0.8, 0.4]');"; + std::string sqlQuery = "SELECT id FROM test order by repr <-> '[1.1, 0.3, 2.2, 6.6, 1.5, 3.1, 0.6, 0.2]' limit 3;"; + + std::pair res = {}; + res = store->Execute(sqlCreateTable.c_str(), {}); + EXPECT_EQ(res.first, E_OK); + res = store->Execute(sqlInsert.c_str(), {}); + EXPECT_EQ(res.first, E_OK); + + std::vector encryptKey; + if (GetParam()) { + encryptKey = config.GetEncryptKey(); + } + + int ret = store->Backup(RdbExecuteRdTest::backupDatabaseName, encryptKey); + EXPECT_EQ(ret, E_OK); + + res = store->Execute("delete from test where id = 1;"); + EXPECT_EQ(E_OK, res.first); + + ret = store->Restore(RdbExecuteRdTest::backupDatabaseName, encryptKey); + EXPECT_EQ(ret, E_OK); + + std::shared_ptr resultSet = store->QueryByStep(sqlQuery.c_str(), std::vector()); + + //check the result + EXPECT_NE(resultSet, nullptr); + EXPECT_EQ(resultSet->GoToNextRow(), E_OK); + std::vector colNames = {}; + resultSet->GetAllColumnNames(colNames); + EXPECT_EQ(colNames.size(), 1); + int columnIndex = 0; + int intVal = 0; + resultSet->GetColumnIndex("id", columnIndex); + resultSet->GetInt(columnIndex, intVal); + EXPECT_EQ(columnIndex, 0); + EXPECT_EQ(intVal, 1); + EXPECT_EQ(E_OK, resultSet->Close()); + res = store->Execute("DROP TABLE test;"); + EXPECT_EQ(E_OK, res.first); + + RdbHelper::DeleteRdbStore(RdbExecuteRdTest::restoreDatabaseName); + RdbHelper::DeleteRdbStore(RdbExecuteRdTest::backupDatabaseName); +} \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/rdb_helper_test.cpp b/relational_store/test/native/rdb/unittest/rdb_helper_test.cpp index f5f79624abedcc2478f7347f1ff6675480310cb9..ac7b09da431ecb0e08283f3731a16e4fb6ca769d 100644 --- a/relational_store/test/native/rdb/unittest/rdb_helper_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_helper_test.cpp @@ -146,6 +146,52 @@ HWTEST_F(RdbHelperTest, DeleteDatabase_001, TestSize.Level1) EXPECT_EQ(ret3, E_INVALID_FILE_PATH); } +/** + * @tc.name: DeleteDatabase_002 + * @tc.desc: DeleteRdbStore if the dbFile is not exists + * @tc.type: FUNC + */ +HWTEST_F(RdbHelperTest, DeleteDatabase_002, TestSize.Level1) +{ + int errCode = E_OK; + RdbStoreConfig config(RdbHelperTest::rdbStorePath); + RdbHelperTestOpenCallback helper; + std::shared_ptr rdbStore = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(rdbStore, nullptr); + + remove(rdbStorePath.c_str()); + + int ret = RdbHelper::DeleteRdbStore("rdbhelper.db"); + EXPECT_EQ(ret, E_OK); + std::string shmFileName = rdbStorePath + "-shm"; + std::string walFileName = rdbStorePath + "-wal"; + EXPECT_NE(access(shmFileName.c_str(), F_OK), 0); + EXPECT_NE(access(walFileName.c_str(), F_OK), 0); +} + +/** + * @tc.name: DeleteDatabase_003 + * @tc.desc: DeleteRdbStore if the dbFile is not exists + * @tc.type: FUNC + */ +HWTEST_F(RdbHelperTest, DeleteDatabase_003, TestSize.Level1) +{ + int errCode = E_OK; + RdbStoreConfig config(RdbHelperTest::rdbStorePath); + RdbHelperTestOpenCallback helper; + std::shared_ptr rdbStore = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(rdbStore, nullptr); + + remove(rdbStorePath.c_str()); + + int ret = RdbHelper::DeleteRdbStore(config); + EXPECT_EQ(ret, E_OK); + std::string shmFileName = rdbStorePath + "-shm"; + std::string walFileName = rdbStorePath + "-wal"; + EXPECT_NE(access(shmFileName.c_str(), F_OK), 0); + EXPECT_NE(access(walFileName.c_str(), F_OK), 0); +} + /** * @tc.name: getrdbstore_001 * @tc.desc: get db file with a invalid path @@ -167,7 +213,6 @@ HWTEST_F(RdbHelperTest, GetDatabase_002, TestSize.Level0) RdbStoreConfig config(dbPath); std::string bundleName = "com.ohos.config.GetDatabase"; config.SetBundleName(bundleName); - config.SetSecurityLevel(SecurityLevel::S1); config.SetArea(1); config.SetEncryptStatus(true); @@ -193,7 +238,6 @@ HWTEST_F(RdbHelperTest, GetDatabase_003, TestSize.Level0) RdbStoreConfig config(dbPath); std::string bundleName = "com.ohos.config.GetDatabase"; config.SetBundleName(bundleName); - config.SetSecurityLevel(SecurityLevel::S1); config.SetArea(1); config.SetEncryptStatus(true); @@ -206,7 +250,7 @@ HWTEST_F(RdbHelperTest, GetDatabase_003, TestSize.Level0) EXPECT_EQ(errCode, E_OK); EXPECT_NE(rdbStore1, nullptr); - config.SetSecurityLevel(SecurityLevel::S2); + config.SetEncryptStatus(false); std::shared_ptr rdbStore2 = RdbHelper::GetRdbStore(config, 1, helper, errCode); EXPECT_EQ(errCode, E_OK); EXPECT_NE(rdbStore2, nullptr); diff --git a/relational_store/test/native/rdb/unittest/rdb_read_only_test.cpp b/relational_store/test/native/rdb/unittest/rdb_read_only_test.cpp index 7405b66556a6359a08c5b72dcb4fec379e364552..e16d009a1ef1fcae05907b1d45fa38a291476114 100644 --- a/relational_store/test/native/rdb/unittest/rdb_read_only_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_read_only_test.cpp @@ -24,7 +24,7 @@ #include "rdb_open_callback.h" using namespace testing::ext; using namespace OHOS::NativeRdb; - +namespace Test { class RdbReadOnlyTest : public testing::Test { public: static void SetUpTestCase(void); @@ -507,3 +507,25 @@ HWTEST_F(RdbReadOnlyTest, RdbStore_ReadOnly_0022, TestSize.Level1) auto ret = store->CleanDirtyData("test", cursor); EXPECT_EQ(E_NOT_SUPPORT, ret); } + +/** + * @tc.name: RdbStore_CreateTransaction_001 + * @tc.desc: test Create Transaction + * @tc.type: FUNC + */ +HWTEST_F(RdbReadOnlyTest, RdbStore_CreateTransaction_001, TestSize.Level1) +{ + std::shared_ptr &store = RdbReadOnlyTest::readOnlyStore; + auto [errCode, trans] = store->CreateTransaction(Transaction::DEFERRED); + EXPECT_EQ(E_NOT_SUPPORT, errCode); + EXPECT_EQ(trans, nullptr); + + std::tie(errCode, trans) = store->CreateTransaction(Transaction::IMMEDIATE); + EXPECT_EQ(E_NOT_SUPPORT, errCode); + EXPECT_EQ(trans, nullptr); + + std::tie(errCode, trans) = store->CreateTransaction(Transaction::EXCLUSIVE); + EXPECT_EQ(E_NOT_SUPPORT, errCode); + EXPECT_EQ(trans, nullptr); +} +} \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/rdb_store_config_test.cpp b/relational_store/test/native/rdb/unittest/rdb_store_config_test.cpp index d7f593e416af0a3cc23ab52f334b70ea94b34681..154c88952ee34c12b15bf54b570d03260e0de7e2 100644 --- a/relational_store/test/native/rdb/unittest/rdb_store_config_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_store_config_test.cpp @@ -918,7 +918,7 @@ HWTEST_F(RdbStoreConfigTest, RdbStoreConfig_029, TestSize.Level1) std::string bundleName = "com.ohos.config.test30"; config.SetBundleName(bundleName); - config.SetSecurityLevel(SecurityLevel::S1); + config.SetSecurityLevel(SecurityLevel::S2); config.SetArea(0); config.SetEncryptStatus(false); @@ -931,10 +931,10 @@ HWTEST_F(RdbStoreConfigTest, RdbStoreConfig_029, TestSize.Level1) store = nullptr; auto invalidConfig = config; - invalidConfig.SetSecurityLevel(SecurityLevel::S2); + invalidConfig.SetSecurityLevel(SecurityLevel::S1); store = RdbHelper::GetRdbStore(invalidConfig, 1, helper, errCode); - EXPECT_EQ(errCode, E_OK); - EXPECT_NE(store, nullptr); + EXPECT_EQ(errCode, E_CONFIG_INVALID_CHANGE); + EXPECT_EQ(store, nullptr); store = nullptr; RdbHelper::DeleteRdbStore(dbPath); @@ -1009,6 +1009,38 @@ HWTEST_F(RdbStoreConfigTest, RdbStoreConfig_032, TestSize.Level1) EXPECT_EQ(300, config.GetWriteTime()); } +/** + * @tc.name: RdbStoreConfig_033 + * @tc.desc: test RdbStoreConfig SetSecurityLevel S2->S1 + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreConfigTest, RdbStoreConfig_033, TestSize.Level1) +{ + const std::string dbPath = RDB_TEST_PATH + "config_test_33.db"; + RdbStoreConfig config(dbPath); + + std::string bundleName = "com.ohos.config.test33"; + config.SetBundleName(bundleName); + config.SetSecurityLevel(SecurityLevel::S2); + + ConfigTestOpenCallback helper; + int errCode = E_ERROR; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_EQ(errCode, E_OK); + EXPECT_NE(store, nullptr); + + store = nullptr; + + auto invalidConfig = config; + invalidConfig.SetSecurityLevel(SecurityLevel::S1); + store = RdbHelper::GetRdbStore(invalidConfig, 1, helper, errCode); + EXPECT_EQ(errCode, E_CONFIG_INVALID_CHANGE); + EXPECT_EQ(store, nullptr); + store = nullptr; + + RdbHelper::DeleteRdbStore(dbPath); +} + /** * @tc.name: RdbStoreConfigVisitor_001 * @tc.desc: test RdbStoreConfigVisitor diff --git a/relational_store/test/native/rdb/unittest/rdb_store_rekey_test.cpp b/relational_store/test/native/rdb/unittest/rdb_store_rekey_test.cpp index 0e736b2a890694810ce9bb6aa0c1879d6b5d381f..4840be058e0309eac06bbc26d05b6fcbfaa470ce 100644 --- a/relational_store/test/native/rdb/unittest/rdb_store_rekey_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_store_rekey_test.cpp @@ -14,6 +14,9 @@ */ #include +#include +#include +#include #include #include @@ -441,4 +444,50 @@ HWTEST_F(RdbRekeyTest, Rdb_Rekey_06, TestSize.Level1) ASSERT_TRUE(std::chrono::system_clock::now() - changedDate > std::chrono::hours(RdbRekeyTest::HOURS_EXPIRED)); CheckQueryData(store); +} + +/** +* @tc.name: Rdb_Delete_Rekey_Test_07 +* @tc.desc: test deleting the key file of the encrypted database +* @tc.type: FUNC +*/ +HWTEST_F(RdbRekeyTest, Rdb_Rekey_07, TestSize.Level1) +{ + RdbStoreConfig config(RdbRekeyTest::encryptedDatabasePath); + config.SetSecurityLevel(SecurityLevel::S1); + config.SetAllowRebuild(true); + config.SetEncryptStatus(true); + config.SetBundleName("com.example.test_rekey"); + RekeyTestOpenCallback helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + ASSERT_EQ(errCode, E_OK); + + std::string keyPath = encryptedDatabaseKeyDir + RemoveSuffix(encryptedDatabaseName) + ".pub_key"; + bool isFileExists = OHOS::FileExists(keyPath); + ASSERT_TRUE(isFileExists); + struct stat fileStat; + ino_t inodeNumber1 = -1; + if (stat(keyPath.c_str(), &fileStat) == 0) { + inodeNumber1 = fileStat.st_ino; + } + store = nullptr; + + { + std::ofstream fsDb(encryptedDatabasePath, std::ios_base::binary | std::ios_base::out); + fsDb.seekp(64); + fsDb.write("hello", 5); + fsDb.close(); + } + + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + isFileExists = OHOS::FileExists(keyPath); + ASSERT_TRUE(isFileExists); + ino_t inodeNumber2 = -1; + if (stat(keyPath.c_str(), &fileStat) == 0) { + inodeNumber2 = fileStat.st_ino; + } + + ASSERT_NE(inodeNumber1, inodeNumber2); } \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/data/preset_type_descriptors.cpp b/udmf/framework/innerkitsimpl/data/preset_type_descriptors.cpp index 7c9006be205f085ad2bcd4000276d107eb3e5663..d948cba1c7dbe616d5346c8cf120ab5c237c7cf5 100644 --- a/udmf/framework/innerkitsimpl/data/preset_type_descriptors.cpp +++ b/udmf/framework/innerkitsimpl/data/preset_type_descriptors.cpp @@ -20,6 +20,7 @@ constexpr const char *REFERENCE_URL = "https://gitee.com/openharmony/docs/blob/m PresetTypeDescriptors::PresetTypeDescriptors() { + InitDescriptors(); } PresetTypeDescriptors::~PresetTypeDescriptors() @@ -36,3256 +37,3258 @@ std::vector &PresetTypeDescriptors::GetPresetTypes() { return typeDescriptors_; } - -std::vector PresetTypeDescriptors::typeDescriptors_ = { - {"general.entity", - {}, - {}, - {}, - "Base type for physical hierarchy.", - REFERENCE_URL, - ""}, - {"general.object", - {}, - {}, - {"*/*"}, - "Base type for logical hierarchy.", - REFERENCE_URL, - ""}, - {"general.composite-object", - {"general.object"}, - {}, - {}, - "Base type for mixed object. For example, a PDF file contains both text and special formatting data.", - REFERENCE_URL, - ""}, - {"general.text", - {"general.object"}, - {}, - {"text/*"}, - "Base type for all text.", - REFERENCE_URL, - ""}, - {"general.plain-text", - {"general.text"}, - {".txt", ".text"}, - {"text/plain"}, - "Text of unspecified encoding, with no markup.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_txt"}, - {"general.html", - {"general.text"}, - {".html", ".htm"}, - {"text/html"}, - "HTML text.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_html"}, - {"general.hyperlink", - {"general.text"}, - {}, - {}, - "Hyperlink.", - REFERENCE_URL, - ""}, - {"general.xml", - {"general.text"}, - {".xml"}, - {"text/xml"}, - "XML text.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_xml"}, - {"com.real.smil", - {"general.xml"}, - {".smil"}, - {"application/smil"}, - "Real synchronized multimedia integration language.", - REFERENCE_URL, - ""}, - {"general.source-code", - {"general.text"}, - {}, - {}, - "Generic source code.", - REFERENCE_URL, - ""}, - {"general.script", - {"general.source-code"}, - {}, - {}, - "Base type for scripting language source code.", - REFERENCE_URL, - ""}, - {"general.shell-script", - {"general.script"}, - {".sh", ".command"}, - {"text/x-shellscript"}, - "Shell script.", - REFERENCE_URL, - ""}, - {"general.csh-script", - {"general.shell-script"}, - {".csh"}, - {"text/x-csh"}, - "C-shell script.", - REFERENCE_URL, - ""}, - {"general.perl-script", - {"general.shell-script"}, - {".pl", ".pm"}, - {"text/x-perl-script"}, - "Perl script.", - REFERENCE_URL, - ""}, - {"general.php-script", - {"general.shell-script"}, - {".php", ".php3", ".php4", ".ph3", ".ph4", ".phtml"}, - {"text/x-php-script", "text/php", "application/php"}, - "PHP script.", - REFERENCE_URL, - ""}, - {"general.python-script", - {"general.shell-script"}, - {".py"}, - {"text/x-python-script"}, - "Python script.", - REFERENCE_URL, - ""}, - {"general.ruby-script", - {"general.shell-script"}, - {".rb", ".rbw"}, - {"text/ruby-script"}, - "Ruby script.", - REFERENCE_URL, - ""}, - {"general.type-script", - {"general.source-code"}, - {".ts"}, - {}, - "TypeScript source code.", - REFERENCE_URL, - ""}, - {"general.java-script", - {"general.source-code"}, - {".js", ".jscript", ".javascript"}, - {"text/javascript"}, - "JavaScript source code.", - REFERENCE_URL, - ""}, - {"general.c-header", - {"general.source-code"}, - {".h"}, - {"text/x-chdr"}, - "C header file.", - REFERENCE_URL, - ""}, - {"general.c-source", - {"general.source-code"}, - {".c"}, - {"text/x-csrc"}, - "C source code.", - REFERENCE_URL, - ""}, - {"general.c-plus-plus-header", - {"general.source-code"}, - {".hpp", ".h++", ".hxx", ".hh"}, - {"text/x-c++hdr"}, - "C++ header file.", - REFERENCE_URL, - ""}, - {"general.c-plus-plus-source", - {"general.source-code"}, - {".cp", ".cpp", ".c++", ".cc", ".cxx"}, - {"text/x-c++src"}, - "C++ source code.", - REFERENCE_URL, - ""}, - {"general.java-source", - {"general.source-code"}, - {".java", ".jav"}, - {"text/x-java"}, - "Java source code.", - REFERENCE_URL, - ""}, - {"general.markdown", - {"general.text"}, - {".md", ".markdown", ".markdn", ".mdown"}, - {"text/markdown"}, - "Markdown format.", - REFERENCE_URL, - ""}, - {"general.ebook", - {"general.composite-object"}, - {}, - {}, - "Base type for ebook.", - REFERENCE_URL, - ""}, - {"general.epub", - {"general.ebook"}, - {".epub"}, - {"application/epub+zip"}, - "Electronic publication (EPUB) format.", - REFERENCE_URL, - ""}, - {"com.amazon.azw", - {"general.ebook"}, - {".azw"}, - {"application/vnd.amazon.ebook"}, - "AZW ebook.", - REFERENCE_URL, - ""}, - {"com.amazon.azw3", - {"general.ebook"}, - {".azw3"}, - {"application/vnd.amazon.mobi8-ebook", "application/x-mobi8-ebook"}, - "AZW3 ebook.", - REFERENCE_URL, - ""}, - {"com.amazon.kfx", - {"general.ebook"}, - {".kfx"}, - {}, - "KFX ebook.", - REFERENCE_URL, - ""}, - {"com.amazon.mobi", - {"general.ebook"}, - {".mobi"}, - {"application/x-mobipocket-ebook"}, - "MOBI ebook.", - REFERENCE_URL, - ""}, - {"general.media", - {"general.object"}, - {}, - {}, - "Base type for media.", - REFERENCE_URL, - ""}, - {"general.image", - {"general.media"}, - {}, - {"image/*"}, - "Base type for images.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_image"}, - {"general.jpeg", - {"general.image"}, - {".jpg", ".jpeg", ".jpe"}, - {"image/jpeg"}, - "JPEG image.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_image"}, - {"general.png", - {"general.image"}, - {".png"}, - {"image/png"}, - "PNG image.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_image"}, - {"general.raw-image", - {"general.image"}, - {}, - {}, - "Base type for digital camera raw image formats.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_image"}, - {"general.tiff", - {"general.image"}, - {".tif", ".tiff"}, - {"image/tiff"}, - "TIFF image.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_image"}, - {"com.microsoft.bmp", - {"general.image"}, - {".bmp"}, - {"image/bmp", "image/x-ms-bmp"}, - "Windows bitmap image.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_image"}, - {"com.microsoft.ico", - {"general.image"}, - {".ico"}, - {"image/ico", "image/x-icon"}, - "Windows icon image.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_image"}, - {"com.adobe.photoshop-image", - {"general.image"}, - {".psd"}, - {"image/x-photoshop", "image/photoshop", "image/psd", "application/photoshop"}, - "Adobe Photoshop document.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_image"}, - {"com.adobe.illustrator.ai-image", - {"general.image"}, - {".ai"}, - {}, - "Adobe Illustrator document.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_image"}, - {"general.fax", - {"general.image"}, - {}, - {}, - "Base type for fax images.", - REFERENCE_URL, - ""}, - {"com.j2.jfx-fax", - {"general.fax"}, - {".jfx"}, - {}, - "J2 fax.", - REFERENCE_URL, - ""}, - {"com.js.efx-fax", - {"general.fax"}, - {".efx"}, - {"image/efax"}, - "eFax fax.", - REFERENCE_URL, - ""}, - {"general.xbitmap-image", - {"general.image"}, - {".xbm"}, - {"image/x-xbitmap", "image/x-xbm"}, - "X bitmap image.", - REFERENCE_URL, - ""}, - {"com.truevision.tga-image", - {"general.image"}, - {".tga"}, - {"image/targa", "image/tga", "application/tga"}, - "TGA image.", - REFERENCE_URL, - ""}, - {"com.sgi.sgi-image", - {"general.image"}, - {".sgi"}, - {"image/sgi"}, - "Silicon Graphics image.", - REFERENCE_URL, - ""}, - {"com.ilm.openexr-image", - {"general.image"}, - {".exr"}, - {}, - "OpenEXR image.", - REFERENCE_URL, - ""}, - {"com.kodak.flashpix.image", - {"general.image"}, - {".fpx"}, - {"image/fpx", "application/vnd.fpx"}, - "FlashPix image.", - REFERENCE_URL, - ""}, - {"com.microsoft.word.doc", - {"general.composite-object"}, - {".doc"}, - {"application/msword"}, - "Microsoft Word data.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_doc"}, - {"com.microsoft.excel.xls", - {"general.composite-object"}, - {".xls"}, - {"application/vnd.ms-excel"}, - "Microsoft Excel data.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_xls"}, - {"com.microsoft.powerpoint.ppt", - {"general.composite-object"}, - {".ppt"}, - {"application/vnd.ms-powerpoint"}, - "Microsoft PowerPoint presentation.", - REFERENCE_URL, - ""}, - {"com.adobe.pdf", - {"general.composite-object"}, - {".pdf"}, - {"application/pdf"}, - "PDF data.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_pdf"}, - {"com.adobe.postscript", - {"general.composite-object"}, - {".ps"}, - {"application/postscript"}, - "PostScript data.", - REFERENCE_URL, - ""}, - {"com.adobe.encapsulated-postscript", - {"com.adobe.postscript"}, - {".eps"}, - {}, - "Encapsulated PostScript.", - REFERENCE_URL, - ""}, - {"general.video", - {"general.media"}, - {}, - {"video/*"}, - "Base type for video.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_video"}, - {"general.avi", - {"general.video"}, - {".avi", ".vfw"}, - {"video/avi", "video/msvideo", "video/x-msvideo"}, - "AVI video.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_video"}, - {"general.mpeg", - {"general.video"}, - {".mpg", ".mpeg", ".m75", ".m15", ".mpe"}, - {"video/mpg", "video/mpeg", "video/x-mpg", "video/x-mpeg"}, - "MPEG-1 or MPEG-2 video.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_video"}, - {"general.mpeg-4", - {"general.video"}, - {".mp4", ".mp4v", ".mpeg4"}, - {"video/mp4", "video/mp4v"}, - "MPEG-4 video.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_video"}, - {"general.3gpp", - {"general.video"}, - {".3gp", ".3gpp"}, - {"video/3gpp"}, - "3GPP video.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_video"}, - {"general.3gpp2", - {"general.video"}, - {".3g2", ".3gp2", ".3gpp2"}, - {"video/3gpp2"}, - "3GPP2 video.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_video"}, - {"com.microsoft.windows-media-wm", - {"general.video", "com.microsoft.advanced-systems-format"}, - {".wm"}, - {"video/x-ms-wm"}, - "Windows WM video.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_video"}, - {"com.microsoft.windows-media-wmv", - {"general.video", "com.microsoft.advanced-systems-format"}, - {".wmv"}, - {"video/x-ms-wmv"}, - "Windows WMV video.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_video"}, - {"com.microsoft.windows-media-wmp", - {"general.video", "com.microsoft.advanced-systems-format"}, - {".wmp"}, - {"video/x-ms-wmp"}, - "Windows WMP video.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_video"}, - {"com.microsoft.windows-media-wvx", - {"general.video", "com.microsoft.advanced-systems-format"}, - {".wvx"}, - {"video/x-ms-wvx"}, - "Windows WVX video.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_video"}, - {"com.microsoft.windows-media-wmx", - {"general.video", "com.microsoft.advanced-systems-format"}, - {".wmx"}, - {"video/x-ms-wmx"}, - "Windows WMX video.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_video"}, - {"com.real.realmedia", - {"general.video"}, - {".rm"}, - {"application/vnd.rn-realmedia"}, - "RealMedia.", - REFERENCE_URL, - ""}, - {"general.audio", - {"general.media"}, - {}, - {"audio/*"}, - "Base type for audio.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_audio"}, - {"general.aac", - {"general.audio"}, - {".aac"}, - {"audio/aac"}, - "AAC audio.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_audio"}, - {"general.aiff", - {"general.audio"}, - {".aiff"}, - {"audio/aiff"}, - "AIFF audio.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_audio"}, - {"general.alac", - {"general.audio"}, - {".alac"}, - {"audio/alac"}, - "ALAC audio.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_audio"}, - {"general.flac", - {"general.audio"}, - {".flac"}, - {"audio/flac"}, - "FLAC audio.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_flac"}, - {"general.mp3", - {"general.audio"}, - {".mp3"}, - {"audio/mp3"}, - "MPEG-3 audio.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_mp3"}, - {"general.ogg", - {"general.audio"}, - {".ogg"}, - {"audio/ogg"}, - "OGG audio.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_audio"}, - {"general.pcm", - {"general.audio"}, - {".pcm"}, - {"audio/pcm"}, - "PCM audio.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_audio"}, - {"com.microsoft.advanced-systems-format", - {"general.media"}, - {".asf"}, - {"video/x-ms-asf", "application/vnd.ms-asf"}, - "Advanced Systems format", - REFERENCE_URL, - ""}, - {"com.microsoft.advanced-stream-redirector", - {"general.video"}, - {".asx"}, - {"video/x-ms-asf"}, - "Advanced stream redirector", - REFERENCE_URL, - ""}, - {"com.microsoft.windows-media-wma", - {"general.audio", "com.microsoft.advanced-systems-format"}, - {".wma"}, - {"audio/x-ms-wma"}, - "Windows WMA audio.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_wma"}, - {"com.microsoft.waveform-audio", - {"general.audio", "com.microsoft.advanced-systems-format"}, - {".wav", ".wave"}, - {"audio/wav", "audio/wave", "audio/x-wav"}, - "Waveform audio.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_wav"}, - {"com.microsoft.windows-media-wax", - {"general.audio", "com.microsoft.advanced-systems-format"}, - {".wax"}, - {"audio/x-ms-wax"}, - "Windows WAX audio.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_audio"}, - {"general.au-audio", - {"general.audio"}, - {".au", ".snd"}, - {"audio/basic", "audio/au", "audio/snd"}, - "Au file format.", - REFERENCE_URL, - ""}, - {"general.aifc-audio", - {"general.audio"}, - {".aifc", ".aif", ".aiff"}, - {"audio/x-aiff"}, - "Audio Interchange File Format.", - REFERENCE_URL, - ""}, - {"com.digidesign.sd2-audio", - {"general.audio"}, - {".sd2"}, - {"audio/x-sd2"}, - "Digidesign Sound Designer II audio.", - REFERENCE_URL, - ""}, - {"com.real.realaudio", - {"general.audio"}, - {".ram", ".ra"}, - {"audio/vnd.rn-realaudio", "audio/x-pn-realaudio"}, - "RealMedia audio.", - REFERENCE_URL, - ""}, - {"general.file", - {"general.entity"}, - {}, - {}, - "Base type for file.", - REFERENCE_URL, - ""}, - {"general.directory", - {"general.entity"}, - {}, - {}, - "Base type for directory.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_folder"}, - {"general.folder", - {"general.directory"}, - {}, - {}, - "Base type for folder.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_folder"}, - {"general.symlink", - {"general.entity"}, - {}, - {}, - "Base type for symlink.", - REFERENCE_URL, - ""}, - {"general.archive", - {"general.object"}, - {}, - {}, - "Base type for an archive of files and directories.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_compress"}, - {"general.bz2-archive", - {"general.archive"}, - {".bz2", ".bzip2"}, - {"application/x-bzip2"}, - "BZip2 archive.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_compress"}, - {"general.disk-image", - {"general.archive"}, - {}, - {}, - "Base type for items mountable as a volume.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_compress"}, - {"general.tar-archive", - {"general.archive"}, - {".tar"}, - {"application/x-tar", "application/tar"}, - "Tar archive.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_compress"}, - {"general.zip-archive", - {"general.archive"}, - {".zip"}, - {"application/zip"}, - "Zip archive.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_zip"}, - {"com.sun.java-archive", - {"general.archive", "general.executable"}, - {".jar"}, - {"application/java-archive"}, - "Java archive.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_compress"}, - {"org.gnu.gnu-tar-archive", - {"general.archive"}, - {".gtar"}, - {"application/x-gtar"}, - "GNU archive.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_compress"}, - {"org.gnu.gnu-zip-archive", - {"general.archive"}, - {".gz", ".gzip"}, - {"application/x-gzip", "application/gzip"}, - "Gzip archive.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_compress"}, - {"org.gnu.gnu-zip-tar-archive", - {"general.archive"}, - {".tgz"}, - {"application/x-gtar"}, - "Gzip tar archive.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_compress"}, - {"org.openxmlformats.openxml", - {"general.archive"}, - {}, - {}, - "Office Open XML.", - REFERENCE_URL, - ""}, - {"org.openxmlformats.wordprocessingml.document", - {"general.composite-object", "org.openxmlformats.openxml"}, - {".docx"}, - {"application/vnd.openxmlformats-officedocument.wordprocessingml.document"}, - "Office Open XML Document.", - REFERENCE_URL, - ""}, - {"org.openxmlformats.spreadsheetml.sheet", - {"general.composite-object", "org.openxmlformats.openxml"}, - {".xlsx"}, - {"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"}, - "Office Open XML Workbook.", - REFERENCE_URL, - ""}, - {"org.openxmlformats.presentationml.presentation", - {"general.composite-object", "org.openxmlformats.openxml"}, - {".pptx"}, - {"application/vnd.openxmlformats-officedocument.presentationml.presentation"}, - "Office Open XML Presentation.", - REFERENCE_URL, - ""}, - {"org.oasis.opendocument", - {"general.archive"}, - {}, - {}, - "Open Document Format for Office Applications.", - REFERENCE_URL, - ""}, - {"org.oasis.opendocument.text", - {"general.composite-object", "org.oasis.opendocument"}, - {".odt", ".fodt"}, - {"application/vnd.oasis.opendocument.text"}, - "OpenDocument Text.", - REFERENCE_URL, - ""}, - {"org.oasis.opendocument.spreadsheet", - {"general.composite-object", "org.oasis.opendocument"}, - {".ods", ".fods"}, - {"application/vnd.oasis.opendocument.spreadsheet"}, - "OpenDocument Spreadsheet.", - REFERENCE_URL, - ""}, - {"org.oasis.opendocument.presentation", - {"general.composite-object", "org.oasis.opendocument"}, - {".odp", ".fodp"}, - {"application/vnd.oasis.opendocument.presentation"}, - "OpenDocument Presentation.", - REFERENCE_URL, - ""}, - {"org.oasis.opendocument.graphics", - {"general.composite-object", "org.oasis.opendocument"}, - {".odg", ".fodg"}, - {"application/vnd.oasis.opendocument.graphics"}, - "OpenDocument Graphics.", - REFERENCE_URL, - ""}, - {"org.oasis.opendocument.formula", - {"org.oasis.opendocument"}, - {".odf"}, - {"application/vnd.oasis.opendocument.formula"}, - "OpenDocument Formulat.", - REFERENCE_URL, - ""}, - {"com.allume.stuffit-archive", - {"general.archive"}, - {".sit", ".sitx"}, - {"application/x-stuffit", "application/x-sit", "application/stuffit"}, - "Stuffit archive.", - REFERENCE_URL, - ""}, - {"general.calendar", - {"general.text"}, - {}, - {"text/calendar"}, - "Base type for scheduled events.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_calendar"}, - {"general.vcs", - {"general.calendar"}, - {".vcs"}, - {"text/calendar"}, - "vCalendar type.", - REFERENCE_URL, - ""}, - {"general.ics", - {"general.calendar"}, - {".ics"}, - {"text/calendar"}, - "iCalendar type.", - REFERENCE_URL, - ""}, - {"general.contact", - {"general.object"}, - {}, - {}, - "Base type for contact information.", - REFERENCE_URL, - ""}, - {"general.database", - {"general.object"}, - {}, - {}, - "Base type for databases.", - REFERENCE_URL, - ""}, - {"general.message", - {"general.object"}, - {}, - {}, - "Base type for messages.", - REFERENCE_URL, - ""}, - {"general.executable", - {"general.object"}, - {}, - {}, - "Base type for executable data.", - REFERENCE_URL, - ""}, - {"com.microsoft.portable-executable", - {"general.executable"}, - {".exe", ".dll"}, - {"application/vnd.microsoft.portable-executable"}, - "Microsoft Windows application.", - REFERENCE_URL, - ""}, - {"com.sun.java-class", - {"general.executable"}, - {".class"}, - {}, - "Java class.", - REFERENCE_URL, - ""}, - {"general.vcard", - {"general.object"}, - {".vcf", ".vcard"}, - {"text/vcard", "text/x-vcard"}, - "Base type for electronic business card.", - REFERENCE_URL, - ""}, - {"general.navigation", - {"general.object"}, - {}, - {}, - "Base type for navigation.", - REFERENCE_URL, - ""}, - {"general.location", - {"general.navigation"}, - {}, - {}, - "Navigation location.", - REFERENCE_URL, - ""}, - {"general.font", - {"general.object"}, - {}, - {}, - "Base type for fonts.", - REFERENCE_URL, - ""}, - {"general.truetype-font", - {"general.font"}, - {".ttf"}, - {"font/ttf"}, - "TrueType font.", - REFERENCE_URL, - ""}, - {"general.truetype-collection-font", - {"general.font"}, - {".ttc"}, - {"font/collection"}, - "TrueType collection font.", - REFERENCE_URL, - ""}, - {"general.opentype-font", - {"general.font"}, - {".otf"}, - {"font/otf"}, - "OpenType font.", - REFERENCE_URL, - ""}, - {"com.adobe.postscript-font", - {"general.font"}, - {}, - {}, - "PostScript font.", - REFERENCE_URL, - ""}, - {"openharmony.form", - {"general.object"}, - {}, - {}, - "OpenHarmony system defined form.", - REFERENCE_URL, - ""}, - {"openharmony.app-item", - {"general.object"}, - {}, - {}, - "OpenHarmony system defined app item.", - REFERENCE_URL, - ""}, - {"openharmony.pixel-map", - {"general.image"}, - {}, - {}, - "OpenHarmony system defined pixel map.", - REFERENCE_URL, - "sys.media.ohos_ic_normal_white_grid_image"}, - {"openharmony.atomic-service", - {"general.object"}, - {}, - {}, - "OpenHarmony system defined atomic service.", - REFERENCE_URL, - ""}, - {"openharmony.package", - {"general.directory"}, - {}, - {}, - "OpenHarmony system defined package (that is, a directory presented to the user as a file).", - REFERENCE_URL, - ""}, - {"openharmony.hap", - {"openharmony.package"}, - {".hap"}, - {}, - "OpenHarmony system defined ability package.", - REFERENCE_URL, - ""}, - {"openharmony.hdoc", - {"general.composite-object"}, - {".hdoc"}, - {}, - "OpenHarmony system AppNotepad data format.", - REFERENCE_URL, - ""}, - {"openharmony.hinote", - {"general.composite-object"}, - {".hinote"}, - {}, - "OpenHarmony system Notes data format.", - REFERENCE_URL, - ""}, - {"openharmony.styled-string", - {"general.composite-object"}, - {}, - {}, - "OpenHarmony system defined styled string.", - REFERENCE_URL, - ""}, - {"openharmony.want", - {"general.object"}, - {}, - {}, - "OpenHarmony system defined Want.", - REFERENCE_URL, - ""}, - {"openharmony.moving-photo", - {"general.media"}, - {}, - {}, - "OpenHarmony system defined moving photo.", - REFERENCE_URL, - ""}, - {"macos.dmg", - {"general.disk-image"}, - {".dmg"}, - {"application/x-apple-diskimage"}, - "Apple Disk Image", - REFERENCE_URL, - ""}, - {"debian.deb", - {"general.archive"}, - {".deb", ".udeb"}, - {"application/x-debian-package", "application/vnd.debian.binary-package"}, - "OpenHarmony system defined Want.", - REFERENCE_URL, - ""}, - {"general.ofd", - {"general.composite-object"}, - {".ofd"}, - {}, - "Open fixed-layout document, a national standard for format documents", - REFERENCE_URL, - ""}, - {"general.opg", - {"general.archive"}, - {".opg"}, - {}, - "OPG archive", - REFERENCE_URL, - ""}, - {"general.tex", - {"general.source-code"}, - {}, - {}, - "Base type for TeX source code", - REFERENCE_URL, - ""}, - {"general.css", - {"general.script"}, - {".css"}, - {"text/css"}, - "Cascading style sheets", - REFERENCE_URL, - ""}, - {"general.vob", - {"general.video"}, - {".vob"}, - {"video/mpeg", "video/x-ms-vob"}, - "", - REFERENCE_URL, - ""}, - {"general.dif-video", - {"general.video"}, - {".dif"}, - {"video/dv"}, - "Digital interface format", - REFERENCE_URL, - ""}, - {"general.dv-video", - {"general.video"}, - {".dv"}, - {"video/dv"}, - "DV video", - REFERENCE_URL, - ""}, - {"general.flc-animation", - {"general.video"}, - {".fli", ".flc"}, - {"video/fli", "video/flc"}, - "FLIC file format", - REFERENCE_URL, - ""}, - {"general.mng", - {"general.video"}, - {".mng"}, - {"video/x-mng"}, - "Multiple-image network graphics", - REFERENCE_URL, - ""}, - {"general.mpegurl-video", - {"general.video"}, - {".mxu", ".m4u"}, - {"video/vnd.mpegurl"}, - "Video playlist", - REFERENCE_URL, - ""}, - {"general.ts", - {"general.video"}, - {".ts"}, - {"video/mp2ts", "video/mp2t"}, - "MPEG transport stream", - REFERENCE_URL, - ""}, - {"general.amr", - {"general.audio"}, - {".amr"}, - {"audio/amr"}, - "The adaptive multi-rate audio codecs", - REFERENCE_URL, - ""}, - {"general.amr-wb", - {"general.audio"}, - {".awb"}, - {"audio/amr-wb"}, - "Adaptive multi-rate wideband", - REFERENCE_URL, - ""}, - {"general.gsm", - {"general.audio"}, - {".gsm"}, - {"audio/x-gsm", "audio/gsm"}, - "Global system form mobile audio format", - REFERENCE_URL, - ""}, - {"general.imy", - {"general.audio"}, - {".imy"}, - {"audio/imelody"}, - "Non-polyphonic ringtone exchange object format", - REFERENCE_URL, - ""}, - {"general.kar", - {"general.audio"}, - {".kar"}, - {"audio/midi"}, - "Karaoke MIDI file format", - REFERENCE_URL, - ""}, - {"general.mpegurl-audio", - {"general.audio"}, - {".m3u"}, - {"audio/mpegurl", "audio/x-mpegurl"}, - "Audio playlist", - REFERENCE_URL, - ""}, - {"general.mpeg-4-audio", - {"general.audio"}, - {".m4a", ".m4b"}, - {"audio/mpeg"}, - "Audio-only MPEG-4 file", - REFERENCE_URL, - ""}, - {"general.midi-audio", - {"general.audio"}, - {".mid", ".midi"}, - {"audio/midi"}, - "MIDI audio", - REFERENCE_URL, - ""}, - {"general.mp2", - {"general.audio"}, - {".mp2"}, - {"audio/mpeg"}, - "MPEG-1 audio layer II or MPEG-2 audio layer II", - REFERENCE_URL, - ""}, - {"general.mpeg-audio", - {"general.audio"}, - {".mpga"}, - {"audio/mpeg"}, - "MPEG audio format", - REFERENCE_URL, - ""}, - {"general.mxmf", - {"general.audio"}, - {".mxmf"}, - {"audio/mobile-xmf"}, - "Mobile XMF audio format", - REFERENCE_URL, - ""}, - {"general.ota", - {"general.audio"}, - {".ota"}, - {"audio/midi"}, - "OTA ringtone file", - REFERENCE_URL, - ""}, - {"general.pls", - {"general.audio"}, - {".pls"}, - {"audio/x-scpls"}, - "Multimedia playlist format", - REFERENCE_URL, - ""}, - {"general.rtttl", - {"general.audio"}, - {".rtttl"}, - {"audio/midi"}, - "Ring tone transfer language file", - REFERENCE_URL, - ""}, - {"general.psid", - {"general.audio"}, - {".sid", ".psid"}, - {"audio/prs.sid"}, - "SID audio", - REFERENCE_URL, - ""}, - {"general.ulaw-audio", - {"general.audio"}, - {".au", ".ulw", ".snd"}, - {"audio/basic", "audio/au", "audio/snd"}, - "uLaw audio", - REFERENCE_URL, - ""}, - {"general.xmf", - {"general.audio"}, - {".xmf"}, - {"audio/midi"}, - "Extensible music file", - REFERENCE_URL, - ""}, - {"general.gif", - {"general.image"}, - {".gif"}, - {"image/gif"}, - "GIF image", - REFERENCE_URL, - ""}, - {"general.djvu-image", - {"general.image"}, - {".djv", ".djvu"}, - {"image/vnd.djvu"}, - "Djvu image", - REFERENCE_URL, - ""}, - {"general.jng-image", - {"general.image"}, - {".jng"}, - {"image/x-jng"}, - "JPEG network graphic", - REFERENCE_URL, - ""}, - {"general.pcx-image", - {"general.image"}, - {".pcx"}, - {"image/vnd.zbrush.pcx"}, - "Paintbrush bitmap image", - REFERENCE_URL, - ""}, - {"general.pbm-image", - {"general.image"}, - {".pbm"}, - {"image/x-portable-bitmap"}, - "Portable bitmap image", - REFERENCE_URL, - ""}, - {"general.pgm-image", - {"general.image"}, - {".pgm"}, - {"image/x-portable-graymap"}, - "Portable gray map image", - REFERENCE_URL, - ""}, - {"general.pnm-image", - {"general.image"}, - {".pnm"}, - {"image/x-portable-anymap"}, - "Portable any map image file", - REFERENCE_URL, - ""}, - {"general.ppm-image", - {"general.image"}, - {".ppm"}, - {"image/x-portable-pixmap"}, - "Portable pixmap image", - REFERENCE_URL, - ""}, - {"general.rgb-image", - {"general.image"}, - {".rgb"}, - {"image/x-rgb"}, - "RGB bitmap", - REFERENCE_URL, - ""}, - {"general.svg-image", - {"general.image"}, - {".svg", ".svgz"}, - {"image/svg+xml"}, - "Scalable vector graphic", - REFERENCE_URL, - ""}, - {"general.wbmp-image", - {"general.image"}, - {".wbmp"}, - {"image/vnd.wap.wbmp"}, - "Wireless bitmap image", - REFERENCE_URL, - ""}, - {"general.xpixmap-image", - {"general.image"}, - {".xpm"}, - {"image/x-xpixmap"}, - "X11 pixmap graphic", - REFERENCE_URL, - ""}, - {"general.xwindowdump-image", - {"general.image"}, - {".xwd"}, - {"image/x-xwindowdump"}, - "X windows dump image", - REFERENCE_URL, - ""}, - {"general.heif", - {"general.image"}, - {".heif", ".heifs", ".hif"}, - {"image/heif"}, - "High efficiency image format", - REFERENCE_URL, - ""}, - {"general.heic", - {"general.image"}, - {".heic", ".heics"}, - {"image/heic"}, - "High efficiency image format", - REFERENCE_URL, - ""}, - {"general.virtual-cd", - {"general.disk-image"}, - {".vcd"}, - {"application/x-cdlink"}, - "Virtual CD", - REFERENCE_URL, - ""}, - {"general.boo-source", - {"general.source-code"}, - {".boo"}, - {"text/x-boo"}, - "Boo source code", - REFERENCE_URL, - ""}, - {"general.d-source", - {"general.source-code"}, - {".d"}, - {"text/x-dsrc"}, - "D source code file", - REFERENCE_URL, - ""}, - {"general.html-component", - {"general.source-code"}, - {".htc"}, - {"text/x-component"}, - "HTML component", - REFERENCE_URL, - ""}, - {"general.pascal-source", - {"general.source-code"}, - {".p", ".pas"}, - {"text/x-pascal"}, - "Pascal source code", - REFERENCE_URL, - ""}, - {"general.haskell-script", - {"general.script"}, - {".hs"}, - {"text/x-haskell"}, - "Haskell script", - REFERENCE_URL, - ""}, - {"general.literate-haskell-script", - {"general.script"}, - {".lhs"}, - {"text/x-literate-haskell"}, - "Literate haskell script", - REFERENCE_URL, - ""}, - {"general.tcl-script", - {"general.script"}, - {".tcl"}, - {"text/x-tcl"}, - "Tcl script", - REFERENCE_URL, - ""}, - {"general.asc-text", - {"general.text"}, - {".asc"}, - {"text/plain"}, - "ASCII text file", - REFERENCE_URL, - ""}, - {"general.portable-object", - {"general.text"}, - {".po"}, - {"text/plain"}, - "Portable object", - REFERENCE_URL, - ""}, - {"general.rich-text", - {"general.text"}, - {".rtf", ".rtx"}, - {"text/rtf", "text/richtext"}, - "Rich text format file", - REFERENCE_URL, - ""}, - {"general.delimited-values-text", - {"general.text"}, - {}, - {}, - "Base type for delimited-values text", - REFERENCE_URL, - ""}, - {"general.comma-separated-values-text", - {"general.delimited-values-text"}, - {".csv"}, - {"text/csv"}, - "Comma-separated values file", - REFERENCE_URL, - ""}, - {"general.diff", - {"general.text"}, - {".diff"}, - {"text/plain"}, - "Patch file", - REFERENCE_URL, - ""}, - {"general.setext", - {"general.text"}, - {".etx"}, - {"text/x-setext"}, - "Structure enhanced Text", - REFERENCE_URL, - ""}, - {"general.gcd", - {"general.text"}, - {".gcd"}, - {"text/x-pcs-gcd"}, - "General content descriptor", - REFERENCE_URL, - ""}, - {"general.tab-separated-values-text", - {"general.delimited-values-text"}, - {".tsv"}, - {"text/tab-separated-values"}, - "Tab-Separated values file", - REFERENCE_URL, - ""}, - {"general.p7r", - {"general.text"}, - {".p7r"}, - {"application/x-pkcs7-certreqresp"}, - "Certificate request response file", - REFERENCE_URL, - ""}, - {"general.pem", - {"general.text"}, - {".pem"}, - {"application/x-pem-file"}, - "Privacy enhanced mail certificate", - REFERENCE_URL, - ""}, - {"general.chess-pgn", - {"general.plain-text"}, - {".pgn"}, - {"application/x-chess-pgn", "application/vnd.chess-pgn"}, - "Portable game notation file", - REFERENCE_URL, - ""}, - {"general.lha-archive", - {"general.archive"}, - {".lha"}, - {"application/x-lha"}, - "LHARC compressed archive", - REFERENCE_URL, - ""}, - {"general.lzh-archive", - {"general.archive"}, - {".lzh"}, - {"application/x-lzh"}, - "LZH compressed file", - REFERENCE_URL, - ""}, - {"general.lzx-archive", - {"general.archive"}, - {".lzx"}, - {"application/x-lzx"}, - "LZX compressed archive", - REFERENCE_URL, - ""}, - {"general.taz-archive", - {"general.tar-archive"}, - {".taz", ".tar.z", ".tz"}, - {"application/x-gtar"}, - "Tar zipped file", - REFERENCE_URL, - ""}, - {"general.shar-archive", - {"general.archive"}, - {".shar"}, - {"application/x-shar"}, - "Unix Shar archive", - REFERENCE_URL, - ""}, - {"general.cpio-archive", - {"general.archive"}, - {".cpio"}, - {"application/x-cpio"}, - "Unix CPIO archive", - REFERENCE_URL, - ""}, - {"general.web-archive", - {"general.archive"}, - {".mht", ".mhtml"}, - {"application/x-mimearchive"}, - "MHTML web archive", - REFERENCE_URL, - ""}, - {"general.ustar", - {"general.archive"}, - {".ustar"}, - {"application/x-ustar"}, - "Uniform standard tape archive format", - REFERENCE_URL, - ""}, - {"general.mathml", - {"general.xml"}, - {".mml"}, - {"text/mathml", "application/mathml+xml"}, - "Mathematical markup language file", - REFERENCE_URL, - ""}, - {"general.xhtml", - {"general.xml"}, - {".xhtml"}, - {"application/xhtml+xml"}, - "XHTML", - REFERENCE_URL, - ""}, - {"general.rss", - {"general.xml"}, - {".rss"}, - {"application/rss+xml"}, - "Rich site summary", - REFERENCE_URL, - ""}, - {"general.rdf", - {"general.xml"}, - {".rdf"}, - {"application/rdf+xml"}, - "Resource description framework file", - REFERENCE_URL, - ""}, - {"general.cad", - {"general.object"}, - {}, - {}, - "Base type for computer-aided design", - REFERENCE_URL, - ""}, - {"general.iges", - {"general.cad"}, - {".iges", ".igs"}, - {"model/iges"}, - "IGES drawing", - REFERENCE_URL, - ""}, - {"general.octet-stream", - {"general.object"}, - {}, - {"application/octet-stream"}, - "Arbitrary binary data", - REFERENCE_URL, - ""}, - {"general.iso", - {"general.disk-image"}, - {".iso"}, - {"application/x-iso9660-image"}, - "Disc image file", - REFERENCE_URL, - ""}, - {"general.mesh-model", - {"general.object"}, - {".msh", ".mesh", ".silo"}, - {"model/mesh"}, - "3D mesh model", - REFERENCE_URL, - ""}, - {"general.certificate", - {"general.object"}, - {}, - {}, - "Base type for security certificate", - REFERENCE_URL, - ""}, - {"general.c-object", - {"general.executable"}, - {".o"}, - {"application/x-object"}, - "Compiled C object file", - REFERENCE_URL, - ""}, - {"general.dvi", - {"general.tex"}, - {".dvi"}, - {"application/x-dvi"}, - "Device independent format file", - REFERENCE_URL, - ""}, - {"general.cer-certificate", - {"general.certificate"}, - {".cer"}, - {"application/pkix-cert"}, - "Internet security certificate", - REFERENCE_URL, - ""}, - {"general.crt-certificate", - {"general.certificate"}, - {".crt"}, - {"application/x-x509-ca-cert", "application/x-x509-server-cert", "application/x-x509-user-cert"}, - "Security Certificate", - REFERENCE_URL, - ""}, - {"general.crl-certificate", - {"general.certificate"}, - {".crl"}, - {"application/x-pkix-crl"}, - "Certificate revocation list file", - REFERENCE_URL, - ""}, - {"general.prn", - {"general.composite-object"}, - {".prn"}, - {}, - "Print to file", - REFERENCE_URL, - ""}, - {"org.oasis-open.opendocument.chart", - {"org.oasis.opendocument", "general.composite-object"}, - {".odc"}, - {"application/vnd.oasis.opendocument.chart"}, - "Open Document chart", - REFERENCE_URL, - ""}, - {"org.oasis-open.opendocument.text-master", - {"org.oasis.opendocument", "general.composite-object"}, - {".odm"}, - {"application/vnd.oasis.opendocument.text-master"}, - "Open Document text master", - REFERENCE_URL, - ""}, - {"org.oasis-open.opendocument.text-web", - {"org.oasis.opendocument", "general.composite-object"}, - {".oth"}, - {"application/vnd.oasis.opendocument.text-web"}, - "Open Document HTML template", - REFERENCE_URL, - ""}, - {"org.oasis-open.opendocument.database", - {"org.oasis.opendocument", "general.database"}, - {".odb"}, - {"application/vnd.oasis.opendocument.database"}, - "Open Document database", - REFERENCE_URL, - ""}, - {"org.oasis-open.opendocument.image", - {"org.oasis.opendocument", "general.image"}, - {".odi"}, - {"application/vnd.oasis.opendocument.image"}, - "Open Document image", - REFERENCE_URL, - ""}, - {"org.oasis-open.opendocument.formula-template", - {"org.oasis.opendocument", "general.composite-object"}, - {".otf"}, - {"application/vnd.oasis.opendocument.formula-template"}, - "Open Document formula template", - REFERENCE_URL, - ""}, - {"org.oasis-open.opendocument.chart-template", - {"org.oasis.opendocument", "general.composite-object"}, - {".otc"}, - {"application/vnd.oasis.opendocument.chart-template"}, - "Open Document chart template", - REFERENCE_URL, - ""}, - {"org.oasis-open.opendocument.presentation-template", - {"org.oasis.opendocument", "general.composite-object"}, - {".otp"}, - {"application/vnd.oasis.opendocument.presentation-template"}, - "Open Document presentation template", - REFERENCE_URL, - ""}, - {"org.oasis-open.opendocument.image-template", - {"org.oasis.opendocument", "general.image"}, - {".oti"}, - {"application/vnd.oasis.opendocument.image-template"}, - "Open Document image template", - REFERENCE_URL, - ""}, - {"org.oasis-open.opendocument.graphics-template", - {"org.oasis.opendocument", "general.composite-object"}, - {".otg"}, - {"application/vnd.oasis.opendocument.graphics-template"}, - "Open Document graphics template", - REFERENCE_URL, - ""}, - {"org.oasis-open.opendocument.spreadsheet-template", - {"org.oasis.opendocument", "general.composite-object"}, - {".ots"}, - {"application/vnd.oasis.opendocument.spreadsheet-template"}, - "Open Document spreadsheet template", - REFERENCE_URL, - ""}, - {"org.oasis-open.opendocument.text-template", - {"org.oasis.opendocument", "general.composite-object"}, - {".ott"}, - {"application/vnd.oasis.opendocument.text-template"}, - "Open Document text template", - REFERENCE_URL, - ""}, - {"com.microsoft.word.dot", - {"general.composite-object"}, - {".dot"}, - {"application/msword"}, - "Microsoft Word document template", - REFERENCE_URL, - ""}, - {"com.microsoft.powerpoint.pps", - {"general.composite-object"}, - {".pps"}, - {"application/vnd.ms-powerpoint"}, - "Microsoft PowerPoint slide show", - REFERENCE_URL, - ""}, - {"com.microsoft.powerpoint.pot", - {"general.composite-object"}, - {".pot"}, - {"application/vnd.ms-powerpoint"}, - "Microsoft PowerPoint Template", - REFERENCE_URL, - ""}, - {"com.microsoft.excel.xlt", - {"general.composite-object"}, - {".xlt"}, - {"application/vnd.ms-excel"}, - "Microsoft Excel spreadsheet template", - REFERENCE_URL, - ""}, - {"com.microsoft.visio.vsd", - {"general.composite-object"}, - {".vsd"}, - {"application/vnd.visio"}, - "Microsoft Office Visio 2003-2010 drawing", - REFERENCE_URL, - ""}, - {"org.openxmlformats.drawingml.visio", - {"org.openxmlformats.openxml", "general.composite-object"}, - {".vsdx"}, - {"application/vnd.openxmlformats-officedocument.drawingml.drawing"}, - "Microsoft Visio drawing", - REFERENCE_URL, - ""}, - {"org.openxmlformats.drawingml.template", - {"org.openxmlformats.openxml", "general.composite-object"}, - {".vstx"}, - {}, - "Microsoft Visio drawing template", - REFERENCE_URL, - ""}, - {"org.openxmlformats.drawingml.visio.macroenabled", - {"org.openxmlformats.openxml", "general.composite-object"}, - {".vsdm"}, - {}, - "Visio macro-enabled drawing", - REFERENCE_URL, - ""}, - {"org.openxmlformats.drawingml.template.macroenabled", - {"org.openxmlformats.openxml", "general.composite-object"}, - {".vstm"}, - {}, - "Visio macro-enabled drawing template", - REFERENCE_URL, - ""}, - {"org.openxmlformats.wordprocessingml.template", - {"org.openxmlformats.openxml", "general.composite-object"}, - {".dotx"}, - {"application/vnd.openxmlformats-officedocument.wordprocessingml.template"}, - "Office Open XML document template.", - REFERENCE_URL, - ""}, - {"org.openxmlformats.presentationml.template", - {"org.openxmlformats.openxml", "general.composite-object"}, - {".potx"}, - {"application/vnd.openxmlformats-officedocument.presentationml.template"}, - "Office Open XML presentation template", - REFERENCE_URL, - ""}, - {"org.openxmlformats.presentationml.slideshow", - {"org.openxmlformats.openxml", "general.composite-object"}, - {".ppsx"}, - {"application/vnd.openxmlformats-officedocument.presentationml.slideshow"}, - "Office Open XML slide show", - REFERENCE_URL, - ""}, - {"org.openxmlformats.spreadsheetml.template", - {"org.openxmlformats.openxml", "general.composite-object"}, - {".xltx"}, - {"application/vnd.openxmlformats-officedocument.spreadsheetml.template"}, - "Office Open XML spreadsheet template", - REFERENCE_URL, - ""}, - {"org.openxmlformats.wordprocessingml.document.macroenabled", - {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, - {".docm"}, - {"application/vnd.ms-word.document.macroEnabled.12"}, - "Office Open XML word processing document (macros enabled)", - REFERENCE_URL, - ""}, - {"org.openxmlformats.wordprocessingml.template.macroenabled", - {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, - {".dotm"}, - {"application/vnd.ms-word.template.macroEnabled.12"}, - "Office Open XML word processing template (macros enabled)", - REFERENCE_URL, - ""}, - {"org.openxmlformats.spreadsheetml.template.macroenabled", - {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, - {".xltm"}, - {"application/vnd.ms-excel.template.macroEnabled.12"}, - "Office Open XML spreadsheet template (macros enabled)", - REFERENCE_URL, - ""}, - {"org.openxmlformats.spreadsheetml.addin.macroenabled", - {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, - {".xlam"}, - {"application/vnd.ms-excel.addin.macroEnabled.12"}, - "Office Open XML spreadsheet addin (macros enabled)", - REFERENCE_URL, - ""}, - {"org.openxmlformats.spreadsheetml.binary.macroenabled", - {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, - {".xlsb"}, - {"application/vnd.ms-excel.sheet.binary.macroEnabled.12"}, - "Office Open XML spreadsheet binary (macros enabled)", - REFERENCE_URL, - ""}, - {"org.openxmlformats.spreadsheetml.sheet.macroenabled", - {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, - {".xlsm"}, - {"application/vnd.ms-excel.sheet.macroEnabled.12"}, - "Office Open XML spreadsheet (macros enabled)", - REFERENCE_URL, - ""}, - {"org.openxmlformats.presentationml.addin.macroenabled", - {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, - {".ppam"}, - {"application/vnd.ms-powerpoint.addin.macroEnabled.12"}, - "Office Open XML presentation addin (macros enabled)", - REFERENCE_URL, - ""}, - {"org.openxmlformats.presentationml.presentation.macroenabled", - {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, - {".pptm"}, - {"application/vnd.ms-powerpoint.presentation.macroEnabled.12"}, - "Office Open XML presentation (macros enabled)", - REFERENCE_URL, - ""}, - {"org.openxmlformats.presentationml.slideshow.macroenabled", - {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, - {".ppsm"}, - {"application/vnd.ms-powerpoint.slideshow.macroEnabled.12"}, - "Office Open XML slide show (macros enabled)", - REFERENCE_URL, - ""}, - {"org.openxmlformats.presentationml.template.macroenabled", - {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, - {".potm"}, - {"application/vnd.ms-powerpoint.template.macroEnabled.12"}, - "Office Open XML presentation template (macros enabled)", - REFERENCE_URL, - ""}, - {"org.openoffice", - {"general.archive"}, - {}, - {}, - "OpenOffice document format for open-source office software suite", - REFERENCE_URL, - ""}, - {"org.openoffice.calc", - {"org.openoffice", "general.composite-object"}, - {".sxc"}, - {"application/vnd.sun.xml.calc"}, - "StarOffice Calc spreadsheet", - REFERENCE_URL, - ""}, - {"org.openoffice.draw", - {"org.openoffice", "general.composite-object"}, - {".sxd"}, - {"application/vnd.sun.xml.draw"}, - "StarOffice Drawing", - REFERENCE_URL, - ""}, - {"org.openoffice.writer-global", - {"org.openoffice", "general.composite-object"}, - {".sxg"}, - {"application/vnd.sun.xml.writer.global"}, - "Apache OpenOffice master document", - REFERENCE_URL, - ""}, - {"org.openoffice.impress", - {"org.openoffice", "general.composite-object"}, - {".sxi"}, - {"application/vnd.sun.xml.impress"}, - "StarOffice Impress presentation", - REFERENCE_URL, - ""}, - {"org.openoffice.math", - {"org.openoffice", "general.composite-object"}, - {".sxm"}, - {"application/vnd.sun.xml.math"}, - "StarMath Formula", - REFERENCE_URL, - ""}, - {"org.openoffice.writer", - {"org.openoffice", "general.composite-object"}, - {".sxw"}, - {"application/vnd.sun.xml.writer"}, - "StarOffice Writer document", - REFERENCE_URL, - ""}, - {"org.openoffice.calc.template", - {"org.openoffice", "general.composite-object"}, - {".stc"}, - {"application/vnd.sun.xml.calc.template"}, - "StarOffice Calc spreadsheet template", - REFERENCE_URL, - ""}, - {"org.openoffice.draw.template", - {"org.openoffice", "general.composite-object"}, - {".std"}, - {"application/vnd.sun.xml.draw.template"}, - "Apache OpenOffice Drawing template", - REFERENCE_URL, - ""}, - {"org.openoffice.impress.template", - {"org.openoffice", "general.composite-object"}, - {".sti"}, - {"application/vnd.sun.xml.impress.template"}, - "StarOffice Presentation template", - REFERENCE_URL, - ""}, - {"org.openoffice.writer.template", - {"org.openoffice", "general.composite-object"}, - {".stw"}, - {"application/vnd.sun.xml.writer.template"}, - "StarOffice Document template", - REFERENCE_URL, - ""}, - {"com.staroffice", - {"general.archive"}, - {}, - {}, - "StarOffice document format", - REFERENCE_URL, - ""}, - {"com.staroffice.draw", - {"com.staroffice", "general.composite-object"}, - {".sda"}, - {"application/vnd.stardivision.draw"}, - "StarOffice Drawing", - REFERENCE_URL, - ""}, - {"com.staroffice.calc", - {"com.staroffice", "general.composite-object"}, - {".sdc"}, - {"application/vnd.stardivision.calc"}, - "StarOffice Calc spreadsheet", - REFERENCE_URL, - ""}, - {"com.staroffice.impress", - {"com.staroffice", "general.composite-object"}, - {".sdd", ".sdp"}, - {"application/vnd.stardivision.impress"}, - "StarOffice Presentation", - REFERENCE_URL, - ""}, - {"com.staroffice.writer", - {"com.staroffice", "general.composite-object"}, - {".sdw"}, - {"application/vnd.stardivision.writer"}, - "StarOffice Writer text document", - REFERENCE_URL, - ""}, - {"com.staroffice.chart", - {"com.staroffice", "general.composite-object"}, - {".sds"}, - {"application/vnd.stardivision.chart"}, - "StarOffice Chart", - REFERENCE_URL, - ""}, - {"com.staroffice.mail", - {"com.staroffice", "general.composite-object"}, - {".sdm"}, - {"application/vnd.stardivision.mail"}, - "StarOffice Mail message", - REFERENCE_URL, - ""}, - {"com.staroffice.writer-global", - {"com.staroffice", "general.composite-object"}, - {".sgl"}, - {"application/vnd.stardivision.writer-global"}, - "StarOffice Master document", - REFERENCE_URL, - ""}, - {"com.staroffice.math", - {"com.staroffice", "general.composite-object"}, - {".smf"}, - {"application/vnd.stardivision.math"}, - "StarMath Formula file", - REFERENCE_URL, - ""}, - {"com.staroffice.template", - {"com.staroffice", "general.composite-object"}, - {".vor"}, - {"application/vnd.stardivision.template"}, - "StarOffice Template", - REFERENCE_URL, - ""}, - {"org.tug.bib", - {"general.tex"}, - {".bib"}, - {"text/x-bibtex"}, - "TeX Bibliography file", - REFERENCE_URL, - ""}, - {"org.tug.cls", - {"general.tex"}, - {".cls"}, - {"text/x-tex"}, - "TeX Class file", - REFERENCE_URL, - ""}, - {"org.tug.sty", - {"general.tex"}, - {".sty"}, - {"text/x-tex"}, - "TeX Style file", - REFERENCE_URL, - ""}, - {"org.tug.tex", - {"general.tex"}, - {".tex"}, - {"text/x-tex"}, - "TeX source document file", - REFERENCE_URL, - ""}, - {"org.latex-project.latex", - {"general.tex"}, - {".ltx", ".latex"}, - {"application/x-latex"}, - "LaTeX source document file", - REFERENCE_URL, - ""}, - {"org.matroska.mkv", - {"general.video"}, - {".mkv"}, - {"video/x-matroska"}, - "Matroska video", - REFERENCE_URL, - ""}, - {"org.matroska.mka", - {"general.audio"}, - {".mka"}, - {"audio/x-matroska"}, - "Matroska audio", - REFERENCE_URL, - ""}, - {"com.sgi.movie", - {"general.video"}, - {".movie"}, - {"video/x-sgi-movie"}, - "SGI movie", - REFERENCE_URL, - ""}, - {"com.apple.m4v", - {"general.video"}, - {".m4v"}, - {"video/m4v"}, - "M4V video", - REFERENCE_URL, - ""}, - {"org.webmproject.webm", - {"general.video"}, - {".webm"}, - {"video/webm"}, - "WebM is an audiovisual media file format", - REFERENCE_URL, - ""}, - {"com.apple.quicktime-movie", - {"general.video"}, - {".mov", ".qt", ".movie"}, - {"video/quicktime"}, - "QuickTime File Format", - REFERENCE_URL, - ""}, - {"com.coreldraw.cdr", - {"general.image"}, - {".cdr"}, - {"image/x-coreldraw"}, - "CorelDRAW file", - REFERENCE_URL, - ""}, - {"com.coreldraw.cdt", - {"general.image"}, - {".cdt"}, - {"image/x-coreldrawtemplate"}, - "CorelDRAW template", - REFERENCE_URL, - ""}, - {"com.coreldraw.cpt", - {"general.image"}, - {".cpt"}, - {"image/x-corelphotopaint"}, - "Corel PHOTO-PAINT image", - REFERENCE_URL, - ""}, - {"com.coreldraw.pat", - {"general.image"}, - {".pat"}, - {"image/x-coreldrawpattern"}, - "CorelDRAW pattern file", - REFERENCE_URL, - ""}, - {"com.microsoft.cur", - {"general.image"}, - {".cur"}, - {"image/ico"}, - "Microsoft Windows cursor image", - REFERENCE_URL, - ""}, - {"com.sun.raster", - {"general.image"}, - {".ras"}, - {"image/x-cmu-raster"}, - "Sun Raster Graphic", - REFERENCE_URL, - ""}, - {"com.google.webp", - {"general.image"}, - {".webp"}, - {"image/webp"}, - "WebP image", - REFERENCE_URL, - ""}, - {"com.sseyo.koan-audio", - {"general.audio"}, - {".skd", ".skm", ".skp", ".skt"}, - {"application/x-koan"}, - "Koan music files over the internet", - REFERENCE_URL, - ""}, - {"io.qt.moc", - {"general.source-code"}, - {".moc"}, - {"text/x-moc"}, - "Qt Meta-Object compiler file", - REFERENCE_URL, - ""}, - {"com.ghostscript.font", - {"general.font"}, - {".gsf"}, - {"application/x-font"}, - "Ghostscript font", - REFERENCE_URL, - ""}, - {"org.x.pcf-font", - {"general.font"}, - {".pcf"}, - {"application/x-font", "application/x-font-pcf"}, - "Portable compiled format", - REFERENCE_URL, - ""}, - {"com.microsoft.windows-media-wmd", - {"com.microsoft.advanced-systems-format", "general.zip-archive"}, - {".wmd"}, - {"application/x-ms-wmd"}, - "Windows media download package", - REFERENCE_URL, - ""}, - {"com.microsoft.windows-media-wmz", - {"com.microsoft.advanced-systems-format", "general.zip-archive"}, - {".wmz"}, - {"application/x-ms-wmz"}, - "Windows media player skin package", - REFERENCE_URL, - ""}, - {"com.microsoft.windows-installer", - {"general.executable"}, - {".msi"}, - {"application/x-msi"}, - "Windows installer package", - REFERENCE_URL, - ""}, - {"com.microsoft.publisher.pub", - {"general.composite-object"}, - {".pub"}, - {"application/x-mspublisher"}, - "Publisher document", - REFERENCE_URL, - ""}, - {"com.microsoft.windows-media-playlist", - {"general.xml", "general.media"}, - {".wpl"}, - {"application/vnd.ms-wpl"}, - "Windows media player playlist", - REFERENCE_URL, - ""}, - {"com.microsoft.access.mdb", - {"general.database"}, - {".mdb"}, - {"application/msaccess"}, - "Microsoft Access database", - REFERENCE_URL, - ""}, - {"com.3dsystems.stereolithography", - {"general.composite-object"}, - {".stl"}, - {"application/vnd.ms-pki.stl"}, - "Stereolithography file", - REFERENCE_URL, - ""}, - {"com.apple.media.playlist", - {"general.media"}, - {".m3u8"}, - {"application/vnd.apple.mpegurl"}, - "UTF-8 M3U playlist", - REFERENCE_URL, - ""}, - {"com.abisource.word", - {"general.composite-object"}, - {".abw"}, - {"application/x-abiword"}, - "AbiWord document", - REFERENCE_URL, - ""}, - {"com.adobe.framemaker", - {"general.composite-object"}, - {".book", ".fm", ".frame", ".maker"}, - {"application/x-maker"}, - "FrameMaker book file", - REFERENCE_URL, - ""}, - {"com.wolfram.cdf", - {"general.composite-object"}, - {".cdf"}, - {"application/x-cdf"}, - "Computable document format file", - REFERENCE_URL, - ""}, - {"de.cinderella.cdy", - {"general.composite-object"}, - {".cdy"}, - {"application/vnd.cinderella"}, - "Cinderella construction file", - REFERENCE_URL, - ""}, - {"com.adobe.dcr", - {"general.video"}, - {".dcr"}, - {"application/x-director"}, - "Shockwave media file", - REFERENCE_URL, - ""}, - {"com.adobe.dir", - {"general.video"}, - {".dir"}, - {"application/x-director"}, - "Adobe Director movie", - REFERENCE_URL, - ""}, - {"com.adobe.dxr", - {"general.video"}, - {".dxr"}, - {"application/x-director"}, - "Protected macromedia director movie", - REFERENCE_URL, - ""}, - {"org.gnumeric.spreadsheet", - {"general.xml"}, - {".gnumeric"}, - {"application/x-gnumeric"}, - "Gnumeric spreadsheet", - REFERENCE_URL, - ""}, - {"org.hdfgroup.hdf", - {"general.composite-object"}, - {".hdf"}, - {"application/x-hdf"}, - "Hierarchical data format", - REFERENCE_URL, - ""}, - {"com.apple.binhex-archive", - {"general.archive"}, - {".hqx"}, - {"application/mac-binhex40"}, - "BinHex 4.0 encoded file", - REFERENCE_URL, - ""}, - {"com.microsoft.hta", - {"general.archive", "general.executable"}, - {".hta"}, - {"application/hta"}, - "HTML application", - REFERENCE_URL, - ""}, - {"com.microsoft.internet.ins", - {"general.text"}, - {".ins"}, - {"application/x-internet-signup"}, - "Internet settings file", - REFERENCE_URL, - ""}, - {"com.microsoft.internet.isp", - {"general.text"}, - {".isp"}, - {"application/x-internet-signup"}, - "IIS internet service provider settings", - REFERENCE_URL, - ""}, - {"org.troff", - {"general.text"}, - {".man", ".t", ".roff"}, - {"text/troff"}, - "Unix troff format", - REFERENCE_URL, - ""}, - {"com.adobe.framemaker.mif", - {"general.composite-object"}, - {".mif"}, - {"application/vnd.mif"}, - "FrameMaker interchange format file", - REFERENCE_URL, - ""}, - {"io.sourceforge.freemind", - {"general.composite-object"}, - {".mm"}, - {"application/x-freemind"}, - "Mind Map file", - REFERENCE_URL, - ""}, - {"com.yamaha.smaf", - {"general.audio"}, - {".mmf"}, - {"application/vnd.smaf"}, - "Synthetic music mobile application file", - REFERENCE_URL, - ""}, - {"com.wolfram.mathematica.notebook", - {"general.text"}, - {".nb"}, - {"application/mathematica"}, - "Mathematica notebook", - REFERENCE_URL, - ""}, - {"org.xiph.ogg", - {"general.audio"}, - {".oga", ".ogg"}, - {"application/ogg"}, - "Ogg vorbis audio", - REFERENCE_URL, - ""}, - {"com.netscape.proxy-autoconfig", - {"general.plain-text"}, - {".pac"}, - {"application/x-ns-proxy-autoconfig"}, - "Proxy auto-config file", - REFERENCE_URL, - ""}, - {"com.rsa.pkcs-12", - {"general.archive"}, - {".pfx", ".p12"}, - {"application/x-pkcs12"}, - "PKCS #12 certificate file", - REFERENCE_URL, - ""}, - {"org.openpgp.signature", - {"general.object"}, - {".pgp"}, - {"application/pgp-signature"}, - "PGP security key", - REFERENCE_URL, - ""}, - {"com.apple.quicktime-link", - {"general.text"}, - {".qtl"}, - {"application/x-quicktimeplayer"}, - "QuickTime link file", - REFERENCE_URL, - ""}, - {"com.rarlab.rar-archive", - {"general.archive"}, - {".rar"}, - {"application/rar", "application/vnd.rar"}, - "WinRAR compressed archive", - REFERENCE_URL, - ""}, - {"org.7-zip.7-zip-archive", - {"general.archive"}, - {".7z"}, - {"application/x-7z-compressed"}, - "7-zip compressed archive", - REFERENCE_URL, - ""}, - {"com.red-bean.sgf", - {"general.text"}, - {".sgf"}, - {"application/x-go-sgf"}, - "Smart game format file", - REFERENCE_URL, - ""}, - {"com.stuffit.sit-archive", - {"general.archive"}, - {".sit"}, - {"application/x-stuffit"}, - "Stuffit archive", - REFERENCE_URL, - ""}, - {"com.adobe.futuresplash", - {"general.video"}, - {".spl"}, - {"application/futuresplash", "application/x-futuresplash"}, - "FutureSplash animation", - REFERENCE_URL, - ""}, - {"com.adobe.flash", - {"general.video"}, - {".swf"}, - {"application/x-shockwave-flash"}, - "Shockwave flash movie", - REFERENCE_URL, - ""}, - {"org.gnu.texinfo", - {"general.source-code"}, - {".texinfo", ".texi"}, - {"application/x-texinfo"}, - "GNU Texinfo", - REFERENCE_URL, - ""}, - {"org.bittorrent.torrent", - {"general.text"}, - {".torrent"}, - {"application/x-bittorrent"}, - "BitTorrent file", - REFERENCE_URL, - ""}, - {"com.idsoftware.doom", - {"general.archive"}, - {".wad"}, - {"application/x-doom"}, - "Doom WAD file", - REFERENCE_URL, - ""}, - {"com.apple.webarchive", - {"general.archive"}, - {".webarchive"}, - {"application/x-webarchive"}, - "Safari web archive", - REFERENCE_URL, - ""}, - {"com.android.webarchive", - {"general.archive"}, - {".webarchivexml"}, - {"application/x-webarchive-xml"}, - "Android web browser archive", - REFERENCE_URL, - ""}, - {"org.gimp.xcf", - {"general.image"}, - {".xcf"}, - {"application/x-xcf", "image/x-xcf"}, - "eXperimental computing facility, GIMP image file", - REFERENCE_URL, - ""}, - {"com.edrawsoft.edrawmax", - {"general.composite-object"}, - {".eddx"}, - {"application/x-eddx"}, - "Edraw Max XML file", - REFERENCE_URL, - ""}, - {"com.edrawsoft.edrawmind", - {"general.composite-object"}, - {".emmx"}, - {"application/x-emmx"}, - "Edraw MindMaster XML file", - REFERENCE_URL, - ""}, - {"net.cnki.caj", - {"general.composite-object"}, - {".caj"}, - {"application/caj"}, - "Chinese academic journal file", - REFERENCE_URL, - ""}, - {"com.dbase.dbf", - {"general.database"}, - {".dbf"}, - {"application/dbf", "application/dbase"}, - "Database file", - REFERENCE_URL, - ""}, - {"com.autodesk.dwg", - {"general.composite-object"}, - {".dwg"}, - {"image/vnd.dwg"}, - "AutoCAD drawing", - REFERENCE_URL, - ""}, - {"com.autodesk.dxf", - {"general.composite-object"}, - {".dxf"}, - {"image/vnd.dxf"}, - "Drawing exchange format file", - REFERENCE_URL, - ""}, - {"com.autodesk.dws", - {"general.composite-object"}, - {".dws"}, - {}, - "AutoCAD drawing standards file", - REFERENCE_URL, - ""}, - {"com.autodesk.dwt", - {"general.composite-object"}, - {".dwt"}, - {}, - "AutoCAD drawing template", - REFERENCE_URL, - ""}, - {"com.autodesk.dwf", - {"general.composite-object"}, - {".dwf"}, - {"model/vnd.dwf"}, - "Design web format file", - REFERENCE_URL, - ""}, - {"com.autodesk.dwfx", - {"general.composite-object"}, - {".dwfx"}, - {}, - "Design web format XPS file", - REFERENCE_URL, - ""}, - {"com.autodesk.shp", - {"general.composite-object"}, - {".shp"}, - {}, - "3D studio shape", - REFERENCE_URL, - ""}, - {"com.autodesk.shx", - {"general.composite-object"}, - {".shx"}, - {}, - "AutoCAD compiled shape file", - REFERENCE_URL, - ""}, - {"com.autodesk.slide-library", - {"general.composite-object"}, - {".slb"}, - {}, - "AutoCAD slide library", - REFERENCE_URL, - ""}, - {"com.autodesk.line", - {"general.text"}, - {".lin"}, - {}, - "AutoCAD linetype file", - REFERENCE_URL, - ""}, - {"com.autodesk.plotter", - {"general.composite-object"}, - {".plt"}, - {}, - "AutoCAD plotter document", - REFERENCE_URL, - ""}, - {"com.hp.graphics-language", - {"general.composite-object"}, - {".hpgl"}, - {"application/vnd.hp-hpgl"}, - "HP graphics language plotter file", - REFERENCE_URL, - ""}, - {"com.microsoft.metafile", - {"general.composite-object"}, - {".wmf"}, - {}, - "Windows metafile", - REFERENCE_URL, - ""}, - {"com.spatial.acis.sat", - {"general.text"}, - {".sat"}, - {}, - "ACIS SAT 3D model", - REFERENCE_URL, - ""}, - {"org.aomedia.avif-image", - {"general.image"}, - {".avif"}, - {"image/avif"}, - "AVIF image", - REFERENCE_URL, - ""}, - {"com.microsoft.dds", - {"general.image"}, - {".dds"}, - {"image/vnd-ms.dds"}, - "DirectDraw surface image", - REFERENCE_URL, - ""}, - {"com.ea.iff-ilbm", - {"general.image"}, - {".ilbm"}, - {"image/x-ilbm"}, - "Interleaved bitmap image", - REFERENCE_URL, - ""}, - {"com.canon.cr2-raw-image", - {"general.raw-image"}, - {".cr2"}, - {"image/x-canon-cr2"}, - "Canon raw 2 image", - REFERENCE_URL, - ""}, - {"com.canon.cr3-raw-image", - {"general.raw-image"}, - {".cr3"}, - {"image/x-canon-cr3"}, - "Canon raw 3 image", - REFERENCE_URL, - ""}, - {"com.canon.crw-raw-image", - {"general.raw-image"}, - {".crw"}, - {"image/x-canon-crw"}, - "Canon raw CIFF image file", - REFERENCE_URL, - ""}, - {"com.adobe.dng-raw-image", - {"general.raw-image"}, - {".dng"}, - {"image/x-adobe-dng"}, - "Digital negative image", - REFERENCE_URL, - ""}, - {"com.sony.arw-raw-image", - {"general.raw-image"}, - {".arw"}, - {"image/x-sony-arw"}, - "Sony alpha raw digital camera image", - REFERENCE_URL, - ""}, - {"com.nikon.nef-raw-image", - {"general.raw-image"}, - {".nef"}, - {"image/x-nikon-nef"}, - "Nikon electronic format RAW image", - REFERENCE_URL, - ""}, - {"com.mindjet.mindmanager.mmap", - {"general.composite-object"}, - {".mmap"}, - {}, - "MindManager Map", - REFERENCE_URL, - ""}, - {"com.microsoft.email", - {"general.message"}, - {".eml"}, - {"message/rfc822"}, - "E-Mail message", - REFERENCE_URL, - ""}, - {"com.microsoft.message", - {"general.message"}, - {".msg"}, - {}, - "Outlook message item file", - REFERENCE_URL, - ""}, - {"com.microsoft.pst", - {"general.archive"}, - {".pst"}, - {}, - "Outlook personal information store", - REFERENCE_URL, - ""}, - {"com.kingsoft.office", - {"general.archive"}, - {}, - {}, - "Kingsoft office suite", - REFERENCE_URL, - ""}, - {"com.kingsoft.office.writer.wps", - {"com.kingsoft.office", "general.composite-object"}, - {".wps"}, - {}, - "Kingsoft Writer document", - REFERENCE_URL, - ""}, - {"com.kingsoft.office.writer.wpt", - {"com.kingsoft.office", "general.composite-object"}, - {".wpt"}, - {}, - "Kingsoft Writer template", - REFERENCE_URL, - ""}, - {"com.kingsoft.office.presentation.dps", - {"com.kingsoft.office", "general.composite-object"}, - {".dps"}, - {}, - "Kingsoft Presentation file", - REFERENCE_URL, - ""}, - {"com.kingsoft.office.presentation.template", - {"com.kingsoft.office", "general.composite-object"}, - {".dpt"}, - {}, - "Kingsoft Presentation template", - REFERENCE_URL, - ""}, - {"com.kingsoft.office.spreadsheets.et", - {"com.kingsoft.office", "general.composite-object"}, - {".et"}, - {}, - "Kingsoft Spreadsheets tile", - REFERENCE_URL, - ""}, - {"com.kingsoft.office.spreadsheets.template", - {"com.kingsoft.office", "general.composite-object"}, - {".ett"}, - {}, - "Kingsoft Spreadsheets template", - REFERENCE_URL, - ""}, - {"com.microsoft.ini", - {"general.text"}, - {".ini"}, - {}, - "Windows Initialization File", - REFERENCE_URL, - ""}, - {"general.json", - {"general.script"}, - {".json"}, - {"application/json"}, - "JavaScript Object Notation File", - REFERENCE_URL, - ""}, - {"general.yaml", - {"general.script"}, - {".yaml", ".yml"}, - {"application/yaml"}, - "YAML Document", - REFERENCE_URL, - ""}, - {"general.log", - {"general.text"}, - {".log"}, - {"text/plain"}, - "Log File", - REFERENCE_URL, - ""}, - {"general.uri", - {"general.object"}, - {}, - {}, - "Universal Resource Identifier", - REFERENCE_URL, - ""}, - {"general.file-uri", - {"general.uri"}, - {}, - {}, - "File URI", - REFERENCE_URL, - ""}, - {"general.text-lst", - {"general.plain-text"}, - {".lst"}, - {}, - "Data List", - REFERENCE_URL, - ""}, - {"com.android.apk", - {"general.archive"}, - {".apk", ".apks", ".aab", ".xapk", ".apkm", ".akp"}, - {"application/vnd.android.package-archive"}, - "Android Package File", - REFERENCE_URL, - ""}, - {"com.adobe.postscript-pfb-font", - {"com.adobe.postscript-font"}, - {".pfb"}, - {"application/x-font"}, - "Printer Font Binary, PostScript Type 1 outline font.", - REFERENCE_URL, - ""}, - {"com.adobe.postscript-pfa-font", - {"com.adobe.postscript-font"}, - {".pfa"}, - {"application/x-font"}, - "Printer Pont ASCII file, PostScript Type 1 outline font.", - REFERENCE_URL, - ""}, - {"general.bz-archive", - {"general.archive"}, - {".bz"}, - {"application/x-bzip"}, - "Bzip Compressed File", - REFERENCE_URL, - ""}, - {"general.tar-bzip-archive", - {"general.bz-archive"}, - {".tbz"}, - {"application/x-bzip-compressed-tar"}, - "Bzip Compressed Tar Archive", - REFERENCE_URL, - ""}, - {"general.tar-bzip2-archive", - {"general.bz2-archive"}, - {".tbz2"}, - {"application/x-bzip2-compressed-tar"}, - "Bzip2-Compressed TAR File", - REFERENCE_URL, - ""}, - {"org.tukaani.xz-archive", - {"general.archive"}, - {".xz"}, - {"application/x-xz"}, - "XZ Compressed Archive", - REFERENCE_URL, - ""}, - {"org.tukaani.tar-xz-archive", - {"org.tukaani.xz-archive"}, - {".txz"}, - {"application/x-xz-compressed-tar"}, - "XZ Compressed Tar Archive", - REFERENCE_URL, - ""}, - {"general.xar-archive", - {"general.archive"}, - {".xar"}, - {"application/x-xar"}, - "Extensible Archive Fromat", - REFERENCE_URL, - ""}, - {"com.microsoft.cab-archive", - {"general.archive"}, - {".cab"}, - {"application/vnd.ms-cab-compressed"}, - "Windows Cabinet File", - REFERENCE_URL, - ""}, - {"redhat.rpm-archive", - {"general.archive"}, - {".rpm"}, - {"application/x-rpm"}, - "RedHat Package Manager File", - REFERENCE_URL, - ""}, - {"org.godotengine.tpz-archive", - {"general.archive"}, - {".tpz"}, - {}, - "Godot Engine Export Template Archive", - REFERENCE_URL, - ""}, - {"general.lza-archive", - {"general.archive"}, - {".lza"}, - {"application/x-lzh-compressed"}, - "LZA Compressed Archive", - REFERENCE_URL, - ""}, - {"general.arj-archive", - {"general.archive"}, - {".arj"}, - {"application/x-arj"}, - "ARJ Compressed File Archive", - REFERENCE_URL, - ""}, - {"com.winzip.zipx", - {"general.archive"}, - {".zipx"}, - {}, - "Extended Zip Archive", - REFERENCE_URL, - ""}, - {"general.lzma-archive", - {"general.archive"}, - {".lzma"}, - {"application/x-lzma"}, - "LZMA Compressed File", - REFERENCE_URL, - ""}, - {"general.lzma86-archive", - {"general.archive"}, - {".lzma86"}, - {}, - "LZMA86 Compressed File", - REFERENCE_URL, - ""}, - {"org.mozilla.xpinstall", - {"general.archive"}, - {".xpi"}, - {"application/x-xpinstall"}, - "Cross-platform Installer Package", - REFERENCE_URL, - ""}, - {"general.hfs-disk-image", - {"general.disk-image"}, - {".hfs"}, - {}, - "HFS Disk Image File", - REFERENCE_URL, - ""}, - {"general.img-disk-image", - {"general.disk-image"}, - {".img"}, - {"application/x-raw-disk-image"}, - "Disc Image Data File", - REFERENCE_URL, - ""}, - {"com.ezbsystems.zipped-iso", - {"general.disk-image"}, - {".isz"}, - {}, - "Zipped ISO Disk Image", - REFERENCE_URL, - ""}, - {"com.microsoft.wim", - {"general.disk-image"}, - {".wim"}, - {"application/x-ms-wim"}, - "Windows Imaging Format File", - REFERENCE_URL, - ""}, - {"com.microsoft.swm", - {"general.disk-image"}, - {".swm"}, - {"application/x-ms-wim"}, - "Split Windows Imaging Format", - REFERENCE_URL, - ""}, - {"com.kingsoft.office.spreadsheets.etx", - {"com.kingsoft.office", "general.composite-object"}, - {".etx"}, - {}, - "Kingsoft Spreadsheets File", - REFERENCE_URL, - ""}, - {"com.kingsoft.office.spreadsheets.ettx", - {"com.kingsoft.office", "general.composite-object"}, - {".ettx"}, - {}, - "Kingsoft Spreadsheets Template", - REFERENCE_URL, - ""}, - {"com.microsoft.excel.dif", - {"general.composite-object"}, - {".dif"}, - {}, - "Data interchange format", - REFERENCE_URL, - ""}, - {"openharmony.app", - {"openharmony.package"}, - {".app"}, - {}, - "OpenHarmony system defined application package", - REFERENCE_URL, - ""}, - {"com.huawei.hmos.settings.wifi", - {"general.text"}, - {".hmoswifi"}, - {}, - "HarmonyOS WIFI sharing setting", - REFERENCE_URL, - ""}, - {"general.tel", - {"general.text"}, - {".tel"}, - {}, - "TEL schematic diagram file format", - REFERENCE_URL, - ""}, - {"general.ets", - {"general.script"}, - {".ets"}, - {}, - "Extended TypeScript source code", - REFERENCE_URL, - ""}, - {"general.json5", - {"general.script"}, - {".json5"}, - {}, - "JSON5 data interchange format", - REFERENCE_URL, - ""}, - {"com.monkeysaudio.ape-audio", - {"general.audio"}, - {".ape"}, - {"audio/x-monkeys-audio"}, - "Monkey's Audio", - REFERENCE_URL, - ""}, - {"org.xiph.opus-audio", - {"general.audio"}, - {".opus"}, - {"audio/opus"}, - "Opus Audio", - REFERENCE_URL, - ""}, - {"general.conf", - {"general.text"}, - {".conf"}, - {}, - "Generic Configuration File", - REFERENCE_URL, - ""}, - {"com.microsoft.dos-batch", - {"general.script"}, - {".bat"}, - {"application/x-bat"}, - "DOS Batch File", - REFERENCE_URL, - ""}, - {"com.microsoft.vbscript", - {"general.script"}, - {".vbs"}, - {"application/x-vbs"}, - "VBScript File", - REFERENCE_URL, - ""}, - {"general.ion", - {"general.text"}, - {".ion"}, - {}, - "File Description File", - REFERENCE_URL, - ""}, - {"com.microsoft.registry", - {"general.database"}, - {".reg"}, - {}, - "Registry File", - REFERENCE_URL, - ""}, - {"com.microsoft.catalog", - {"general.object"}, - {".cat"}, - {}, - "Windows Catalog File", - REFERENCE_URL, - ""}, - {"com.microsoft.powershell-script", - {"general.script"}, - {".ps1"}, - {}, - "Windows PowerShell Cmdlet File", - REFERENCE_URL, - ""}, - {"org.w3.woff", - {"general.font"}, - {".woff"}, - {"font/woff"}, - "Web Open Font Format File", - REFERENCE_URL, - ""}, - {"org.sqlite.database", - {"general.database"}, - {".sqlite", ".sqlite3", ".db", ".db3", ".s3db", ".sl3"}, - {"application/vnd.sqlite3"}, - "SQLite Database", - REFERENCE_URL, - ""}, - {"com.microsoft.sys", - {"general.object"}, - {".sys"}, - {}, - "Windows System File", - REFERENCE_URL, - ""}, - {"com.microsoft.inf", - {"general.text"}, - {".inf"}, - {"text/plain"}, - "Setup Information File", - REFERENCE_URL, - ""}, - {"com.microsoft.pdb", - {"general.database"}, - {".pdb"}, - {"application/x-ms-pdb"}, - "Program Database", - REFERENCE_URL, - ""}, - {"com.microsoft.tlb", - {"general.object"}, - {".tlb"}, - {}, - "OLE Type Library", - REFERENCE_URL, - ""}, - {"com.microsoft.sccd", - {"general.xml"}, - {".sccd"}, - {}, - "Signed Custom Capability Descriptor", - REFERENCE_URL, - ""}, - {"com.adobe.f4v", - {"general.video"}, - {".f4v"}, - {"video/mp4"}, - "Flash MP4 Video File", - REFERENCE_URL, - ""}, - {"general.mp2t", - {"general.video"}, - {".m2ts", ".mts", ".m2t"}, - {"video/mp2t"}, - "Blu-ray BDAV Video File Format", - REFERENCE_URL, - ""}, - {"com.youtube.video", - {"general.video"}, - {".yt", ".vt"}, - {"video/vnd.youtube.yt"}, - "Youtube Video format", - REFERENCE_URL, - ""}, - {"com.cisco.webex-video", - {"general.video"}, - {".wrf"}, - {"video/x-webex"}, - "WebEx Recording", - REFERENCE_URL, - ""}, - {"general.mpeg-2", - {"general.video"}, - {".mpeg2", ".mpv2", ".mp2v", ".m2v", ".mpv"}, - {"video/mpeg"}, - "MPEG-2 Video format", - REFERENCE_URL, - ""}, - {"general.mpeg-1", - {"general.video"}, - {".mpeg1", ".mpv1", ".mp1v", ".m1v"}, - {"video/mpeg"}, - "MPEG-1 Video format", - REFERENCE_URL, - ""}, - {"com.real.realmedia-vbr", - {"general.video"}, - {".rmvb"}, - {"application/vnd.rn-realmedia-vbr"}, - "RealMedia Variable Bit Rate Format", - REFERENCE_URL, - ""}, - {"com.real.realvideo", - {"general.video"}, - {".rv"}, - {"video/x-pn-realvideo"}, - "RealVideo Format", - REFERENCE_URL, - ""}, - {"general.divx-video", - {"general.video"}, - {".divx"}, - {"video/divx"}, - "DivX-Encoded Movie", - REFERENCE_URL, - ""}, - {"org.csiro.annodex", - {"general.video"}, - {".axv"}, - {"video/annodex"}, - "Annodex Video Format", - REFERENCE_URL, - ""}, - {"general.ogv", - {"general.video"}, - {".ogv"}, - {"video/ogg"}, - "Ogg Video Format", - REFERENCE_URL, - ""}, - {"com.microsoft.lsf-video", - {"general.video"}, - {".lsf", ".lsx"}, - {"video/x-la-asf"}, - "Streaming Media Format", - REFERENCE_URL, - ""}, - {"general.h264-video", - {"general.video"}, - {".h264"}, - {"video/H264"}, - "H.264 Encoded Video Format", - REFERENCE_URL, - ""}, - {"general.jpeg-2000", - {"general.image"}, - {".jp2", ".jpg2", ".jpx", ".jpf", ".jpm"}, - {"image/jp2", "image/jpx", "image/jpm"}, - "JPEG 2000 Image", - REFERENCE_URL, - ""}, - {"com.fujifilm.raf-raw-image", - {"general.raw-image"}, - {".raf"}, - {"image/x-fuji-raf"}, - "Fujifilm RAW Image", - REFERENCE_URL, - ""}, - {"com.nikon.nrw-raw-image", - {"general.raw-image"}, - {".nrw"}, - {"image/x-nikon-nrw"}, - "Nikon Raw Image", - REFERENCE_URL, - ""}, - {"com.panasonic.rw2-raw-image", - {"general.raw-image"}, - {".rw2", ".raw"}, - {"image/x-panasonic-raw"}, - "Panasonic RAW Image", - REFERENCE_URL, - ""}, - {"com.pentax.pef-raw-image", - {"general.raw-image"}, - {".pef"}, - {"image/x-pentax-pef"}, - "Pentax Electronic RAW Image", - REFERENCE_URL, - ""}, - {"com.sumsung.srw-raw-image", - {"general.raw-image"}, - {".srw"}, - {"image/x-samsung-srw"}, - "Samsung RAW Image", - REFERENCE_URL, - ""}, - {"com.epson.erf-raw-image", - {"general.raw-image"}, - {".erf"}, - {"image/x-epson-erf"}, - "Epson RAW Imager", - REFERENCE_URL, - ""}, - {"com.olympus.orf-raw-image", - {"general.raw-image"}, - {".orf"}, - {"image/x-olympus-orf"}, - "Olympus RAW Image", - REFERENCE_URL, - ""}, - {"general.ief-image", - {"general.image"}, - {".ief"}, - {"image/ief"}, - "Image Exchange Format", - REFERENCE_URL, - ""}, - {"com.aol.art-image", - {"general.image"}, - {".art"}, - {"image/x-jg"}, - "ART image format", - REFERENCE_URL, - ""}, - {"general.content-form", - {"general.object"}, - {}, - {}, - "Content form format", - REFERENCE_URL, - ""}, - {"com.apple.m4p-audio", - {"general.audio"}, - {".m4p"}, - {"audio/mp4"}, - "iTunes Music Store Audio File Format", - REFERENCE_URL, - ""}, - {"general.ac3-audio", - {"general.audio"}, - {".ac3"}, - {"audio/ac3"}, - "Audio Codec 3 File Format", - REFERENCE_URL, - ""} +void PresetTypeDescriptors::InitDescriptors() +{ + typeDescriptors_ = { + {"general.entity", + {}, + {}, + {}, + "Base type for physical hierarchy.", + REFERENCE_URL, + ""}, + {"general.object", + {}, + {}, + {"*/*"}, + "Base type for logical hierarchy.", + REFERENCE_URL, + ""}, + {"general.composite-object", + {"general.object"}, + {}, + {}, + "Base type for mixed object. For example, a PDF file contains both text and special formatting data.", + REFERENCE_URL, + ""}, + {"general.text", + {"general.object"}, + {}, + {"text/*"}, + "Base type for all text.", + REFERENCE_URL, + ""}, + {"general.plain-text", + {"general.text"}, + {".txt", ".text"}, + {"text/plain"}, + "Text of unspecified encoding, with no markup.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_txt"}, + {"general.html", + {"general.text"}, + {".html", ".htm"}, + {"text/html"}, + "HTML text.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_html"}, + {"general.hyperlink", + {"general.text"}, + {}, + {}, + "Hyperlink.", + REFERENCE_URL, + ""}, + {"general.xml", + {"general.text"}, + {".xml"}, + {"text/xml"}, + "XML text.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_xml"}, + {"com.real.smil", + {"general.xml"}, + {".smil"}, + {"application/smil"}, + "Real synchronized multimedia integration language.", + REFERENCE_URL, + ""}, + {"general.source-code", + {"general.text"}, + {}, + {}, + "Generic source code.", + REFERENCE_URL, + ""}, + {"general.script", + {"general.source-code"}, + {}, + {}, + "Base type for scripting language source code.", + REFERENCE_URL, + ""}, + {"general.shell-script", + {"general.script"}, + {".sh", ".command"}, + {"text/x-shellscript"}, + "Shell script.", + REFERENCE_URL, + ""}, + {"general.csh-script", + {"general.shell-script"}, + {".csh"}, + {"text/x-csh"}, + "C-shell script.", + REFERENCE_URL, + ""}, + {"general.perl-script", + {"general.shell-script"}, + {".pl", ".pm"}, + {"text/x-perl-script"}, + "Perl script.", + REFERENCE_URL, + ""}, + {"general.php-script", + {"general.shell-script"}, + {".php", ".php3", ".php4", ".ph3", ".ph4", ".phtml"}, + {"text/x-php-script", "text/php", "application/php"}, + "PHP script.", + REFERENCE_URL, + ""}, + {"general.python-script", + {"general.shell-script"}, + {".py"}, + {"text/x-python-script"}, + "Python script.", + REFERENCE_URL, + ""}, + {"general.ruby-script", + {"general.shell-script"}, + {".rb", ".rbw"}, + {"text/ruby-script"}, + "Ruby script.", + REFERENCE_URL, + ""}, + {"general.type-script", + {"general.source-code"}, + {".ts"}, + {}, + "TypeScript source code.", + REFERENCE_URL, + ""}, + {"general.java-script", + {"general.source-code"}, + {".js", ".jscript", ".javascript"}, + {"text/javascript"}, + "JavaScript source code.", + REFERENCE_URL, + ""}, + {"general.c-header", + {"general.source-code"}, + {".h"}, + {"text/x-chdr"}, + "C header file.", + REFERENCE_URL, + ""}, + {"general.c-source", + {"general.source-code"}, + {".c"}, + {"text/x-csrc"}, + "C source code.", + REFERENCE_URL, + ""}, + {"general.c-plus-plus-header", + {"general.source-code"}, + {".hpp", ".h++", ".hxx", ".hh"}, + {"text/x-c++hdr"}, + "C++ header file.", + REFERENCE_URL, + ""}, + {"general.c-plus-plus-source", + {"general.source-code"}, + {".cp", ".cpp", ".c++", ".cc", ".cxx"}, + {"text/x-c++src"}, + "C++ source code.", + REFERENCE_URL, + ""}, + {"general.java-source", + {"general.source-code"}, + {".java", ".jav"}, + {"text/x-java"}, + "Java source code.", + REFERENCE_URL, + ""}, + {"general.markdown", + {"general.text"}, + {".md", ".markdown", ".markdn", ".mdown"}, + {"text/markdown"}, + "Markdown format.", + REFERENCE_URL, + ""}, + {"general.ebook", + {"general.composite-object"}, + {}, + {}, + "Base type for ebook.", + REFERENCE_URL, + ""}, + {"general.epub", + {"general.ebook"}, + {".epub"}, + {"application/epub+zip"}, + "Electronic publication (EPUB) format.", + REFERENCE_URL, + ""}, + {"com.amazon.azw", + {"general.ebook"}, + {".azw"}, + {"application/vnd.amazon.ebook"}, + "AZW ebook.", + REFERENCE_URL, + ""}, + {"com.amazon.azw3", + {"general.ebook"}, + {".azw3"}, + {"application/vnd.amazon.mobi8-ebook", "application/x-mobi8-ebook"}, + "AZW3 ebook.", + REFERENCE_URL, + ""}, + {"com.amazon.kfx", + {"general.ebook"}, + {".kfx"}, + {}, + "KFX ebook.", + REFERENCE_URL, + ""}, + {"com.amazon.mobi", + {"general.ebook"}, + {".mobi"}, + {"application/x-mobipocket-ebook"}, + "MOBI ebook.", + REFERENCE_URL, + ""}, + {"general.media", + {"general.object"}, + {}, + {}, + "Base type for media.", + REFERENCE_URL, + ""}, + {"general.image", + {"general.media"}, + {}, + {"image/*"}, + "Base type for images.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_image"}, + {"general.jpeg", + {"general.image"}, + {".jpg", ".jpeg", ".jpe"}, + {"image/jpeg"}, + "JPEG image.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_image"}, + {"general.png", + {"general.image"}, + {".png"}, + {"image/png"}, + "PNG image.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_image"}, + {"general.raw-image", + {"general.image"}, + {}, + {}, + "Base type for digital camera raw image formats.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_image"}, + {"general.tiff", + {"general.image"}, + {".tif", ".tiff"}, + {"image/tiff"}, + "TIFF image.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_image"}, + {"com.microsoft.bmp", + {"general.image"}, + {".bmp", ".bm"}, + {"image/bmp", "image/x-ms-bmp"}, + "Windows bitmap image.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_image"}, + {"com.microsoft.ico", + {"general.image"}, + {".ico"}, + {"image/ico", "image/x-icon"}, + "Windows icon image.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_image"}, + {"com.adobe.photoshop-image", + {"general.image"}, + {".psd"}, + {"image/x-photoshop", "image/photoshop", "image/psd", "application/photoshop"}, + "Adobe Photoshop document.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_image"}, + {"com.adobe.illustrator.ai-image", + {"general.image"}, + {".ai"}, + {}, + "Adobe Illustrator document.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_image"}, + {"general.fax", + {"general.image"}, + {}, + {}, + "Base type for fax images.", + REFERENCE_URL, + ""}, + {"com.j2.jfx-fax", + {"general.fax"}, + {".jfx"}, + {}, + "J2 fax.", + REFERENCE_URL, + ""}, + {"com.js.efx-fax", + {"general.fax"}, + {".efx"}, + {"image/efax"}, + "eFax fax.", + REFERENCE_URL, + ""}, + {"general.xbitmap-image", + {"general.image"}, + {".xbm"}, + {"image/x-xbitmap", "image/x-xbm"}, + "X bitmap image.", + REFERENCE_URL, + ""}, + {"com.truevision.tga-image", + {"general.image"}, + {".tga"}, + {"image/targa", "image/tga", "application/tga"}, + "TGA image.", + REFERENCE_URL, + ""}, + {"com.sgi.sgi-image", + {"general.image"}, + {".sgi"}, + {"image/sgi"}, + "Silicon Graphics image.", + REFERENCE_URL, + ""}, + {"com.ilm.openexr-image", + {"general.image"}, + {".exr"}, + {}, + "OpenEXR image.", + REFERENCE_URL, + ""}, + {"com.kodak.flashpix.image", + {"general.image"}, + {".fpx"}, + {"image/fpx", "application/vnd.fpx"}, + "FlashPix image.", + REFERENCE_URL, + ""}, + {"com.microsoft.word.doc", + {"general.composite-object"}, + {".doc"}, + {"application/msword"}, + "Microsoft Word data.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_doc"}, + {"com.microsoft.excel.xls", + {"general.composite-object"}, + {".xls"}, + {"application/vnd.ms-excel"}, + "Microsoft Excel data.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_xls"}, + {"com.microsoft.powerpoint.ppt", + {"general.composite-object"}, + {".ppt"}, + {"application/vnd.ms-powerpoint"}, + "Microsoft PowerPoint presentation.", + REFERENCE_URL, + ""}, + {"com.adobe.pdf", + {"general.composite-object"}, + {".pdf"}, + {"application/pdf"}, + "PDF data.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_pdf"}, + {"com.adobe.postscript", + {"general.composite-object"}, + {".ps"}, + {"application/postscript"}, + "PostScript data.", + REFERENCE_URL, + ""}, + {"com.adobe.encapsulated-postscript", + {"com.adobe.postscript"}, + {".eps"}, + {}, + "Encapsulated PostScript.", + REFERENCE_URL, + ""}, + {"general.video", + {"general.media"}, + {}, + {"video/*"}, + "Base type for video.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_video"}, + {"general.avi", + {"general.video"}, + {".avi", ".vfw"}, + {"video/avi", "video/msvideo", "video/x-msvideo"}, + "AVI video.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_video"}, + {"general.mpeg", + {"general.video"}, + {".mpg", ".mpeg", ".m75", ".m15", ".mpe"}, + {"video/mpg", "video/mpeg", "video/x-mpg", "video/x-mpeg"}, + "MPEG-1 or MPEG-2 video.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_video"}, + {"general.mpeg-4", + {"general.video"}, + {".mp4", ".mp4v", ".mpeg4"}, + {"video/mp4", "video/mp4v"}, + "MPEG-4 video.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_video"}, + {"general.3gpp", + {"general.video"}, + {".3gp", ".3gpp"}, + {"video/3gpp"}, + "3GPP video.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_video"}, + {"general.3gpp2", + {"general.video"}, + {".3g2", ".3gp2", ".3gpp2"}, + {"video/3gpp2"}, + "3GPP2 video.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_video"}, + {"com.microsoft.windows-media-wm", + {"general.video", "com.microsoft.advanced-systems-format"}, + {".wm"}, + {"video/x-ms-wm"}, + "Windows WM video.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_video"}, + {"com.microsoft.windows-media-wmv", + {"general.video", "com.microsoft.advanced-systems-format"}, + {".wmv"}, + {"video/x-ms-wmv"}, + "Windows WMV video.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_video"}, + {"com.microsoft.windows-media-wmp", + {"general.video", "com.microsoft.advanced-systems-format"}, + {".wmp"}, + {"video/x-ms-wmp"}, + "Windows WMP video.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_video"}, + {"com.microsoft.windows-media-wvx", + {"general.video", "com.microsoft.advanced-systems-format"}, + {".wvx"}, + {"video/x-ms-wvx"}, + "Windows WVX video.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_video"}, + {"com.microsoft.windows-media-wmx", + {"general.video", "com.microsoft.advanced-systems-format"}, + {".wmx"}, + {"video/x-ms-wmx"}, + "Windows WMX video.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_video"}, + {"com.real.realmedia", + {"general.video"}, + {".rm"}, + {"application/vnd.rn-realmedia"}, + "RealMedia.", + REFERENCE_URL, + ""}, + {"general.audio", + {"general.media"}, + {}, + {"audio/*"}, + "Base type for audio.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_audio"}, + {"general.aac", + {"general.audio"}, + {".aac"}, + {"audio/aac"}, + "AAC audio.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_audio"}, + {"general.aiff", + {"general.audio"}, + {".aiff"}, + {"audio/aiff"}, + "AIFF audio.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_audio"}, + {"general.alac", + {"general.audio"}, + {".alac"}, + {"audio/alac"}, + "ALAC audio.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_audio"}, + {"general.flac", + {"general.audio"}, + {".flac"}, + {"audio/flac"}, + "FLAC audio.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_flac"}, + {"general.mp3", + {"general.audio"}, + {".mp3"}, + {"audio/mp3"}, + "MPEG-3 audio.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_mp3"}, + {"general.ogg", + {"general.audio"}, + {".ogg"}, + {"audio/ogg"}, + "OGG audio.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_audio"}, + {"general.pcm", + {"general.audio"}, + {".pcm"}, + {"audio/pcm"}, + "PCM audio.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_audio"}, + {"com.microsoft.advanced-systems-format", + {"general.media"}, + {".asf"}, + {"video/x-ms-asf", "application/vnd.ms-asf"}, + "Advanced Systems format", + REFERENCE_URL, + ""}, + {"com.microsoft.advanced-stream-redirector", + {"general.video"}, + {".asx"}, + {"video/x-ms-asf"}, + "Advanced stream redirector", + REFERENCE_URL, + ""}, + {"com.microsoft.windows-media-wma", + {"general.audio", "com.microsoft.advanced-systems-format"}, + {".wma"}, + {"audio/x-ms-wma"}, + "Windows WMA audio.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_wma"}, + {"com.microsoft.waveform-audio", + {"general.audio", "com.microsoft.advanced-systems-format"}, + {".wav", ".wave"}, + {"audio/wav", "audio/wave", "audio/x-wav"}, + "Waveform audio.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_wav"}, + {"com.microsoft.windows-media-wax", + {"general.audio", "com.microsoft.advanced-systems-format"}, + {".wax"}, + {"audio/x-ms-wax"}, + "Windows WAX audio.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_audio"}, + {"general.au-audio", + {"general.audio"}, + {".au", ".snd"}, + {"audio/basic", "audio/au", "audio/snd"}, + "Au file format.", + REFERENCE_URL, + ""}, + {"general.aifc-audio", + {"general.audio"}, + {".aifc", ".aif", ".aiff"}, + {"audio/x-aiff"}, + "Audio Interchange File Format.", + REFERENCE_URL, + ""}, + {"com.digidesign.sd2-audio", + {"general.audio"}, + {".sd2"}, + {"audio/x-sd2"}, + "Digidesign Sound Designer II audio.", + REFERENCE_URL, + ""}, + {"com.real.realaudio", + {"general.audio"}, + {".ram", ".ra"}, + {"audio/vnd.rn-realaudio", "audio/x-pn-realaudio"}, + "RealMedia audio.", + REFERENCE_URL, + ""}, + {"general.file", + {"general.entity"}, + {}, + {}, + "Base type for file.", + REFERENCE_URL, + ""}, + {"general.directory", + {"general.entity"}, + {}, + {}, + "Base type for directory.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_folder"}, + {"general.folder", + {"general.directory"}, + {}, + {}, + "Base type for folder.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_folder"}, + {"general.symlink", + {"general.entity"}, + {}, + {}, + "Base type for symlink.", + REFERENCE_URL, + ""}, + {"general.archive", + {"general.object"}, + {}, + {}, + "Base type for an archive of files and directories.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_compress"}, + {"general.bz2-archive", + {"general.archive"}, + {".bz2", ".bzip2"}, + {"application/x-bzip2"}, + "BZip2 archive.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_compress"}, + {"general.disk-image", + {"general.archive"}, + {}, + {}, + "Base type for items mountable as a volume.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_compress"}, + {"general.tar-archive", + {"general.archive"}, + {".tar"}, + {"application/x-tar", "application/tar"}, + "Tar archive.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_compress"}, + {"general.zip-archive", + {"general.archive"}, + {".zip"}, + {"application/zip"}, + "Zip archive.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_zip"}, + {"com.sun.java-archive", + {"general.archive", "general.executable"}, + {".jar"}, + {"application/java-archive"}, + "Java archive.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_compress"}, + {"org.gnu.gnu-tar-archive", + {"general.archive"}, + {".gtar"}, + {"application/x-gtar"}, + "GNU archive.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_compress"}, + {"org.gnu.gnu-zip-archive", + {"general.archive"}, + {".gz", ".gzip"}, + {"application/x-gzip", "application/gzip"}, + "Gzip archive.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_compress"}, + {"org.gnu.gnu-zip-tar-archive", + {"general.archive"}, + {".tgz"}, + {"application/x-gtar"}, + "Gzip tar archive.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_compress"}, + {"org.openxmlformats.openxml", + {"general.archive"}, + {}, + {}, + "Office Open XML.", + REFERENCE_URL, + ""}, + {"org.openxmlformats.wordprocessingml.document", + {"general.composite-object", "org.openxmlformats.openxml"}, + {".docx"}, + {"application/vnd.openxmlformats-officedocument.wordprocessingml.document"}, + "Office Open XML Document.", + REFERENCE_URL, + ""}, + {"org.openxmlformats.spreadsheetml.sheet", + {"general.composite-object", "org.openxmlformats.openxml"}, + {".xlsx"}, + {"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"}, + "Office Open XML Workbook.", + REFERENCE_URL, + ""}, + {"org.openxmlformats.presentationml.presentation", + {"general.composite-object", "org.openxmlformats.openxml"}, + {".pptx"}, + {"application/vnd.openxmlformats-officedocument.presentationml.presentation"}, + "Office Open XML Presentation.", + REFERENCE_URL, + ""}, + {"org.oasis.opendocument", + {"general.archive"}, + {}, + {}, + "Open Document Format for Office Applications.", + REFERENCE_URL, + ""}, + {"org.oasis.opendocument.text", + {"general.composite-object", "org.oasis.opendocument"}, + {".odt", ".fodt"}, + {"application/vnd.oasis.opendocument.text"}, + "OpenDocument Text.", + REFERENCE_URL, + ""}, + {"org.oasis.opendocument.spreadsheet", + {"general.composite-object", "org.oasis.opendocument"}, + {".ods", ".fods"}, + {"application/vnd.oasis.opendocument.spreadsheet"}, + "OpenDocument Spreadsheet.", + REFERENCE_URL, + ""}, + {"org.oasis.opendocument.presentation", + {"general.composite-object", "org.oasis.opendocument"}, + {".odp", ".fodp"}, + {"application/vnd.oasis.opendocument.presentation"}, + "OpenDocument Presentation.", + REFERENCE_URL, + ""}, + {"org.oasis.opendocument.graphics", + {"general.composite-object", "org.oasis.opendocument"}, + {".odg", ".fodg"}, + {"application/vnd.oasis.opendocument.graphics"}, + "OpenDocument Graphics.", + REFERENCE_URL, + ""}, + {"org.oasis.opendocument.formula", + {"org.oasis.opendocument"}, + {".odf"}, + {"application/vnd.oasis.opendocument.formula"}, + "OpenDocument Formulat.", + REFERENCE_URL, + ""}, + {"com.allume.stuffit-archive", + {"general.archive"}, + {".sit", ".sitx"}, + {"application/x-stuffit", "application/x-sit", "application/stuffit"}, + "Stuffit archive.", + REFERENCE_URL, + ""}, + {"general.calendar", + {"general.text"}, + {}, + {"text/calendar"}, + "Base type for scheduled events.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_calendar"}, + {"general.vcs", + {"general.calendar"}, + {".vcs"}, + {"text/calendar"}, + "vCalendar type.", + REFERENCE_URL, + ""}, + {"general.ics", + {"general.calendar"}, + {".ics"}, + {"text/calendar"}, + "iCalendar type.", + REFERENCE_URL, + ""}, + {"general.contact", + {"general.object"}, + {}, + {}, + "Base type for contact information.", + REFERENCE_URL, + ""}, + {"general.database", + {"general.object"}, + {}, + {}, + "Base type for databases.", + REFERENCE_URL, + ""}, + {"general.message", + {"general.object"}, + {}, + {}, + "Base type for messages.", + REFERENCE_URL, + ""}, + {"general.executable", + {"general.object"}, + {}, + {}, + "Base type for executable data.", + REFERENCE_URL, + ""}, + {"com.microsoft.portable-executable", + {"general.executable"}, + {".exe", ".dll"}, + {"application/vnd.microsoft.portable-executable"}, + "Microsoft Windows application.", + REFERENCE_URL, + ""}, + {"com.sun.java-class", + {"general.executable"}, + {".class"}, + {}, + "Java class.", + REFERENCE_URL, + ""}, + {"general.vcard", + {"general.object"}, + {".vcf", ".vcard"}, + {"text/vcard", "text/x-vcard"}, + "Base type for electronic business card.", + REFERENCE_URL, + ""}, + {"general.navigation", + {"general.object"}, + {}, + {}, + "Base type for navigation.", + REFERENCE_URL, + ""}, + {"general.location", + {"general.navigation"}, + {}, + {}, + "Navigation location.", + REFERENCE_URL, + ""}, + {"general.font", + {"general.object"}, + {}, + {}, + "Base type for fonts.", + REFERENCE_URL, + ""}, + {"general.truetype-font", + {"general.font"}, + {".ttf"}, + {"font/ttf"}, + "TrueType font.", + REFERENCE_URL, + ""}, + {"general.truetype-collection-font", + {"general.font"}, + {".ttc"}, + {"font/collection"}, + "TrueType collection font.", + REFERENCE_URL, + ""}, + {"general.opentype-font", + {"general.font"}, + {".otf"}, + {"font/otf"}, + "OpenType font.", + REFERENCE_URL, + ""}, + {"com.adobe.postscript-font", + {"general.font"}, + {}, + {}, + "PostScript font.", + REFERENCE_URL, + ""}, + {"openharmony.form", + {"general.object"}, + {}, + {}, + "OpenHarmony system defined form.", + REFERENCE_URL, + ""}, + {"openharmony.app-item", + {"general.object"}, + {}, + {}, + "OpenHarmony system defined app item.", + REFERENCE_URL, + ""}, + {"openharmony.pixel-map", + {"general.image"}, + {}, + {}, + "OpenHarmony system defined pixel map.", + REFERENCE_URL, + "sys.media.ohos_ic_normal_white_grid_image"}, + {"openharmony.atomic-service", + {"general.object"}, + {}, + {}, + "OpenHarmony system defined atomic service.", + REFERENCE_URL, + ""}, + {"openharmony.package", + {"general.directory"}, + {}, + {}, + "OpenHarmony system defined package (that is, a directory presented to the user as a file).", + REFERENCE_URL, + ""}, + {"openharmony.hap", + {"openharmony.package"}, + {".hap"}, + {}, + "OpenHarmony system defined ability package.", + REFERENCE_URL, + ""}, + {"openharmony.hdoc", + {"general.composite-object"}, + {".hdoc"}, + {}, + "OpenHarmony system AppNotepad data format.", + REFERENCE_URL, + ""}, + {"openharmony.hinote", + {"general.composite-object"}, + {".hinote"}, + {}, + "OpenHarmony system Notes data format.", + REFERENCE_URL, + ""}, + {"openharmony.styled-string", + {"general.composite-object"}, + {}, + {}, + "OpenHarmony system defined styled string.", + REFERENCE_URL, + ""}, + {"openharmony.want", + {"general.object"}, + {}, + {}, + "OpenHarmony system defined Want.", + REFERENCE_URL, + ""}, + {"openharmony.moving-photo", + {"general.media"}, + {}, + {}, + "OpenHarmony system defined moving photo.", + REFERENCE_URL, + ""}, + {"macos.dmg", + {"general.disk-image"}, + {".dmg"}, + {"application/x-apple-diskimage"}, + "Apple Disk Image", + REFERENCE_URL, + ""}, + {"debian.deb", + {"general.archive"}, + {".deb", ".udeb"}, + {"application/x-debian-package", "application/vnd.debian.binary-package"}, + "OpenHarmony system defined Want.", + REFERENCE_URL, + ""}, + {"general.ofd", + {"general.composite-object"}, + {".ofd"}, + {}, + "Open fixed-layout document, a national standard for format documents", + REFERENCE_URL, + ""}, + {"general.opg", + {"general.archive"}, + {".opg"}, + {}, + "OPG archive", + REFERENCE_URL, + ""}, + {"general.tex", + {"general.source-code"}, + {}, + {}, + "Base type for TeX source code", + REFERENCE_URL, + ""}, + {"general.css", + {"general.script"}, + {".css"}, + {"text/css"}, + "Cascading style sheets", + REFERENCE_URL, + ""}, + {"general.vob", + {"general.video"}, + {".vob"}, + {"video/mpeg", "video/x-ms-vob"}, + "", + REFERENCE_URL, + ""}, + {"general.dif-video", + {"general.video"}, + {".dif"}, + {"video/dv"}, + "Digital interface format", + REFERENCE_URL, + ""}, + {"general.dv-video", + {"general.video"}, + {".dv"}, + {"video/dv"}, + "DV video", + REFERENCE_URL, + ""}, + {"general.flc-animation", + {"general.video"}, + {".fli", ".flc"}, + {"video/fli", "video/flc"}, + "FLIC file format", + REFERENCE_URL, + ""}, + {"general.mng", + {"general.video"}, + {".mng"}, + {"video/x-mng"}, + "Multiple-image network graphics", + REFERENCE_URL, + ""}, + {"general.mpegurl-video", + {"general.video"}, + {".mxu", ".m4u"}, + {"video/vnd.mpegurl"}, + "Video playlist", + REFERENCE_URL, + ""}, + {"general.ts", + {"general.video"}, + {".ts"}, + {"video/mp2ts", "video/mp2t"}, + "MPEG transport stream", + REFERENCE_URL, + ""}, + {"general.amr", + {"general.audio"}, + {".amr"}, + {"audio/amr"}, + "The adaptive multi-rate audio codecs", + REFERENCE_URL, + ""}, + {"general.amr-wb", + {"general.audio"}, + {".awb"}, + {"audio/amr-wb"}, + "Adaptive multi-rate wideband", + REFERENCE_URL, + ""}, + {"general.gsm", + {"general.audio"}, + {".gsm"}, + {"audio/x-gsm", "audio/gsm"}, + "Global system form mobile audio format", + REFERENCE_URL, + ""}, + {"general.imy", + {"general.audio"}, + {".imy"}, + {"audio/imelody"}, + "Non-polyphonic ringtone exchange object format", + REFERENCE_URL, + ""}, + {"general.kar", + {"general.audio"}, + {".kar"}, + {"audio/midi"}, + "Karaoke MIDI file format", + REFERENCE_URL, + ""}, + {"general.mpegurl-audio", + {"general.audio"}, + {".m3u"}, + {"audio/mpegurl", "audio/x-mpegurl"}, + "Audio playlist", + REFERENCE_URL, + ""}, + {"general.mpeg-4-audio", + {"general.audio"}, + {".m4a", ".m4b"}, + {"audio/mpeg"}, + "Audio-only MPEG-4 file", + REFERENCE_URL, + ""}, + {"general.midi-audio", + {"general.audio"}, + {".mid", ".midi"}, + {"audio/midi"}, + "MIDI audio", + REFERENCE_URL, + ""}, + {"general.mp2", + {"general.audio"}, + {".mp2"}, + {"audio/mpeg"}, + "MPEG-1 audio layer II or MPEG-2 audio layer II", + REFERENCE_URL, + ""}, + {"general.mpeg-audio", + {"general.audio"}, + {".mpga"}, + {"audio/mpeg"}, + "MPEG audio format", + REFERENCE_URL, + ""}, + {"general.mxmf", + {"general.audio"}, + {".mxmf"}, + {"audio/mobile-xmf"}, + "Mobile XMF audio format", + REFERENCE_URL, + ""}, + {"general.ota", + {"general.audio"}, + {".ota"}, + {"audio/midi"}, + "OTA ringtone file", + REFERENCE_URL, + ""}, + {"general.pls", + {"general.audio"}, + {".pls"}, + {"audio/x-scpls"}, + "Multimedia playlist format", + REFERENCE_URL, + ""}, + {"general.rtttl", + {"general.audio"}, + {".rtttl"}, + {"audio/midi"}, + "Ring tone transfer language file", + REFERENCE_URL, + ""}, + {"general.psid", + {"general.audio"}, + {".sid", ".psid"}, + {"audio/prs.sid"}, + "SID audio", + REFERENCE_URL, + ""}, + {"general.ulaw-audio", + {"general.audio"}, + {".au", ".ulw", ".snd"}, + {"audio/basic", "audio/au", "audio/snd"}, + "uLaw audio", + REFERENCE_URL, + ""}, + {"general.xmf", + {"general.audio"}, + {".xmf"}, + {"audio/midi"}, + "Extensible music file", + REFERENCE_URL, + ""}, + {"general.gif", + {"general.image"}, + {".gif"}, + {"image/gif"}, + "GIF image", + REFERENCE_URL, + ""}, + {"general.djvu-image", + {"general.image"}, + {".djv", ".djvu"}, + {"image/vnd.djvu"}, + "Djvu image", + REFERENCE_URL, + ""}, + {"general.jng-image", + {"general.image"}, + {".jng"}, + {"image/x-jng"}, + "JPEG network graphic", + REFERENCE_URL, + ""}, + {"general.pcx-image", + {"general.image"}, + {".pcx"}, + {"image/vnd.zbrush.pcx"}, + "Paintbrush bitmap image", + REFERENCE_URL, + ""}, + {"general.pbm-image", + {"general.image"}, + {".pbm"}, + {"image/x-portable-bitmap"}, + "Portable bitmap image", + REFERENCE_URL, + ""}, + {"general.pgm-image", + {"general.image"}, + {".pgm"}, + {"image/x-portable-graymap"}, + "Portable gray map image", + REFERENCE_URL, + ""}, + {"general.pnm-image", + {"general.image"}, + {".pnm"}, + {"image/x-portable-anymap"}, + "Portable any map image file", + REFERENCE_URL, + ""}, + {"general.ppm-image", + {"general.image"}, + {".ppm"}, + {"image/x-portable-pixmap"}, + "Portable pixmap image", + REFERENCE_URL, + ""}, + {"general.rgb-image", + {"general.image"}, + {".rgb"}, + {"image/x-rgb"}, + "RGB bitmap", + REFERENCE_URL, + ""}, + {"general.svg-image", + {"general.image"}, + {".svg", ".svgz"}, + {"image/svg+xml"}, + "Scalable vector graphic", + REFERENCE_URL, + ""}, + {"general.wbmp-image", + {"general.image"}, + {".wbmp"}, + {"image/vnd.wap.wbmp"}, + "Wireless bitmap image", + REFERENCE_URL, + ""}, + {"general.xpixmap-image", + {"general.image"}, + {".xpm"}, + {"image/x-xpixmap"}, + "X11 pixmap graphic", + REFERENCE_URL, + ""}, + {"general.xwindowdump-image", + {"general.image"}, + {".xwd"}, + {"image/x-xwindowdump"}, + "X windows dump image", + REFERENCE_URL, + ""}, + {"general.heif", + {"general.image"}, + {".heif", ".heifs", ".hif"}, + {"image/heif"}, + "High efficiency image format", + REFERENCE_URL, + ""}, + {"general.heic", + {"general.image"}, + {".heic", ".heics"}, + {"image/heic"}, + "High efficiency image format", + REFERENCE_URL, + ""}, + {"general.virtual-cd", + {"general.disk-image"}, + {".vcd"}, + {"application/x-cdlink"}, + "Virtual CD", + REFERENCE_URL, + ""}, + {"general.boo-source", + {"general.source-code"}, + {".boo"}, + {"text/x-boo"}, + "Boo source code", + REFERENCE_URL, + ""}, + {"general.d-source", + {"general.source-code"}, + {".d"}, + {"text/x-dsrc"}, + "D source code file", + REFERENCE_URL, + ""}, + {"general.html-component", + {"general.source-code"}, + {".htc"}, + {"text/x-component"}, + "HTML component", + REFERENCE_URL, + ""}, + {"general.pascal-source", + {"general.source-code"}, + {".p", ".pas"}, + {"text/x-pascal"}, + "Pascal source code", + REFERENCE_URL, + ""}, + {"general.haskell-script", + {"general.script"}, + {".hs"}, + {"text/x-haskell"}, + "Haskell script", + REFERENCE_URL, + ""}, + {"general.literate-haskell-script", + {"general.script"}, + {".lhs"}, + {"text/x-literate-haskell"}, + "Literate haskell script", + REFERENCE_URL, + ""}, + {"general.tcl-script", + {"general.script"}, + {".tcl"}, + {"text/x-tcl"}, + "Tcl script", + REFERENCE_URL, + ""}, + {"general.asc-text", + {"general.text"}, + {".asc"}, + {"text/plain"}, + "ASCII text file", + REFERENCE_URL, + ""}, + {"general.portable-object", + {"general.text"}, + {".po"}, + {"text/plain"}, + "Portable object", + REFERENCE_URL, + ""}, + {"general.rich-text", + {"general.text"}, + {".rtf", ".rtx"}, + {"text/rtf", "text/richtext"}, + "Rich text format file", + REFERENCE_URL, + ""}, + {"general.delimited-values-text", + {"general.text"}, + {}, + {}, + "Base type for delimited-values text", + REFERENCE_URL, + ""}, + {"general.comma-separated-values-text", + {"general.delimited-values-text"}, + {".csv"}, + {"text/csv"}, + "Comma-separated values file", + REFERENCE_URL, + ""}, + {"general.diff", + {"general.text"}, + {".diff"}, + {"text/plain"}, + "Patch file", + REFERENCE_URL, + ""}, + {"general.setext", + {"general.text"}, + {".etx"}, + {"text/x-setext"}, + "Structure enhanced Text", + REFERENCE_URL, + ""}, + {"general.gcd", + {"general.text"}, + {".gcd"}, + {"text/x-pcs-gcd"}, + "General content descriptor", + REFERENCE_URL, + ""}, + {"general.tab-separated-values-text", + {"general.delimited-values-text"}, + {".tsv"}, + {"text/tab-separated-values"}, + "Tab-Separated values file", + REFERENCE_URL, + ""}, + {"general.p7r", + {"general.text"}, + {".p7r"}, + {"application/x-pkcs7-certreqresp"}, + "Certificate request response file", + REFERENCE_URL, + ""}, + {"general.pem", + {"general.text"}, + {".pem"}, + {"application/x-pem-file"}, + "Privacy enhanced mail certificate", + REFERENCE_URL, + ""}, + {"general.chess-pgn", + {"general.plain-text"}, + {".pgn"}, + {"application/x-chess-pgn", "application/vnd.chess-pgn"}, + "Portable game notation file", + REFERENCE_URL, + ""}, + {"general.lha-archive", + {"general.archive"}, + {".lha"}, + {"application/x-lha"}, + "LHARC compressed archive", + REFERENCE_URL, + ""}, + {"general.lzh-archive", + {"general.archive"}, + {".lzh"}, + {"application/x-lzh"}, + "LZH compressed file", + REFERENCE_URL, + ""}, + {"general.lzx-archive", + {"general.archive"}, + {".lzx"}, + {"application/x-lzx"}, + "LZX compressed archive", + REFERENCE_URL, + ""}, + {"general.taz-archive", + {"general.tar-archive"}, + {".taz", ".tar.z", ".tz"}, + {"application/x-gtar"}, + "Tar zipped file", + REFERENCE_URL, + ""}, + {"general.shar-archive", + {"general.archive"}, + {".shar"}, + {"application/x-shar"}, + "Unix Shar archive", + REFERENCE_URL, + ""}, + {"general.cpio-archive", + {"general.archive"}, + {".cpio"}, + {"application/x-cpio"}, + "Unix CPIO archive", + REFERENCE_URL, + ""}, + {"general.web-archive", + {"general.archive"}, + {".mht", ".mhtml"}, + {"application/x-mimearchive"}, + "MHTML web archive", + REFERENCE_URL, + ""}, + {"general.ustar", + {"general.archive"}, + {".ustar"}, + {"application/x-ustar"}, + "Uniform standard tape archive format", + REFERENCE_URL, + ""}, + {"general.mathml", + {"general.xml"}, + {".mml"}, + {"text/mathml", "application/mathml+xml"}, + "Mathematical markup language file", + REFERENCE_URL, + ""}, + {"general.xhtml", + {"general.xml"}, + {".xhtml"}, + {"application/xhtml+xml"}, + "XHTML", + REFERENCE_URL, + ""}, + {"general.rss", + {"general.xml"}, + {".rss"}, + {"application/rss+xml"}, + "Rich site summary", + REFERENCE_URL, + ""}, + {"general.rdf", + {"general.xml"}, + {".rdf"}, + {"application/rdf+xml"}, + "Resource description framework file", + REFERENCE_URL, + ""}, + {"general.cad", + {"general.object"}, + {}, + {}, + "Base type for computer-aided design", + REFERENCE_URL, + ""}, + {"general.iges", + {"general.cad"}, + {".iges", ".igs"}, + {"model/iges"}, + "IGES drawing", + REFERENCE_URL, + ""}, + {"general.octet-stream", + {"general.object"}, + {}, + {"application/octet-stream"}, + "Arbitrary binary data", + REFERENCE_URL, + ""}, + {"general.iso", + {"general.disk-image"}, + {".iso"}, + {"application/x-iso9660-image"}, + "Disc image file", + REFERENCE_URL, + ""}, + {"general.mesh-model", + {"general.object"}, + {".msh", ".mesh", ".silo"}, + {"model/mesh"}, + "3D mesh model", + REFERENCE_URL, + ""}, + {"general.certificate", + {"general.object"}, + {}, + {}, + "Base type for security certificate", + REFERENCE_URL, + ""}, + {"general.c-object", + {"general.executable"}, + {".o"}, + {"application/x-object"}, + "Compiled C object file", + REFERENCE_URL, + ""}, + {"general.dvi", + {"general.tex"}, + {".dvi"}, + {"application/x-dvi"}, + "Device independent format file", + REFERENCE_URL, + ""}, + {"general.cer-certificate", + {"general.certificate"}, + {".cer"}, + {"application/pkix-cert"}, + "Internet security certificate", + REFERENCE_URL, + ""}, + {"general.crt-certificate", + {"general.certificate"}, + {".crt"}, + {"application/x-x509-ca-cert", "application/x-x509-server-cert", "application/x-x509-user-cert"}, + "Security Certificate", + REFERENCE_URL, + ""}, + {"general.crl-certificate", + {"general.certificate"}, + {".crl"}, + {"application/x-pkix-crl"}, + "Certificate revocation list file", + REFERENCE_URL, + ""}, + {"general.prn", + {"general.composite-object"}, + {".prn"}, + {}, + "Print to file", + REFERENCE_URL, + ""}, + {"org.oasis-open.opendocument.chart", + {"org.oasis.opendocument", "general.composite-object"}, + {".odc"}, + {"application/vnd.oasis.opendocument.chart"}, + "Open Document chart", + REFERENCE_URL, + ""}, + {"org.oasis-open.opendocument.text-master", + {"org.oasis.opendocument", "general.composite-object"}, + {".odm"}, + {"application/vnd.oasis.opendocument.text-master"}, + "Open Document text master", + REFERENCE_URL, + ""}, + {"org.oasis-open.opendocument.text-web", + {"org.oasis.opendocument", "general.composite-object"}, + {".oth"}, + {"application/vnd.oasis.opendocument.text-web"}, + "Open Document HTML template", + REFERENCE_URL, + ""}, + {"org.oasis-open.opendocument.database", + {"org.oasis.opendocument", "general.database"}, + {".odb"}, + {"application/vnd.oasis.opendocument.database"}, + "Open Document database", + REFERENCE_URL, + ""}, + {"org.oasis-open.opendocument.image", + {"org.oasis.opendocument", "general.image"}, + {".odi"}, + {"application/vnd.oasis.opendocument.image"}, + "Open Document image", + REFERENCE_URL, + ""}, + {"org.oasis-open.opendocument.formula-template", + {"org.oasis.opendocument", "general.composite-object"}, + {".otf"}, + {"application/vnd.oasis.opendocument.formula-template"}, + "Open Document formula template", + REFERENCE_URL, + ""}, + {"org.oasis-open.opendocument.chart-template", + {"org.oasis.opendocument", "general.composite-object"}, + {".otc"}, + {"application/vnd.oasis.opendocument.chart-template"}, + "Open Document chart template", + REFERENCE_URL, + ""}, + {"org.oasis-open.opendocument.presentation-template", + {"org.oasis.opendocument", "general.composite-object"}, + {".otp"}, + {"application/vnd.oasis.opendocument.presentation-template"}, + "Open Document presentation template", + REFERENCE_URL, + ""}, + {"org.oasis-open.opendocument.image-template", + {"org.oasis.opendocument", "general.image"}, + {".oti"}, + {"application/vnd.oasis.opendocument.image-template"}, + "Open Document image template", + REFERENCE_URL, + ""}, + {"org.oasis-open.opendocument.graphics-template", + {"org.oasis.opendocument", "general.composite-object"}, + {".otg"}, + {"application/vnd.oasis.opendocument.graphics-template"}, + "Open Document graphics template", + REFERENCE_URL, + ""}, + {"org.oasis-open.opendocument.spreadsheet-template", + {"org.oasis.opendocument", "general.composite-object"}, + {".ots"}, + {"application/vnd.oasis.opendocument.spreadsheet-template"}, + "Open Document spreadsheet template", + REFERENCE_URL, + ""}, + {"org.oasis-open.opendocument.text-template", + {"org.oasis.opendocument", "general.composite-object"}, + {".ott"}, + {"application/vnd.oasis.opendocument.text-template"}, + "Open Document text template", + REFERENCE_URL, + ""}, + {"com.microsoft.word.dot", + {"general.composite-object"}, + {".dot"}, + {"application/msword"}, + "Microsoft Word document template", + REFERENCE_URL, + ""}, + {"com.microsoft.powerpoint.pps", + {"general.composite-object"}, + {".pps"}, + {"application/vnd.ms-powerpoint"}, + "Microsoft PowerPoint slide show", + REFERENCE_URL, + ""}, + {"com.microsoft.powerpoint.pot", + {"general.composite-object"}, + {".pot"}, + {"application/vnd.ms-powerpoint"}, + "Microsoft PowerPoint Template", + REFERENCE_URL, + ""}, + {"com.microsoft.excel.xlt", + {"general.composite-object"}, + {".xlt"}, + {"application/vnd.ms-excel"}, + "Microsoft Excel spreadsheet template", + REFERENCE_URL, + ""}, + {"com.microsoft.visio.vsd", + {"general.composite-object"}, + {".vsd"}, + {"application/vnd.visio"}, + "Microsoft Office Visio 2003-2010 drawing", + REFERENCE_URL, + ""}, + {"org.openxmlformats.drawingml.visio", + {"org.openxmlformats.openxml", "general.composite-object"}, + {".vsdx"}, + {"application/vnd.openxmlformats-officedocument.drawingml.drawing"}, + "Microsoft Visio drawing", + REFERENCE_URL, + ""}, + {"org.openxmlformats.drawingml.template", + {"org.openxmlformats.openxml", "general.composite-object"}, + {".vstx"}, + {}, + "Microsoft Visio drawing template", + REFERENCE_URL, + ""}, + {"org.openxmlformats.drawingml.visio.macroenabled", + {"org.openxmlformats.openxml", "general.composite-object"}, + {".vsdm"}, + {}, + "Visio macro-enabled drawing", + REFERENCE_URL, + ""}, + {"org.openxmlformats.drawingml.template.macroenabled", + {"org.openxmlformats.openxml", "general.composite-object"}, + {".vstm"}, + {}, + "Visio macro-enabled drawing template", + REFERENCE_URL, + ""}, + {"org.openxmlformats.wordprocessingml.template", + {"org.openxmlformats.openxml", "general.composite-object"}, + {".dotx"}, + {"application/vnd.openxmlformats-officedocument.wordprocessingml.template"}, + "Office Open XML document template.", + REFERENCE_URL, + ""}, + {"org.openxmlformats.presentationml.template", + {"org.openxmlformats.openxml", "general.composite-object"}, + {".potx"}, + {"application/vnd.openxmlformats-officedocument.presentationml.template"}, + "Office Open XML presentation template", + REFERENCE_URL, + ""}, + {"org.openxmlformats.presentationml.slideshow", + {"org.openxmlformats.openxml", "general.composite-object"}, + {".ppsx"}, + {"application/vnd.openxmlformats-officedocument.presentationml.slideshow"}, + "Office Open XML slide show", + REFERENCE_URL, + ""}, + {"org.openxmlformats.spreadsheetml.template", + {"org.openxmlformats.openxml", "general.composite-object"}, + {".xltx"}, + {"application/vnd.openxmlformats-officedocument.spreadsheetml.template"}, + "Office Open XML spreadsheet template", + REFERENCE_URL, + ""}, + {"org.openxmlformats.wordprocessingml.document.macroenabled", + {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, + {".docm"}, + {"application/vnd.ms-word.document.macroEnabled.12"}, + "Office Open XML word processing document (macros enabled)", + REFERENCE_URL, + ""}, + {"org.openxmlformats.wordprocessingml.template.macroenabled", + {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, + {".dotm"}, + {"application/vnd.ms-word.template.macroEnabled.12"}, + "Office Open XML word processing template (macros enabled)", + REFERENCE_URL, + ""}, + {"org.openxmlformats.spreadsheetml.template.macroenabled", + {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, + {".xltm"}, + {"application/vnd.ms-excel.template.macroEnabled.12"}, + "Office Open XML spreadsheet template (macros enabled)", + REFERENCE_URL, + ""}, + {"org.openxmlformats.spreadsheetml.addin.macroenabled", + {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, + {".xlam"}, + {"application/vnd.ms-excel.addin.macroEnabled.12"}, + "Office Open XML spreadsheet addin (macros enabled)", + REFERENCE_URL, + ""}, + {"org.openxmlformats.spreadsheetml.binary.macroenabled", + {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, + {".xlsb"}, + {"application/vnd.ms-excel.sheet.binary.macroEnabled.12"}, + "Office Open XML spreadsheet binary (macros enabled)", + REFERENCE_URL, + ""}, + {"org.openxmlformats.spreadsheetml.sheet.macroenabled", + {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, + {".xlsm"}, + {"application/vnd.ms-excel.sheet.macroEnabled.12"}, + "Office Open XML spreadsheet (macros enabled)", + REFERENCE_URL, + ""}, + {"org.openxmlformats.presentationml.addin.macroenabled", + {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, + {".ppam"}, + {"application/vnd.ms-powerpoint.addin.macroEnabled.12"}, + "Office Open XML presentation addin (macros enabled)", + REFERENCE_URL, + ""}, + {"org.openxmlformats.presentationml.presentation.macroenabled", + {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, + {".pptm"}, + {"application/vnd.ms-powerpoint.presentation.macroEnabled.12"}, + "Office Open XML presentation (macros enabled)", + REFERENCE_URL, + ""}, + {"org.openxmlformats.presentationml.slideshow.macroenabled", + {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, + {".ppsm"}, + {"application/vnd.ms-powerpoint.slideshow.macroEnabled.12"}, + "Office Open XML slide show (macros enabled)", + REFERENCE_URL, + ""}, + {"org.openxmlformats.presentationml.template.macroenabled", + {"org.openxmlformats.openxml", "general.composite-object", "general.executable"}, + {".potm"}, + {"application/vnd.ms-powerpoint.template.macroEnabled.12"}, + "Office Open XML presentation template (macros enabled)", + REFERENCE_URL, + ""}, + {"org.openoffice", + {"general.archive"}, + {}, + {}, + "OpenOffice document format for open-source office software suite", + REFERENCE_URL, + ""}, + {"org.openoffice.calc", + {"org.openoffice", "general.composite-object"}, + {".sxc"}, + {"application/vnd.sun.xml.calc"}, + "StarOffice Calc spreadsheet", + REFERENCE_URL, + ""}, + {"org.openoffice.draw", + {"org.openoffice", "general.composite-object"}, + {".sxd"}, + {"application/vnd.sun.xml.draw"}, + "StarOffice Drawing", + REFERENCE_URL, + ""}, + {"org.openoffice.writer-global", + {"org.openoffice", "general.composite-object"}, + {".sxg"}, + {"application/vnd.sun.xml.writer.global"}, + "Apache OpenOffice master document", + REFERENCE_URL, + ""}, + {"org.openoffice.impress", + {"org.openoffice", "general.composite-object"}, + {".sxi"}, + {"application/vnd.sun.xml.impress"}, + "StarOffice Impress presentation", + REFERENCE_URL, + ""}, + {"org.openoffice.math", + {"org.openoffice", "general.composite-object"}, + {".sxm"}, + {"application/vnd.sun.xml.math"}, + "StarMath Formula", + REFERENCE_URL, + ""}, + {"org.openoffice.writer", + {"org.openoffice", "general.composite-object"}, + {".sxw"}, + {"application/vnd.sun.xml.writer"}, + "StarOffice Writer document", + REFERENCE_URL, + ""}, + {"org.openoffice.calc.template", + {"org.openoffice", "general.composite-object"}, + {".stc"}, + {"application/vnd.sun.xml.calc.template"}, + "StarOffice Calc spreadsheet template", + REFERENCE_URL, + ""}, + {"org.openoffice.draw.template", + {"org.openoffice", "general.composite-object"}, + {".std"}, + {"application/vnd.sun.xml.draw.template"}, + "Apache OpenOffice Drawing template", + REFERENCE_URL, + ""}, + {"org.openoffice.impress.template", + {"org.openoffice", "general.composite-object"}, + {".sti"}, + {"application/vnd.sun.xml.impress.template"}, + "StarOffice Presentation template", + REFERENCE_URL, + ""}, + {"org.openoffice.writer.template", + {"org.openoffice", "general.composite-object"}, + {".stw"}, + {"application/vnd.sun.xml.writer.template"}, + "StarOffice Document template", + REFERENCE_URL, + ""}, + {"com.staroffice", + {"general.archive"}, + {}, + {}, + "StarOffice document format", + REFERENCE_URL, + ""}, + {"com.staroffice.draw", + {"com.staroffice", "general.composite-object"}, + {".sda"}, + {"application/vnd.stardivision.draw"}, + "StarOffice Drawing", + REFERENCE_URL, + ""}, + {"com.staroffice.calc", + {"com.staroffice", "general.composite-object"}, + {".sdc"}, + {"application/vnd.stardivision.calc"}, + "StarOffice Calc spreadsheet", + REFERENCE_URL, + ""}, + {"com.staroffice.impress", + {"com.staroffice", "general.composite-object"}, + {".sdd", ".sdp"}, + {"application/vnd.stardivision.impress"}, + "StarOffice Presentation", + REFERENCE_URL, + ""}, + {"com.staroffice.writer", + {"com.staroffice", "general.composite-object"}, + {".sdw"}, + {"application/vnd.stardivision.writer"}, + "StarOffice Writer text document", + REFERENCE_URL, + ""}, + {"com.staroffice.chart", + {"com.staroffice", "general.composite-object"}, + {".sds"}, + {"application/vnd.stardivision.chart"}, + "StarOffice Chart", + REFERENCE_URL, + ""}, + {"com.staroffice.mail", + {"com.staroffice", "general.composite-object"}, + {".sdm"}, + {"application/vnd.stardivision.mail"}, + "StarOffice Mail message", + REFERENCE_URL, + ""}, + {"com.staroffice.writer-global", + {"com.staroffice", "general.composite-object"}, + {".sgl"}, + {"application/vnd.stardivision.writer-global"}, + "StarOffice Master document", + REFERENCE_URL, + ""}, + {"com.staroffice.math", + {"com.staroffice", "general.composite-object"}, + {".smf"}, + {"application/vnd.stardivision.math"}, + "StarMath Formula file", + REFERENCE_URL, + ""}, + {"com.staroffice.template", + {"com.staroffice", "general.composite-object"}, + {".vor"}, + {"application/vnd.stardivision.template"}, + "StarOffice Template", + REFERENCE_URL, + ""}, + {"org.tug.bib", + {"general.tex"}, + {".bib"}, + {"text/x-bibtex"}, + "TeX Bibliography file", + REFERENCE_URL, + ""}, + {"org.tug.cls", + {"general.tex"}, + {".cls"}, + {"text/x-tex"}, + "TeX Class file", + REFERENCE_URL, + ""}, + {"org.tug.sty", + {"general.tex"}, + {".sty"}, + {"text/x-tex"}, + "TeX Style file", + REFERENCE_URL, + ""}, + {"org.tug.tex", + {"general.tex"}, + {".tex"}, + {"text/x-tex"}, + "TeX source document file", + REFERENCE_URL, + ""}, + {"org.latex-project.latex", + {"general.tex"}, + {".ltx", ".latex"}, + {"application/x-latex"}, + "LaTeX source document file", + REFERENCE_URL, + ""}, + {"org.matroska.mkv", + {"general.video"}, + {".mkv"}, + {"video/x-matroska"}, + "Matroska video", + REFERENCE_URL, + ""}, + {"org.matroska.mka", + {"general.audio"}, + {".mka"}, + {"audio/x-matroska"}, + "Matroska audio", + REFERENCE_URL, + ""}, + {"com.sgi.movie", + {"general.video"}, + {".movie"}, + {"video/x-sgi-movie"}, + "SGI movie", + REFERENCE_URL, + ""}, + {"com.apple.m4v", + {"general.video"}, + {".m4v"}, + {"video/m4v"}, + "M4V video", + REFERENCE_URL, + ""}, + {"org.webmproject.webm", + {"general.video"}, + {".webm"}, + {"video/webm"}, + "WebM is an audiovisual media file format", + REFERENCE_URL, + ""}, + {"com.apple.quicktime-movie", + {"general.video"}, + {".mov", ".qt", ".movie"}, + {"video/quicktime"}, + "QuickTime File Format", + REFERENCE_URL, + ""}, + {"com.coreldraw.cdr", + {"general.image"}, + {".cdr"}, + {"image/x-coreldraw"}, + "CorelDRAW file", + REFERENCE_URL, + ""}, + {"com.coreldraw.cdt", + {"general.image"}, + {".cdt"}, + {"image/x-coreldrawtemplate"}, + "CorelDRAW template", + REFERENCE_URL, + ""}, + {"com.coreldraw.cpt", + {"general.image"}, + {".cpt"}, + {"image/x-corelphotopaint"}, + "Corel PHOTO-PAINT image", + REFERENCE_URL, + ""}, + {"com.coreldraw.pat", + {"general.image"}, + {".pat"}, + {"image/x-coreldrawpattern"}, + "CorelDRAW pattern file", + REFERENCE_URL, + ""}, + {"com.microsoft.cur", + {"general.image"}, + {".cur"}, + {"image/ico"}, + "Microsoft Windows cursor image", + REFERENCE_URL, + ""}, + {"com.sun.raster", + {"general.image"}, + {".ras"}, + {"image/x-cmu-raster"}, + "Sun Raster Graphic", + REFERENCE_URL, + ""}, + {"com.google.webp", + {"general.image"}, + {".webp"}, + {"image/webp"}, + "WebP image", + REFERENCE_URL, + ""}, + {"com.sseyo.koan-audio", + {"general.audio"}, + {".skd", ".skm", ".skp", ".skt"}, + {"application/x-koan"}, + "Koan music files over the internet", + REFERENCE_URL, + ""}, + {"io.qt.moc", + {"general.source-code"}, + {".moc"}, + {"text/x-moc"}, + "Qt Meta-Object compiler file", + REFERENCE_URL, + ""}, + {"com.ghostscript.font", + {"general.font"}, + {".gsf"}, + {"application/x-font"}, + "Ghostscript font", + REFERENCE_URL, + ""}, + {"org.x.pcf-font", + {"general.font"}, + {".pcf"}, + {"application/x-font", "application/x-font-pcf"}, + "Portable compiled format", + REFERENCE_URL, + ""}, + {"com.microsoft.windows-media-wmd", + {"com.microsoft.advanced-systems-format", "general.zip-archive"}, + {".wmd"}, + {"application/x-ms-wmd"}, + "Windows media download package", + REFERENCE_URL, + ""}, + {"com.microsoft.windows-media-wmz", + {"com.microsoft.advanced-systems-format", "general.zip-archive"}, + {".wmz"}, + {"application/x-ms-wmz"}, + "Windows media player skin package", + REFERENCE_URL, + ""}, + {"com.microsoft.windows-installer", + {"general.executable"}, + {".msi"}, + {"application/x-msi"}, + "Windows installer package", + REFERENCE_URL, + ""}, + {"com.microsoft.publisher.pub", + {"general.composite-object"}, + {".pub"}, + {"application/x-mspublisher"}, + "Publisher document", + REFERENCE_URL, + ""}, + {"com.microsoft.windows-media-playlist", + {"general.xml", "general.media"}, + {".wpl"}, + {"application/vnd.ms-wpl"}, + "Windows media player playlist", + REFERENCE_URL, + ""}, + {"com.microsoft.access.mdb", + {"general.database"}, + {".mdb"}, + {"application/msaccess"}, + "Microsoft Access database", + REFERENCE_URL, + ""}, + {"com.3dsystems.stereolithography", + {"general.composite-object"}, + {".stl"}, + {"application/vnd.ms-pki.stl"}, + "Stereolithography file", + REFERENCE_URL, + ""}, + {"com.apple.media.playlist", + {"general.media"}, + {".m3u8"}, + {"application/vnd.apple.mpegurl"}, + "UTF-8 M3U playlist", + REFERENCE_URL, + ""}, + {"com.abisource.word", + {"general.composite-object"}, + {".abw"}, + {"application/x-abiword"}, + "AbiWord document", + REFERENCE_URL, + ""}, + {"com.adobe.framemaker", + {"general.composite-object"}, + {".book", ".fm", ".frame", ".maker"}, + {"application/x-maker"}, + "FrameMaker book file", + REFERENCE_URL, + ""}, + {"com.wolfram.cdf", + {"general.composite-object"}, + {".cdf"}, + {"application/x-cdf"}, + "Computable document format file", + REFERENCE_URL, + ""}, + {"de.cinderella.cdy", + {"general.composite-object"}, + {".cdy"}, + {"application/vnd.cinderella"}, + "Cinderella construction file", + REFERENCE_URL, + ""}, + {"com.adobe.dcr", + {"general.video"}, + {".dcr"}, + {"application/x-director"}, + "Shockwave media file", + REFERENCE_URL, + ""}, + {"com.adobe.dir", + {"general.video"}, + {".dir"}, + {"application/x-director"}, + "Adobe Director movie", + REFERENCE_URL, + ""}, + {"com.adobe.dxr", + {"general.video"}, + {".dxr"}, + {"application/x-director"}, + "Protected macromedia director movie", + REFERENCE_URL, + ""}, + {"org.gnumeric.spreadsheet", + {"general.xml"}, + {".gnumeric"}, + {"application/x-gnumeric"}, + "Gnumeric spreadsheet", + REFERENCE_URL, + ""}, + {"org.hdfgroup.hdf", + {"general.composite-object"}, + {".hdf"}, + {"application/x-hdf"}, + "Hierarchical data format", + REFERENCE_URL, + ""}, + {"com.apple.binhex-archive", + {"general.archive"}, + {".hqx"}, + {"application/mac-binhex40"}, + "BinHex 4.0 encoded file", + REFERENCE_URL, + ""}, + {"com.microsoft.hta", + {"general.archive", "general.executable"}, + {".hta"}, + {"application/hta"}, + "HTML application", + REFERENCE_URL, + ""}, + {"com.microsoft.internet.ins", + {"general.text"}, + {".ins"}, + {"application/x-internet-signup"}, + "Internet settings file", + REFERENCE_URL, + ""}, + {"com.microsoft.internet.isp", + {"general.text"}, + {".isp"}, + {"application/x-internet-signup"}, + "IIS internet service provider settings", + REFERENCE_URL, + ""}, + {"org.troff", + {"general.text"}, + {".man", ".t", ".roff"}, + {"text/troff"}, + "Unix troff format", + REFERENCE_URL, + ""}, + {"com.adobe.framemaker.mif", + {"general.composite-object"}, + {".mif"}, + {"application/vnd.mif"}, + "FrameMaker interchange format file", + REFERENCE_URL, + ""}, + {"io.sourceforge.freemind", + {"general.composite-object"}, + {".mm"}, + {"application/x-freemind"}, + "Mind Map file", + REFERENCE_URL, + ""}, + {"com.yamaha.smaf", + {"general.audio"}, + {".mmf"}, + {"application/vnd.smaf"}, + "Synthetic music mobile application file", + REFERENCE_URL, + ""}, + {"com.wolfram.mathematica.notebook", + {"general.text"}, + {".nb"}, + {"application/mathematica"}, + "Mathematica notebook", + REFERENCE_URL, + ""}, + {"org.xiph.ogg", + {"general.audio"}, + {".oga", ".ogg"}, + {"application/ogg"}, + "Ogg vorbis audio", + REFERENCE_URL, + ""}, + {"com.netscape.proxy-autoconfig", + {"general.plain-text"}, + {".pac"}, + {"application/x-ns-proxy-autoconfig"}, + "Proxy auto-config file", + REFERENCE_URL, + ""}, + {"com.rsa.pkcs-12", + {"general.archive"}, + {".pfx", ".p12"}, + {"application/x-pkcs12"}, + "PKCS #12 certificate file", + REFERENCE_URL, + ""}, + {"org.openpgp.signature", + {"general.object"}, + {".pgp"}, + {"application/pgp-signature"}, + "PGP security key", + REFERENCE_URL, + ""}, + {"com.apple.quicktime-link", + {"general.text"}, + {".qtl"}, + {"application/x-quicktimeplayer"}, + "QuickTime link file", + REFERENCE_URL, + ""}, + {"com.rarlab.rar-archive", + {"general.archive"}, + {".rar"}, + {"application/rar", "application/vnd.rar"}, + "WinRAR compressed archive", + REFERENCE_URL, + ""}, + {"org.7-zip.7-zip-archive", + {"general.archive"}, + {".7z"}, + {"application/x-7z-compressed"}, + "7-zip compressed archive", + REFERENCE_URL, + ""}, + {"com.red-bean.sgf", + {"general.text"}, + {".sgf"}, + {"application/x-go-sgf"}, + "Smart game format file", + REFERENCE_URL, + ""}, + {"com.stuffit.sit-archive", + {"general.archive"}, + {".sit"}, + {"application/x-stuffit"}, + "Stuffit archive", + REFERENCE_URL, + ""}, + {"com.adobe.futuresplash", + {"general.video"}, + {".spl"}, + {"application/futuresplash", "application/x-futuresplash"}, + "FutureSplash animation", + REFERENCE_URL, + ""}, + {"com.adobe.flash", + {"general.video"}, + {".swf", ".flv"}, + {"application/x-shockwave-flash", "video/x-flv"}, + "Shockwave flash movie", + REFERENCE_URL, + ""}, + {"org.gnu.texinfo", + {"general.source-code"}, + {".texinfo", ".texi"}, + {"application/x-texinfo"}, + "GNU Texinfo", + REFERENCE_URL, + ""}, + {"org.bittorrent.torrent", + {"general.text"}, + {".torrent"}, + {"application/x-bittorrent"}, + "BitTorrent file", + REFERENCE_URL, + ""}, + {"com.idsoftware.doom", + {"general.archive"}, + {".wad"}, + {"application/x-doom"}, + "Doom WAD file", + REFERENCE_URL, + ""}, + {"com.apple.webarchive", + {"general.archive"}, + {".webarchive"}, + {"application/x-webarchive"}, + "Safari web archive", + REFERENCE_URL, + ""}, + {"com.android.webarchive", + {"general.archive"}, + {".webarchivexml"}, + {"application/x-webarchive-xml"}, + "Android web browser archive", + REFERENCE_URL, + ""}, + {"org.gimp.xcf", + {"general.image"}, + {".xcf"}, + {"application/x-xcf", "image/x-xcf"}, + "eXperimental computing facility, GIMP image file", + REFERENCE_URL, + ""}, + {"com.edrawsoft.edrawmax", + {"general.composite-object"}, + {".eddx"}, + {"application/x-eddx"}, + "Edraw Max XML file", + REFERENCE_URL, + ""}, + {"com.edrawsoft.edrawmind", + {"general.composite-object"}, + {".emmx"}, + {"application/x-emmx"}, + "Edraw MindMaster XML file", + REFERENCE_URL, + ""}, + {"net.cnki.caj", + {"general.composite-object"}, + {".caj"}, + {"application/caj"}, + "Chinese academic journal file", + REFERENCE_URL, + ""}, + {"com.dbase.dbf", + {"general.database"}, + {".dbf"}, + {"application/dbf", "application/dbase"}, + "Database file", + REFERENCE_URL, + ""}, + {"com.autodesk.dwg", + {"general.composite-object"}, + {".dwg"}, + {"image/vnd.dwg"}, + "AutoCAD drawing", + REFERENCE_URL, + ""}, + {"com.autodesk.dxf", + {"general.composite-object"}, + {".dxf"}, + {"image/vnd.dxf"}, + "Drawing exchange format file", + REFERENCE_URL, + ""}, + {"com.autodesk.dws", + {"general.composite-object"}, + {".dws"}, + {}, + "AutoCAD drawing standards file", + REFERENCE_URL, + ""}, + {"com.autodesk.dwt", + {"general.composite-object"}, + {".dwt"}, + {}, + "AutoCAD drawing template", + REFERENCE_URL, + ""}, + {"com.autodesk.dwf", + {"general.composite-object"}, + {".dwf"}, + {"model/vnd.dwf"}, + "Design web format file", + REFERENCE_URL, + ""}, + {"com.autodesk.dwfx", + {"general.composite-object"}, + {".dwfx"}, + {}, + "Design web format XPS file", + REFERENCE_URL, + ""}, + {"com.autodesk.shp", + {"general.composite-object"}, + {".shp"}, + {}, + "3D studio shape", + REFERENCE_URL, + ""}, + {"com.autodesk.shx", + {"general.composite-object"}, + {".shx"}, + {}, + "AutoCAD compiled shape file", + REFERENCE_URL, + ""}, + {"com.autodesk.slide-library", + {"general.composite-object"}, + {".slb"}, + {}, + "AutoCAD slide library", + REFERENCE_URL, + ""}, + {"com.autodesk.line", + {"general.text"}, + {".lin"}, + {}, + "AutoCAD linetype file", + REFERENCE_URL, + ""}, + {"com.autodesk.plotter", + {"general.composite-object"}, + {".plt"}, + {}, + "AutoCAD plotter document", + REFERENCE_URL, + ""}, + {"com.hp.graphics-language", + {"general.composite-object"}, + {".hpgl"}, + {"application/vnd.hp-hpgl"}, + "HP graphics language plotter file", + REFERENCE_URL, + ""}, + {"com.microsoft.metafile", + {"general.composite-object"}, + {".wmf"}, + {}, + "Windows metafile", + REFERENCE_URL, + ""}, + {"com.spatial.acis.sat", + {"general.text"}, + {".sat"}, + {}, + "ACIS SAT 3D model", + REFERENCE_URL, + ""}, + {"org.aomedia.avif-image", + {"general.image"}, + {".avif"}, + {"image/avif"}, + "AVIF image", + REFERENCE_URL, + ""}, + {"com.microsoft.dds", + {"general.image"}, + {".dds"}, + {"image/vnd-ms.dds"}, + "DirectDraw surface image", + REFERENCE_URL, + ""}, + {"com.ea.iff-ilbm", + {"general.image"}, + {".ilbm"}, + {"image/x-ilbm"}, + "Interleaved bitmap image", + REFERENCE_URL, + ""}, + {"com.canon.cr2-raw-image", + {"general.raw-image"}, + {".cr2"}, + {"image/x-canon-cr2"}, + "Canon raw 2 image", + REFERENCE_URL, + ""}, + {"com.canon.cr3-raw-image", + {"general.raw-image"}, + {".cr3"}, + {"image/x-canon-cr3"}, + "Canon raw 3 image", + REFERENCE_URL, + ""}, + {"com.canon.crw-raw-image", + {"general.raw-image"}, + {".crw"}, + {"image/x-canon-crw"}, + "Canon raw CIFF image file", + REFERENCE_URL, + ""}, + {"com.adobe.dng-raw-image", + {"general.raw-image"}, + {".dng"}, + {"image/x-adobe-dng"}, + "Digital negative image", + REFERENCE_URL, + ""}, + {"com.sony.arw-raw-image", + {"general.raw-image"}, + {".arw"}, + {"image/x-sony-arw"}, + "Sony alpha raw digital camera image", + REFERENCE_URL, + ""}, + {"com.nikon.nef-raw-image", + {"general.raw-image"}, + {".nef"}, + {"image/x-nikon-nef"}, + "Nikon electronic format RAW image", + REFERENCE_URL, + ""}, + {"com.mindjet.mindmanager.mmap", + {"general.composite-object"}, + {".mmap"}, + {}, + "MindManager Map", + REFERENCE_URL, + ""}, + {"com.microsoft.email", + {"general.message"}, + {".eml"}, + {"message/rfc822"}, + "E-Mail message", + REFERENCE_URL, + ""}, + {"com.microsoft.message", + {"general.message"}, + {".msg"}, + {}, + "Outlook message item file", + REFERENCE_URL, + ""}, + {"com.microsoft.pst", + {"general.archive"}, + {".pst"}, + {}, + "Outlook personal information store", + REFERENCE_URL, + ""}, + {"com.kingsoft.office", + {"general.archive"}, + {}, + {}, + "Kingsoft office suite", + REFERENCE_URL, + ""}, + {"com.kingsoft.office.writer.wps", + {"com.kingsoft.office", "general.composite-object"}, + {".wps"}, + {}, + "Kingsoft Writer document", + REFERENCE_URL, + ""}, + {"com.kingsoft.office.writer.wpt", + {"com.kingsoft.office", "general.composite-object"}, + {".wpt"}, + {}, + "Kingsoft Writer template", + REFERENCE_URL, + ""}, + {"com.kingsoft.office.presentation.dps", + {"com.kingsoft.office", "general.composite-object"}, + {".dps"}, + {}, + "Kingsoft Presentation file", + REFERENCE_URL, + ""}, + {"com.kingsoft.office.presentation.template", + {"com.kingsoft.office", "general.composite-object"}, + {".dpt"}, + {}, + "Kingsoft Presentation template", + REFERENCE_URL, + ""}, + {"com.kingsoft.office.spreadsheets.et", + {"com.kingsoft.office", "general.composite-object"}, + {".et"}, + {}, + "Kingsoft Spreadsheets tile", + REFERENCE_URL, + ""}, + {"com.kingsoft.office.spreadsheets.template", + {"com.kingsoft.office", "general.composite-object"}, + {".ett"}, + {}, + "Kingsoft Spreadsheets template", + REFERENCE_URL, + ""}, + {"com.microsoft.ini", + {"general.text"}, + {".ini"}, + {}, + "Windows Initialization File", + REFERENCE_URL, + ""}, + {"general.json", + {"general.script"}, + {".json"}, + {"application/json"}, + "JavaScript Object Notation File", + REFERENCE_URL, + ""}, + {"general.yaml", + {"general.script"}, + {".yaml", ".yml"}, + {"application/yaml"}, + "YAML Document", + REFERENCE_URL, + ""}, + {"general.log", + {"general.text"}, + {".log"}, + {"text/plain"}, + "Log File", + REFERENCE_URL, + ""}, + {"general.uri", + {"general.object"}, + {}, + {}, + "Universal Resource Identifier", + REFERENCE_URL, + ""}, + {"general.file-uri", + {"general.uri"}, + {}, + {}, + "File URI", + REFERENCE_URL, + ""}, + {"general.text-lst", + {"general.plain-text"}, + {".lst"}, + {}, + "Data List", + REFERENCE_URL, + ""}, + {"com.android.apk", + {"general.archive"}, + {".apk", ".apks", ".aab", ".xapk", ".apkm", ".akp"}, + {"application/vnd.android.package-archive"}, + "Android Package File", + REFERENCE_URL, + ""}, + {"com.adobe.postscript-pfb-font", + {"com.adobe.postscript-font"}, + {".pfb"}, + {"application/x-font"}, + "Printer Font Binary, PostScript Type 1 outline font.", + REFERENCE_URL, + ""}, + {"com.adobe.postscript-pfa-font", + {"com.adobe.postscript-font"}, + {".pfa"}, + {"application/x-font"}, + "Printer Pont ASCII file, PostScript Type 1 outline font.", + REFERENCE_URL, + ""}, + {"general.bz-archive", + {"general.archive"}, + {".bz"}, + {"application/x-bzip"}, + "Bzip Compressed File", + REFERENCE_URL, + ""}, + {"general.tar-bzip-archive", + {"general.bz-archive"}, + {".tbz"}, + {"application/x-bzip-compressed-tar"}, + "Bzip Compressed Tar Archive", + REFERENCE_URL, + ""}, + {"general.tar-bzip2-archive", + {"general.bz2-archive"}, + {".tbz2"}, + {"application/x-bzip2-compressed-tar"}, + "Bzip2-Compressed TAR File", + REFERENCE_URL, + ""}, + {"org.tukaani.xz-archive", + {"general.archive"}, + {".xz"}, + {"application/x-xz"}, + "XZ Compressed Archive", + REFERENCE_URL, + ""}, + {"org.tukaani.tar-xz-archive", + {"org.tukaani.xz-archive"}, + {".txz"}, + {"application/x-xz-compressed-tar"}, + "XZ Compressed Tar Archive", + REFERENCE_URL, + ""}, + {"general.xar-archive", + {"general.archive"}, + {".xar"}, + {"application/x-xar"}, + "Extensible Archive Fromat", + REFERENCE_URL, + ""}, + {"com.microsoft.cab-archive", + {"general.archive"}, + {".cab"}, + {"application/vnd.ms-cab-compressed"}, + "Windows Cabinet File", + REFERENCE_URL, + ""}, + {"redhat.rpm-archive", + {"general.archive"}, + {".rpm"}, + {"application/x-rpm"}, + "RedHat Package Manager File", + REFERENCE_URL, + ""}, + {"org.godotengine.tpz-archive", + {"general.archive"}, + {".tpz"}, + {}, + "Godot Engine Export Template Archive", + REFERENCE_URL, + ""}, + {"general.lza-archive", + {"general.archive"}, + {".lza"}, + {"application/x-lzh-compressed"}, + "LZA Compressed Archive", + REFERENCE_URL, + ""}, + {"general.arj-archive", + {"general.archive"}, + {".arj"}, + {"application/x-arj"}, + "ARJ Compressed File Archive", + REFERENCE_URL, + ""}, + {"com.winzip.zipx", + {"general.archive"}, + {".zipx"}, + {}, + "Extended Zip Archive", + REFERENCE_URL, + ""}, + {"general.lzma-archive", + {"general.archive"}, + {".lzma"}, + {"application/x-lzma"}, + "LZMA Compressed File", + REFERENCE_URL, + ""}, + {"general.lzma86-archive", + {"general.archive"}, + {".lzma86"}, + {}, + "LZMA86 Compressed File", + REFERENCE_URL, + ""}, + {"org.mozilla.xpinstall", + {"general.archive"}, + {".xpi"}, + {"application/x-xpinstall"}, + "Cross-platform Installer Package", + REFERENCE_URL, + ""}, + {"general.hfs-disk-image", + {"general.disk-image"}, + {".hfs"}, + {}, + "HFS Disk Image File", + REFERENCE_URL, + ""}, + {"general.img-disk-image", + {"general.disk-image"}, + {".img"}, + {"application/x-raw-disk-image"}, + "Disc Image Data File", + REFERENCE_URL, + ""}, + {"com.ezbsystems.zipped-iso", + {"general.disk-image"}, + {".isz"}, + {}, + "Zipped ISO Disk Image", + REFERENCE_URL, + ""}, + {"com.microsoft.wim", + {"general.disk-image"}, + {".wim"}, + {"application/x-ms-wim"}, + "Windows Imaging Format File", + REFERENCE_URL, + ""}, + {"com.microsoft.swm", + {"general.disk-image"}, + {".swm"}, + {"application/x-ms-wim"}, + "Split Windows Imaging Format", + REFERENCE_URL, + ""}, + {"com.kingsoft.office.spreadsheets.etx", + {"com.kingsoft.office", "general.composite-object"}, + {".etx"}, + {}, + "Kingsoft Spreadsheets File", + REFERENCE_URL, + ""}, + {"com.kingsoft.office.spreadsheets.ettx", + {"com.kingsoft.office", "general.composite-object"}, + {".ettx"}, + {}, + "Kingsoft Spreadsheets Template", + REFERENCE_URL, + ""}, + {"com.microsoft.excel.dif", + {"general.composite-object"}, + {".dif"}, + {}, + "Data interchange format", + REFERENCE_URL, + ""}, + {"openharmony.app", + {"openharmony.package"}, + {".app"}, + {}, + "OpenHarmony system defined application package", + REFERENCE_URL, + ""}, + {"com.huawei.hmos.settings.wifi", + {"general.text"}, + {".hmoswifi"}, + {}, + "HarmonyOS WIFI sharing setting", + REFERENCE_URL, + ""}, + {"general.tel", + {"general.text"}, + {".tel"}, + {}, + "TEL schematic diagram file format", + REFERENCE_URL, + ""}, + {"general.ets", + {"general.script"}, + {".ets"}, + {}, + "Extended TypeScript source code", + REFERENCE_URL, + ""}, + {"general.json5", + {"general.script"}, + {".json5"}, + {}, + "JSON5 data interchange format", + REFERENCE_URL, + ""}, + {"com.monkeysaudio.ape-audio", + {"general.audio"}, + {".ape"}, + {"audio/x-monkeys-audio"}, + "Monkey's Audio", + REFERENCE_URL, + ""}, + {"org.xiph.opus-audio", + {"general.audio"}, + {".opus"}, + {"audio/opus"}, + "Opus Audio", + REFERENCE_URL, + ""}, + {"general.conf", + {"general.text"}, + {".conf"}, + {}, + "Generic Configuration File", + REFERENCE_URL, + ""}, + {"com.microsoft.dos-batch", + {"general.script"}, + {".bat"}, + {"application/x-bat"}, + "DOS Batch File", + REFERENCE_URL, + ""}, + {"com.microsoft.vbscript", + {"general.script"}, + {".vbs"}, + {"application/x-vbs"}, + "VBScript File", + REFERENCE_URL, + ""}, + {"general.ion", + {"general.text"}, + {".ion"}, + {}, + "File Description File", + REFERENCE_URL, + ""}, + {"com.microsoft.registry", + {"general.database"}, + {".reg"}, + {}, + "Registry File", + REFERENCE_URL, + ""}, + {"com.microsoft.catalog", + {"general.object"}, + {".cat"}, + {}, + "Windows Catalog File", + REFERENCE_URL, + ""}, + {"com.microsoft.powershell-script", + {"general.script"}, + {".ps1"}, + {}, + "Windows PowerShell Cmdlet File", + REFERENCE_URL, + ""}, + {"org.w3.woff", + {"general.font"}, + {".woff"}, + {"font/woff"}, + "Web Open Font Format File", + REFERENCE_URL, + ""}, + {"org.sqlite.database", + {"general.database"}, + {".sqlite", ".sqlite3", ".db", ".db3", ".s3db", ".sl3"}, + {"application/vnd.sqlite3"}, + "SQLite Database", + REFERENCE_URL, + ""}, + {"com.microsoft.sys", + {"general.object"}, + {".sys"}, + {}, + "Windows System File", + REFERENCE_URL, + ""}, + {"com.microsoft.inf", + {"general.text"}, + {".inf"}, + {"text/plain"}, + "Setup Information File", + REFERENCE_URL, + ""}, + {"com.microsoft.pdb", + {"general.database"}, + {".pdb"}, + {"application/x-ms-pdb"}, + "Program Database", + REFERENCE_URL, + ""}, + {"com.microsoft.tlb", + {"general.object"}, + {".tlb"}, + {}, + "OLE Type Library", + REFERENCE_URL, + ""}, + {"com.microsoft.sccd", + {"general.xml"}, + {".sccd"}, + {}, + "Signed Custom Capability Descriptor", + REFERENCE_URL, + ""}, + {"com.adobe.f4v", + {"general.video"}, + {".f4v"}, + {"video/mp4"}, + "Flash MP4 Video File", + REFERENCE_URL, + ""}, + {"general.mp2t", + {"general.video"}, + {".m2ts", ".mts", ".m2t"}, + {"video/mp2t"}, + "Blu-ray BDAV Video File Format", + REFERENCE_URL, + ""}, + {"com.youtube.video", + {"general.video"}, + {".yt", ".vt"}, + {"video/vnd.youtube.yt"}, + "Youtube Video format", + REFERENCE_URL, + ""}, + {"com.cisco.webex-video", + {"general.video"}, + {".wrf"}, + {"video/x-webex"}, + "WebEx Recording", + REFERENCE_URL, + ""}, + {"general.mpeg-2", + {"general.video"}, + {".mpeg2", ".mpv2", ".mp2v", ".m2v", ".mpv"}, + {"video/mpeg"}, + "MPEG-2 Video format", + REFERENCE_URL, + ""}, + {"general.mpeg-1", + {"general.video"}, + {".mpeg1", ".mpv1", ".mp1v", ".m1v"}, + {"video/mpeg"}, + "MPEG-1 Video format", + REFERENCE_URL, + ""}, + {"com.real.realmedia-vbr", + {"general.video"}, + {".rmvb"}, + {"application/vnd.rn-realmedia-vbr"}, + "RealMedia Variable Bit Rate Format", + REFERENCE_URL, + ""}, + {"com.real.realvideo", + {"general.video"}, + {".rv"}, + {"video/x-pn-realvideo"}, + "RealVideo Format", + REFERENCE_URL, + ""}, + {"general.divx-video", + {"general.video"}, + {".divx"}, + {"video/divx"}, + "DivX-Encoded Movie", + REFERENCE_URL, + ""}, + {"org.csiro.annodex", + {"general.video"}, + {".axv"}, + {"video/annodex"}, + "Annodex Video Format", + REFERENCE_URL, + ""}, + {"general.ogv", + {"general.video"}, + {".ogv"}, + {"video/ogg"}, + "Ogg Video Format", + REFERENCE_URL, + ""}, + {"com.microsoft.lsf-video", + {"general.video"}, + {".lsf", ".lsx"}, + {"video/x-la-asf"}, + "Streaming Media Format", + REFERENCE_URL, + ""}, + {"general.h264-video", + {"general.video"}, + {".h264"}, + {"video/H264"}, + "H.264 Encoded Video Format", + REFERENCE_URL, + ""}, + {"general.jpeg-2000", + {"general.image"}, + {".jp2", ".jpg2", ".jpx", ".jpf", ".jpm"}, + {"image/jp2", "image/jpx", "image/jpm"}, + "JPEG 2000 Image", + REFERENCE_URL, + ""}, + {"com.fujifilm.raf-raw-image", + {"general.raw-image"}, + {".raf"}, + {"image/x-fuji-raf"}, + "Fujifilm RAW Image", + REFERENCE_URL, + ""}, + {"com.nikon.nrw-raw-image", + {"general.raw-image"}, + {".nrw"}, + {"image/x-nikon-nrw"}, + "Nikon Raw Image", + REFERENCE_URL, + ""}, + {"com.panasonic.rw2-raw-image", + {"general.raw-image"}, + {".rw2", ".raw"}, + {"image/x-panasonic-raw"}, + "Panasonic RAW Image", + REFERENCE_URL, + ""}, + {"com.pentax.pef-raw-image", + {"general.raw-image"}, + {".pef"}, + {"image/x-pentax-pef"}, + "Pentax Electronic RAW Image", + REFERENCE_URL, + ""}, + {"com.sumsung.srw-raw-image", + {"general.raw-image"}, + {".srw"}, + {"image/x-samsung-srw"}, + "Samsung RAW Image", + REFERENCE_URL, + ""}, + {"com.epson.erf-raw-image", + {"general.raw-image"}, + {".erf"}, + {"image/x-epson-erf"}, + "Epson RAW Imager", + REFERENCE_URL, + ""}, + {"com.olympus.orf-raw-image", + {"general.raw-image"}, + {".orf"}, + {"image/x-olympus-orf"}, + "Olympus RAW Image", + REFERENCE_URL, + ""}, + {"general.ief-image", + {"general.image"}, + {".ief"}, + {"image/ief"}, + "Image Exchange Format", + REFERENCE_URL, + ""}, + {"com.aol.art-image", + {"general.image"}, + {".art"}, + {"image/x-jg"}, + "ART image format", + REFERENCE_URL, + ""}, + {"general.content-form", + {"general.object"}, + {}, + {}, + "Content form format", + REFERENCE_URL, + ""}, + {"com.apple.m4p-audio", + {"general.audio"}, + {".m4p"}, + {"audio/mp4"}, + "iTunes Music Store Audio File Format", + REFERENCE_URL, + ""}, + {"general.ac3-audio", + {"general.audio"}, + {".ac3"}, + {"audio/ac3"}, + "Audio Codec 3 File Format", + REFERENCE_URL, + ""} + }; }; } // namespace UDMF } // namespace OHOS diff --git a/udmf/framework/innerkitsimpl/data/preset_type_descriptors.h b/udmf/framework/innerkitsimpl/data/preset_type_descriptors.h index 6412ed112bedc1fc218d6286207ec2ad15dfc873..08e6cbd008b810ca55a10be3f13127de89c248ab 100644 --- a/udmf/framework/innerkitsimpl/data/preset_type_descriptors.h +++ b/udmf/framework/innerkitsimpl/data/preset_type_descriptors.h @@ -29,8 +29,8 @@ private: ~PresetTypeDescriptors(); PresetTypeDescriptors(const PresetTypeDescriptors &obj) = delete; PresetTypeDescriptors &operator=(const PresetTypeDescriptors &obj) = delete; - - static std::vector typeDescriptors_; + void InitDescriptors(); + std::vector typeDescriptors_; }; } // namespace UDMF } // namespace OHOS diff --git a/udmf/framework/innerkitsimpl/data/unified_data.cpp b/udmf/framework/innerkitsimpl/data/unified_data.cpp index 7872cc8fba7bf139ef8738079660d355d77f9d60..866cd9f5298f1a91c248fababf289a678b78826d 100644 --- a/udmf/framework/innerkitsimpl/data/unified_data.cpp +++ b/udmf/framework/innerkitsimpl/data/unified_data.cpp @@ -71,14 +71,15 @@ void UnifiedData::AddRecords(const std::vector> & { for (auto &record :records) { if (record == nullptr) { - return; + LOG_ERROR(UDMF_FRAMEWORK, "Invalid record, skip!"); + continue; } record->SetRecordId(++recordId_); this->records_.push_back(record); } } -std::shared_ptr UnifiedData::GetRecordAt(std::size_t index) +std::shared_ptr UnifiedData::GetRecordAt(std::size_t index) const { if (records_.size() > index) { return records_[index]; @@ -96,17 +97,6 @@ std::vector> UnifiedData::GetRecords() const return this->records_; } -std::string UnifiedData::GetTypes() -{ - std::string types; - for (const auto &record : records_) { - for (const auto &type : record->GetUtdIds()) { - types.append("-").append(type); - } - } - return types; -} - std::vector UnifiedData::GetTypesLabels() const { std::vector types; @@ -139,6 +129,10 @@ std::vector UnifiedData::GetEntriesTypes() const bool UnifiedData::HasTypeInEntries(const std::string &type) const { for (const auto &record : records_) { + if (record == nullptr) { + LOG_ERROR(UDMF_FRAMEWORK, "Invalid record, skip!"); + continue; + } auto types = record->GetUtdIds(); if (types.find(type) != types.end()) { return true; diff --git a/udmf/framework/innerkitsimpl/test/unittest/BUILD.gn b/udmf/framework/innerkitsimpl/test/unittest/BUILD.gn index d46bea24d77dbc403c62ce46ab6afe3df5748614..974e0568cad5d4eb458dbebab1ddf12bc47eeda5 100644 --- a/udmf/framework/innerkitsimpl/test/unittest/BUILD.gn +++ b/udmf/framework/innerkitsimpl/test/unittest/BUILD.gn @@ -124,11 +124,7 @@ ohos_unittest("UtdClientTest") { ohos_unittest("NdkDataConversionTest") { module_out_path = module_output_path - sources = [ - "${udmf_framework_path}/ndkimpl/data/udmf.cpp", - "${udmf_framework_path}/ndkimpl/data/uds.cpp", - "ndk_data_conversion_test.cpp", - ] + sources = [ "ndk_data_conversion_test.cpp" ] configs = [ ":module_private_config" ] diff --git a/udmf/framework/innerkitsimpl/test/unittest/ndk_data_conversion_test.cpp b/udmf/framework/innerkitsimpl/test/unittest/ndk_data_conversion_test.cpp index e05ee39fb39dabe34eec6fa313ba74943022102e..3ccf608df6cc98b872366f8969e36059b8088584 100644 --- a/udmf/framework/innerkitsimpl/test/unittest/ndk_data_conversion_test.cpp +++ b/udmf/framework/innerkitsimpl/test/unittest/ndk_data_conversion_test.cpp @@ -600,30 +600,33 @@ HWTEST_F(NdkDataConversionTest, ConvertApplicationDefined_004, TestSize.Level1) } /* * - * @tc.name: ConvertHtml_001 - * @tc.desc: test html conversion between JS and C-API + * @tc.name: ConvertOhtherUds_001 + * @tc.desc: test other conversion between JS and C-API * @tc.type: FUNC */ -HWTEST_F(NdkDataConversionTest, ConvertHtml_001, TestSize.Level1) +HWTEST_F(NdkDataConversionTest, ConvertOhtherUds_001, TestSize.Level1) { - LOG_INFO(UDMF_TEST, "ConvertHtml_001 begin."); + LOG_INFO(UDMF_TEST, "ConvertOhtherUds_001 begin."); std::string definedTypeId = "person_app_demo"; std::shared_ptr html = std::make_shared("htmlContent", "plainContent"); + std::map value; + std::vector thumbData = {1, 2, 3, 4, 5}; + auto obj = std::make_shared(); + obj->value_.emplace(UNIFORM_DATA_TYPE, "general.content-form"); + obj->value_.emplace(TITLE, "title"); + obj->value_.emplace(THUMB_DATA, thumbData); + std::shared_ptr contentForm = std::make_shared(UDType::CONTENT_FORM, obj); UnifiedData data; - std::vector> records = { html }; + std::vector> records = { html, contentForm }; data.SetRecords(records); std::string key; - CustomOption option = { - .intention = UD_INTENTION_DRAG - }; + CustomOption option = { .intention = UD_INTENTION_DRAG }; auto setRet = UdmfClient::GetInstance().SetData(option, data, key); EXPECT_EQ(setRet, E_OK); std::shared_ptr readData = std::make_shared(); - QueryOption query = { - .key = key - }; + QueryOption query = { .key = key }; auto getRet = UdmfClient::GetInstance().GetData(query, *readData); EXPECT_EQ(getRet, E_OK); @@ -631,27 +634,39 @@ HWTEST_F(NdkDataConversionTest, ConvertHtml_001, TestSize.Level1) NdkDataConversion::GetNdkUnifiedData(readData, ndkData); unsigned int count; OH_UdmfData_GetRecords(ndkData, &count); - EXPECT_EQ(1, count); + EXPECT_EQ(2, count); auto record = OH_UdmfData_GetRecord(ndkData, 0); auto htmlNdk = OH_UdsHtml_Create(); auto result = OH_UdmfRecord_GetHtml(record, htmlNdk); EXPECT_EQ(0, result); + EXPECT_EQ("general.html", std::string(OH_UdsHtml_GetType(htmlNdk))); EXPECT_EQ("htmlContent", std::string(OH_UdsHtml_GetContent(htmlNdk))); EXPECT_EQ("plainContent", std::string(OH_UdsHtml_GetPlainContent(htmlNdk))); + auto contentFormRecord = OH_UdmfData_GetRecord(ndkData, 1); + auto contentFormNdk = OH_UdsContentForm_Create(); + result = OH_UdmfRecord_GetContentForm(contentFormRecord, contentFormNdk); + EXPECT_EQ(0, result); + EXPECT_EQ("general.content-form", std::string(OH_UdsContentForm_GetType(contentFormNdk))); + EXPECT_EQ("title", std::string(OH_UdsContentForm_GetTitle(contentFormNdk))); + unsigned char *readThumbData; + unsigned int thumbDataLen = 0; + EXPECT_EQ(0, OH_UdsContentForm_GetThumbData(contentFormNdk, &readThumbData, &thumbDataLen)); + EXPECT_EQ(5, thumbDataLen); OH_UdsHtml_Destroy(htmlNdk); + OH_UdsContentForm_Destroy(contentFormNdk); OH_UdmfData_Destroy(ndkData); - LOG_INFO(UDMF_TEST, "ConvertHtml_001 end."); + LOG_INFO(UDMF_TEST, "ConvertOhtherUds_001 end."); } /* * - * @tc.name: ConvertHtml_002 + * @tc.name: ConvertOhtherUds_002 * @tc.desc: test html conversion between JS and C-API * @tc.type: FUNC */ -HWTEST_F(NdkDataConversionTest, ConvertHtml_002, TestSize.Level1) +HWTEST_F(NdkDataConversionTest, ConvertOhtherUds_002, TestSize.Level1) { - LOG_INFO(UDMF_TEST, "ConvertHtml_002 begin."); + LOG_INFO(UDMF_TEST, "ConvertOhtherUds_002 begin."); auto htmlNdk = OH_UdsHtml_Create(); OH_UdsHtml_SetContent(htmlNdk, "htmlContent"); OH_UdsHtml_SetPlainContent(htmlNdk, "plainContent"); @@ -659,20 +674,24 @@ HWTEST_F(NdkDataConversionTest, ConvertHtml_002, TestSize.Level1) OH_UdmfRecord_AddHtml(record, htmlNdk); auto ndkData = OH_UdmfData_Create(); OH_UdmfData_AddRecord(ndkData, record); + auto record2 = OH_UdmfRecord_Create(); + auto contentFormNdk = OH_UdsContentForm_Create(); + OH_UdsContentForm_SetTitle(contentFormNdk, "title"); + unsigned char thumbData[] = {0, 1, 2, 3, 4}; + OH_UdsContentForm_SetThumbData(contentFormNdk, thumbData, 5); + OH_UdmfRecord_AddContentForm(record2, contentFormNdk); + OH_UdmfData_AddRecord(ndkData, record2); + std::shared_ptr unifiedData = std::make_shared(); auto conversionStatus = NdkDataConversion::GetNativeUnifiedData(ndkData, unifiedData); EXPECT_EQ(conversionStatus, E_OK); std::string key; - CustomOption option = { - .intention = UD_INTENTION_DRAG - }; + CustomOption option = { .intention = UD_INTENTION_DRAG }; auto setRet = UdmfClient::GetInstance().SetData(option, *unifiedData, key); EXPECT_EQ(setRet, E_OK); std::shared_ptr readData = std::make_shared(); - QueryOption query = { - .key = key - }; + QueryOption query = { .key = key }; auto getRet = UdmfClient::GetInstance().GetData(query, *readData); EXPECT_EQ(getRet, E_OK); @@ -681,9 +700,19 @@ HWTEST_F(NdkDataConversionTest, ConvertHtml_002, TestSize.Level1) EXPECT_EQ("htmlContent", html->GetHtmlContent()); EXPECT_EQ("plainContent", html->GetPlainContent()); + auto contentForm = readData->GetRecordAt(1); + auto value = contentForm->GetValue(); + auto obj = std::get>(value); + EXPECT_EQ("general.content-form", std::get(obj->value_[UNIFORM_DATA_TYPE])); + EXPECT_EQ(5, std::get(obj->value_[THUMB_DATA_LENGTH])); + auto readThumbData = std::get>(obj->value_[THUMB_DATA]); + EXPECT_EQ(4, readThumbData.at(4)); + OH_UdsHtml_Destroy(htmlNdk); + OH_UdsContentForm_Destroy(contentFormNdk); OH_UdmfRecord_Destroy(record); + OH_UdmfRecord_Destroy(record2); OH_UdmfData_Destroy(ndkData); - LOG_INFO(UDMF_TEST, "ConvertHtml_002 end."); + LOG_INFO(UDMF_TEST, "ConvertOhtherUds_002 end."); } } diff --git a/udmf/framework/jskitsimpl/unittest/UdmfUtdJsTest.js b/udmf/framework/jskitsimpl/unittest/UdmfUtdJsTest.js index 1e098acf883bdf013e8ef161813d8aa61a6a2c2b..ebed18d961be2c8f9f74fbfcefb8e846aa043863 100644 --- a/udmf/framework/jskitsimpl/unittest/UdmfUtdJsTest.js +++ b/udmf/framework/jskitsimpl/unittest/UdmfUtdJsTest.js @@ -285,6 +285,19 @@ describe('UdmfUtdJSTest', function () { expect(UTD.UniformDataType.MP3).assertEqual('general.mp3'); expect(UTD.UniformDataType.OGG).assertEqual('general.ogg'); expect(UTD.UniformDataType.PCM).assertEqual('general.pcm'); + expect(UTD.UniformDataType.ADOBE_F4V).assertEqual('com.adobe.f4v'); + expect(UTD.UniformDataType.MP2T).assertEqual('general.mp2t'); + expect(UTD.UniformDataType.YOUTUBE_VIDEO).assertEqual('com.youtube.video'); + expect(UTD.UniformDataType.WEBEX_VIDEO).assertEqual('com.cisco.webex-video'); + expect(UTD.UniformDataType.MPEG2).assertEqual('general.mpeg-2'); + expect(UTD.UniformDataType.MPEG1).assertEqual('general.mpeg-1'); + expect(UTD.UniformDataType.REALMEDIA_VBR).assertEqual('com.real.realmedia-vbr'); + expect(UTD.UniformDataType.REAL_REALVIDEO).assertEqual('com.real.realvideo'); + expect(UTD.UniformDataType.DIVX_VIDEO).assertEqual('general.divx-video'); + expect(UTD.UniformDataType.CSIRO_ANNODEX).assertEqual('org.csiro.annodex'); + expect(UTD.UniformDataType.OGV).assertEqual('general.ogv'); + expect(UTD.UniformDataType.LSF_VIDEO).assertEqual('com.microsoft.lsf-video'); + expect(UTD.UniformDataType.H264_VIDEO).assertEqual('general.h264-video'); console.info(TAG, 'end'); }); @@ -326,6 +339,19 @@ describe('UdmfUtdJSTest', function () { expect(UTD.UniformDataType.OPENHARMONY_APP_ITEM).assertEqual('openharmony.app-item'); expect(UTD.UniformDataType.OPENHARMONY_PIXEL_MAP).assertEqual('openharmony.pixel-map'); expect(UTD.UniformDataType.OPENHARMONY_ATOMIC_SERVICE).assertEqual('openharmony.atomic-service'); + expect(UTD.UniformDataType.JPEG2000).assertEqual('general.jpeg-2000'); + expect(UTD.UniformDataType.RAF_RAW_IMAGE).assertEqual('com.fujifilm.raf-raw-image'); + expect(UTD.UniformDataType.NRW_RAW_IMAGE).assertEqual('com.nikon.nrw-raw-image'); + expect(UTD.UniformDataType.RW2_RAW_IMAGE).assertEqual('com.panasonic.rw2-raw-image'); + expect(UTD.UniformDataType.PEF_RAW_IMAGE).assertEqual('com.pentax.pef-raw-image'); + expect(UTD.UniformDataType.SRW_RAW_IMAGE).assertEqual('com.sumsung.srw-raw-image'); + expect(UTD.UniformDataType.ERF_RAW_IMAGE).assertEqual('com.epson.erf-raw-image'); + expect(UTD.UniformDataType.ORF_RAW_IMAGE).assertEqual('com.olympus.orf-raw-image'); + expect(UTD.UniformDataType.IEF_IMAGE).assertEqual('general.ief-image'); + expect(UTD.UniformDataType.ART_IMAGE).assertEqual('com.aol.art-image'); + expect(UTD.UniformDataType.CONTENT_FORM).assertEqual('general.content-form'); + expect(UTD.UniformDataType.M4P_AUDIO).assertEqual('com.apple.m4p-audio'); + expect(UTD.UniformDataType.AC3_AUDIO).assertEqual('general.ac3-audio'); console.info(TAG, 'end'); }); @@ -985,4 +1011,204 @@ describe('UdmfUtdJSTest', function () { } console.info(TAG, 'end'); }); + + /* + * @tc.name UdmfTestTypeDescriptor046 + * @tc.desc Test Js Api + * @tc.type: FUNC + * @tc.require: issueIAY1VI + */ + it('UdmfTestTypeDescriptor046', 0, function () { + const TAG = 'UdmfTestTypeDescriptor046:'; + console.info(TAG, 'start'); + let typeObj = UTD.getTypeDescriptor('com.adobe.f4v'); + let typeId = typeObj.typeId; + let belonging = typeObj.belongingToTypes; + let description = typeObj.description; + let referenceURL = typeObj.referenceURL; + let iconFile = typeObj.iconFile; + let filenameExtensions = typeObj.filenameExtensions; + let mimeTypes = typeObj.mimeTypes; + console.info(TAG, ', typeId: ' + typeId + ', ' + Object.prototype.toString.call(typeId) + + ', belongingToTypes: ' + belonging + ', ' + Object.prototype.toString.call(belonging)); + console.info(TAG, 'description: ' + typeObj.description + ', ' + Object.prototype.toString.call(description)); + console.info(TAG, 'referenceURL: ' + referenceURL + ', ' + Object.prototype.toString.call(referenceURL) + + ', iconFile: ' + iconFile + ', ' + Object.prototype.toString.call(iconFile)); + expect(typeObj.typeId).assertEqual(UTD.UniformDataType.ADOBE_F4V); + expect(typeObj.belongingToTypes[0]).assertEqual('general.video'); + expect(typeObj.description).assertEqual('Flash MP4 Video File'); + let equalStr = 'https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/' + + 'apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype'; + expect(typeObj.referenceURL).assertEqual(equalStr); + expect(typeObj.iconFile).assertEqual(''); + expect(typeObj.filenameExtensions[0]).assertEqual('.f4v'); + expect(typeObj.mimeTypes[0]).assertEqual('video/mp4'); + console.info(TAG, 'end'); + }); + + /* + * @tc.name UdmfTestTypeDescriptor047 + * @tc.desc Test Js Api + * @tc.type: FUNC + * @tc.require: issueIAY1VI + */ + it('UdmfTestTypeDescriptor047', 0, function () { + const TAG = 'UdmfTestTypeDescriptor047:'; + console.info(TAG, 'start'); + let typeObj = UTD.getTypeDescriptor('general.ac3-audio'); + let typeId = typeObj.typeId; + let belonging = typeObj.belongingToTypes; + let description = typeObj.description; + let referenceURL = typeObj.referenceURL; + let iconFile = typeObj.iconFile; + let filenameExtensions = typeObj.filenameExtensions; + let mimeTypes = typeObj.mimeTypes; + console.info(TAG, ', typeId: ' + typeId + ', ' + Object.prototype.toString.call(typeId) + + ', belongingToTypes: ' + belonging + ', ' + Object.prototype.toString.call(belonging)); + console.info(TAG, 'description: ' + typeObj.description + ', ' + Object.prototype.toString.call(description)); + console.info(TAG, 'referenceURL: ' + referenceURL + ', ' + Object.prototype.toString.call(referenceURL) + + ', iconFile: ' + iconFile + ', ' + Object.prototype.toString.call(iconFile)); + expect(typeObj.typeId).assertEqual(UTD.UniformDataType.AC3_AUDIO); + expect(typeObj.belongingToTypes[0]).assertEqual('general.audio'); + expect(typeObj.description).assertEqual('Audio Codec 3 File Format'); + let equalStr = 'https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/' + + 'apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype'; + expect(typeObj.referenceURL).assertEqual(equalStr); + expect(typeObj.iconFile).assertEqual(''); + expect(typeObj.filenameExtensions[0]).assertEqual('.ac3'); + expect(typeObj.mimeTypes[0]).assertEqual('audio/ac3'); + console.info(TAG, 'end'); + }); + + /* + * @tc.name UdmfTestTypeDescriptor048 + * @tc.desc Test Js Api isLowerLevelType + * @tc.type: FUNC + * @tc.require: issueIAY1VI + */ + it('UdmfTestTypeDescriptor048', 0, function () { + const TAG = 'UdmfTestTypeDescriptor048:'; + console.info(TAG, 'start'); + let typeObj = UTD.getTypeDescriptor('com.aol.art-image'); + let belongsToRet = typeObj.belongsTo('general.image'); + expect(belongsToRet === true).assertTrue(); + let LowerLevelRet = typeObj.isLowerLevelType('general.object'); + expect(LowerLevelRet === true).assertTrue(); + console.info(TAG, 'end'); + }); + + /* + * @tc.name UdmfTestTypeDescriptor049 + * @tc.desc Test Js Api isLowerLevelType + * @tc.type: FUNC + * @tc.require: issueIAY1VI + */ + it('UdmfTestTypeDescriptor049', 0, function () { + const TAG = 'UdmfTestTypeDescriptor049:'; + console.info(TAG, 'start'); + let typeObj = UTD.getTypeDescriptor('com.aol.art-image'); + let belongsToRet = typeObj.belongsTo('general.image'); + expect(belongsToRet === true).assertTrue(); + let LowerLevelRet = typeObj.isLowerLevelType('general.object'); + expect(LowerLevelRet === true).assertTrue(); + console.info(TAG, 'end'); + }); + + /* + * @tc.name UdmfTestTypeDescriptor050 + * @tc.desc Test Js Api isHigherLevelType + * @tc.type: FUNC + * @tc.require: issueIAY1VI + */ + it('UdmfTestTypeDescriptor050', 0, function () { + const TAG = 'UdmfTestTypeDescriptor050:'; + console.info(TAG, 'start'); + let typeObj = UTD.getTypeDescriptor('com.apple.m4p-audio'); + let belongsToRet = typeObj.belongsTo('general.audio'); + expect(belongsToRet === true).assertTrue(); + let higherLevelRet = UTD.getTypeDescriptor('general.media').isHigherLevelType(UTD.UniformDataType.M4P_AUDIO); + expect(higherLevelRet === true).assertTrue(); + console.info(TAG, 'end'); + }); + + /* + * @tc.name UdmfTestTypeDescriptor051 + * @tc.desc Test Js Api getUniformDataTypeByFilenameExtension + * @tc.type: FUNC + * @tc.require: issueIAY1VI + */ + it('UdmfTestTypeDescriptor051', 0, function () { + const TAG = 'UdmfTestTypeDescriptor051:'; + console.info(TAG, 'start'); + let typeId = UTD.getUniformDataTypeByFilenameExtension('.nrw'); + expect(typeId === 'com.nikon.nrw-raw-image').assertTrue(); + console.info(TAG, 'typeDescriptor, ret ' + typeId); + console.info(TAG, 'end'); + }); + + /* + * @tc.name UdmfTestTypeDescriptor052 + * @tc.desc Test utd(general.mpeg-4) filename extension + * @tc.type: FUNC + * @tc.require: issueIAY1VI + */ + it('UdmfTestTypeDescriptor052', 0, function () { + const TAG = 'UdmfTestTypeDescriptor052:'; + console.info(TAG, 'start'); + let typeObj = UTD.getTypeDescriptor('general.mpeg-4'); + let filenameExtensions = typeObj.filenameExtensions; + expect(typeObj.filenameExtensions[0]).assertEqual('.mp4'); + expect(typeObj.filenameExtensions[1]).assertEqual('.mp4v'); + expect(typeObj.filenameExtensions[2]).assertEqual('.mpeg4'); + console.info(TAG, 'end'); + }); + + /* + * @tc.name UdmfTestTypeDescriptor053 + * @tc.desc Test utd(general.heif) filename extension + * @tc.type: FUNC + * @tc.require: issueIAY1VI + */ + it('UdmfTestTypeDescriptor053', 0, function () { + const TAG = 'UdmfTestTypeDescriptor053:'; + console.info(TAG, 'start'); + let typeObj = UTD.getTypeDescriptor('general.heif'); + let filenameExtensions = typeObj.filenameExtensions; + expect(typeObj.filenameExtensions[0]).assertEqual('.heif'); + expect(typeObj.filenameExtensions[1]).assertEqual('.heifs'); + expect(typeObj.filenameExtensions[2]).assertEqual('.hif'); + console.info(TAG, 'end'); + }); + + /* + * @tc.name UdmfTestTypeDescriptor054 + * @tc.desc Test utd(general.mpeg-4-audio) filename extension + * @tc.type: FUNC + * @tc.require: issueIAY1VI + */ + it('UdmfTestTypeDescriptor054', 0, function () { + const TAG = 'UdmfTestTypeDescriptor054:'; + console.info(TAG, 'start'); + let typeObj = UTD.getTypeDescriptor('general.mpeg-4-audio'); + let filenameExtensions = typeObj.filenameExtensions; + expect(typeObj.filenameExtensions[0]).assertEqual('.m4a'); + expect(typeObj.filenameExtensions[1]).assertEqual('.m4b'); + console.info(TAG, 'end'); + }); + + /* + * @tc.name UdmfTestTypeDescriptor055 + * @tc.desc Test utd(general.heic) filename extension + * @tc.type: FUNC + * @tc.require: issueIAY1VI + */ + it('UdmfTestTypeDescriptor055', 0, function () { + const TAG = 'UdmfTestTypeDescriptor055:'; + console.info(TAG, 'start'); + let typeObj = UTD.getTypeDescriptor('general.heic'); + let filenameExtensions = typeObj.filenameExtensions; + expect(typeObj.filenameExtensions[0]).assertEqual('.heic'); + expect(typeObj.filenameExtensions[1]).assertEqual('.heics'); + console.info(TAG, 'end'); + }); }); \ No newline at end of file diff --git a/udmf/framework/ndkimpl/data/udmf.cpp b/udmf/framework/ndkimpl/data/udmf.cpp index fd50926015dbcb4e652bf82fab1278f5e2105dfc..b3ccc75da6791afb0afd99e24d12c8e42ad2198f 100644 --- a/udmf/framework/ndkimpl/data/udmf.cpp +++ b/udmf/framework/ndkimpl/data/udmf.cpp @@ -627,6 +627,15 @@ int OH_UdmfRecord_AddArrayBuffer(OH_UdmfRecord* record, const char* type, OH_Uds return OH_UdmfRecord_AddGeneralEntry(record, type, entry, size); } +int OH_UdmfRecord_AddContentForm(OH_UdmfRecord* record, OH_UdsContentForm* contentForm) +{ + if (!IsUnifiedRecordValid(record) || IsInvalidUdsObjectPtr(contentForm, UDS_CONTENT_FORM_STRUCT_ID)) { + return UDMF_E_INVALID_PARAM; + } + AddUds(record, contentForm, UDType::CONTENT_FORM); + return UDMF_E_OK; +} + int OH_UdmfRecord_GetPlainText(OH_UdmfRecord* record, OH_UdsPlainText* plainText) { if (!IsUnifiedRecordValid(record) || IsInvalidUdsObjectPtr(plainText, UDS_PLAIN_TEXT_STRUCT_ID)) { @@ -699,6 +708,14 @@ int OH_UdmfRecord_GetArrayBuffer(OH_UdmfRecord* record, const char* type, OH_Uds return OH_UdsArrayBuffer_SetData(buffer, entry, size); } +int OH_UdmfRecord_GetContentForm(OH_UdmfRecord* record, OH_UdsContentForm* contentForm) +{ + if (!IsUnifiedRecordValid(record) || IsInvalidUdsObjectPtr(contentForm, UDS_CONTENT_FORM_STRUCT_ID)) { + return UDMF_E_INVALID_PARAM; + } + return GetUds(record, contentForm, UDType::CONTENT_FORM); +} + OH_UdmfProperty* OH_UdmfProperty_Create(OH_UdmfData* data) { if (!IsUnifiedDataValid(data)) { diff --git a/udmf/framework/ndkimpl/data/udmf_capi_common.h b/udmf/framework/ndkimpl/data/udmf_capi_common.h index 1515bb305e5624dc44b5f992bd6cfd807ad68835..e91d41c973f92c137f409c6a1b6dfedf607e8d40 100644 --- a/udmf/framework/ndkimpl/data/udmf_capi_common.h +++ b/udmf/framework/ndkimpl/data/udmf_capi_common.h @@ -45,6 +45,7 @@ enum NdkStructId : std::int64_t { UDS_FILE_URI_STRUCT_ID, UDS_PIXEL_MAP_STRUCT_ID, UDS_ARRAY_BUFFER_STRUCT_ID, + UDS_CONTENT_FORM_STRUCT_ID }; struct OH_Utd { @@ -83,6 +84,9 @@ struct OH_UdsPixelMap : public UdsObject { struct OH_UdsArrayBuffer : public UdsObject { OH_UdsArrayBuffer(); }; +struct OH_UdsContentForm : public UdsObject { + OH_UdsContentForm(); +}; struct OH_UdmfRecord { const int64_t cid = UDMF_UNIFIED_RECORD_STRUCT_ID; diff --git a/udmf/framework/ndkimpl/data/uds.cpp b/udmf/framework/ndkimpl/data/uds.cpp index 6de50e45ac7ca0b26709a459a2e5dbe0e428c176..08094efdd1bfb4f6a151a641c2afaa93781af909 100644 --- a/udmf/framework/ndkimpl/data/uds.cpp +++ b/udmf/framework/ndkimpl/data/uds.cpp @@ -26,16 +26,43 @@ using namespace OHOS::UDMF; -static const char* GetUdsStrValue(UdsObject* pThis, NdkStructId ndkStructId, const char* pramName) +static const char* GetUdsStrValue(UdsObject* pThis, NdkStructId ndkStructId, const char* paramName) { if (IsInvalidUdsObjectPtr(pThis, ndkStructId)) { return nullptr; } - auto value = pThis->GetUdsValue(pramName); + auto value = pThis->GetUdsValue(paramName); return value == nullptr ? nullptr : value->c_str(); } -bool IsInvalidUdsObjectPtr(const UdsObject* pThis, int cid) +static int GetUdsUint8Value(UdsObject* pThis, const char* paramName, const char* paramNameLen, unsigned char** data, + unsigned int* len) +{ + auto value = pThis->GetUdsValue>(paramName); + if (value == nullptr) { + return UDMF_ERR; + } + auto lengthPtr = pThis->GetUdsValue(paramNameLen); + int length; + if (lengthPtr == nullptr) { + if (value->size() > MAX_GENERAL_ENTRY_SIZE) { + LOG_ERROR(UDMF_CAPI, "length invalid. value'size = %{public}zu", value->size()); + return UDMF_ERR; + } + length = static_cast(value->size()); + } else { + length = *lengthPtr; + } + if (length < 0 || length > MAX_GENERAL_ENTRY_SIZE) { + LOG_ERROR(UDMF_CAPI, "length invalid! length'size = %{public}d", length); + return UDMF_ERR; + } + *data = value->data(); + *len = length; + return UDMF_E_OK; +} + +bool IsInvalidUdsObjectPtr(const UdsObject *pThis, int cid) { return pThis == nullptr || pThis->cid != cid || pThis->obj == nullptr; } @@ -76,8 +103,9 @@ OH_UdsPixelMap::OH_UdsPixelMap() : UdsObject(NdkStructId::UDS_PIXEL_MAP_STRUCT_I OH_UdsArrayBuffer::OH_UdsArrayBuffer() : UdsObject(NdkStructId::UDS_ARRAY_BUFFER_STRUCT_ID) {} -template -bool UdsObject::HasObjectKey(const char* paramName) +OH_UdsContentForm::OH_UdsContentForm() : UdsObject(NdkStructId::UDS_CONTENT_FORM_STRUCT_ID) {} + +template bool UdsObject::HasObjectKey(const char* paramName) { auto it = obj->value_.find(paramName); if (it == obj->value_.end() || !std::holds_alternative(it->second)) { @@ -512,20 +540,142 @@ int OH_UdsArrayBuffer_SetData(OH_UdsArrayBuffer* buffer, unsigned char* data, un int OH_UdsArrayBuffer_GetData(OH_UdsArrayBuffer* buffer, unsigned char** data, unsigned int* len) { - if (buffer == nullptr || IsInvalidUdsObjectPtr(buffer, NdkStructId::UDS_ARRAY_BUFFER_STRUCT_ID)) { + if (IsInvalidUdsObjectPtr(buffer, NdkStructId::UDS_ARRAY_BUFFER_STRUCT_ID)) { + return UDMF_E_INVALID_PARAM; + } + return GetUdsUint8Value(buffer, ARRAY_BUFFER, ARRAY_BUFFER_LENGTH, data, len); +} + +OH_UdsContentForm* OH_UdsContentForm_Create() +{ + auto contentForm = new (std::nothrow) OH_UdsContentForm(); + if (contentForm == nullptr) { + LOG_ERROR(UDMF_CAPI, "Failed to apply for memory."); + return nullptr; + } + contentForm->obj = std::make_shared(); + contentForm->obj->value_[UNIFORM_DATA_TYPE] = UDMF_METE_GENERAL_CONTENT_FORM; + contentForm->obj->value_[THUMB_DATA] = std::vector(); + contentForm->obj->value_[THUMB_DATA_LENGTH] = 0; + contentForm->obj->value_[DESCRIPTION] = ""; + contentForm->obj->value_[TITLE] = ""; + contentForm->obj->value_[APP_ICON] = std::vector(); + contentForm->obj->value_[APP_ICON_LENGTH] = 0; + contentForm->obj->value_[APP_NAME] = ""; + contentForm->obj->value_[LINK_URL] = ""; + return contentForm; +} + +void OH_UdsContentForm_Destroy(OH_UdsContentForm* pThis) +{ + if (pThis != nullptr && pThis->cid == NdkStructId::UDS_CONTENT_FORM_STRUCT_ID) { + delete pThis; + } +} + +const char* OH_UdsContentForm_GetType(OH_UdsContentForm* pThis) +{ + return GetUdsStrValue(pThis, NdkStructId::UDS_CONTENT_FORM_STRUCT_ID, UNIFORM_DATA_TYPE); +} + +int OH_UdsContentForm_GetThumbData(OH_UdsContentForm* pThis, unsigned char** thumbData, unsigned int* len) +{ + if (IsInvalidUdsObjectPtr(pThis, NdkStructId::UDS_CONTENT_FORM_STRUCT_ID)) { + return UDMF_E_INVALID_PARAM; + } + return GetUdsUint8Value(pThis, THUMB_DATA, THUMB_DATA_LENGTH, thumbData, len); +} + +const char* OH_UdsContentForm_GetDescription(OH_UdsContentForm* pThis) +{ + return GetUdsStrValue(pThis, NdkStructId::UDS_CONTENT_FORM_STRUCT_ID, DESCRIPTION); +} + +const char* OH_UdsContentForm_GetTitle(OH_UdsContentForm* pThis) +{ + return GetUdsStrValue(pThis, NdkStructId::UDS_CONTENT_FORM_STRUCT_ID, TITLE); +} + +int OH_UdsContentForm_GetAppIcon(OH_UdsContentForm* pThis, unsigned char** appIcon, unsigned int* len) +{ + if (IsInvalidUdsObjectPtr(pThis, NdkStructId::UDS_CONTENT_FORM_STRUCT_ID)) { + return UDMF_E_INVALID_PARAM; + } + return GetUdsUint8Value(pThis, APP_ICON, APP_ICON_LENGTH, appIcon, len); +} + +const char* OH_UdsContentForm_GetAppName(OH_UdsContentForm* pThis) +{ + return GetUdsStrValue(pThis, NdkStructId::UDS_CONTENT_FORM_STRUCT_ID, APP_NAME); +} + +const char* OH_UdsContentForm_GetLinkUri(OH_UdsContentForm* pThis) +{ + return GetUdsStrValue(pThis, NdkStructId::UDS_CONTENT_FORM_STRUCT_ID, LINK_URL); +} + +int OH_UdsContentForm_SetThumbData(OH_UdsContentForm* pThis, const unsigned char* thumbData, unsigned int len) +{ + if (thumbData == nullptr || len == 0 || IsInvalidUdsObjectPtr(pThis, NdkStructId::UDS_CONTENT_FORM_STRUCT_ID) || + len > MAX_GENERAL_ENTRY_SIZE) { LOG_ERROR(UDMF_CAPI, "Param is invalid."); return UDMF_E_INVALID_PARAM; } - const auto arrayBuffer = buffer->GetUdsValue>(ARRAY_BUFFER); - if (arrayBuffer == nullptr || arrayBuffer->empty()) { - return UDMF_ERR; + std::vector data(thumbData, thumbData + len); + int ret = pThis->SetUdsValue>(THUMB_DATA, data); + if (ret != UDMF_E_OK) { + LOG_ERROR(UDMF_CAPI, "Failed to apply for memory. ret: %{public}d", ret); + return ret; } - const auto length = buffer->GetUdsValue(ARRAY_BUFFER_LENGTH); - if (length == nullptr || *length <= 0 || *length > MAX_GENERAL_ENTRY_SIZE) { - return UDMF_ERR; + ret = pThis->SetUdsValue(THUMB_DATA_LENGTH, static_cast(len)); + return ret; +} + +int OH_UdsContentForm_SetDescription(OH_UdsContentForm* pThis, const char* description) +{ + if (description == nullptr || IsInvalidUdsObjectPtr(pThis, NdkStructId::UDS_CONTENT_FORM_STRUCT_ID)) { + return Udmf_ErrCode::UDMF_E_INVALID_PARAM; } + return pThis->SetUdsValue(DESCRIPTION, description); +} - *data = arrayBuffer->data(); - *len = *length; - return UDMF_E_OK; +int OH_UdsContentForm_SetTitle(OH_UdsContentForm* pThis, const char* title) +{ + if (title == nullptr || IsInvalidUdsObjectPtr(pThis, NdkStructId::UDS_CONTENT_FORM_STRUCT_ID)) { + return Udmf_ErrCode::UDMF_E_INVALID_PARAM; + } + return pThis->SetUdsValue(TITLE, title); +} + +int OH_UdsContentForm_SetAppIcon(OH_UdsContentForm* pThis, const unsigned char* appIcon, unsigned int len) +{ + if (appIcon == nullptr || len == 0 || IsInvalidUdsObjectPtr(pThis, NdkStructId::UDS_CONTENT_FORM_STRUCT_ID) || + len > MAX_GENERAL_ENTRY_SIZE) { + LOG_ERROR(UDMF_CAPI, "Param is invalid."); + return UDMF_E_INVALID_PARAM; + } + std::vector data(appIcon, appIcon + len); + int ret = pThis->SetUdsValue>(APP_ICON, data); + if (ret != UDMF_E_OK) { + LOG_ERROR(UDMF_CAPI, "Failed to apply for memory. ret: %{public}d", ret); + return ret; + } + ret = pThis->SetUdsValue(APP_ICON_LENGTH, static_cast(len)); + return ret; +} + +int OH_UdsContentForm_SetAppName(OH_UdsContentForm* pThis, const char* appName) +{ + if (appName == nullptr || IsInvalidUdsObjectPtr(pThis, NdkStructId::UDS_CONTENT_FORM_STRUCT_ID)) { + return Udmf_ErrCode::UDMF_E_INVALID_PARAM; + } + return pThis->SetUdsValue(APP_NAME, appName); +} + +int OH_UdsContentForm_SetLinkUri(OH_UdsContentForm* pThis, const char* linkUri) +{ + if (linkUri == nullptr || IsInvalidUdsObjectPtr(pThis, NdkStructId::UDS_CONTENT_FORM_STRUCT_ID)) { + return Udmf_ErrCode::UDMF_E_INVALID_PARAM; + } + return pThis->SetUdsValue(LINK_URL, linkUri); } \ No newline at end of file diff --git a/udmf/framework/ndkimpl/unittest/ndk_data_conversion_test.cpp b/udmf/framework/ndkimpl/unittest/ndk_data_conversion_test.cpp deleted file mode 100644 index 7d8dc45592d7257d496d073331f1cfff3e101f27..0000000000000000000000000000000000000000 --- a/udmf/framework/ndkimpl/unittest/ndk_data_conversion_test.cpp +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (c) 2024 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#define LOG_TAG "NdkDataConversionTest" - -#include "ndk_data_conversion.h" -#include -#include -#include "token_setproc.h" -#include "accesstoken_kit.h" -#include "nativetoken_kit.h" -#include "logger.h" -#include "error_code.h" -#include "udmf.h" -#include "udmf_capi_common.h" -#include "uds.h" - -using namespace testing::ext; -using namespace OHOS::Security::AccessToken; -using namespace OHOS::UDMF; -using namespace OHOS; - -namespace OHOS::Test { - class NdkDataConversionTest : public testing::Test { - public: - static void SetUpTestCase(void); - - static void TearDownTestCase(void); - - void SetUp(); - - void TearDown(); - }; - - void NdkDataConversionTest::SetUpTestCase(void) {} - - void NdkDataConversionTest::TearDownTestCase(void) {} - - void NdkDataConversionTest::SetUp(void) {} - - void NdkDataConversionTest::TearDown(void) {} - - /** - * @tc.name: GetNativeUnifiedData_001 - * @tc.desc: Normal testcase of GetNativeUnifiedData - * @tc.type: FUNC - */ - HWTEST_F(NdkDataConversionTest, GetNativeUnifiedData_001, TestSize.Level1) { - LOG_INFO(UDMF_TEST, "GetNativeUnifiedData_001 begin."); - UnifiedRecord unifiedRecord; - const std::string uid("typeId"); - unifiedRecord.SetUid(uid); - OH_UdmfData* ndkData = OH_UdmfData_Create(); - const std::shared_ptr recordPtr = std::make_shared(unifiedRecord); - ndkData->unifiedData_->AddRecord(recordPtr); - auto data = std::make_shared(); - - Status status = NdkDataConversion::GetNativeUnifiedData(ndkData, data); - ASSERT_EQ(E_OK, status); - EXPECT_EQ("typeId", data->GetRecordAt(0)->GetUid()); - - OH_UdmfData* ndkDataNull = nullptr; - status = NdkDataConversion::GetNativeUnifiedData(ndkDataNull, data); - ASSERT_EQ(E_INVALID_PARAMETERS, status); - - std::shared_ptr dataNull; - status = NdkDataConversion::GetNativeUnifiedData(ndkData, dataNull); - OH_UdmfData_Destroy(ndkData); - ASSERT_EQ(E_INVALID_PARAMETERS, status); - LOG_INFO(UDMF_TEST, "GetNativeUnifiedData_001 end."); - } - - /** - * @tc.name: GetNativeUnifiedData_002 - * @tc.desc: Normal testcase of GetNativeUnifiedData - * @tc.type: FUNC - */ - HWTEST_F(NdkDataConversionTest, GetNativeUnifiedData_002, TestSize.Level1) { - LOG_INFO(UDMF_TEST, "GetNativeUnifiedData_002 begin."); - auto plainText = OH_UdsPlainText_Create(); - OH_UdmfData* fakeNdkData = reinterpret_cast(plainText); - auto data = std::make_shared(); - Status status = NdkDataConversion::GetNativeUnifiedData(fakeNdkData, data); - OH_UdsPlainText_Destroy(plainText); - ASSERT_EQ(E_INVALID_PARAMETERS, status); - LOG_INFO(UDMF_TEST, "GetNativeUnifiedData_002 end."); - } - - /** - * @tc.name: GetNdkUnifiedData_001 - * @tc.desc: Error testcase of GetNdkUnifiedData - * @tc.type: FUNC - */ - HWTEST_F(NdkDataConversionTest, GetNdkUnifiedData_001, TestSize.Level1) { - LOG_INFO(UDMF_TEST, "GetNdkUnifiedData_001 begin."); - UnifiedRecord unifiedRecord; - const std::string uid("typeId"); - unifiedRecord.SetUid(uid); - const std::shared_ptr recordPtr = std::make_shared(unifiedRecord); - auto data= std::make_shared(); - data->AddRecord(recordPtr); - OH_UdmfData* ndkData = OH_UdmfData_Create(); - Status status = NdkDataConversion::GetNdkUnifiedData(data, ndkData); - ASSERT_EQ(E_OK, status); - EXPECT_EQ("typeId", ndkData->unifiedData_->GetRecordAt(0)->GetUid()); - - OH_UdmfData* ndkDataNull = nullptr; - status = NdkDataConversion::GetNdkUnifiedData(data, ndkDataNull); - ASSERT_EQ(E_INVALID_PARAMETERS, status); - - std::shared_ptr dataNull; - status = NdkDataConversion::GetNdkUnifiedData(dataNull, ndkData); - OH_UdmfData_Destroy(ndkData); - ASSERT_EQ(E_INVALID_PARAMETERS, status); - LOG_INFO(UDMF_TEST, "GetNdkUnifiedData_001 end."); - } - - /** - * @tc.name: GetNdkUnifiedData_002 - * @tc.desc: Error testcase of GetNdkUnifiedData - * @tc.type: FUNC - */ - HWTEST_F(NdkDataConversionTest, GetNdkUnifiedData_002, TestSize.Level1) { - LOG_INFO(UDMF_TEST, "GetNdkUnifiedData_002 begin."); - auto plainText = OH_UdsPlainText_Create(); - OH_UdmfData* fakeNdkData = reinterpret_cast(plainText); - auto data = std::make_shared(); - Status status = NdkDataConversion::GetNdkUnifiedData(data, fakeNdkData); - OH_UdsPlainText_Destroy(plainText); - ASSERT_EQ(E_INVALID_PARAMETERS, status); - LOG_INFO(UDMF_TEST, "GetNdkUnifiedData_002 end."); - } -} \ No newline at end of file diff --git a/udmf/framework/ndkimpl/unittest/udmf_test.cpp b/udmf/framework/ndkimpl/unittest/udmf_test.cpp index e4521d326b965ba89f68a61dc1e9e00a1159b9b7..23ab655a14c001d9f8ee5d8347eb124f8b30c076 100644 --- a/udmf/framework/ndkimpl/unittest/udmf_test.cpp +++ b/udmf/framework/ndkimpl/unittest/udmf_test.cpp @@ -2349,4 +2349,49 @@ HWTEST_F(UDMFTest, OH_Udmf_SetAndGetUnifiedData005, TestSize.Level1) OH_UdsFileUri_Destroy(getFileUri); OH_UdmfData_Destroy(readUnifiedData); } + +/** + * @tc.name: OH_Udmf_SetAndGetUnifiedData006 + * @tc.desc: OH_Udmf_SetUnifiedData and OH_Udmf_GetUnifiedData with content form + * @tc.type: FUNC + */ +HWTEST_F(UDMFTest, OH_Udmf_SetAndGetUnifiedData006, TestSize.Level1) +{ + OH_UdmfData *udmfUnifiedData = OH_UdmfData_Create(); + OH_UdmfRecord *record = OH_UdmfRecord_Create(); + OH_UdsContentForm *contentForm = OH_UdsContentForm_Create(); + unsigned char thumbData[] = {0, 1, 2, 3, 4}; + OH_UdsContentForm_SetThumbData(contentForm, thumbData, 5); + OH_UdsContentForm_SetDescription(contentForm, "description"); + OH_UdmfRecord_AddContentForm(record, contentForm); + OH_UdmfData_AddRecord(udmfUnifiedData, record); + Udmf_Intention intention = UDMF_INTENTION_DRAG; + char key[UDMF_KEY_BUFFER_LEN]; + + int setRes = OH_Udmf_SetUnifiedData(intention, udmfUnifiedData, key, UDMF_KEY_BUFFER_LEN); + EXPECT_EQ(setRes, UDMF_E_OK); + EXPECT_NE(key[0], '\0'); + OH_UdmfData *readUnifiedData = OH_UdmfData_Create(); + int getRes = OH_Udmf_GetUnifiedData(key, intention, readUnifiedData); + EXPECT_EQ(getRes, UDMF_E_OK); + unsigned int count = 0; + OH_UdmfRecord **getRecords = OH_UdmfData_GetRecords(readUnifiedData, &count); + EXPECT_EQ(count, 1); + OH_UdsContentForm *getContentForm = OH_UdsContentForm_Create(); + OH_UdmfRecord_GetContentForm(getRecords[0], getContentForm); + EXPECT_EQ("description", std::string(OH_UdsContentForm_GetDescription(getContentForm))); + + unsigned char *readThumbData; + unsigned int thumbDataLen = 0; + OH_UdsContentForm_GetThumbData(getContentForm, &readThumbData, &thumbDataLen); + ASSERT_EQ(5, thumbDataLen); + ASSERT_TRUE(CheckUnsignedChar(thumbData, readThumbData, thumbDataLen)); + + OH_UdsContentForm_Destroy(contentForm); + OH_UdmfRecord_Destroy(record); + OH_UdmfData_Destroy(udmfUnifiedData); + + OH_UdsContentForm_Destroy(getContentForm); + OH_UdmfData_Destroy(readUnifiedData); +} } diff --git a/udmf/framework/ndkimpl/unittest/uds_test.cpp b/udmf/framework/ndkimpl/unittest/uds_test.cpp index 4dd4603e6f1f799a3b72f6082855888689a6e66e..7ea8012fe529025f47395de0de3ec092bf7888f6 100644 --- a/udmf/framework/ndkimpl/unittest/uds_test.cpp +++ b/udmf/framework/ndkimpl/unittest/uds_test.cpp @@ -1081,4 +1081,44 @@ HWTEST_F(UdsTest, OH_UdsArrayBuffer_SetData_001, TestSize.Level1) LOG_INFO(UDMF_TEST, "OH_UdsArrayBuffer_SetData_001 end."); } +/** + * @tc.name: OH_UdsContentForm_SetAndGetParm_001 + * @tc.desc: Normal testcase of OH_UdsContentForm's interface + * @tc.type: FUNC + */ +HWTEST_F(UdsTest, OH_UdsContentForm_SetAndGetParm_001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "OH_UdsContentForm_SetAndGetParm_001 begin."); + auto contentForm = OH_UdsContentForm_Create(); + EXPECT_EQ(UDMF_METE_GENERAL_CONTENT_FORM, std::string(OH_UdsContentForm_GetType(contentForm))); + unsigned char thumbData[] = {0, 1, 2, 3, 4}; + unsigned char appIcon[] = {5, 6, 7, 8, 9}; + auto result = OH_UdsContentForm_SetThumbData(contentForm, thumbData, 5); + result = (result == UDMF_E_OK) && OH_UdsContentForm_SetDescription(contentForm, "description"); + result = (result == UDMF_E_OK) && OH_UdsContentForm_SetTitle(contentForm, "title"); + result = (result == UDMF_E_OK) && OH_UdsContentForm_SetAppIcon(contentForm, appIcon, 5); + result = (result == UDMF_E_OK) && OH_UdsContentForm_SetAppName(contentForm, "appName"); + result = (result == UDMF_E_OK) && OH_UdsContentForm_SetLinkUri(contentForm, "link url"); + EXPECT_EQ(UDMF_E_OK, result); + EXPECT_EQ("description", std::string(OH_UdsContentForm_GetDescription(contentForm))); + EXPECT_EQ("title", std::string(OH_UdsContentForm_GetTitle(contentForm))); + EXPECT_EQ("appName", std::string(OH_UdsContentForm_GetAppName(contentForm))); + EXPECT_EQ("link url", std::string(OH_UdsContentForm_GetLinkUri(contentForm))); + + unsigned char *readThumbData; + unsigned int thumbDataLen = 0; + result = OH_UdsContentForm_GetThumbData(contentForm, &readThumbData, &thumbDataLen); + ASSERT_EQ(5, thumbDataLen); + ASSERT_TRUE(CheckUnsignedChar(thumbData, readThumbData, thumbDataLen)); + + unsigned char *readAppIcon; + unsigned int appIconLen = 0; + result = OH_UdsContentForm_GetAppIcon(contentForm, &readAppIcon, &appIconLen); + ASSERT_EQ(5, thumbDataLen); + ASSERT_TRUE(CheckUnsignedChar(thumbData, readThumbData, thumbDataLen)); + + OH_UdsContentForm_Destroy(contentForm); + LOG_INFO(UDMF_TEST, "OH_UdsContentForm_SetAndGetParm_001 end."); +} + } diff --git a/udmf/interfaces/innerkits/common/unified_meta.h b/udmf/interfaces/innerkits/common/unified_meta.h index 100fcead74acaeb92aa7205107d40a17750a0627..c376a0d9b2f1ac4e2eafecd52d193a5202027299 100644 --- a/udmf/interfaces/innerkits/common/unified_meta.h +++ b/udmf/interfaces/innerkits/common/unified_meta.h @@ -56,6 +56,12 @@ constexpr const char *ORI_URI = "oriUri"; constexpr const char *REMOTE_URI = "remoteUri"; constexpr const char *DETAILS = "details"; constexpr const char *VALUE_TYPE = "VALUE_TYPE"; +constexpr const char *THUMB_DATA = "thumbData"; +constexpr const char *THUMB_DATA_LENGTH = "thumbDataLen"; +constexpr const char *TITLE = "title"; +constexpr const char* APP_ICON = "appIcon"; +constexpr const char* APP_ICON_LENGTH = "appIconLen"; +constexpr const char* LINK_URL = "linkUrl"; enum UDType : int32_t { ENTITY = 0, diff --git a/udmf/interfaces/innerkits/data/unified_data.h b/udmf/interfaces/innerkits/data/unified_data.h index eb7a31f834137d98952ece9804940558819da7c0..9a28474b8584d3d34148713509606c69e4c43edf 100644 --- a/udmf/interfaces/innerkits/data/unified_data.h +++ b/udmf/interfaces/innerkits/data/unified_data.h @@ -34,7 +34,7 @@ public: void AddRecord(const std::shared_ptr &record); void AddRecords(const std::vector> &records); - std::shared_ptr GetRecordAt(std::size_t index); + std::shared_ptr GetRecordAt(std::size_t index) const; void SetRecords(std::vector> records); std::vector> GetRecords() const; diff --git a/udmf/interfaces/ndk/data/udmf.h b/udmf/interfaces/ndk/data/udmf.h index 8d03a6e60ccad4d81ebe65c2639eb8dbf64789cf..ffc1fe268d153247de44768da94fbf631238730b 100644 --- a/udmf/interfaces/ndk/data/udmf.h +++ b/udmf/interfaces/ndk/data/udmf.h @@ -335,7 +335,7 @@ int OH_UdmfRecord_AddGeneralEntry(OH_UdmfRecord* record, const char* typeId, const unsigned char* entry, unsigned int count); /** - * @brief Add one {OH_UdsPlainText} data to the {@link OH_UdmfRecord} record. + * @brief Add one {@link OH_UdsPlainText} data to the {@link OH_UdmfRecord} record. * * @param pThis Represents a pointer to an instance of {@link OH_UdmfRecord}. * @param plainText Represents a pointer to an instance of {@link OH_UdsPlainText}. @@ -348,7 +348,7 @@ int OH_UdmfRecord_AddGeneralEntry(OH_UdmfRecord* record, const char* typeId, int OH_UdmfRecord_AddPlainText(OH_UdmfRecord* pThis, OH_UdsPlainText* plainText); /** - * @brief Add one {OH_UdsHyperlink} data to the {@link OH_UdmfRecord} record. + * @brief Add one {@link OH_UdsHyperlink} data to the {@link OH_UdmfRecord} record. * * @param pThis Represents a pointer to an instance of {@link OH_UdmfRecord}. * @param hyperlink Represents a pointer to an instance of {@link OH_UdsHyperlink}. @@ -361,7 +361,7 @@ int OH_UdmfRecord_AddPlainText(OH_UdmfRecord* pThis, OH_UdsPlainText* plainText) int OH_UdmfRecord_AddHyperlink(OH_UdmfRecord* pThis, OH_UdsHyperlink* hyperlink); /** - * @brief Add one {OH_UdsHtml} data to the {@link OH_UdmfRecord} record. + * @brief Add one {@link OH_UdsHtml} data to the {@link OH_UdmfRecord} record. * * @param pThis Represents a pointer to an instance of {@link OH_UdmfRecord}. * @param html Represents a pointer to an instance of {@link OH_UdsHtml}. @@ -374,7 +374,7 @@ int OH_UdmfRecord_AddHyperlink(OH_UdmfRecord* pThis, OH_UdsHyperlink* hyperlink) int OH_UdmfRecord_AddHtml(OH_UdmfRecord* pThis, OH_UdsHtml* html); /** - * @brief Add one {OH_UdsAppItem} data to the {@link OH_UdmfRecord} record. + * @brief Add one {@link OH_UdsAppItem} data to the {@link OH_UdmfRecord} record. * * @param pThis Represents a pointer to an instance of {@link OH_UdmfRecord}. * @param appItem Represents a pointer to an instance of {@link OH_UdsAppItem}. @@ -387,7 +387,7 @@ int OH_UdmfRecord_AddHtml(OH_UdmfRecord* pThis, OH_UdsHtml* html); int OH_UdmfRecord_AddAppItem(OH_UdmfRecord* pThis, OH_UdsAppItem* appItem); /** - * @brief Add one {OH_UdsFileUri} data to the {@link OH_UdmfRecord} record. + * @brief Add one {@link OH_UdsFileUri} data to the {@link OH_UdmfRecord} record. * * @param pThis Represents a pointer to an instance of {@link OH_UdmfRecord}. * @param fileUri Represents a pointer to an instance of {@link OH_UdsFileUri}. @@ -400,7 +400,7 @@ int OH_UdmfRecord_AddAppItem(OH_UdmfRecord* pThis, OH_UdsAppItem* appItem); int OH_UdmfRecord_AddFileUri(OH_UdmfRecord* pThis, OH_UdsFileUri* fileUri); /** - * @brief Add one {OH_UdsPixelMap} data to the {@link OH_UdmfRecord} record. + * @brief Add one {@link OH_UdsPixelMap} data to the {@link OH_UdmfRecord} record. * * @param pThis Represents a pointer to an instance of {@link OH_UdmfRecord}. * @param pixelMap Represents a pointer to an instance of {@link OH_UdsPixelMap}. @@ -426,6 +426,19 @@ int OH_UdmfRecord_AddPixelMap(OH_UdmfRecord* pThis, OH_UdsPixelMap* pixelMap); */ int OH_UdmfRecord_AddArrayBuffer(OH_UdmfRecord* record, const char* type, OH_UdsArrayBuffer* buffer); +/** + * @brief Add one {@link OH_UdsContentForm} data to the {@link OH_UdmfRecord} record. + * + * @param pThis Represents a pointer to an instance of {@link OH_UdmfRecord}. + * @param contentForm Represents a pointer to an instance of {@link OH_UdsContentForm}. + * @return Returns the status code of the execution. See {@link Udmf_ErrCode}. + * {@link UDMF_E_OK} success. + * {@link UDMF_E_INVALID_PARAM} The error code for common invalid args. + * @see OH_UdmfRecord OH_UdsContentForm Udmf_ErrCode. + * @since 14 + */ +int OH_UdmfRecord_AddContentForm(OH_UdmfRecord* pThis, OH_UdsContentForm* contentForm); + /** * @brief Get all types in the {@link OH_UdmfRecord} record. * @@ -455,7 +468,7 @@ int OH_UdmfRecord_GetGeneralEntry(OH_UdmfRecord* pThis, const char* typeId, unsigned char** entry, unsigned int* count); /** - * @brief Get one {OH_UdsPlainText} data from the {@link OH_UdmfRecord} record. + * @brief Get one {@link OH_UdsPlainText} data from the {@link OH_UdmfRecord} record. * * @param pThis Represents a pointer to an instance of {@link OH_UdmfRecord}. * @param plainText Represents a pointer to an instance of {@link OH_UdsPlainText}. @@ -468,7 +481,7 @@ int OH_UdmfRecord_GetGeneralEntry(OH_UdmfRecord* pThis, const char* typeId, int OH_UdmfRecord_GetPlainText(OH_UdmfRecord* pThis, OH_UdsPlainText* plainText); /** - * @brief Get one {OH_UdsHyperlink} data from the {@link OH_UdmfRecord} record. + * @brief Get one {@link OH_UdsHyperlink} data from the {@link OH_UdmfRecord} record. * * @param pThis Represents a pointer to an instance of {@link OH_UdmfRecord}. * @param hyperlink Represents a pointer to an instance of {@link OH_UdsHyperlink}. @@ -481,7 +494,7 @@ int OH_UdmfRecord_GetPlainText(OH_UdmfRecord* pThis, OH_UdsPlainText* plainText) int OH_UdmfRecord_GetHyperlink(OH_UdmfRecord* pThis, OH_UdsHyperlink* hyperlink); /** - * @brief Get one {OH_UdsHtml} data from the {@link OH_UdmfRecord} record. + * @brief Get one {@link OH_UdsHtml} data from the {@link OH_UdmfRecord} record. * * @param pThis Represents a pointer to an instance of {@link OH_UdmfRecord}. * @param html Represents a pointer to an instance of {@link OH_UdsHtml}. @@ -494,7 +507,7 @@ int OH_UdmfRecord_GetHyperlink(OH_UdmfRecord* pThis, OH_UdsHyperlink* hyperlink) int OH_UdmfRecord_GetHtml(OH_UdmfRecord* pThis, OH_UdsHtml* html); /** - * @brief Get one {OH_UdsAppItem} data from the {@link OH_UdmfRecord} record. + * @brief Get one {@link OH_UdsAppItem} data from the {@link OH_UdmfRecord} record. * * @param pThis Represents a pointer to an instance of {@link OH_UdmfRecord}. * @param appItem Represents a pointer to an instance of {@link OH_UdsAppItem}. @@ -507,7 +520,7 @@ int OH_UdmfRecord_GetHtml(OH_UdmfRecord* pThis, OH_UdsHtml* html); int OH_UdmfRecord_GetAppItem(OH_UdmfRecord* pThis, OH_UdsAppItem* appItem); /** - * @brief Get one {OH_UdsFileUri} data from the {@link OH_UdmfRecord} record. + * @brief Get one {@link OH_UdsFileUri} data from the {@link OH_UdmfRecord} record. * * @param pThis Represents a pointer to an instance of {@link OH_UdmfRecord}. * @param fileUri Represents a pointer to an instance of {@link OH_UdsFileUri}. @@ -520,7 +533,7 @@ int OH_UdmfRecord_GetAppItem(OH_UdmfRecord* pThis, OH_UdsAppItem* appItem); int OH_UdmfRecord_GetFileUri(OH_UdmfRecord* pThis, OH_UdsFileUri* fileUri); /** - * @brief Get one {OH_UdsPixelMap} data from the {@link OH_UdmfRecord} record. + * @brief Get one {@link OH_UdsPixelMap} data from the {@link OH_UdmfRecord} record. * * @param pThis Represents a pointer to an instance of {@link OH_UdmfRecord}. * @param pixelMap Represents a pointer to an instance of {@link OH_UdsPixelMap}. @@ -533,34 +546,47 @@ int OH_UdmfRecord_GetFileUri(OH_UdmfRecord* pThis, OH_UdsFileUri* fileUri); int OH_UdmfRecord_GetPixelMap(OH_UdmfRecord* pThis, OH_UdsPixelMap* pixelMap); /** - * @brief Set the data provider of the types. + * @brief Get one {@link OH_UdsArrayBuffer} data from the {@link OH_UdmfRecord} record. * - * @param pThis Represents a pointer to an instance of {@link OH_UdmfRecord}. - * @param types Represents a pointer to a group of data types; - * @param count Represents the number of data types; - * @param provider Represents a pointer an instance of {@link OH_UdmfRecordProvider}. + * @param record Represents a pointer to an instance of {@link OH_UdmfRecord}. + * @param type Represents record type, reference udmf_meta.h. + * @param buffer Represents a pointer to an instance of {@link OH_UdsArrayBuffer}. * @return Returns the status code of the execution. See {@link Udmf_ErrCode}. * {@link UDMF_E_OK} success. * {@link UDMF_E_INVALID_PARAM} The error code for common invalid args. - * @see OH_UdmfRecord OH_UdmfRecordProvider Udmf_ErrCode. + * @see OH_UdmfRecord OH_UdsArrayBuffer Udmf_ErrCode. * @since 13 */ -int OH_UdmfRecord_SetProvider(OH_UdmfRecord* pThis, const char* const* types, unsigned int count, - OH_UdmfRecordProvider* provider); +int OH_UdmfRecord_GetArrayBuffer(OH_UdmfRecord* record, const char* type, OH_UdsArrayBuffer* buffer); /** - * @brief Get one {@link OH_UdsArrayBuffer} data from the {@link OH_UdmfRecord} record. + * @brief Get one {@link OH_UdsContentForm} data from the {@link OH_UdmfRecord} record. * - * @param record Represents a pointer to an instance of {@link OH_UdmfRecord}. - * @param type Represents record type, reference udmf_meta.h. - * @param buffer Represents a pointer to an instance of {@link OH_UdsArrayBuffer}. + * @param pThis Represents a pointer to an instance of {@link OH_UdmfRecord}. + * @param contentForm Represents a pointer to an instance of {@link OH_UdsContentForm}. * @return Returns the status code of the execution. See {@link Udmf_ErrCode}. * {@link UDMF_E_OK} success. * {@link UDMF_E_INVALID_PARAM} The error code for common invalid args. - * @see OH_UdmfRecord OH_UdsArrayBuffer Udmf_ErrCode. + * @see OH_UdmfRecord OH_UdsContentForm Udmf_ErrCode. + * @since 14 + */ +int OH_UdmfRecord_GetContentForm(OH_UdmfRecord* pThis, OH_UdsContentForm* contentForm); + +/** + * @brief Set the data provider of the types. + * + * @param pThis Represents a pointer to an instance of {@link OH_UdmfRecord}. + * @param types Represents a pointer to a group of data types; + * @param count Represents the number of data types; + * @param provider Represents a pointer an instance of {@link OH_UdmfRecordProvider}. + * @return Returns the status code of the execution. See {@link Udmf_ErrCode}. + * {@link UDMF_E_OK} success. + * {@link UDMF_E_INVALID_PARAM} The error code for common invalid args. + * @see OH_UdmfRecord OH_UdmfRecordProvider Udmf_ErrCode. * @since 13 */ -int OH_UdmfRecord_GetArrayBuffer(OH_UdmfRecord* record, const char* type, OH_UdsArrayBuffer* buffer); +int OH_UdmfRecord_SetProvider(OH_UdmfRecord* pThis, const char* const* types, unsigned int count, + OH_UdmfRecordProvider* provider); /** * @brief Creation a pointer to the instance of the {@link OH_UdmfProperty} diff --git a/udmf/interfaces/ndk/data/udmf_meta.h b/udmf/interfaces/ndk/data/udmf_meta.h index e9c3914ed3e9c6c884e28a85c488f946b4fd1cf5..29f50a30068f004dd5f1e4350edd51b5c6cff8b6 100644 --- a/udmf/interfaces/ndk/data/udmf_meta.h +++ b/udmf/interfaces/ndk/data/udmf_meta.h @@ -997,6 +997,13 @@ extern "C" { */ #define UDMF_META_GENERAL_FILE_URI "general.file-uri" +/** + * @brief A specific type of uniform data type. + * + * @since 14 + */ +#define UDMF_METE_GENERAL_CONTENT_FORM "general.content-form" + #ifdef __cplusplus }; #endif diff --git a/udmf/interfaces/ndk/data/uds.h b/udmf/interfaces/ndk/data/uds.h index 8c0083f78aae079ca5a8df33e1cebebd0824cf48..a1a774103e554ff46e3efdb02f15ff4cfbdb5f57 100644 --- a/udmf/interfaces/ndk/data/uds.h +++ b/udmf/interfaces/ndk/data/uds.h @@ -86,6 +86,13 @@ typedef struct OH_UdsFileUri OH_UdsFileUri; */ typedef struct OH_UdsPixelMap OH_UdsPixelMap; +/** + * @brief Describes the unified data struct of content form. + * + * @since 14 + */ +typedef struct OH_UdsContentForm OH_UdsContentForm; + /** * @brief Describes the of pixel map native. * @@ -669,6 +676,185 @@ int OH_UdsArrayBuffer_SetData(OH_UdsArrayBuffer* buffer, unsigned char* data, un */ int OH_UdsArrayBuffer_GetData(OH_UdsArrayBuffer* buffer, unsigned char** data, unsigned int* len); +/** + * @brief Creation a pointer to the instance of the {@link OH_UdsContentForm}. + * + * @return If the operation is successful, a pointer to the instance of the {@link OH_UdsContentForm} + * structure is returned. If the operation is failed, nullptr is returned. + * @see OH_UdsContentForm + * @since 14 + */ +OH_UdsContentForm* OH_UdsContentForm_Create(); + +/** + * @brief Destroy a pointer that points to the {@link OH_UdsContentForm} instance. + * + * @param pThis Represents a pointer to an instance of {@link OH_UdsContentForm}. + * @see OH_UdsContentForm + * @since 14 + */ +void OH_UdsContentForm_Destroy(OH_UdsContentForm* pThis); + +/** + * @brief Get type id from the {@link OH_UdsContentForm}. + * + * @param pThis Represents a pointer to an instance of {@link OH_UdsContentForm}. + * @return Returns a pointer of the value string when input args normally, otherwise return nullptr. + * @see OH_UdsContentForm + * @since 14 + */ +const char* OH_UdsContentForm_GetType(OH_UdsContentForm* pThis); + +/** + * @brief Get thumb data from the {@link OH_UdsContentForm}. + * + * @param pThis Represents a pointer to an instance of {@link OH_UdsContentForm}. + * @param thumbData Represents a pointer to thumb data that is a output param. + * @param len Represents the thumb data length that is a output param. + * @return Returns the status code of the execution. See {@link Udmf_ErrCode}. + * {@link UDMF_E_OK} success. + * {@link UDMF_E_INVALID_PARAM} The error code for common invalid args. + * {@link UDMF_ERR} Internal data error. + * @see OH_UdsContentForm Udmf_ErrCode + * @since 14 + */ +int OH_UdsContentForm_GetThumbData(OH_UdsContentForm* pThis, unsigned char** thumbData, unsigned int* len); + +/** + * @brief Get description from the {@link OH_UdsContentForm}. + * + * @param pThis Represents a pointer to an instance of {@link OH_UdsContentForm}. + * @return Returns a pointer of the value string when input args normally, otherwise return nullptr. + * @see OH_UdsContentForm + * @since 14 + */ +const char* OH_UdsContentForm_GetDescription(OH_UdsContentForm* pThis); + +/** + * @brief Get title from the {@link OH_UdsContentForm}. + * + * @param pThis Represents a pointer to an instance of {@link OH_UdsContentForm}. + * @return Returns a pointer of the value string when input args normally, otherwise return nullptr. + * @see OH_UdsContentForm + * @since 14 + */ +const char* OH_UdsContentForm_GetTitle(OH_UdsContentForm* pThis); + +/** + * @brief Get thumb data from the {@link OH_UdsContentForm}. + * + * @param pThis Represents a pointer to an instance of {@link OH_UdsContentForm}. + * @param appIcon Represents a pointer to app icon that is a output param. + * @param len Represents the app icon length that is a output param. + * @return Returns the status code of the execution. See {@link Udmf_ErrCode}. + * {@link UDMF_E_OK} success. + * {@link UDMF_E_INVALID_PARAM} The error code for common invalid args. + * {@link UDMF_ERR} Internal data error. + * @see OH_UdsContentForm Udmf_ErrCode + * @since 14 + */ +int OH_UdsContentForm_GetAppIcon(OH_UdsContentForm* pThis, unsigned char** appIcon, unsigned int* len); + +/** + * @brief Get app name from the {@link OH_UdsContentForm}. + * + * @param pThis Represents a pointer to an instance of {@link OH_UdsContentForm}. + * @return Returns a pointer of the value string when input args normally, otherwise return nullptr. + * @see OH_UdsContentForm + * @since 14 + */ +const char* OH_UdsContentForm_GetAppName(OH_UdsContentForm* pThis); + +/** + * @brief Get link url from the {@link OH_UdsContentForm}. + * + * @param pThis Represents a pointer to an instance of {@link OH_UdsContentForm}. + * @return Returns a pointer of the value string when input args normally, otherwise return nullptr. + * @see OH_UdsContentForm + * @since 14 + */ +const char* OH_UdsContentForm_GetLinkUri(OH_UdsContentForm* pThis); + +/** + * @brief Set thumb data to the {@link OH_UdsContentForm}. + * + * @param pThis Represents a pointer to an instance of {@link OH_UdsContentForm}. + * @param thumbData Represents the thumb data. + * @param len Represents the length of thumb data param. + * @return Returns the status code of the execution. See {@link Udmf_ErrCode}. + * {@link UDMF_E_OK} success. + * {@link UDMF_E_INVALID_PARAM} The error code for common invalid args. + * @see OH_UdsContentForm Udmf_ErrCode + * @since 14 + */ +int OH_UdsContentForm_SetThumbData(OH_UdsContentForm* pThis, const unsigned char* thumbData, unsigned int len); + +/** + * @brief Set description to the {@link OH_UdsContentForm}. + * + * @param pThis Represents a pointer to an instance of {@link OH_UdsContentForm}. + * @param description Represents a description string. + * @return Returns the status code of the execution. See {@link Udmf_ErrCode}. + * {@link UDMF_E_OK} success. + * {@link UDMF_E_INVALID_PARAM} The error code for common invalid args. + * @see OH_UdsContentForm Udmf_ErrCode + * @since 14 + */ +int OH_UdsContentForm_SetDescription(OH_UdsContentForm* pThis, const char* description); + +/** + * @brief Set title to the {@link OH_UdsContentForm}. + * + * @param pThis Represents a pointer to an instance of {@link OH_UdsContentForm}. + * @param title Represents a title string. + * @return Returns the status code of the execution. See {@link Udmf_ErrCode}. + * {@link UDMF_E_OK} success. + * {@link UDMF_E_INVALID_PARAM} The error code for common invalid args. + * @see OH_UdsContentForm Udmf_ErrCode + * @since 14 + */ +int OH_UdsContentForm_SetTitle(OH_UdsContentForm* pThis, const char* title); + +/** + * @brief Set thumb data to the {@link OH_UdsContentForm}. + * + * @param pThis Represents a pointer to an instance of {@link OH_UdsContentForm}. + * @param appIcon Represents the app icon. + * @param len Represents the length of app icon param. + * @return Returns the status code of the execution. See {@link Udmf_ErrCode}. + * {@link UDMF_E_OK} success. + * {@link UDMF_E_INVALID_PARAM} The error code for common invalid args. + * @see OH_UdsContentForm Udmf_ErrCode + * @since 14 + */ +int OH_UdsContentForm_SetAppIcon(OH_UdsContentForm* pThis, const unsigned char* appIcon, unsigned int len); + +/** + * @brief Set app name to the {@link OH_UdsContentForm}. + * + * @param pThis Represents a pointer to an instance of {@link OH_UdsContentForm}. + * @param appName Represents a app name string. + * @return Returns the status code of the execution. See {@link Udmf_ErrCode}. + * {@link UDMF_E_OK} success. + * {@link UDMF_E_INVALID_PARAM} The error code for common invalid args. + * @see OH_UdsContentForm Udmf_ErrCode + * @since 14 + */ +int OH_UdsContentForm_SetAppName(OH_UdsContentForm* pThis, const char* appName); + +/** + * @brief Set link uri to the {@link OH_UdsContentForm}. + * + * @param pThis Represents a pointer to an instance of {@link OH_UdsContentForm}. + * @param linkUri Represents a link uri string. + * @return Returns the status code of the execution. See {@link Udmf_ErrCode}. + * {@link UDMF_E_OK} success. + * {@link UDMF_E_INVALID_PARAM} The error code for common invalid args. + * @see OH_UdsContentForm Udmf_ErrCode + * @since 14 + */ +int OH_UdsContentForm_SetLinkUri(OH_UdsContentForm* pThis, const char* linkUri); + #ifdef __cplusplus }; #endif