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 92f8339696196f3bbcadf6c19d4173d88c7c1ed3..6aa7762062bda2c0c9b0ae05932d5e4f669eae36 100644 --- a/data_object/frameworks/innerkitsimpl/src/communicator/softbus_adapter_standard.cpp +++ b/data_object/frameworks/innerkitsimpl/src/communicator/softbus_adapter_standard.cpp @@ -13,19 +13,18 @@ * limitations under the License. */ -#include -#include -#include +#include "softbus_adapter.h" +#include "anonymous.h" +#include "bundle_mgr_interface.h" #include "dev_manager.h" #include "dms_handler.h" -#include "anonymous.h" -#include "kv_store_delegate_manager.h" -#include "process_communicator_impl.h" +#include "iservice_registry.h" +#include "logger.h" #include "securec.h" #include "session.h" -#include "softbus_adapter.h" #include "softbus_bus_center.h" +#include "system_ability_definition.h" namespace OHOS { namespace ObjectStore { @@ -37,7 +36,7 @@ constexpr const char *DEFAULT_ANONYMOUS = "******"; constexpr int32_t SOFTBUS_OK = 0; constexpr int32_t INVALID_SOCKET_ID = 0; constexpr size_t TASK_CAPACITY_MAX = 15; -using namespace std; +constexpr const char *PKG_NAME = "ohos.objectstore"; SoftBusAdapter *AppDataListenerWrap::softBusAdapter_; std::shared_ptr SoftBusAdapter::instance_; @@ -191,7 +190,7 @@ DeviceInfo SoftBusAdapter::GetLocalDevice() } NodeBasicInfo info; - int32_t ret = GetLocalNodeDeviceInfo("ohos.objectstore", &info); + int32_t ret = GetLocalNodeDeviceInfo(PKG_NAME, &info); if (ret != SOFTBUS_OK) { LOG_ERROR("GetLocalNodeDeviceInfo error"); return DeviceInfo(); @@ -207,7 +206,7 @@ DeviceInfo SoftBusAdapter::GetLocalBasicInfo() const { LOG_DEBUG("begin"); NodeBasicInfo info; - int32_t ret = GetLocalNodeDeviceInfo("ohos.objectstore", &info); + int32_t ret = GetLocalNodeDeviceInfo(PKG_NAME, &info); if (ret != SOFTBUS_OK) { LOG_ERROR("GetLocalNodeDeviceInfo error"); return DeviceInfo(); @@ -228,7 +227,7 @@ std::vector SoftBusAdapter::GetRemoteNodesBasicInfo() const int32_t infoNum = 0; dis.clear(); - int32_t ret = GetAllNodeDeviceInfo("ohos.objectstore", &info, &infoNum); + int32_t ret = GetAllNodeDeviceInfo(PKG_NAME, &info, &infoNum); if (ret != SOFTBUS_OK) { LOG_ERROR("GetAllNodeDeviceInfo error"); return dis; @@ -248,7 +247,7 @@ std::vector SoftBusAdapter::GetRemoteNodesBasicInfo() const void SoftBusAdapter::UpdateRelationship(const std::string &networkId, const DeviceChangeType &type) { auto uuid = DevManager::GetInstance()->GetUuidByNodeId(networkId); - lock_guard lock(networkMutex_); + std::lock_guard lock(networkMutex_); switch (type) { case DeviceChangeType::DEVICE_OFFLINE: { auto size = this->networkId2Uuid_.erase(networkId); @@ -274,7 +273,7 @@ void SoftBusAdapter::UpdateRelationship(const std::string &networkId, const Devi std::string SoftBusAdapter::ToNodeID(const std::string &nodeId) const { { - lock_guard lock(networkMutex_); + std::lock_guard lock(networkMutex_); for (auto const &e : networkId2Uuid_) { if (nodeId == e.second) { // id is uuid return e.first; @@ -285,9 +284,9 @@ std::string SoftBusAdapter::ToNodeID(const std::string &nodeId) const NodeBasicInfo *info = nullptr; int32_t infoNum = 0; std::string networkId; - int32_t ret = GetAllNodeDeviceInfo("ohos.objectstore", &info, &infoNum); + int32_t ret = GetAllNodeDeviceInfo(PKG_NAME, &info, &infoNum); if (ret == SOFTBUS_OK) { - lock_guard lock(networkMutex_); + std::lock_guard lock(networkMutex_); for (int i = 0; i < infoNum; i++) { if (networkId2Uuid_.find(info[i].networkId) != networkId2Uuid_.end()) { continue; @@ -331,7 +330,7 @@ Status SoftBusAdapter::StartWatchDataChange(const AppDataChangeListener *observe if (observer == nullptr) { return Status::INVALID_ARGUMENT; } - lock_guard lock(dataChangeMutex_); + std::lock_guard lock(dataChangeMutex_); auto it = dataChangeListeners_.find(pipeInfo.pipeId); if (it != dataChangeListeners_.end()) { LOG_WARN("Add listener error or repeated adding."); @@ -346,7 +345,7 @@ Status SoftBusAdapter::StopWatchDataChange( __attribute__((unused)) const AppDataChangeListener *observer, const PipeInfo &pipeInfo) { LOG_DEBUG("begin"); - lock_guard lock(dataChangeMutex_); + std::lock_guard lock(dataChangeMutex_); if (dataChangeListeners_.erase(pipeInfo.pipeId)) { return Status::SUCCESS; } @@ -357,7 +356,7 @@ Status SoftBusAdapter::StopWatchDataChange( Status SoftBusAdapter::SendData(const PipeInfo &pipeInfo, const DeviceId &deviceId, const DataInfo &dataInfo, uint32_t totalLength, const MessageInfo &info) { - lock_guard lock(sendDataMutex_); + std::lock_guard lock(sendDataMutex_); auto result = CacheData(deviceId.deviceId, dataInfo); if (result != Status::SUCCESS) { return result; @@ -383,7 +382,7 @@ Status SoftBusAdapter::CacheData(const std::string &deviceId, const DataInfo &da return Status::INVALID_ARGUMENT; } BytesMsg bytesMsg = { data, dataInfo.length }; - lock_guard lock(deviceDataLock_); + std::lock_guard lock(deviceDataLock_); auto deviceIdData = dataCaches_.find(deviceId); if (deviceIdData == dataCaches_.end()) { dataCaches_[deviceId] = { bytesMsg }; @@ -398,7 +397,7 @@ Status SoftBusAdapter::CacheData(const std::string &deviceId, const DataInfo &da int SoftBusAdapter::GetSocket(const PipeInfo &pipeInfo, const DeviceId &deviceId) { - lock_guard lock(socketLock_); + std::lock_guard lock(socketLock_); auto it = sockets_.find(deviceId.deviceId); if (it != sockets_.end()) { return it->second; @@ -411,41 +410,69 @@ int SoftBusAdapter::GetSocket(const PipeInfo &pipeInfo, const DeviceId &deviceId return socketId; } +static std::string GetSelfAppId() +{ + sptr saManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (saManager == nullptr) { + LOG_ERROR("Get system ability manager failed"); + return ""; + } + sptr remoteObject = saManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID); + if (remoteObject == nullptr) { + LOG_ERROR("Get system ability failed"); + return ""; + } + sptr bundleManager = iface_cast(remoteObject); + if (bundleManager == nullptr) { + LOG_ERROR("Get bundle manager failed"); + return ""; + } + AppExecFwk::BundleInfo bundleInfo; + auto status = bundleManager->GetBundleInfoForSelf( + 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 bundleInfo.appId; +} + int SoftBusAdapter::CreateClientSocket(const PipeInfo &pipeInfo, const DeviceId &deviceId) { - SocketInfo socketInfo; - socketInfo.name = const_cast(pipeInfo.pipeId.c_str()); - socketInfo.peerName = const_cast(pipeInfo.pipeId.c_str()); - std::string networkId = ToNodeID(deviceId.deviceId); - socketInfo.peerNetworkId = const_cast(networkId.c_str()); - - std::string pkgName = "ohos.objectstore"; - socketInfo.pkgName = pkgName.data(); - socketInfo.dataType = DATA_TYPE_BYTES; - int socketId = Socket(socketInfo); - if (socketId <= 0) { - LOG_ERROR("Create socket failed, error code: %{public}d, name:%{public}s", socketId, socketInfo.name); - return INVALID_SOCKET_ID; - } - int32_t res = Bind(socketId, Qos, QOS_COUNT, &clientListener_); - if (res != 0) { - LOG_ERROR("Bind failed, error code: %{public}d, peerName: %{public}s, peerNetworkId: %{public}s", - res, socketInfo.peerName, Anonymous::Change(networkId).c_str()); - Shutdown(socketId); - return INVALID_SOCKET_ID; - } - return socketId; + SocketInfo socketInfo; + // AppId is used only for socket verification. The created socket name does not contain appId. + std::string socketNameAndAppId = pipeInfo.pipeId + '-' + GetSelfAppId(); + socketInfo.name = socketNameAndAppId.data(); + socketInfo.peerName = const_cast(pipeInfo.pipeId.c_str()); + std::string networkId = ToNodeID(deviceId.deviceId); + socketInfo.peerNetworkId = networkId.data(); + socketInfo.pkgName = const_cast(PKG_NAME); + socketInfo.dataType = DATA_TYPE_BYTES; + int socketId = Socket(socketInfo); + if (socketId <= 0) { + LOG_ERROR("Create socket failed, error code: %{public}d, name: %{public}s, networkId: %{public}s", socketId, + Anonymous::Change(socketNameAndAppId).c_str(), Anonymous::Change(networkId).c_str()); + return INVALID_SOCKET_ID; + } + int32_t res = Bind(socketId, Qos, QOS_COUNT, &clientListener_); + if (res != 0) { + LOG_ERROR("Bind failed, error code: %{public}d, socket: %{public}d, name: %{public}s, networkId: %{public}s", + res, socketId, Anonymous::Change(socketNameAndAppId).c_str(), Anonymous::Change(networkId).c_str()); + Shutdown(socketId); + return INVALID_SOCKET_ID; + } + return socketId; } void SoftBusAdapter::DoSend() { auto task([this]() { - lock_guard lock(socketLock_); + std::lock_guard lock(socketLock_); for (auto &it : sockets_) { if (it.second <= INVALID_SOCKET_ID) { continue; } - lock_guard lock(deviceDataLock_); + std::lock_guard lock(deviceDataLock_); auto dataCache = dataCaches_.find(it.first); if (dataCache == dataCaches_.end()) { continue; @@ -467,7 +494,7 @@ void SoftBusAdapter::DoSend() void SoftBusAdapter::OnClientShutdown(int32_t socket) { - lock_guard lock(socketLock_); + std::lock_guard lock(socketLock_); for (auto iter = sockets_.begin(); iter != sockets_.end();) { if (iter->second == socket) { iter = sockets_.erase(iter); @@ -487,17 +514,20 @@ bool SoftBusAdapter::IsSameStartedOnPeer( int SoftBusAdapter::CreateSessionServerAdapter(const std::string &sessionName) { SocketInfo socketInfo; - socketInfo.name = const_cast(sessionName.c_str()); - std::string pkgName = "ohos.objectstore"; - socketInfo.pkgName = pkgName.data(); + // AppId is used only for socket verification. The created socket name does not contain appId. + std::string socketNameAndAppId = sessionName + '-' + GetSelfAppId(); + socketInfo.name = socketNameAndAppId.data(); + socketInfo.pkgName = const_cast(PKG_NAME); socketServer_ = Socket(socketInfo); if (socketServer_ <= 0) { - LOG_ERROR("Create socket failed, error code: %{public}d, name:%{public}s", socketServer_, socketInfo.name); + LOG_ERROR("Create socket failed, error code: %{public}d, name: %{public}s", socketServer_, + Anonymous::Change(socketNameAndAppId).c_str()); return static_cast(Status::ERROR); } int res = Listen(socketServer_, Qos, QOS_COUNT, &serverListener_); if (res != SOFTBUS_OK) { - LOG_ERROR("Listen socket failed, error code: %{public}d, socket:%{public}d", res, socketServer_); + LOG_ERROR("Listen socket failed, error code: %{public}d, socket: %{public}d, name: %{public}s", res, + socketServer_, Anonymous::Change(socketNameAndAppId).c_str()); return static_cast(Status::ERROR); } return SOFTBUS_OK; @@ -513,7 +543,7 @@ int SoftBusAdapter::RemoveSessionServerAdapter(const std::string &sessionName) c void SoftBusAdapter::NotifyDataListeners( const uint8_t *ptr, const int size, const std::string &deviceId, const PipeInfo &pipeInfo) { - lock_guard lock(dataChangeMutex_); + std::lock_guard lock(dataChangeMutex_); auto it = dataChangeListeners_.find(pipeInfo.pipeId); if (it != dataChangeListeners_.end()) { LOG_DEBUG("ready to notify, pipeName:%{public}s, deviceId:%{public}s.", pipeInfo.pipeId.c_str(), diff --git a/data_object/frameworks/innerkitsimpl/test/unittest/mock/src/mock_soft_bus.cpp b/data_object/frameworks/innerkitsimpl/test/unittest/mock/src/mock_soft_bus.cpp index 6fe83b9b7e723c00368e029aa9498432c3b1b09c..3950c4840e769e2034461b739e2acbb7548facc2 100644 --- a/data_object/frameworks/innerkitsimpl/test/unittest/mock/src/mock_soft_bus.cpp +++ b/data_object/frameworks/innerkitsimpl/test/unittest/mock/src/mock_soft_bus.cpp @@ -95,7 +95,7 @@ int CreateSessionServer(const char *pkgName, const char *sessionName, const ISes int Socket(SocketInfo info) { const char *invalidSessionName = "INVALID_SESSION_NAME"; - if (!strcmp(info.name, invalidSessionName)) { + if (strstr(info.name, invalidSessionName) != nullptr) { return 0; } return 1; diff --git a/data_object/frameworks/innerkitsimpl/test/unittest/src/object_store_test.cpp b/data_object/frameworks/innerkitsimpl/test/unittest/src/object_store_test.cpp index 7e764e70d6e96b52a83a1d82b179e91c45135e79..c95ddb0e162d5fbdfd80b21ef39e2705b893f37b 100644 --- a/data_object/frameworks/innerkitsimpl/test/unittest/src/object_store_test.cpp +++ b/data_object/frameworks/innerkitsimpl/test/unittest/src/object_store_test.cpp @@ -14,32 +14,34 @@ */ #include - -#include #include #include "accesstoken_kit.h" -#include "auto_launch_export.h" #include "distributed_object.h" #include "distributed_object_impl.h" #include "distributed_objectstore.h" #include "distributed_objectstore_impl.h" #include "flat_object_storage_engine.h" #include "flat_object_store.h" -#include "ipc_skeleton.h" -#include "kv_store_delegate_manager.h" #include "mock_flat_object_watcher.h" #include "mock_object_watcher.h" #include "nativetoken_kit.h" #include "object_storage_engine.h" #include "objectstore_errors.h" -#include "store_observer.h" #include "token_setproc.h" using namespace testing::ext; using namespace OHOS::ObjectStore; using namespace OHOS::Security::AccessToken; namespace { +// object service error code +enum Status : int32_t { + OBJECT_SUCCESS, + OBJECT_DBSTATUS_ERROR, + OBJECT_INNER_ERROR, + OBJECT_PERMISSION_DENIED, + OBJECT_STORE_NOT_FOUND +}; constexpr static double SALARY = 100.5; class TableWatcherImpl : public TableWatcher { public: @@ -1223,7 +1225,7 @@ HWTEST_F(NativeObjectStoreTest, CacheManager_Save_001, TestSize.Level1) std::map> objectData; CacheManager cacheManager; auto ret = cacheManager.Save(bundleName, sessionId, deviceId, objectData); - EXPECT_EQ(DistributedDB::DBStatus::INVALID_ARGS, ret); + EXPECT_EQ(OBJECT_PERMISSION_DENIED, ret); } /** @@ -1237,7 +1239,7 @@ HWTEST_F(NativeObjectStoreTest, CacheManager_RevokeSave_001, TestSize.Level1) std::string sessionId = ""; CacheManager cacheManager; auto ret = cacheManager.RevokeSave(bundleName, sessionId); - EXPECT_EQ(DistributedDB::DBStatus::INVALID_ARGS, ret); + EXPECT_EQ(OBJECT_PERMISSION_DENIED, ret); } /** @@ -1253,7 +1255,7 @@ HWTEST_F(NativeObjectStoreTest, CacheManager_ResumeObject_001, TestSize.Level1) std::function> &data, bool allReady)> callback = [](const std::map> &data, bool allReady) {}; auto ret = cacheManager.ResumeObject(bundleName, sessionId, callback); - EXPECT_EQ(DistributedDB::DBStatus::INVALID_ARGS, ret); + EXPECT_EQ(OBJECT_PERMISSION_DENIED, ret); } /** @@ -1269,7 +1271,7 @@ HWTEST_F(NativeObjectStoreTest, CacheManager_SubscribeDataChange_001, TestSize.L std::function> &data, bool allReady)> callback = [](const std::map> &data, bool allReady) {}; auto ret = cacheManager.SubscribeDataChange(bundleName, sessionId, callback); - EXPECT_EQ(DistributedDB::DBStatus::INVALID_ARGS, ret); + EXPECT_EQ(OBJECT_PERMISSION_DENIED, ret); } /** @@ -1283,7 +1285,7 @@ HWTEST_F(NativeObjectStoreTest, CacheManager_UnregisterDataChange_001, TestSize. std::string sessionId = ""; CacheManager cacheManager; auto ret = cacheManager.UnregisterDataChange(bundleName, sessionId); - EXPECT_EQ(DistributedDB::DBStatus::INVALID_ARGS, ret); + EXPECT_EQ(OBJECT_PERMISSION_DENIED, ret); } /** diff --git a/data_object/frameworks/jskitsimpl/include/common/uv_queue.h b/data_object/frameworks/jskitsimpl/include/common/uv_queue.h index d7fe19a6c614fbad370459321a402113b898e4d4..4823fd180988e854959aa49732b6d091bd5c73b6 100644 --- a/data_object/frameworks/jskitsimpl/include/common/uv_queue.h +++ b/data_object/frameworks/jskitsimpl/include/common/uv_queue.h @@ -19,6 +19,7 @@ #include #include #include + #include "napi/native_api.h" #include "napi/native_node_api.h" #include "uv.h" diff --git a/data_object/frameworks/jskitsimpl/src/adaptor/js_distributedobjectstore.cpp b/data_object/frameworks/jskitsimpl/src/adaptor/js_distributedobjectstore.cpp index 49d167a3927020bfebe0cc52369ce680e2b53f30..5b52811f4588422f40a10b6655dc2c522800b8a0 100644 --- a/data_object/frameworks/jskitsimpl/src/adaptor/js_distributedobjectstore.cpp +++ b/data_object/frameworks/jskitsimpl/src/adaptor/js_distributedobjectstore.cpp @@ -20,7 +20,6 @@ #include "ability_context.h" #include "accesstoken_kit.h" -#include "anonymous.h" #include "application_context.h" #include "distributed_objectstore.h" #include "js_ability.h" diff --git a/data_share/frameworks/js/napi/common/src/datashare_predicates_proxy.cpp b/data_share/frameworks/js/napi/common/src/datashare_predicates_proxy.cpp index 1a68e8c597f93a11da44de9d5b9d42b4474b1e2e..e748ff4ffd0f20b6fcce6cf52e9749d3bdced889 100644 --- a/data_share/frameworks/js/napi/common/src/datashare_predicates_proxy.cpp +++ b/data_share/frameworks/js/napi/common/src/datashare_predicates_proxy.cpp @@ -157,6 +157,10 @@ napi_value DataSharePredicatesProxy::NewInstance(napi_env env, std::shared_ptrSetInstance(value); return instance; } @@ -170,6 +174,10 @@ std::shared_ptr DataSharePredicatesProxy::GetNativePredi } DataSharePredicatesProxy *proxy = nullptr; napi_unwrap(env, arg, reinterpret_cast(&proxy)); + if (proxy == nullptr) { + LOG_ERROR("Native Predicates is nullptr!"); + return nullptr; + } return proxy->GetInstance(); } @@ -195,6 +203,10 @@ std::shared_ptr DataSharePredicatesProxy::GetNativePredi napi_value thiz; napi_get_cb_info(env, info, nullptr, nullptr, &thiz, nullptr); napi_unwrap(env, thiz, reinterpret_cast(&predicatesProxy)); + if (predicatesProxy == nullptr) { + LOG_ERROR("predicatesProxy is nullptr!"); + return nullptr; + } return predicatesProxy->GetInstance(); } diff --git a/data_share/frameworks/js/napi/common/src/datashare_result_set_proxy.cpp b/data_share/frameworks/js/napi/common/src/datashare_result_set_proxy.cpp index 9b3db78ef9fe0179965ffe5c03fc03a85884b5ae..14e53a8f6f79df40f9455a2658adb000b72f8915 100644 --- a/data_share/frameworks/js/napi/common/src/datashare_result_set_proxy.cpp +++ b/data_share/frameworks/js/napi/common/src/datashare_result_set_proxy.cpp @@ -161,6 +161,10 @@ std::shared_ptr DataShareResultSetProxy::GetInnerResultSet(n napi_value self = nullptr; napi_get_cb_info(env, info, nullptr, nullptr, &self, nullptr); napi_unwrap(env, self, reinterpret_cast(&resultSet)); + if (resultSet == nullptr) { + LOG_ERROR("Inner ResultSet is nullptr!"); + return nullptr; + } return resultSet->GetInstance(); } diff --git a/data_share/frameworks/js/napi/dataShare/src/async_call.cpp b/data_share/frameworks/js/napi/dataShare/src/async_call.cpp index b4e1bf9b6f461b326706cb47963915861327fc0a..3610dd9481406fd171f2dd90353c892f15c7f9d8 100644 --- a/data_share/frameworks/js/napi/dataShare/src/async_call.cpp +++ b/data_share/frameworks/js/napi/dataShare/src/async_call.cpp @@ -151,7 +151,7 @@ void AsyncCall::OnComplete(napi_env env, napi_status status, void *data) void AsyncCall::DeleteContext(napi_env env, AsyncContext *context) { - if (env != nullptr) { + if (env != nullptr && context != nullptr) { napi_delete_reference(env, context->callback); napi_delete_reference(env, context->self); napi_delete_async_work(env, context->work); diff --git a/data_share/frameworks/native/consumer/src/datashare_helper.cpp b/data_share/frameworks/native/consumer/src/datashare_helper.cpp index 7f11998b2172e19910862480751c021fe492466b..6e3ad68d16e2e9ddf023cbac4e4c43ee93c4bee8 100644 --- a/data_share/frameworks/native/consumer/src/datashare_helper.cpp +++ b/data_share/frameworks/native/consumer/src/datashare_helper.cpp @@ -95,9 +95,9 @@ std::shared_ptr DataShareHelper::Creator( return nullptr; } Uri ext(extUri); - helper = CreateExtHelper(ext, token); + helper = CreateExtHelper(ext, token, waitTime); } else { - helper = CreateExtHelper(uri, token); + helper = CreateExtHelper(uri, token, waitTime); } return helper; } @@ -111,7 +111,7 @@ std::shared_ptr DataShareHelper::Creator(const string &strUri, LOG_ERROR("token is nullptr"); return nullptr; } - return options.isProxy_ ? CreateServiceHelper("", bundleName) : CreateExtHelper(uri, options.token_); + return options.isProxy_ ? CreateServiceHelper("", bundleName) : CreateExtHelper(uri, options.token_, waitTime); } std::pair> DataShareHelper::Create(const sptr &token, @@ -142,7 +142,7 @@ std::pair> DataShareHelper::Create(const s } uri = Uri(extUri); } - auto helper = CreateExtHelper(uri, token); + auto helper = CreateExtHelper(uri, token, waitTime); if (helper != nullptr) { return std::make_pair(E_OK, helper); } 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 1175c279548006a7e22bd8bb5dd3fc3a8e55e721..ee7d41c55d6828f1d21ab075acc0d278afc15ceb 100644 --- a/data_share/frameworks/native/provider/include/datashare_uv_queue.h +++ b/data_share/frameworks/native/provider/include/datashare_uv_queue.h @@ -16,6 +16,7 @@ #ifndef DATASHARE_UV_QUEUE_H #define DATASHARE_UV_QUEUE_H +#include #include #include #include @@ -44,10 +45,9 @@ private: napi_env env; NapiVoidFunc func; bool done; - bool purge; std::condition_variable condition; std::mutex mutex; - NapiBoolFunc retFunc; + std::atomic count; }; static void LambdaForWork(uv_work_t* work, int uvstatus); diff --git a/data_share/frameworks/native/provider/src/datashare_stub_impl.cpp b/data_share/frameworks/native/provider/src/datashare_stub_impl.cpp index bee637f5292604c1b0ad0f9fbc2a473141707974..280738395fde03bc90d8f42152b7d77b0598563d 100644 --- a/data_share/frameworks/native/provider/src/datashare_stub_impl.cpp +++ b/data_share/frameworks/native/provider/src/datashare_stub_impl.cpp @@ -62,8 +62,9 @@ std::vector DataShareStubImpl::GetFileTypes(const Uri &uri, const s if (extension == nullptr) { return false; } + bool isRecvReply = extension->GetRecvReply(); extension->GetResult(ret); - return extension->GetRecvReply(); + return isRecvReply; }; std::lock_guard lock(mutex_); uvQueue_->SyncCall(syncTaskFunc, getRetFunc); @@ -88,8 +89,9 @@ int DataShareStubImpl::OpenFile(const Uri &uri, const std::string &mode) if (extension == nullptr) { return false; } + bool isRecvReply = extension->GetRecvReply(); extension->GetResult(ret); - return extension->GetRecvReply(); + return isRecvReply; }; std::lock_guard lock(mutex_); uvQueue_->SyncCall(syncTaskFunc, getRetFunc); @@ -141,8 +143,9 @@ int DataShareStubImpl::Insert(const Uri &uri, const DataShareValuesBucket &value if (extension == nullptr) { return false; } + bool isRecvReply = extension->GetRecvReply(); extension->GetResult(ret); - return extension->GetRecvReply(); + return isRecvReply; }; std::lock_guard lock(mutex_); uvQueue_->SyncCall(syncTaskFunc, getRetFunc); @@ -175,8 +178,9 @@ int DataShareStubImpl::Update(const Uri &uri, const DataSharePredicates &predica if (extension == nullptr) { return false; } + bool isRecvReply = extension->GetRecvReply(); extension->GetResult(ret); - return extension->GetRecvReply(); + return isRecvReply; }; std::lock_guard lock(mutex_); uvQueue_->SyncCall(syncTaskFunc, getRetFunc); @@ -206,8 +210,9 @@ int DataShareStubImpl::BatchUpdate(const UpdateOperations &operations, std::vect if (extension == nullptr) { return false; } + bool isRecvReply = extension->GetRecvReply(); extension->GetResult(results); - return extension->GetRecvReply(); + return isRecvReply; }; std::lock_guard lock(mutex_); uvQueue_->SyncCall(syncTaskFunc, getRetFunc); @@ -239,8 +244,9 @@ int DataShareStubImpl::Delete(const Uri &uri, const DataSharePredicates &predica if (extension == nullptr) { return false; } + bool isRecvReply = extension->GetRecvReply(); extension->GetResult(ret); - return extension->GetRecvReply(); + return isRecvReply; }; std::lock_guard lock(mutex_); uvQueue_->SyncCall(syncTaskFunc, getRetFunc); @@ -272,8 +278,9 @@ std::pair DataShareStubImpl::InsertEx(const Uri &uri, const Da if (extension == nullptr) { return false; } + bool isRecvReply = extension->GetRecvReply(); extension->GetResult(ret); - return extension->GetRecvReply(); + return isRecvReply; }; std::lock_guard lock(mutex_); uvQueue_->SyncCall(syncTaskFunc, getRetFunc); @@ -306,8 +313,9 @@ std::pair DataShareStubImpl::UpdateEx(const Uri &uri, const Da if (extension == nullptr) { return false; } + bool isRecvReply = extension->GetRecvReply(); extension->GetResult(ret); - return extension->GetRecvReply(); + return isRecvReply; }; std::lock_guard lock(mutex_); uvQueue_->SyncCall(syncTaskFunc, getRetFunc); @@ -339,8 +347,9 @@ std::pair DataShareStubImpl::DeleteEx(const Uri &uri, const Da if (extension == nullptr) { return false; } + bool isRecvReply = extension->GetRecvReply(); extension->GetResult(ret); - return extension->GetRecvReply(); + return isRecvReply; }; std::lock_guard lock(mutex_); uvQueue_->SyncCall(syncTaskFunc, getRetFunc); @@ -404,8 +413,9 @@ std::string DataShareStubImpl::GetType(const Uri &uri) if (extension == nullptr) { return false; } + bool isRecvReply = extension->GetRecvReply(); extension->GetResult(ret); - return extension->GetRecvReply(); + return isRecvReply; }; std::lock_guard lock(mutex_); uvQueue_->SyncCall(syncTaskFunc, getRetFunc); @@ -436,8 +446,9 @@ int DataShareStubImpl::BatchInsert(const Uri &uri, const std::vectorGetRecvReply(); extension->GetResult(ret); - return extension->GetRecvReply(); + return isRecvReply; }; std::lock_guard lock(mutex_); uvQueue_->SyncCall(syncTaskFunc, getRetFunc); @@ -508,11 +519,12 @@ Uri DataShareStubImpl::NormalizeUri(const Uri &uri) if (extension == nullptr) { return false; } + bool isRecvReply = extension->GetRecvReply(); std::string ret; extension->GetResult(ret); Uri tmp(ret); normalizeUri = tmp; - return extension->GetRecvReply(); + return isRecvReply; }; std::lock_guard lock(mutex_); uvQueue_->SyncCall(syncTaskFunc, getRetFunc); @@ -537,11 +549,12 @@ Uri DataShareStubImpl::DenormalizeUri(const Uri &uri) if (extension == nullptr) { return false; } + bool isRecvReply = extension->GetRecvReply(); std::string ret; extension->GetResult(ret); Uri tmp(ret); denormalizedUri = tmp; - return extension->GetRecvReply(); + return isRecvReply; }; std::lock_guard lock(mutex_); uvQueue_->SyncCall(syncTaskFunc, getRetFunc); diff --git a/data_share/frameworks/native/provider/src/datashare_uv_queue.cpp b/data_share/frameworks/native/provider/src/datashare_uv_queue.cpp index ada7b561794885e538052abf0a04be9f1f8931ba..307d8810cf93e6fce160e0a39e74e1dc41e99c77 100644 --- a/data_share/frameworks/native/provider/src/datashare_uv_queue.cpp +++ b/data_share/frameworks/native/provider/src/datashare_uv_queue.cpp @@ -34,6 +34,7 @@ void DataShareUvQueue::LambdaForWork(uv_work_t *work, int uvstatus) { if (UV_ECANCELED == uvstatus || work == nullptr || work->data == nullptr) { LOG_ERROR("invalid work or work->data."); + DataShareUvQueue::Purge(work); return; } auto *entry = static_cast(work->data); @@ -43,10 +44,7 @@ void DataShareUvQueue::LambdaForWork(uv_work_t *work, int uvstatus) entry->func(); } entry->done = true; - if (!entry->purge) { - entry->condition.notify_all(); - return; - } + entry->condition.notify_all(); } DataShareUvQueue::Purge(work); } @@ -58,17 +56,17 @@ void DataShareUvQueue::SyncCall(NapiVoidFunc func, NapiBoolFunc retFunc) LOG_ERROR("invalid work."); return; } - work->data = new UvEntry {env_, std::move(func), false, false, {}, {}, std::move(retFunc)}; + work->data = new UvEntry {env_, std::move(func), false, {}, {}, std::atomic(1)}; if (work->data == nullptr) { delete work; LOG_ERROR("invalid uvEntry."); return; } - bool noNeedPurge = false; auto *uvEntry = static_cast(work->data); { std::unique_lock lock(uvEntry->mutex); + uvEntry->count.fetch_add(1); auto status = uv_queue_work( loop_, work, [](uv_work_t *work) {}, LambdaForWork); if (status != napi_ok) { @@ -83,15 +81,11 @@ void DataShareUvQueue::SyncCall(NapiVoidFunc func, NapiBoolFunc retFunc) } if (!uvEntry->done && uv_cancel((uv_req_t*)work) != napi_ok) { LOG_ERROR("uv_cancel failed."); - uvEntry->purge = true; - noNeedPurge = true; } } - CheckFuncAndExec(uvEntry->retFunc); - if (!noNeedPurge) { - DataShareUvQueue::Purge(work); - } + CheckFuncAndExec(retFunc); + DataShareUvQueue::Purge(work); } void DataShareUvQueue::Purge(uv_work_t* work) @@ -107,6 +101,10 @@ void DataShareUvQueue::Purge(uv_work_t* work) } auto *entry = static_cast(work->data); + auto count = entry->count.fetch_sub(1); + if (count != 1) { + return; + } delete entry; entry = nullptr; diff --git a/data_share/frameworks/native/provider/src/js_datashare_ext_ability.cpp b/data_share/frameworks/native/provider/src/js_datashare_ext_ability.cpp index c43489a8248466860d68835b81ddcb7f43e9c2ae..036c37b580cdf32065dbabc4a2da908593cff092 100644 --- a/data_share/frameworks/native/provider/src/js_datashare_ext_ability.cpp +++ b/data_share/frameworks/native/provider/src/js_datashare_ext_ability.cpp @@ -101,6 +101,10 @@ void JsDataShareExtAbility::Init(const std::shared_ptr &reco } napi_value contextObj = CreateJsDataShareExtAbilityContext(env, context); auto contextRef = jsRuntime_.LoadSystemModule("application.DataShareExtensionAbilityContext", &contextObj, 1); + if (contextRef == nullptr) { + LOG_ERROR("Failed to get contextRef"); + return; + } contextObj = contextRef->GetNapiValue(); context->Bind(jsRuntime_, contextRef.release()); napi_set_named_property(env, obj, "context", contextObj); @@ -936,7 +940,8 @@ std::string JsDataShareExtAbility::UnWrapProperty(napi_env env, napi_value info, UnwrapStringByPropertyName(env, info, key.c_str(), value); return value; } else { - LOG_ERROR("ValueType should be napi_number or napi_string, property is %{public}s", key.c_str()); + LOG_ERROR("ValueType should be napi_number or napi_string, property is %{public}s, ValueType: %{public}d", + key.c_str(), type); return ""; } } diff --git a/data_share/frameworks/native/proxy/include/ams_mgr_proxy.h b/data_share/frameworks/native/proxy/include/ams_mgr_proxy.h index 080f428b7ec3a80117b0ba75d9d091d8f99308d5..3a4fdac873aa6e21646564fb5fa585111636d502 100644 --- a/data_share/frameworks/native/proxy/include/ams_mgr_proxy.h +++ b/data_share/frameworks/native/proxy/include/ams_mgr_proxy.h @@ -24,16 +24,15 @@ namespace OHOS::DataShare { class AmsMgrProxy { public: ~AmsMgrProxy(); - static AmsMgrProxy *GetInstance(); + static AmsMgrProxy* GetInstance(); int Connect(const std::string &uri, const sptr &connect, const sptr &callerToken); int DisConnect(sptr connect); - private: using Proxy = AAFwk::ExtensionManagerProxy; AmsMgrProxy() = default; class ServiceDeathRecipient : public IRemoteObject::DeathRecipient { public: - explicit ServiceDeathRecipient(AmsMgrProxy *owner) : owner_(owner) + explicit ServiceDeathRecipient(AmsMgrProxy* owner) : owner_(owner) { } void OnRemoteDied(const wptr &object) override @@ -44,7 +43,7 @@ private: } private: - AmsMgrProxy *owner_; + AmsMgrProxy* owner_; }; void OnProxyDied(); bool ConnectSA(); diff --git a/data_share/frameworks/native/proxy/include/published_data_subscriber_manager.h b/data_share/frameworks/native/proxy/include/published_data_subscriber_manager.h index 8983837afe55df3a740b701c8bf0d87c52393ff7..c6e420cf6a5c83d748947bc4a764005bc06191da 100644 --- a/data_share/frameworks/native/proxy/include/published_data_subscriber_manager.h +++ b/data_share/frameworks/native/proxy/include/published_data_subscriber_manager.h @@ -18,6 +18,7 @@ #include #include "callbacks_manager.h" +#include "concurrent_map.h" #include "data_proxy_observer.h" #include "data_proxy_observer_stub.h" #include "datashare_template.h" @@ -98,7 +99,7 @@ private: bool Init(); void Destroy(); sptr serviceCallback_; - std::map lastChangeNodeMap_; + ConcurrentMap lastChangeNodeMap_; }; } // namespace DataShare } // namespace OHOS diff --git a/data_share/frameworks/native/proxy/src/published_data_subscriber_manager.cpp b/data_share/frameworks/native/proxy/src/published_data_subscriber_manager.cpp index fe41f1d3185ffad3052b8fa043095f67157eee38..8314395271e46d6f10e36e793fa13ffaf357d1a4 100644 --- a/data_share/frameworks/native/proxy/src/published_data_subscriber_manager.cpp +++ b/data_share/frameworks/native/proxy/src/published_data_subscriber_manager.cpp @@ -79,7 +79,7 @@ std::vector PublishedDataSubscriberManager::DelObservers(void * // delete all obs by subscriber std::map> keysMap; for (auto const &key : lastDelKeys) { - lastChangeNodeMap_.erase(key); + lastChangeNodeMap_.Erase(key); keysMap[key.subscriberId_].emplace_back(key.uri_); } for (auto const &[subscriberId, uris] : keysMap) { @@ -109,7 +109,7 @@ std::vector PublishedDataSubscriberManager::DelObservers(void * [&proxy, &subscriberId, this](const std::vector &lastDelKeys, std::vector &opResult) { std::vector lastDelUris; std::for_each(lastDelKeys.begin(), lastDelKeys.end(), [&lastDelUris, this](auto &result) { - lastChangeNodeMap_.erase(result); + lastChangeNodeMap_.Erase(result); lastDelUris.emplace_back(result); }); if (lastDelUris.empty()) { @@ -214,7 +214,10 @@ void PublishedDataSubscriberManager::Emit(PublishedDataChangeNode &changeNode) { for (auto &data : changeNode.datas_) { Key key(data.key_, data.subscriberId_); - lastChangeNodeMap_[key].datas_.clear(); + lastChangeNodeMap_.Compute(key, [](const Key &, PublishedDataChangeNode &value) { + value.datas_.clear(); + return true; + }); } std::map, PublishedDataChangeNode> results; for (auto &data : changeNode.datas_) { @@ -224,8 +227,11 @@ void PublishedDataSubscriberManager::Emit(PublishedDataChangeNode &changeNode) LOG_WARN("%{private}s nobody subscribe, but still notify", data.key_.c_str()); continue; } - lastChangeNodeMap_[key].datas_.emplace_back(data.key_, data.subscriberId_, data.GetData()); - lastChangeNodeMap_[key].ownerBundleName_ = changeNode.ownerBundleName_; + lastChangeNodeMap_.Compute(key, [&data, &changeNode](const Key &, PublishedDataChangeNode &value) { + value.datas_.emplace_back(data.key_, data.subscriberId_, data.GetData()); + value.ownerBundleName_ = changeNode.ownerBundleName_; + return true; + }); for (auto const &obs : callbacks) { results[obs].datas_.emplace_back(data.key_, data.subscriberId_, data.GetData()); } @@ -241,14 +247,13 @@ void PublishedDataSubscriberManager::Emit(const std::vector &keys, const st { PublishedDataChangeNode node; for (auto &key : keys) { - auto it = lastChangeNodeMap_.find(key); - if (it == lastChangeNodeMap_.end()) { - continue; - } - for (auto &data : it->second.datas_) { - node.datas_.emplace_back(data.key_, data.subscriberId_, data.GetData()); - } - node.ownerBundleName_ = it->second.ownerBundleName_; + lastChangeNodeMap_.ComputeIfPresent(key, [&node](const Key &, PublishedDataChangeNode &value) { + for (auto &data : value.datas_) { + node.datas_.emplace_back(data.key_, data.subscriberId_, data.GetData()); + } + node.ownerBundleName_ = value.ownerBundleName_; + return true; + }); } observer->OnChange(node); } @@ -257,21 +262,21 @@ void PublishedDataSubscriberManager::EmitOnEnable(std::map, PublishedDataChangeNode> results; for (auto &[key, obsVector] : obsMap) { - auto it = lastChangeNodeMap_.find(key); - if (it == lastChangeNodeMap_.end()) { - continue; - } uint32_t num = 0; - for (auto &data : it->second.datas_) { - PublishedObserverMapKey mapKey(data.key_, data.subscriberId_); - for (auto &obs : obsVector) { - if (obs.isNotifyOnEnabled_) { - num++; - results[obs.observer_].datas_.emplace_back(data.key_, data.subscriberId_, data.GetData()); - results[obs.observer_].ownerBundleName_ = it->second.ownerBundleName_; + lastChangeNodeMap_.ComputeIfPresent(key, [obsVector = obsVector, &results, &num](const Key &, + PublishedDataChangeNode &value) { + for (auto &data : value.datas_) { + PublishedObserverMapKey mapKey(data.key_, data.subscriberId_); + for (auto &obs : obsVector) { + if (obs.isNotifyOnEnabled_) { + num++; + results[obs.observer_].datas_.emplace_back(data.key_, data.subscriberId_, data.GetData()); + results[obs.observer_].ownerBundleName_ = value.ownerBundleName_; + } } } - } + return true; + }); if (num > 0) { LOG_INFO("%{public}u will refresh, total %{public}zu, uri %{public}s, subscribeId %{public}" PRId64, num, obsVector.size(), DataShareStringUtils::Anonymous(key.uri_).c_str(), key.subscriberId_); diff --git a/data_share/interfaces/inner_api/common/include/datashare_errno.h b/data_share/interfaces/inner_api/common/include/datashare_errno.h index 0c58659ef56431820f2923b700447579cc6567a3..0b175bcb93c16ba4e2998f910366e436eeb4b4d1 100644 --- a/data_share/interfaces/inner_api/common/include/datashare_errno.h +++ b/data_share/interfaces/inner_api/common/include/datashare_errno.h @@ -153,6 +153,11 @@ constexpr int E_WRITE_TO_PARCE_ERROR = (E_BASE + 60); * @brief The error code for resultSet busy error. */ constexpr int E_RESULTSET_BUSY = (E_BASE + 61); + +/** +* @brief The error code for invalid appIndex error. +*/ +constexpr int E_APPINDEX_INVALID = (E_BASE + 62); } // namespace DataShare } // namespace OHOS diff --git a/data_share/test/native/unittest/mediadatashare_test/src/join_test.cpp b/data_share/test/native/unittest/mediadatashare_test/src/join_test.cpp index bc855064327cff2b5bad7a0527170ba93d00bad8..a8563cd9fbedc70f45bbf8b10c9cc7b28f2ccdf9 100644 --- a/data_share/test/native/unittest/mediadatashare_test/src/join_test.cpp +++ b/data_share/test/native/unittest/mediadatashare_test/src/join_test.cpp @@ -29,7 +29,6 @@ namespace DataShare { using namespace testing::ext; using namespace OHOS::Security::AccessToken; constexpr int STORAGE_MANAGER_MANAGER_ID = 5003; - class JoinTest : public testing::Test { public: static void SetUpTestCase(void); diff --git a/datamgr_service/bundle.json b/datamgr_service/bundle.json index 059721cd519ad9cba482486ab6cabc182c8ac25d..b24e8c386e84b89f208f3999b4b1c43d23a5dccb 100644 --- a/datamgr_service/bundle.json +++ b/datamgr_service/bundle.json @@ -117,6 +117,7 @@ "cloud/cloud_db.h", "cloud/cloud_event.h", "cloud/cloud_info.h", + "cloud/cloud_report.h", "cloud/cloud_server.h", "cloud/schema_meta.h", "cloud/subscription.h", diff --git a/datamgr_service/services/distributeddataservice/adapter/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/BUILD.gn index 15f7c5f80409ee949dc0c5e2a6263b5cb0bb44aa..80c6b4594486d7131bee6316607960501cf5da8e 100644 --- a/datamgr_service/services/distributeddataservice/adapter/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/BUILD.gn @@ -51,7 +51,7 @@ ohos_shared_library("distributeddata_adapter") { ubsan = true } sources = [] - + cflags = [ "-D_LIBCPP_HAS_COND_CLOCKWAIT" ] configs = [ ":distributeddata_adapter_private_config" ] deps = [ "${data_service_path}/adapter/account:distributeddata_account_static", diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_adapter_standard.cpp b/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_adapter_standard.cpp index 0827053dd03c0dc42fd3c579571769841d4a3cc0..8edf7755dc7552dc80b2a152cd8b07e1b1f04a4c 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_adapter_standard.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_adapter_standard.cpp @@ -196,25 +196,24 @@ Status SoftBusAdapter::SendData(const PipeInfo &pipeInfo, const DeviceId &device bool isOHOSType = DmAdapter::GetInstance().IsOHOSType(deviceId.deviceId); uint32_t qosType = isOHOSType ? SoftBusClient::QOS_HML : SoftBusClient::QOS_BR; bool isReuse = false; - connects_.Compute(deviceId.deviceId, - [&pipeInfo, &deviceId, &conn, qosType, isOHOSType, &isReuse](const auto &key, - std::vector> &connects) -> bool { - for (auto &connect : connects) { - if (connect->GetQoSType() != qosType) { - continue; - } - if (!isOHOSType && connect->needRemove) { - isReuse = true; - return false; - } - conn = connect; - return true; + connects_.Compute(deviceId.deviceId, [&pipeInfo, &deviceId, &conn, qosType, isOHOSType, &isReuse](const auto &key, + std::vector> &connects) -> bool { + for (auto &connect : connects) { + if (connect->GetQoSType() != qosType) { + continue; + } + if (!isOHOSType && connect->needRemove) { + isReuse = true; + return false; } - auto connect = std::make_shared(pipeInfo, deviceId, qosType); - connects.emplace_back(connect); conn = connect; return true; - }); + } + auto connect = std::make_shared(pipeInfo, deviceId, qosType); + connects.emplace_back(connect); + conn = connect; + return true; + }); if (!isOHOSType && isReuse) { Reuse(pipeInfo, deviceId, qosType, conn); } @@ -226,8 +225,11 @@ Status SoftBusAdapter::SendData(const PipeInfo &pipeInfo, const DeviceId &device return Status::RATE_LIMIT; } if (status != Status::SUCCESS) { - auto task = [this, conn]() { - conn->OpenConnect(&clientListener_); + auto task = [this, connect = std::weak_ptr(conn)]() { + auto conn = connect.lock(); + if (conn != nullptr) { + conn->OpenConnect(&clientListener_); + } }; auto networkId = DmAdapter::GetInstance().GetDeviceInfo(deviceId.deviceId).networkId; ConnectManager::GetInstance()->ApplyConnect(networkId, task); diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_client.cpp b/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_client.cpp index 304b8cd204974fd2da2bac1368c6ea046a50660c..742628d5e92dc6d2d2b07aa3c02006f408a7a262 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_client.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_client.cpp @@ -36,6 +36,7 @@ SoftBusClient::SoftBusClient(const PipeInfo& pipeInfo, const DeviceId& deviceId, SoftBusClient::~SoftBusClient() { + ZLOGI("Shutdown socket:%{public}d", socket_); if (socket_ > 0) { Shutdown(socket_); } @@ -111,7 +112,8 @@ Status SoftBusClient::OpenConnect(const ISocketListener *listener) ZLOGE("OpenSessionByAsync client is nullptr."); return; } - ZLOGI("Bind Start, socket:%{public}d type:%{public}u", clientSocket, type); + ZLOGI("Bind Start, device:%{public}s socket:%{public}d type:%{public}u", + KvStoreUtils::ToBeAnonymous(client->device_.deviceId).c_str(), clientSocket, type); auto status = client->Open(clientSocket, QOS_INFOS[type % QOS_BUTT], listener); if (status == Status::SUCCESS) { Context::GetInstance().NotifySessionReady(client->device_.deviceId); diff --git a/datamgr_service/services/distributeddataservice/app/BUILD.gn b/datamgr_service/services/distributeddataservice/app/BUILD.gn index fd6efcbc4db415376a48c1f74cc9e0ca332547c7..61a689385968efa39441c94daf08ac873263efd6 100644 --- a/datamgr_service/services/distributeddataservice/app/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/app/BUILD.gn @@ -70,7 +70,10 @@ config("module_private_config") { "src/backup_rule/include", ] - cflags = [ "-Wno-multichar" ] + cflags = [ + "-Wno-multichar", + "-D_LIBCPP_HAS_COND_CLOCKWAIT", + ] cflags_cc = [ "-fvisibility=hidden" ] } diff --git a/datamgr_service/services/distributeddataservice/app/distributed_data.cfg b/datamgr_service/services/distributeddataservice/app/distributed_data.cfg index b4b210b2cdad4f26204c34495a716365a1de0410..e8a9f783a837f38f28fc32ae82ac1ba3332c5c25 100644 --- a/datamgr_service/services/distributeddataservice/app/distributed_data.cfg +++ b/datamgr_service/services/distributeddataservice/app/distributed_data.cfg @@ -37,6 +37,7 @@ "ohos.permission.CLOUDFILE_SYNC", "ohos.permission.PUBLISH_SYSTEM_COMMON_EVENT", "ohos.permission.GET_BUNDLE_INFO", + "ohos.permission.GET_BUNDLE_INFO_PRIVILEGED", "ohos.permission.GET_NETWORK_INFO", "ohos.permission.DISTRIBUTED_SOFTBUS_CENTER", "ohos.permission.MONITOR_DEVICE_NETWORK_STATE", diff --git a/datamgr_service/services/distributeddataservice/framework/BUILD.gn b/datamgr_service/services/distributeddataservice/framework/BUILD.gn index 0c0c13486206eb2bdc07c40e3f4b89c442ac9c2e..19dc6cfa65639eace05caa11c627c45011639ba8 100644 --- a/datamgr_service/services/distributeddataservice/framework/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/framework/BUILD.gn @@ -60,6 +60,7 @@ ohos_shared_library("distributeddatasvcfwk") { "cloud/cloud_extra_data.cpp", "cloud/cloud_info.cpp", "cloud/cloud_lock_event.cpp", + "cloud/cloud_report.cpp", "cloud/cloud_server.cpp", "cloud/cloud_share_event.cpp", "cloud/cloud_sync_finished_event.cpp", @@ -104,7 +105,10 @@ ohos_shared_library("distributeddatasvcfwk") { "utils/crypto.cpp", "utils/ref_count.cpp", ] - cflags = [ "-Wno-multichar" ] + cflags = [ + "-Wno-multichar", + "-D_LIBCPP_HAS_COND_CLOCKWAIT", + ] cflags_cc = [ "-fvisibility=hidden" ] diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/asset_loader.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/asset_loader.cpp index 711879f758e757d1d0951bd05ea71a9a6d7486da..af4b0c626d27ce2ebc11cdb00b18cfd1093fa8f2 100644 --- a/datamgr_service/services/distributeddataservice/framework/cloud/asset_loader.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/asset_loader.cpp @@ -15,18 +15,20 @@ #include "cloud/asset_loader.h" namespace OHOS::DistributedData { -int32_t AssetLoader::Download(const std::string &tableName, const std::string &gid, const Value &prefix, - VBucket &assets) +int32_t AssetLoader::Download( + const std::string &tableName, const std::string &gid, const Value &prefix, VBucket &assets) { return E_NOT_SUPPORT; } -int32_t AssetLoader::RemoveLocalAssets(const std::string &tableName, const std::string &gid, - const Value &prefix, VBucket &assets) + +int32_t AssetLoader::RemoveLocalAssets( + const std::string &tableName, const std::string &gid, const Value &prefix, VBucket &assets) { return E_NOT_SUPPORT; } + int32_t AssetLoader::Cancel() { return E_NOT_SUPPORT; } -} // namespace OHOS::DistributedData +} // namespace OHOS::DistributedData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_config_manager.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_config_manager.cpp index 458cf0467b2500c42dcda2cf3578824b290c79e1..71b5bbf00afeba6f4986527615cfdbbf54a974bc 100644 --- a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_config_manager.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_config_manager.cpp @@ -14,9 +14,10 @@ */ #define LOG_TAG "CloudConfigManager" -#include #include "cloud/cloud_config_manager.h" +#include + namespace OHOS::DistributedData { CloudConfigManager &CloudConfigManager::GetInstance() { diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_db.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_db.cpp index 0e3c2a4c607d79173d4e437cea11c2c61336741c..ab0a7b50eb253b50191bbe5aabd5547d169341fb 100644 --- a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_db.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_db.cpp @@ -45,12 +45,12 @@ std::shared_ptr CloudDB::Query(const std::string &table, const VBucket & return nullptr; } -std::shared_ptr CloudDB::Query(GenQuery& query, const VBucket& extend) +std::shared_ptr CloudDB::Query(GenQuery &query, const VBucket &extend) { return nullptr; } -int32_t CloudDB::PreSharing(const std::string& table, VBuckets& extend) +int32_t CloudDB::PreSharing(const std::string &table, VBuckets &extend) { return E_NOT_SUPPORT; } @@ -99,4 +99,9 @@ std::pair CloudDB::GetEmptyCursor(const std::string &table { return { E_NOT_SUPPORT, "" }; } + +void CloudDB::SetPrepareTraceId(const std::string &prepareTraceId) +{ + (void)prepareTraceId; +} } // namespace OHOS::DistributedData diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_event.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_event.cpp index 701bce29cfc04cf90646f386c1dfeb254632c579..8c09d9bbae2b33fd7407fb1495685b833f54c69e 100644 --- a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_event.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_event.cpp @@ -21,7 +21,7 @@ CloudEvent::CloudEvent(int32_t evtId, StoreInfo storeInfo) { } -const StoreInfo& CloudEvent::GetStoreInfo() const +const StoreInfo &CloudEvent::GetStoreInfo() const { return storeInfo_; } @@ -30,4 +30,4 @@ int32_t CloudEvent::GetEventId() const { return eventId_; } -} \ No newline at end of file +} // namespace OHOS::DistributedData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_extra_data.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_extra_data.cpp index 2527c69f1e98a96054b440468db6323cca0925db..6bf1d91377801c9bf01aa5ba6d70d4828481358b 100644 --- a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_extra_data.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_extra_data.cpp @@ -12,11 +12,25 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - #include "cloud/cloud_extra_data.h" + #include "cloud/cloud_config_manager.h" namespace OHOS::DistributedData { +bool Context::Marshal(Serializable::json &node) const +{ + SetValue(node[GET_NAME(traceId)], traceId); + SetValue(node[GET_NAME(prepareTraceId)], prepareTraceId); + return true; +} + +bool Context::Unmarshal(const Serializable::json &node) +{ + GetValue(node, GET_NAME(traceId), traceId); + GetValue(node, GET_NAME(prepareTraceId), prepareTraceId); + return true; +} + bool ExtensionInfo::Marshal(Serializable::json &node) const { SetValue(node[GET_NAME(accountId)], accountId); @@ -38,7 +52,15 @@ bool ExtensionInfo::Unmarshal(const Serializable::json &node) return false; } GetValue(node, GET_NAME(recordTypes), recordTypes); - return Unmarshall(recordTypes, tables); + if (!Unmarshall(recordTypes, tables)) { + return false; + } + std::string data; + GetValue(node, GET_NAME(context), data); + if (data.empty()) { + return true; + } + return context.Unmarshall(data); } bool ExtraData::Marshal(Serializable::json &node) const diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_lock_event.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_lock_event.cpp index c0bf9a1ad79953e6d62cd28bd48b2dece6a6cd8f..c9d2b4eaf2ad588787af216346e9187d25cc78eb 100644 --- a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_lock_event.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_lock_event.cpp @@ -17,9 +17,10 @@ namespace OHOS::DistributedData { CloudLockEvent::CloudLockEvent(int32_t evtId, StoreInfo storeInfo, Callback callback) - :CloudEvent(evtId, storeInfo), callback_(std::move(callback)) + : CloudEvent(evtId, storeInfo), callback_(std::move(callback)) { } + CloudLockEvent::Callback CloudLockEvent::GetCallback() const { return callback_; diff --git a/relational_store/interfaces/inner_api/rdb/mock/include/rdb_common.h b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_report.cpp similarity index 46% rename from relational_store/interfaces/inner_api/rdb/mock/include/rdb_common.h rename to datamgr_service/services/distributeddataservice/framework/cloud/cloud_report.cpp index cffbdf8e69d33120e693a44bd1cfcc854fb9e680..34e44bc20d9faa5b2c50cdad97e555f4252fe422 100644 --- a/relational_store/interfaces/inner_api/rdb/mock/include/rdb_common.h +++ b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_report.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Huawei Device Co., Ltd. + * 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 @@ -13,40 +13,37 @@ * limitations under the License. */ -#ifndef NATIVE_RDB_RDB_COMMON_H -#define NATIVE_RDB_RDB_COMMON_H -#include -namespace OHOS { -namespace NativeRdb { -enum class ConflictResolution { - ON_CONFLICT_NONE = 0, - ON_CONFLICT_ROLLBACK, - ON_CONFLICT_ABORT, - ON_CONFLICT_FAIL, - ON_CONFLICT_IGNORE, - ON_CONFLICT_REPLACE, -}; +#include "cloud/cloud_report.h" -enum RebuiltType : uint32_t { - NONE, - REBUILT, - REPAIRED, -}; +namespace OHOS::DistributedData { +CloudReport *CloudReport::instance_ = nullptr; -enum SlaveStatus : uint32_t { - UNDEFINED, - DB_NOT_EXITS, - BACKING_UP, - BACKUP_INTERRUPT, - BACKUP_FINISHED, -}; +CloudReport *CloudReport::GetInstance() +{ + return instance_; +} -enum ExchangeStrategy : uint32_t { - NOT_HANDLE, - BACKUP, - RESTORE, -}; +bool CloudReport::RegisterCloudReportInstance(CloudReport *instance) +{ + if (instance_ != nullptr) { + return false; + } + instance_ = instance; + return true; } + +std::string CloudReport::GetPrepareTraceId(int32_t userId) +{ + return ""; } -#endif // NATIVE_RDB_RDB_COMMON_H +std::string CloudReport::GetRequestTraceId(int32_t userId) +{ + return ""; +} + +bool CloudReport::Report(const ReportParam &reportParam) +{ + return true; +} +} // namespace OHOS::DistributedData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_server.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_server.cpp index 05829100c3579b66b43bee265bdbbf62685e6b59..1488cda20d00cb5eea3c0383643168d8a017fa71 100644 --- a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_server.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_server.cpp @@ -77,17 +77,11 @@ std::shared_ptr CloudServer::ConnectSharingCenter(int32_t userId, return nullptr; } -void CloudServer::Clean(int32_t userId) -{ -} +void CloudServer::Clean(int32_t userId) {} -void CloudServer::ReleaseUserInfo(int32_t userId) -{ -} +void CloudServer::ReleaseUserInfo(int32_t userId) {} -void CloudServer::Bind(std::shared_ptr executor) -{ -} +void CloudServer::Bind(std::shared_ptr executor) {} bool CloudServer::IsSupportCloud(int32_t userId) { diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_share_event.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_share_event.cpp index a4d3d93dd2ff5a516f0d8b2cad3e3dd5253f4465..4540c524d4bd5d8987d1d57d7ab5eac823c62605 100644 --- a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_share_event.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_share_event.cpp @@ -20,10 +20,12 @@ CloudShareEvent::CloudShareEvent(StoreInfo storeInfo, std::shared_ptr : CloudEvent(CLOUD_SHARE, std::move(storeInfo)), query_(std::move(query)), callback_(std::move(callback)) { } + std::shared_ptr CloudShareEvent::GetQuery() const { return query_; } + CloudShareEvent::Callback CloudShareEvent::GetCallback() const { return callback_; diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_sync_finished_event.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_sync_finished_event.cpp index 7640656ec3daba5d5177eff46c421f4beabd9a52..3909f752d58738d6f301ca1e2dfd81012eeb8432 100644 --- a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_sync_finished_event.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_sync_finished_event.cpp @@ -25,4 +25,4 @@ StoreMetaData CloudSyncFinishedEvent::GetStoreMeta() const { return metaData_; } -} \ No newline at end of file +} // namespace OHOS::DistributedData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/make_query_event.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/make_query_event.cpp index 0ed24b9c816f664fe7abd6ef75a764ea9e896490..a0e37117aaaa2a88752c1d50de20f1dee6c1827c 100644 --- a/datamgr_service/services/distributeddataservice/framework/cloud/make_query_event.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/make_query_event.cpp @@ -16,17 +16,18 @@ #include "cloud/make_query_event.h" namespace OHOS::DistributedData { -MakeQueryEvent::MakeQueryEvent(StoreInfo storeInfo, - std::shared_ptr predicates, const std::vector& columns, - Callback callback) +MakeQueryEvent::MakeQueryEvent(StoreInfo storeInfo, std::shared_ptr predicates, + const std::vector &columns, Callback callback) : CloudEvent(MAKE_QUERY, std::move(storeInfo)), predicates_(std::move(predicates)), columns_(columns), callback_(std::move(callback)) { } + std::shared_ptr MakeQueryEvent::GetPredicates() const { return predicates_; } + std::vector MakeQueryEvent::GetColumns() const { return columns_; diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/sync_event.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/sync_event.cpp index f2c78e6c34e8b67735832ffe3d76785644c7f585..2d1dc05f6486711d27fce1827aa96a9fc99eaa55 100644 --- a/datamgr_service/services/distributeddataservice/framework/cloud/sync_event.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/sync_event.cpp @@ -20,9 +20,11 @@ SyncEvent::EventInfo::EventInfo(int32_t mode, int32_t wait, bool retry, std::sha : retry_(retry), mode_(mode), wait_(wait), query_(std::move(query)), asyncDetail_(std::move(async)) { } + SyncEvent::EventInfo::EventInfo(const SyncParam &syncParam, bool retry, std::shared_ptr query, GenAsync async) : retry_(retry), mode_(syncParam.mode), wait_(syncParam.wait), query_(std::move(query)), - asyncDetail_(std::move(async)), isCompensation_(syncParam.isCompensation), triggerMode_(syncParam.triggerMode) + asyncDetail_(std::move(async)), isCompensation_(syncParam.isCompensation), triggerMode_(syncParam.triggerMode), + prepareTraceId_(syncParam.prepareTraceId), user_(syncParam.user) { } @@ -43,6 +45,8 @@ SyncEvent::EventInfo &SyncEvent::EventInfo::operator=(SyncEvent::EventInfo &&inf asyncDetail_ = std::move(info.asyncDetail_); isCompensation_ = info.isCompensation_; triggerMode_ = info.triggerMode_; + prepareTraceId_ = info.prepareTraceId_; + user_ = info.user_; return *this; } @@ -90,4 +94,14 @@ int32_t SyncEvent::GetTriggerMode() const { return info_.triggerMode_; } + +std::string SyncEvent::GetPrepareTraceId() const +{ + return info_.prepareTraceId_; +} + +int32_t SyncEvent::GetUser() const +{ + return info_.user_; +} } // namespace OHOS::DistributedData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/sync_strategy.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/sync_strategy.cpp index 15a08fc812f8f25f606d242582cbc39f5507197d..b12ee7e5924b4bc1be8faa3e049cb52c7a300aa6 100644 --- a/datamgr_service/services/distributeddataservice/framework/cloud/sync_strategy.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/sync_strategy.cpp @@ -15,7 +15,7 @@ #include "cloud/sync_strategy.h" namespace OHOS::DistributedData { -int32_t SyncStrategy::CheckSyncAction(const StoreInfo& storeInfo) +int32_t SyncStrategy::CheckSyncAction(const StoreInfo &storeInfo) { return 0; } @@ -25,4 +25,4 @@ std::shared_ptr SyncStrategy::SetNext(std::shared_ptr -#include #include #include +#include +#include + #include "visibility.h" namespace OHOS { namespace DistributedData { diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_db.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_db.h index 6927a277a20fdcf004960657e8d778e9c8c732ba..a6818dbb5473055590eb40b4dc22feffe3f6165d 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_db.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_db.h @@ -63,6 +63,8 @@ public: virtual int32_t Close(); virtual std::pair GetEmptyCursor(const std::string &tableName); + + virtual void SetPrepareTraceId(const std::string &prepareTraceId); }; } // namespace OHOS::DistributedData #endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_CLOUD_DB_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_event.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_event.h index 8cd2d2d47b3df14737edf6ad688450dc80cf14ce..abb96c1dd217ddcdc96bd57abdb89c01e10336a0 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_event.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_event.h @@ -17,6 +17,7 @@ #define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_CLOUD_EVENT_H #include + #include "eventcenter/event.h" #include "store/store_info.h" @@ -37,12 +38,13 @@ public: DATA_SYNC, LOCK_CLOUD_CONTAINER, UNLOCK_CLOUD_CONTAINER, + SET_SEARCH_TRIGGER, CLOUD_BUTT }; CloudEvent(int32_t evtId, StoreInfo storeInfo); ~CloudEvent() = default; - const StoreInfo& GetStoreInfo() const; + const StoreInfo &GetStoreInfo() const; int32_t GetEventId() const; private: diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_extra_data.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_extra_data.h index c4d89192a57f39d65d96d2f0f65349b20a86c803..1a45499c767b7327cec11b16ed73e44d880bb262 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_extra_data.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_extra_data.h @@ -20,6 +20,14 @@ #include "serializable/serializable.h" namespace OHOS::DistributedData { +class API_EXPORT Context final : public Serializable { +public: + std::string traceId; + std::string prepareTraceId; + bool Marshal(json &node) const override; + bool Unmarshal(const json &node) override; +}; + class API_EXPORT ExtensionInfo final : public Serializable { public: std::string accountId; @@ -29,6 +37,7 @@ public: std::vector scopes; std::string recordTypes; std::vector tables; + Context context; bool Marshal(json &node) const override; bool Unmarshal(const json &node) override; }; @@ -47,5 +56,5 @@ public: static constexpr const char *PRIVATE_TABLE = "private"; static constexpr const char *SHARED_TABLE = "shared"; }; -} +} // namespace OHOS::DistributedData #endif // DISTRIBUTEDDATAMGR_DATAMGR_SERVICE5_CLOUD_EXTRA_DATA_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_info.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_info.h index 35fa2cd5fff9d0dbcaaa2a866bf1175d3d4f79ed..b8ef793b4e4a383cdf2bf5864cb0eb5cc83bdf30 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_info.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_info.h @@ -62,5 +62,5 @@ private: static std::string GetKey(const std::string &prefix, const std::initializer_list &fields); }; -} +} // namespace OHOS::DistributedData #endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_CLOUD_INFO_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_lock_event.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_lock_event.h index cbced1b0324d1f5046b263c1ddeed1af5ad1e8f4..f1daf8a1ef0756bc6e917e831eae39b6af15c2aa 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_lock_event.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_lock_event.h @@ -16,8 +16,8 @@ #ifndef OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_LOCK_EVENT_H #define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_LOCK_EVENT_H #include "cloud/cloud_event.h" -#include "store/general_value.h" #include "store/general_store.h" +#include "store/general_value.h" #include "visibility.h" namespace OHOS::DistributedData { @@ -27,6 +27,7 @@ public: CloudLockEvent(int32_t evtId, StoreInfo storeInfo, Callback callback); ~CloudLockEvent() override = default; Callback GetCallback() const; + private: Callback callback_; }; diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/test/unittest/api/documentdb_test_utils.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_report.h similarity index 40% rename from kv_store/frameworks/libs/distributeddb/gaussdb_rd/test/unittest/api/documentdb_test_utils.h rename to datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_report.h index b1dc3f516b59db00e5cd2cf3643e631ecece1eb8..5b1a19e8e98bc63e5d77fc6cf97f62cbbe0ff82f 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/test/unittest/api/documentdb_test_utils.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_report.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2023 Huawei Device Co., Ltd. +* 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 @@ -13,14 +13,24 @@ * limitations under the License. */ -#ifndef DOCUMENTDB_TEST_UTILS_H -#define DOCUMENTDB_TEST_UTILS_H -#include +#ifndef OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_CLOUD_REPORT_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_CLOUD_REPORT_H -namespace DocumentDBUnitTest { -class DocumentDBTestUtils { +#include "store/general_value.h" +#include "visibility.h" + +namespace OHOS::DistributedData { +class API_EXPORT CloudReport { public: - static int RemoveTestDbFiles(const std::string &dir); + using ReportParam = DistributedData::ReportParam; + API_EXPORT static CloudReport *GetInstance(); + API_EXPORT static bool RegisterCloudReportInstance(CloudReport *instance); + virtual std::string GetPrepareTraceId(int32_t userId); + virtual std::string GetRequestTraceId(int32_t userId); + virtual bool Report(const ReportParam &reportParam); + +private: + static CloudReport *instance_; }; -} // namespace DocumentDBUnitTest -#endif // DOCUMENTDB_TEST_UTILS_H \ No newline at end of file +} // namespace OHOS::DistributedData +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_CLOUD_REPORT_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_share_event.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_share_event.h index 2ff7d83ff54ccf684138de6441080887be8c393d..d4456c7553f605c98de50dc3e70c62bb6611eccb 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_share_event.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_share_event.h @@ -16,8 +16,8 @@ #ifndef OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_SHARE_EVENT_H #define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_SHARE_EVENT_H #include "cloud/cloud_event.h" -#include "store/general_value.h" #include "store/cursor.h" +#include "store/general_value.h" #include "visibility.h" namespace OHOS::DistributedData { class API_EXPORT CloudShareEvent : public CloudEvent { diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_sync_finished_event.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_sync_finished_event.h index b8cee5f38d71fa08f590e86fca0dd1e44f5c9d69..9d044aefe971739c8eb32fbc35fba3c2f5b5864e 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_sync_finished_event.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_sync_finished_event.h @@ -17,6 +17,7 @@ #define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_CLOUD_SYNC_FINISHED_EVENT_H #include + #include "cloud_event.h" #include "metadata/store_meta_data.h" diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/make_query_event.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/make_query_event.h index 0725d5b6c8aa429ec5439a95534c6753e656fedb..c7b1496df3b8ee61500dc3f3c31c6937c175dca2 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/make_query_event.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/make_query_event.h @@ -16,8 +16,8 @@ #ifndef OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_RDB_SHARE_EVENT_H #define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_RDB_SHARE_EVENT_H #include "cloud/cloud_event.h" -#include "store/general_value.h" #include "store/cursor.h" +#include "store/general_value.h" #include "visibility.h" namespace OHOS { namespace DistributedRdb { @@ -28,7 +28,7 @@ class API_EXPORT MakeQueryEvent : public CloudEvent { public: using Callback = std::function)>; MakeQueryEvent(StoreInfo storeInfo, std::shared_ptr predicates, - const std::vector& columns, Callback callback); + const std::vector &columns, Callback callback); ~MakeQueryEvent() override = default; std::shared_ptr GetPredicates() const; std::vector GetColumns() const; diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/sharing_center.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/sharing_center.h index e7a914637e5091b666995f36eafc59e9f1e3446e..c89819f49766ed22a9459f7e08727137e3e8e8e2 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/sharing_center.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/sharing_center.h @@ -17,19 +17,15 @@ #define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_SHARING_CENTER_H #include -#include #include #include +#include + #include "visibility.h" namespace OHOS::DistributedData { class API_EXPORT SharingCenter { public: - enum Role { - ROLE_NIL = -1, - ROLE_INVITER, - ROLE_INVITEE, - ROLE_BUTT - }; + enum Role { ROLE_NIL = -1, ROLE_INVITER, ROLE_INVITEE, ROLE_BUTT }; enum Confirmation { CFM_NIL = -1, @@ -87,17 +83,17 @@ public: const Participants &participants); virtual Results Unshare(int32_t userId, const std::string &bundleName, const std::string &sharingRes, const Participants &participants); - virtual std::pair Exit(int32_t userId, const std::string &bundleName, - const std::string &sharingRes); + virtual std::pair Exit( + int32_t userId, const std::string &bundleName, const std::string &sharingRes); virtual Results ChangePrivilege(int32_t userId, const std::string &bundleName, const std::string &sharingRes, const Participants &participants); virtual QueryResults Query(int32_t userId, const std::string &bundleName, const std::string &sharingRes); - virtual QueryResults QueryByInvitation(int32_t userId, const std::string &bundleName, - const std::string &invitation); - virtual std::tuple ConfirmInvitation(int32_t userId, - const std::string &bundleName, const std::string &invitation, int32_t confirmation); - virtual std::pair ChangeConfirmation(int32_t userId, - const std::string &bundleName, const std::string &sharingRes, int32_t confirmation); + virtual QueryResults QueryByInvitation( + int32_t userId, const std::string &bundleName, const std::string &invitation); + virtual std::tuple ConfirmInvitation( + int32_t userId, const std::string &bundleName, const std::string &invitation, int32_t confirmation); + virtual std::pair ChangeConfirmation( + int32_t userId, const std::string &bundleName, const std::string &sharingRes, int32_t confirmation); }; } // namespace OHOS::DistributedData #endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_SHARING_CENTER_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/subscription.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/subscription.h index 1d81ea3a974d728a48678a3b05ba96d8026b7ec8..4054a91f30f71da07bb124da8a6611d5fb9f5308 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/subscription.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/subscription.h @@ -38,6 +38,7 @@ struct API_EXPORT Subscription final : public Serializable { static std::string GetKey(int32_t userId); static std::string GetRelationKey(int32_t userId, const std::string &bundleName); static std::string GetPrefix(const std::initializer_list &fields); + private: static constexpr const char *PREFIX = "CLOUD_SUBSCRIPTION"; static constexpr const char *RELATION_PREFIX = "CLOUD_RELATION"; diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/sync_event.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/sync_event.h index 22a06c077f1d891121c71d1278b2462dad24349e..9396a6e87a7abfe15f8a55519a9e7cabef74fa83 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/sync_event.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/sync_event.h @@ -29,6 +29,7 @@ public: EventInfo(const EventInfo &info) = default; API_EXPORT EventInfo &operator=(EventInfo &&info) noexcept; EventInfo &operator=(const EventInfo &info) = default; + private: friend SyncEvent; bool retry_ = false; @@ -38,6 +39,8 @@ public: GenAsync asyncDetail_; bool isCompensation_ = false; int32_t triggerMode_ = MODE_DEFAULT; + std::string prepareTraceId_; + int32_t user_ = 0; }; SyncEvent(StoreInfo storeInfo, EventInfo info); ~SyncEvent() override = default; @@ -48,6 +51,9 @@ public: GenAsync GetAsyncDetail() const; bool IsCompensation() const; int32_t GetTriggerMode() const; + std::string GetPrepareTraceId() const; + int32_t GetUser() const; + protected: SyncEvent(int32_t evtId, StoreInfo storeInfo, EventInfo info); diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/sync_strategy.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/sync_strategy.h index 843237183ee314258d702203cf62f04356c01265..4c79fb900aeb567dfff84d4486198e57b860f2a6 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/sync_strategy.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/sync_strategy.h @@ -21,11 +21,12 @@ namespace OHOS::DistributedData { class API_EXPORT SyncStrategy { public: virtual ~SyncStrategy() = default; - virtual int32_t CheckSyncAction(const StoreInfo& storeInfo); + virtual int32_t CheckSyncAction(const StoreInfo &storeInfo); virtual std::shared_ptr SetNext(std::shared_ptr next); static constexpr const char *GLOBAL_BUNDLE = "GLOBAL"; + private: std::shared_ptr next_; }; -} +} // namespace OHOS::DistributedData #endif //OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_SYNC_STRATEGY_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/commonevent/set_searchable_event.h b/datamgr_service/services/distributeddataservice/framework/include/commonevent/set_searchable_event.h index 833ddd82e88652ff291304504dd182917008d71d..14e0f0bc05eb581ed4a58b7784dac8805be8cf52 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/commonevent/set_searchable_event.h +++ b/datamgr_service/services/distributeddataservice/framework/include/commonevent/set_searchable_event.h @@ -23,10 +23,11 @@ class API_EXPORT SetSearchableEvent : public CloudEvent { public: struct EventInfo { bool isSearchable; + bool isRebuild; }; - SetSearchableEvent(StoreInfo storeInfo, EventInfo evtInfo) - : CloudEvent(SET_SEARCHABLE, std::move(storeInfo)), info_(std::move(evtInfo)) + SetSearchableEvent(StoreInfo storeInfo, EventInfo evtInfo, int32_t evtId = SET_SEARCHABLE) + : CloudEvent(evtId, std::move(storeInfo)), info_(std::move(evtInfo)) { } @@ -36,6 +37,11 @@ public: { return info_.isSearchable; } + + bool GetIsRebuild() const + { + return info_.isRebuild; + } private: EventInfo info_; }; diff --git a/datamgr_service/services/distributeddataservice/framework/include/metadata/store_debug_info.h b/datamgr_service/services/distributeddataservice/framework/include/metadata/store_debug_info.h index 8d9ff9484b1ec7b561485ad74a5a5012aa4d131c..5a25972fbfe7e3df6875fbeae926e1ce5ca1c0ad 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/metadata/store_debug_info.h +++ b/datamgr_service/services/distributeddataservice/framework/include/metadata/store_debug_info.h @@ -21,7 +21,7 @@ namespace OHOS::DistributedData { struct API_EXPORT StoreDebugInfo final : public Serializable { struct FileInfo final : public Serializable { uint64_t inode = 0; - uint64_t size = 0; + int64_t size = 0; uint32_t dev = 0; uint32_t mode = 0; uint32_t uid = 0; 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 efc2db665a067774de5591daa374b65148cbbb9f..da35babc8e6cbb61903b00b06a9723344aaa1233 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/store/general_store.h +++ b/datamgr_service/services/distributeddataservice/framework/include/store/general_store.h @@ -132,7 +132,7 @@ public: const std::vector &tables, int type, const std::vector &references) = 0; virtual int32_t SetTrackerTable(const std::string &tableName, const std::set &trackerColNames, - const std::string &extendColName) = 0; + const std::string &extendColName, bool isForceUpgrade) = 0; virtual int32_t Insert(const std::string &table, VBuckets &&values) = 0; 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 f0bc9b2504a6e6901f5d7c3149329467a6d2471a..a0b22bd0bca627d5d5e924b0c2488fbf84e5e457 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/store/general_value.h +++ b/datamgr_service/services/distributeddataservice/framework/include/store/general_value.h @@ -97,6 +97,22 @@ struct SyncParam { int32_t wait; bool isCompensation = false; int32_t triggerMode = MODE_DEFAULT; + std::string prepareTraceId; + int32_t user; +}; + +enum SyncStage : int8_t { + PREPARE = 0, + START, + END +}; + +struct ReportParam { + int32_t user = 0; + std::string bundleName; + std::string prepareTraceId; + SyncStage syncStage = SyncStage::PREPARE; + int32_t errCode = 0; }; using Assets = std::vector; diff --git a/datamgr_service/services/distributeddataservice/framework/include/utils/anonymous.h b/datamgr_service/services/distributeddataservice/framework/include/utils/anonymous.h index b7ff9ccef421568a784ed79e7f3685414287b853..bf34e8c8d2679586fc2cf3c23b146dd43eb5cf0f 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/utils/anonymous.h +++ b/datamgr_service/services/distributeddataservice/framework/include/utils/anonymous.h @@ -21,7 +21,7 @@ namespace OHOS { namespace DistributedData { class Anonymous { public: - API_EXPORT static std::string Change(const std::string &name, bool end = false); + API_EXPORT static std::string Change(const std::string &name); }; } // namespace DistributedData } // namespace OHOS diff --git a/datamgr_service/services/distributeddataservice/framework/test/meta_data_test.cpp b/datamgr_service/services/distributeddataservice/framework/test/meta_data_test.cpp index 1e99a72101f0c175eb990d9c3c23950a581952f4..2bf97f93974ab3c43cab059608f6fa0047b597f7 100644 --- a/datamgr_service/services/distributeddataservice/framework/test/meta_data_test.cpp +++ b/datamgr_service/services/distributeddataservice/framework/test/meta_data_test.cpp @@ -303,7 +303,7 @@ HWTEST_F(ServiceMetaDataTest, StoreMetaData003, TestSize.Level1) StoreMetaData storeMeta; auto storealias = storeMetaData.GetStoreAlias(); - EXPECT_EQ(storealias, "tes***ore"); + EXPECT_EQ(storealias, "test_store"); std::string strategykey = storeMetaData.GetStrategyKey(); EXPECT_EQ(strategykey, "StrategyMetaData######100###default######test_store"); std::initializer_list fields = {"100", "appid", "test_store"}; diff --git a/datamgr_service/services/distributeddataservice/framework/utils/anonymous.cpp b/datamgr_service/services/distributeddataservice/framework/utils/anonymous.cpp index ce2ee7ff3e61498dd7fce275a40b4ee38e0c7279..4a1d3d0dec1c59cf4a46d6cee7d984b1aef73475 100644 --- a/datamgr_service/services/distributeddataservice/framework/utils/anonymous.cpp +++ b/datamgr_service/services/distributeddataservice/framework/utils/anonymous.cpp @@ -14,28 +14,67 @@ */ #include "utils/anonymous.h" +#include namespace OHOS { namespace DistributedData { -constexpr int32_t HEAD_SIZE = 3; -constexpr int32_t END_SIZE = 3; -constexpr int32_t MIN_SIZE = HEAD_SIZE + END_SIZE + 3; -constexpr int32_t TAIL_SIZE = 6; -constexpr const char *REPLACE_CHAIN = "***"; -constexpr const char *DEFAULT_ANONYMOUS = "******"; -std::string Anonymous::Change(const std::string &name, bool end) + +constexpr int32_t CONTINUOUS_DIGITS_MINI_SIZE = 6; + +std::string AnonyDigits(const std::string &fileName) { - if (name.length() <= HEAD_SIZE) { - return DEFAULT_ANONYMOUS; + std::string::size_type digitsNum = fileName.size(); + if (digitsNum < CONTINUOUS_DIGITS_MINI_SIZE) { + return fileName; } - - if (name.length() < MIN_SIZE) { - return (name.substr(0, HEAD_SIZE) + REPLACE_CHAIN); + std::string::size_type endDigitsNum = 4; + std::string::size_type shortEndDigitsNum = 3; + std::string name = fileName; + std::string last = ""; + if (digitsNum == CONTINUOUS_DIGITS_MINI_SIZE) { + last = name.substr(name.size() - shortEndDigitsNum); + } else { + last = name.substr(name.size() - endDigitsNum); } - if (!end) { - return (name.substr(0, HEAD_SIZE) + REPLACE_CHAIN + name.substr(name.length() - END_SIZE, END_SIZE)); + return "***" + last; +} + +std::string Anonymous::Change(const std::string &name) +{ + std::vector alnum; + std::vector noAlnum; + std::string alnumStr; + std::string noAlnumStr; + for (const auto &letter : name) { + if (isxdigit(letter)) { + if (!noAlnumStr.empty()) { + noAlnum.push_back(noAlnumStr); + noAlnumStr.clear(); + alnum.push_back(""); + } + alnumStr += letter; + } else { + if (!alnumStr.empty()) { + alnum.push_back(alnumStr); + alnumStr.clear(); + noAlnum.push_back(""); + } + noAlnumStr += letter; + } + } + if (!alnumStr.empty()) { + alnum.push_back(alnumStr); + noAlnum.push_back(""); + } + if (!noAlnumStr.empty()) { + noAlnum.push_back(alnumStr); + alnum.push_back(""); + } + std::string res = ""; + for (size_t i = 0; i < alnum.size(); ++i) { + res += (AnonyDigits(alnum[i]) + noAlnum[i]); } - return (REPLACE_CHAIN + name.substr(name.length() - TAIL_SIZE, TAIL_SIZE)); + return res; } } // namespace DistributedData } // namespace OHOS diff --git a/datamgr_service/services/distributeddataservice/service/BUILD.gn b/datamgr_service/services/distributeddataservice/service/BUILD.gn index 6f0b47f2a595a6d7f2ea04053f5987409a478b4a..4c04cb7e45a9510673290bdf528594c46c6a705b 100644 --- a/datamgr_service/services/distributeddataservice/service/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/BUILD.gn @@ -134,6 +134,7 @@ ohos_shared_library("distributeddatasvc") { cflags = [ "-Wno-multichar", "-Wno-c99-designator", + "-D_LIBCPP_HAS_COND_CLOCKWAIT", ] cflags_cc = [ "-fvisibility=hidden" ] diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp index f48a1f651bed90c8240bb491bbab541190cb62d8..2be9b510441a895810a39bf44c72f6edce2733f8 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp @@ -46,6 +46,7 @@ #include "sync_strategies/network_sync_strategy.h" #include "utils/anonymous.h" #include "values_bucket.h" +#include "xcollie.h" namespace OHOS::CloudData { using namespace DistributedData; @@ -102,6 +103,7 @@ CloudServiceImpl::CloudServiceImpl() int32_t CloudServiceImpl::EnableCloud(const std::string &id, const std::map &switches) { + XCollie xcollie(__FUNCTION__, HiviewDFX::XCOLLIE_FLAG_LOG | HiviewDFX::XCOLLIE_FLAG_RECOVERY); auto tokenId = IPCSkeleton::GetCallingTokenID(); auto user = Account::GetInstance()->GetUserByToken(tokenId); auto [status, cloudInfo] = GetCloudInfo(user); @@ -126,6 +128,7 @@ int32_t CloudServiceImpl::EnableCloud(const std::string &id, const std::mapGetUserByToken(tokenId); std::lock_guard lock(rwMetaMutex_); @@ -149,21 +152,31 @@ int32_t CloudServiceImpl::DisableCloud(const std::string &id) int32_t CloudServiceImpl::ChangeAppSwitch(const std::string &id, const std::string &bundleName, int32_t appSwitch) { + XCollie xcollie(__FUNCTION__, HiviewDFX::XCOLLIE_FLAG_LOG | HiviewDFX::XCOLLIE_FLAG_RECOVERY); auto tokenId = IPCSkeleton::GetCallingTokenID(); auto user = Account::GetInstance()->GetUserByToken(tokenId); std::lock_guard lock(rwMetaMutex_); auto [status, cloudInfo] = GetCloudInfo(user); - if (status != SUCCESS) { + if (status != SUCCESS || !cloudInfo.enableCloud) { return status; } - if (!cloudInfo.enableCloud) { - return SUCCESS; - } - if (cloudInfo.id != id || !cloudInfo.Exist(bundleName)) { - ZLOGE("invalid args, [input] id:%{public}s, [exist] id:%{public}s, bundleName:%{public}s", + if (cloudInfo.id != id) { + ZLOGW("invalid args, [input] id:%{public}s, [exist] id:%{public}s, bundleName:%{public}s", Anonymous::Change(id).c_str(), Anonymous::Change(cloudInfo.id).c_str(), bundleName.c_str()); + Execute(GenTask(0, cloudInfo.user, { WORK_CLOUD_INFO_UPDATE, WORK_SCHEMA_UPDATE, WORK_SUB, + WORK_DO_CLOUD_SYNC })); return INVALID_ARGUMENT; } + if (!cloudInfo.Exist(bundleName)) { + std::tie(status, cloudInfo) = GetCloudInfoFromServer(user); + if (status != SUCCESS || !cloudInfo.enableCloud || cloudInfo.id != id || !cloudInfo.Exist(bundleName)) { + ZLOGE("invalid args, status:%{public}d, enableCloud:%{public}d, [input] id:%{public}s," + "[exist] id:%{public}s, bundleName:%{public}s", status, cloudInfo.enableCloud, + Anonymous::Change(id).c_str(), Anonymous::Change(cloudInfo.id).c_str(), bundleName.c_str()); + return INVALID_ARGUMENT; + } + ZLOGI("add app switch, bundleName:%{public}s", bundleName.c_str()); + } cloudInfo.apps[bundleName].cloudSwitch = (appSwitch == SWITCH_ON); if (!MetaDataManager::GetInstance().SaveMeta(cloudInfo.GetKey(), cloudInfo, true)) { return ERROR; @@ -380,6 +393,7 @@ int32_t CloudServiceImpl::NotifyDataChange(const std::string &id, const std::str int32_t CloudServiceImpl::NotifyDataChange(const std::string &eventId, const std::string &extraData, int32_t userId) { + XCollie xcollie(__FUNCTION__, HiviewDFX::XCOLLIE_FLAG_LOG | HiviewDFX::XCOLLIE_FLAG_RECOVERY); ExtraData exData; if (eventId != DATA_CHANGE_EVENT_ID || extraData.empty() || !exData.Unmarshall(extraData)) { ZLOGE("invalid args, eventId:%{public}s, user:%{public}d, extraData is %{public}s", eventId.c_str(), @@ -396,25 +410,30 @@ int32_t CloudServiceImpl::NotifyDataChange(const std::string &eventId, const std if (user == DEFAULT_USER) { continue; } + auto &bundleName = exData.info.bundleName; + auto &prepareTraceId = exData.info.context.prepareTraceId; auto [status, cloudInfo] = GetCloudInfoFromMeta(user); - if (CheckNotifyConditions(exData.info.accountId, exData.info.bundleName, cloudInfo) != E_OK) { - ZLOGD("invalid user:%{public}d", user); + if (CheckNotifyConditions(exData.info.accountId, bundleName, cloudInfo) != E_OK) { + ZLOGD("invalid user:%{public}d, traceId:%{public}s", user, prepareTraceId.c_str()); + syncManager_.Report({ user, bundleName, prepareTraceId, SyncStage::END, INVALID_ARGUMENT }); return INVALID_ARGUMENT; } - auto schemaKey = CloudInfo::GetSchemaKey(user, exData.info.bundleName); + auto schemaKey = CloudInfo::GetSchemaKey(user, bundleName); SchemaMeta schemaMeta; if (!MetaDataManager::GetInstance().LoadMeta(schemaKey, schemaMeta, true)) { - ZLOGE("no exist meta, user:%{public}d", user); + ZLOGE("no exist meta, user:%{public}d, traceId:%{public}s", user, prepareTraceId.c_str()); + syncManager_.Report({ user, bundleName, prepareTraceId, SyncStage::END, INVALID_ARGUMENT }); return INVALID_ARGUMENT; } auto dbInfos = GetDbInfoFromExtraData(exData, schemaMeta); if (dbInfos.empty()) { - ZLOGE("GetDbInfoFromExtraData failed, empty database info."); + ZLOGE("GetDbInfoFromExtraData failed, empty database info. traceId:%{public}s.", prepareTraceId.c_str()); + syncManager_.Report({ user, bundleName, prepareTraceId, SyncStage::END, INVALID_ARGUMENT }); return INVALID_ARGUMENT; } for (const auto &dbInfo : dbInfos) { - syncManager_.DoCloudSync( - SyncManager::SyncInfo(cloudInfo.user, exData.info.bundleName, dbInfo.first, dbInfo.second, MODE_PUSH)); + syncManager_.DoCloudSync(SyncManager::SyncInfo( + { cloudInfo.user, bundleName, dbInfo.first, dbInfo.second, MODE_PUSH, prepareTraceId })); } } return SUCCESS; @@ -607,6 +626,7 @@ std::pair CloudServiceImpl::QueryLastSyncInfo(const s int32_t CloudServiceImpl::OnInitialize() { + XCollie xcollie(__FUNCTION__, HiviewDFX::XCOLLIE_FLAG_LOG | HiviewDFX::XCOLLIE_FLAG_RECOVERY); DistributedDB::RuntimeConfig::SetCloudTranslate(std::make_shared()); Execute(GenTask(0, 0, { WORK_CLOUD_INFO_UPDATE, WORK_SCHEMA_UPDATE, WORK_DO_CLOUD_SYNC, WORK_SUB })); std::vector users; @@ -642,6 +662,7 @@ int32_t CloudServiceImpl::OnBind(const BindInfo &info) int32_t CloudServiceImpl::OnUserChange(uint32_t code, const std::string &user, const std::string &account) { + XCollie xcollie(__FUNCTION__, HiviewDFX::XCOLLIE_FLAG_LOG | HiviewDFX::XCOLLIE_FLAG_RECOVERY); int32_t userId = atoi(user.c_str()); ZLOGI("code:%{public}d, user:%{public}s, account:%{public}s", code, user.c_str(), Anonymous::Change(account).c_str()); @@ -663,6 +684,7 @@ int32_t CloudServiceImpl::OnUserChange(uint32_t code, const std::string &user, c int32_t CloudServiceImpl::OnReady(const std::string &device) { + XCollie xcollie(__FUNCTION__, HiviewDFX::XCOLLIE_FLAG_LOG | HiviewDFX::XCOLLIE_FLAG_RECOVERY); if (device != DeviceManagerAdapter::CLOUD_DEVICE_UUID) { return SUCCESS; } @@ -779,7 +801,7 @@ bool CloudServiceImpl::UpdateSchema(int32_t user) std::tie(status, schemaMeta) = GetAppSchemaFromServer(user, bundle); if (status == NOT_SUPPORT) { ZLOGW("app not support, del cloudInfo! user:%{public}d, bundleName:%{public}s", user, bundle.c_str()); - MetaDataManager::GetInstance().DelMeta(cloudInfo.GetKey()); + MetaDataManager::GetInstance().DelMeta(cloudInfo.GetKey(), true); return false; } if (status != SUCCESS) { @@ -1206,6 +1228,7 @@ CloudServiceImpl::HapInfo CloudServiceImpl::GetHapInfo(uint32_t tokenId) int32_t CloudServiceImpl::Share(const std::string &sharingRes, const Participants &participants, Results &results) { + XCollie xcollie(__FUNCTION__, HiviewDFX::XCOLLIE_FLAG_LOG | HiviewDFX::XCOLLIE_FLAG_RECOVERY); auto hapInfo = GetHapInfo(IPCSkeleton::GetCallingTokenID()); if (hapInfo.bundleName.empty()) { ZLOGE("bundleName is empty, sharingRes:%{public}s", Anonymous::Change(sharingRes).c_str()); @@ -1226,6 +1249,7 @@ int32_t CloudServiceImpl::Share(const std::string &sharingRes, const Participant int32_t CloudServiceImpl::Unshare(const std::string &sharingRes, const Participants &participants, Results &results) { + XCollie xcollie(__FUNCTION__, HiviewDFX::XCOLLIE_FLAG_LOG | HiviewDFX::XCOLLIE_FLAG_RECOVERY); auto hapInfo = GetHapInfo(IPCSkeleton::GetCallingTokenID()); if (hapInfo.bundleName.empty()) { ZLOGE("bundleName is empty, sharingRes:%{public}s", Anonymous::Change(sharingRes).c_str()); @@ -1246,6 +1270,7 @@ int32_t CloudServiceImpl::Unshare(const std::string &sharingRes, const Participa int32_t CloudServiceImpl::Exit(const std::string &sharingRes, std::pair &result) { + XCollie xcollie(__FUNCTION__, HiviewDFX::XCOLLIE_FLAG_LOG | HiviewDFX::XCOLLIE_FLAG_RECOVERY); auto hapInfo = GetHapInfo(IPCSkeleton::GetCallingTokenID()); if (hapInfo.bundleName.empty()) { ZLOGE("bundleName is empty, sharingRes:%{public}s", Anonymous::Change(sharingRes).c_str()); @@ -1268,6 +1293,7 @@ int32_t CloudServiceImpl::Exit(const std::string &sharingRes, std::pair &result) { + XCollie xcollie(__FUNCTION__, HiviewDFX::XCOLLIE_FLAG_LOG | HiviewDFX::XCOLLIE_FLAG_RECOVERY); auto hapInfo = GetHapInfo(IPCSkeleton::GetCallingTokenID()); if (hapInfo.bundleName.empty()) { ZLOGE("bundleName is empty, invitation:%{public}s, confirmation:%{public}d", @@ -1349,6 +1378,7 @@ int32_t CloudServiceImpl::ConfirmInvitation(const std::string &invitation, int32 int32_t CloudServiceImpl::ChangeConfirmation(const std::string &sharingRes, int32_t confirmation, std::pair &result) { + XCollie xcollie(__FUNCTION__, HiviewDFX::XCOLLIE_FLAG_LOG | HiviewDFX::XCOLLIE_FLAG_RECOVERY); auto hapInfo = GetHapInfo(IPCSkeleton::GetCallingTokenID()); if (hapInfo.bundleName.empty()) { ZLOGE("bundleName is empty, sharingRes:%{public}s", Anonymous::Change(sharingRes).c_str()); @@ -1380,7 +1410,7 @@ std::shared_ptr CloudServiceImpl::GetSharingHandle(const HapInfo ExecutorPool::Task CloudServiceImpl::GenSubTask(Task task, int32_t user) { - return [this, user, work = std::move(task)] () { + return [this, user, work = std::move(task)]() { { std::lock_guard lock(mutex_); subTask_ = ExecutorPool::INVALID_TASK_ID; diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h index 212b7780d55104c42e564bde3d37af56f54ed0f5..59fcacc9741734b27fced25890a2908ce02662ea 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h @@ -41,21 +41,20 @@ public: int32_t ChangeAppSwitch(const std::string &id, const std::string &bundleName, int32_t appSwitch) override; int32_t Clean(const std::string &id, const std::map &actions) override; int32_t NotifyDataChange(const std::string &id, const std::string &bundleName) override; - int32_t NotifyDataChange(const std::string& eventId, const std::string& extraData, int32_t userId) override; - std::pair> QueryStatistics(const std::string &id, - const std::string &bundleName, const std::string &storeId) override; - std::pair QueryLastSyncInfo(const std::string &id, const std::string &bundleName, - const std::string &storeId) override; - int32_t SetGlobalCloudStrategy(Strategy strategy, const std::vector& values) override; - - std::pair> AllocResourceAndShare(const std::string& storeId, - const DistributedRdb::PredicatesMemo& predicates, const std::vector& columns, - const Participants& participants) override; + int32_t NotifyDataChange(const std::string &eventId, const std::string &extraData, int32_t userId) override; + std::pair> QueryStatistics( + const std::string &id, const std::string &bundleName, const std::string &storeId) override; + std::pair QueryLastSyncInfo( + const std::string &id, const std::string &bundleName, const std::string &storeId) override; + int32_t SetGlobalCloudStrategy(Strategy strategy, const std::vector &values) override; + + std::pair> AllocResourceAndShare(const std::string &storeId, + const DistributedRdb::PredicatesMemo &predicates, const std::vector &columns, + const Participants &participants) override; int32_t Share(const std::string &sharingRes, const Participants &participants, Results &results) override; int32_t Unshare(const std::string &sharingRes, const Participants &participants, Results &results) override; int32_t Exit(const std::string &sharingRes, std::pair &result) override; - int32_t ChangePrivilege( - const std::string &sharingRes, const Participants &participants, Results &results) override; + int32_t ChangePrivilege(const std::string &sharingRes, const Participants &participants, Results &results) override; int32_t Query(const std::string &sharingRes, QueryResults &results) override; int32_t QueryByInvitation(const std::string &invitation, QueryResults &results) override; int32_t ConfirmInvitation(const std::string &invitation, int32_t confirmation, @@ -63,7 +62,7 @@ public: int32_t ChangeConfirmation( const std::string &sharingRes, int32_t confirmation, std::pair &result) override; - int32_t SetCloudStrategy(Strategy strategy, const std::vector& values) override; + int32_t SetCloudStrategy(Strategy strategy, const std::vector &values) override; int32_t OnInitialize() override; int32_t OnBind(const BindInfo &info) override; @@ -75,7 +74,7 @@ private: using StaticActs = DistributedData::StaticActs; class CloudStatic : public StaticActs { public: - ~CloudStatic() override {}; + ~CloudStatic() override{}; int32_t OnAppUninstall(const std::string &bundleName, int32_t user, int32_t index) override; int32_t OnAppInstall(const std::string &bundleName, int32_t user, int32_t index) override; }; @@ -83,6 +82,7 @@ private: public: Factory() noexcept; ~Factory(); + private: std::shared_ptr product_; std::shared_ptr staticActs_; @@ -114,9 +114,9 @@ private: static constexpr int32_t RETRY_TIMES = 3; static constexpr int32_t RETRY_INTERVAL = 60; static constexpr int32_t EXPIRE_INTERVAL = 2 * 24; // 2 day - static constexpr int32_t WAIT_TIME = 30; // 30 seconds + static constexpr int32_t WAIT_TIME = 30; // 30 seconds static constexpr int32_t DEFAULT_USER = 0; - static constexpr int32_t TIME_BEFORE_SUB = 12 * 60 * 60 * 1000; // 12hours, ms + static constexpr int32_t TIME_BEFORE_SUB = 12 * 60 * 60 * 1000; // 12hours, ms static constexpr int32_t SUBSCRIPTION_INTERVAL = 60 * 60 * 1000; // 1hours bool UpdateCloudInfo(int32_t user); @@ -134,8 +134,8 @@ private: std::pair GetSchemaMeta(int32_t userId, const std::string &bundleName, int32_t instanceId); std::pair GetAppSchemaFromServer(int32_t user, const std::string &bundleName); void UpgradeSchemaMeta(int32_t user, const SchemaMeta &schemaMeta); - std::map ExecuteStatistics(const std::string &storeId, const CloudInfo &cloudInfo, - const SchemaMeta &schemaMeta); + std::map ExecuteStatistics( + const std::string &storeId, const CloudInfo &cloudInfo, const SchemaMeta &schemaMeta); StatisticInfos QueryStatistics(const StoreMetaData &storeMetaData, const DistributedData::Database &database); std::pair QueryTableStatistic(const std::string &tableName, AutoCache::Store store); std::string BuildStatisticSql(const std::string &tableName); @@ -150,13 +150,13 @@ private: void CleanSubscription(Subscription &sub); int32_t DoClean(const CloudInfo &cloudInfo, const std::map &actions); void DoClean(int32_t user, const SchemaMeta &schemaMeta, int32_t action); - std::pair> PreShare(const StoreInfo& storeInfo, - DistributedData::GenQuery& query); + std::pair> PreShare( + const StoreInfo &storeInfo, DistributedData::GenQuery &query); std::vector ConvertCursor(std::shared_ptr cursor) const; int32_t CheckNotifyConditions(const std::string &id, const std::string &bundleName, CloudInfo &cloudInfo); std::map> GetDbInfoFromExtraData( const DistributedData::ExtraData &extraData, const SchemaMeta &schemaMeta); - std::shared_ptr GetSharingHandle(const HapInfo& hapInfo); + std::shared_ptr GetSharingHandle(const HapInfo &hapInfo); bool GetStoreMetaData(StoreMetaData &meta); bool DoKvCloudSync(int32_t userId, const std::string &bundleName = "", int32_t triggerMode = 0); @@ -169,8 +169,9 @@ private: std::mutex mutex_; std::mutex rwMetaMutex_; TaskId subTask_ = ExecutorPool::INVALID_TASK_ID; - uint64_t expireTime_ = static_cast(std::chrono::duration_cast( - std::chrono::system_clock::now().time_since_epoch()).count()); + uint64_t expireTime_ = static_cast( + std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()) + .count()); static constexpr Handle WORK_CLOUD_INFO_UPDATE = &CloudServiceImpl::UpdateCloudInfo; static constexpr Handle WORK_SCHEMA_UPDATE = &CloudServiceImpl::UpdateSchema; @@ -179,6 +180,6 @@ private: static constexpr Handle WORK_DO_CLOUD_SYNC = &CloudServiceImpl::DoCloudSync; static constexpr Handle WORK_STOP_CLOUD_SYNC = &CloudServiceImpl::StopCloudSync; }; -} // namespace OHOS::DistributedData +} // namespace OHOS::CloudData #endif // OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_SERVICE_IMPL_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.h b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.h index 4d30fcca5d08202fbe1240f5dceb6baafd77a756..5f51fe846ee8bb27c0e04e689e84d22d01f63b6a 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.h +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.h @@ -15,9 +15,11 @@ #ifndef OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_SERVICE_STUB_H #define OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_SERVICE_STUB_H + #include "cloud_service.h" #include "feature/feature_system.h" #include "iremote_broker.h" + namespace OHOS::CloudData { class CloudServiceStub : public CloudService, public DistributedData::FeatureSystem::Feature { public: diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_types_util.h b/datamgr_service/services/distributeddataservice/service/cloud/cloud_types_util.h index afb74b6cba7fab57226c791f35e205c389a03d87..7a53f6938a15cb195dd299992813811ab26295c3 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_types_util.h +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_types_util.h @@ -15,6 +15,7 @@ #ifndef OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_TYPES_UTIL_H #define OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_TYPES_UTIL_H + #include "cloud_types.h" #include "itypes_util.h" #include "values_bucket.h" diff --git a/datamgr_service/services/distributeddataservice/service/cloud/sync_manager.cpp b/datamgr_service/services/distributeddataservice/service/cloud/sync_manager.cpp index 40f41784feb55fe88e45be94bf84cf0c22910270..19fa812216e59d45a84ee5e4202f91184bf2e7b9 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/sync_manager.cpp +++ b/datamgr_service/services/distributeddataservice/service/cloud/sync_manager.cpp @@ -20,11 +20,12 @@ #include "account/account_delegate.h" #include "bootstrap.h" #include "checker/checker_manager.h" +#include "cloud/cloud_lock_event.h" +#include "cloud/cloud_report.h" #include "cloud/cloud_server.h" #include "cloud/schema_meta.h" #include "cloud/sync_event.h" #include "cloud_value_util.h" -#include "cloud/cloud_lock_event.h" #include "device_manager_adapter.h" #include "dfx/radar_reporter.h" #include "eventcenter/event_center.h" @@ -69,6 +70,16 @@ SyncManager::SyncInfo::SyncInfo(int32_t user, const std::string &bundleName, con syncId_ = SyncManager::GenerateId(user); } +SyncManager::SyncInfo::SyncInfo(const Param ¶m) + : user_(param.user), bundleName_(param.bundleName), triggerMode_(param.triggerMode) +{ + if (!param.store.empty()) { + tables_[param.store] = param.tables; + } + syncId_ = SyncManager::GenerateId(param.user); + prepareTraceId_ = param.prepareTraceId; +} + void SyncManager::SyncInfo::SetMode(int32_t mode) { mode_ = mode; @@ -152,6 +163,14 @@ std::function SyncManager::GetLockChangeHandler() storeInfo.bundleName.c_str(), Anonymous::Change(storeInfo.storeName).c_str(), storeInfo.user); return; } + CloudInfo cloud; + cloud.user = storeInfo.user; + SyncInfo info(storeInfo.user, storeInfo.bundleName); + auto code = IsValid(info, cloud); + if (code != E_OK) { + return; + } + StoreMetaData meta(storeInfo); meta.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true)) { @@ -265,32 +284,41 @@ GeneralError SyncManager::IsValid(SyncInfo &info, CloudInfo &cloud) return E_OK; } -std::function SyncManager::GetPostEventTask(const std::vector &schemas, CloudInfo &cloud, - SyncInfo &info, bool retry) +std::function SyncManager::GetPostEventTask(const std::vector &schemas, CloudInfo &cloud, + SyncInfo &info, bool retry, const TraceIds &traceIds) { - return [this, &cloud, &info, &schemas, retry]() { + return [this, &cloud, &info, &schemas, retry, &traceIds]() { bool isPostEvent = false; for (auto &schema : schemas) { + auto it = traceIds.find(schema.bundleName); if (!cloud.IsOn(schema.bundleName)) { + UpdateFinishSyncInfo({ cloud.id, schema.bundleName, "" }, info.syncId_, E_ERROR); + Report({ cloud.user, schema.bundleName, it == traceIds.end() ? "" : it->second, SyncStage::END, + E_ERROR }); continue; } for (const auto &database : schema.databases) { if (!info.Contains(database.name)) { + UpdateFinishSyncInfo({ cloud.id, schema.bundleName, "" }, info.syncId_, E_ERROR); + Report({ cloud.user, schema.bundleName, it == traceIds.end() ? "" : it->second, SyncStage::END, + E_ERROR }); continue; } StoreInfo storeInfo = { 0, schema.bundleName, database.name, cloud.apps[schema.bundleName].instanceId, - info.user_, "", info.syncId_ }; + info.user_, "", info.syncId_ }; auto status = syncStrategy_->CheckSyncAction(storeInfo); if (status != SUCCESS) { ZLOGW("Verification strategy failed, status:%{public}d. %{public}d:%{public}s:%{public}s", status, storeInfo.user, storeInfo.bundleName.c_str(), Anonymous::Change(storeInfo.storeName).c_str()); - QueryKey queryKey{ cloud.id, schema.bundleName, "" }; - UpdateFinishSyncInfo(queryKey, info.syncId_, E_BLOCKED_BY_NETWORK_STRATEGY); + UpdateFinishSyncInfo({ cloud.id, schema.bundleName, "" }, info.syncId_, status); + Report({ cloud.user, schema.bundleName, it == traceIds.end() ? "" : it->second, SyncStage::END, + status }); info.SetError(status); continue; } auto query = info.GenerateQuery(database.name, database.GetTableNames()); - SyncParam syncParam = { info.mode_, info.wait_, info.isCompensation_, info.triggerMode_ }; + SyncParam syncParam = { info.mode_, info.wait_, info.isCompensation_, info.triggerMode_, + it == traceIds.end() ? "" : it->second, cloud.user }; auto evt = std::make_unique(std::move(storeInfo), SyncEvent::EventInfo{ syncParam, retry, std::move(query), info.async_ }); EventCenter::GetInstance().PostEvent(std::move(evt)); @@ -301,7 +329,6 @@ std::function SyncManager::GetPostEventTask(const std::vectorsecond); BatchUpdateFinishState(cloudSyncInfos, E_CLOUD_DISABLED); + BatchReport(info.user_, traceIds, SyncStage::END, E_CLOUD_DISABLED); return; } } @@ -342,11 +374,8 @@ ExecutorPool::Task SyncManager::GetSyncTask(int32_t times, bool retry, RefCount if (createdByDefaultUser) { info.user_ = 0; } - auto task = GetPostEventTask(schemas, cloud, info, retry); - if (task != nullptr && task()) { - return; - } - BatchUpdateFinishState(cloudSyncInfos, E_ERROR); + auto task = GetPostEventTask(schemas, cloud, info, retry, traceIds); + task(); }; } @@ -356,35 +385,31 @@ std::function SyncManager::GetSyncHandler(Retryer retryer) auto &evt = static_cast(event); auto &storeInfo = evt.GetStoreInfo(); GenAsync async = evt.GetAsyncDetail(); + auto prepareTraceId = evt.GetPrepareTraceId(); + auto user = evt.GetUser(); GenDetails details; auto &detail = details[SyncInfo::DEFAULT_ID]; detail.progress = GenProgress::SYNC_FINISH; - StoreMetaData meta(storeInfo); - meta.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; - if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true)) { - meta.user = "0"; // check if it is a public store. - StoreMetaDataLocal localMetaData; - if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKeyLocal(), localMetaData, true) || - !localMetaData.isPublic || !MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true)) { - ZLOGE("failed, no store meta. bundleName:%{public}s, storeId:%{public}s", meta.bundleName.c_str(), - meta.GetStoreAlias().c_str()); - return DoExceptionalCallback(async, details, storeInfo); - } + auto [result, meta] = GetMetaData(storeInfo); + if (!result) { + return DoExceptionalCallback(async, details, storeInfo, prepareTraceId); } auto store = GetStore(meta, storeInfo.user); if (store == nullptr) { - ZLOGE("store null, storeId:%{public}s", meta.GetStoreAlias().c_str()); - return DoExceptionalCallback(async, details, storeInfo); + ZLOGE("store null, storeId:%{public}s, prepareTraceId:%{public}s", meta.GetStoreAlias().c_str(), + prepareTraceId.c_str()); + return DoExceptionalCallback(async, details, storeInfo, prepareTraceId); } - ZLOGD("database:<%{public}d:%{public}s:%{public}s> sync start", storeInfo.user, storeInfo.bundleName.c_str(), - meta.GetStoreAlias().c_str()); + ZLOGI("database:<%{public}d:%{public}s:%{public}s:%{public}s> sync start", storeInfo.user, + storeInfo.bundleName.c_str(), meta.GetStoreAlias().c_str(), prepareTraceId.c_str()); RadarReporter::Report( { storeInfo.bundleName.c_str(), CLOUD_SYNC, TRIGGER_SYNC, storeInfo.syncId, evt.GetTriggerMode() }, - "GetSyncHandler", BEGIN); - SyncParam syncParam = { evt.GetMode(), evt.GetWait(), evt.IsCompensation() }; + "GetSyncHandler", BizState::BEGIN); + Report({ user, storeInfo.bundleName, prepareTraceId, SyncStage::START, E_OK }); + SyncParam syncParam = { evt.GetMode(), evt.GetWait(), evt.IsCompensation(), MODE_DEFAULT, prepareTraceId }; auto status = store->Sync({ SyncInfo::DEFAULT_ID }, *(evt.GetQuery()), - evt.AutoRetry() ? RetryCallback(storeInfo, retryer, evt.GetTriggerMode()) - : GetCallback(evt.GetAsyncDetail(), storeInfo, evt.GetTriggerMode()), + evt.AutoRetry() ? RetryCallback(storeInfo, retryer, evt.GetTriggerMode(), prepareTraceId, user) + : GetCallback(evt.GetAsyncDetail(), storeInfo, evt.GetTriggerMode(), prepareTraceId, user), syncParam); if (status != E_OK) { if (async) { @@ -397,7 +422,8 @@ std::function SyncManager::GetSyncHandler(Retryer retryer) } int32_t errCode = status + GenStore::DB_ERR_OFFSET; RadarReporter::Report({ storeInfo.bundleName.c_str(), CLOUD_SYNC, FINISH_SYNC, storeInfo.syncId, - evt.GetTriggerMode(), false, errCode }, "GetSyncHandler", END); + evt.GetTriggerMode(), false, errCode }, "GetSyncHandler", BizState::END); + Report({ user, storeInfo.bundleName, prepareTraceId, SyncStage::END, errCode }); } }; } @@ -419,29 +445,35 @@ std::function SyncManager::GetClientChangeHandler() }; } -SyncManager::Retryer SyncManager::GetRetryer(int32_t times, const SyncInfo &syncInfo) +SyncManager::Retryer SyncManager::GetRetryer(int32_t times, const SyncInfo &syncInfo, int32_t user) { if (times >= RETRY_TIMES) { - return [info = SyncInfo(syncInfo)](Duration, int32_t code, int32_t dbCode) mutable { + return [this, user, info = SyncInfo(syncInfo)](Duration, int32_t code, int32_t dbCode, + const std::string &prepareTraceId) mutable { if (code == E_OK || code == E_SYNC_TASK_MERGED) { return true; } info.SetError(code); - RadarReporter::Report( - { info.bundleName_.c_str(), CLOUD_SYNC, FINISH_SYNC, info.syncId_, info.triggerMode_, false, dbCode }, - "GetRetryer", END); + RadarReporter::Report({ info.bundleName_.c_str(), CLOUD_SYNC, FINISH_SYNC, info.syncId_, info.triggerMode_, + false, dbCode }, + "GetRetryer", BizState::END); + Report({ user, info.bundleName_, prepareTraceId, SyncStage::END, + dbCode == GenStore::DB_ERR_OFFSET ? 0 : dbCode }); return true; }; } - return [this, times, info = SyncInfo(syncInfo)](Duration interval, int32_t code, int32_t dbCode) mutable { + return [this, times, user, info = SyncInfo(syncInfo)](Duration interval, int32_t code, int32_t dbCode, + const std::string &prepareTraceId) mutable { if (code == E_OK || code == E_SYNC_TASK_MERGED) { return true; } if (code == E_NO_SPACE_FOR_ASSET || code == E_RECODE_LIMIT_EXCEEDED) { info.SetError(code); - RadarReporter::Report( - { info.bundleName_.c_str(), CLOUD_SYNC, FINISH_SYNC, info.syncId_, info.triggerMode_, false, dbCode }, - "GetRetryer", END); + RadarReporter::Report({ info.bundleName_.c_str(), CLOUD_SYNC, FINISH_SYNC, info.syncId_, info.triggerMode_, + false, dbCode }, + "GetRetryer", BizState::END); + Report({ user, info.bundleName_, prepareTraceId, SyncStage::END, + dbCode == GenStore::DB_ERR_OFFSET ? 0 : dbCode }); return true; } @@ -569,6 +601,36 @@ AutoCache::Store SyncManager::GetStore(const StoreMetaData &meta, int32_t user, return store; } +void SyncManager::Report(const ReportParam &reportParam) +{ + auto cloudReport = CloudReport::GetInstance(); + if (cloudReport == nullptr) { + return; + } + cloudReport->Report(reportParam); +} + +SyncManager::TraceIds SyncManager::GetPrepareTraceId(const SyncInfo &info, const CloudInfo &cloud) +{ + TraceIds traceIds; + if (!info.prepareTraceId_.empty()) { + traceIds.emplace(info.bundleName_, info.prepareTraceId_); + return traceIds; + } + auto cloudReport = CloudReport::GetInstance(); + if (cloudReport == nullptr) { + return traceIds; + } + if (info.bundleName_.empty()) { + for (const auto &it : cloud.apps) { + traceIds.emplace(it.first, cloudReport->GetPrepareTraceId(info.user_)); + } + } else { + traceIds.emplace(info.bundleName_, cloudReport->GetPrepareTraceId(info.user_)); + } + return traceIds; +} + bool SyncManager::NeedGetCloudInfo(CloudInfo &cloud) { return (!MetaDataManager::GetInstance().LoadMeta(cloud.GetKey(), cloud, true) || !cloud.enableCloud) && @@ -678,9 +740,9 @@ void SyncManager::UpdateFinishSyncInfo(const QueryKey &queryKey, uint64_t syncId } std::function SyncManager::GetCallback(const GenAsync &async, - const StoreInfo &storeInfo, int32_t triggerMode) + const StoreInfo &storeInfo, int32_t triggerMode, const std::string &prepareTraceId, int32_t user) { - return [this, async, storeInfo, triggerMode](const GenDetails &result) { + return [this, async, storeInfo, triggerMode, prepareTraceId, user](const GenDetails &result) { if (async != nullptr) { async(result); } @@ -694,6 +756,12 @@ std::function SyncManager::GetCallback(const Gen return; } + int32_t dbCode = (result.begin()->second.dbCode == GenStore::DB_ERR_OFFSET) ? 0 : result.begin()->second.dbCode; + RadarReporter::Report({ storeInfo.bundleName.c_str(), CLOUD_SYNC, FINISH_SYNC, storeInfo.syncId, triggerMode, + result.begin()->second.changeCount, dbCode }, + "GetCallback", BizState::END); + Report({ user, storeInfo.bundleName, prepareTraceId, SyncStage::END, dbCode }); + auto id = GetAccountId(storeInfo.user); if (id.empty()) { ZLOGD("account id is empty"); @@ -706,11 +774,7 @@ std::function SyncManager::GetCallback(const Gen }; int32_t code = result.begin()->second.code; - int32_t dbCode = (result.begin()->second.dbCode == GenStore::DB_ERR_OFFSET) ? 0 : result.begin()->second.dbCode; UpdateFinishSyncInfo(queryKey, storeInfo.syncId, code); - RadarReporter::Report({ storeInfo.bundleName.c_str(), CLOUD_SYNC, FINISH_SYNC, storeInfo.syncId, triggerMode, - result.begin()->second.changeCount, dbCode }, - "GetCallback", END); }; } @@ -745,7 +809,8 @@ std::vector SyncManager::GetSchemaMeta(const CloudInfo &cloud, const return schemas; } -void SyncManager::DoExceptionalCallback(const GenAsync &async, GenDetails &details, const StoreInfo &storeInfo) +void SyncManager::DoExceptionalCallback(const GenAsync &async, GenDetails &details, const StoreInfo &storeInfo, + const std::string &prepareTraceId) { if (async) { details[SyncInfo::DEFAULT_ID].code = E_ERROR; @@ -753,6 +818,7 @@ void SyncManager::DoExceptionalCallback(const GenAsync &async, GenDetails &detai } QueryKey queryKey{ GetAccountId(storeInfo.user), storeInfo.bundleName, "" }; UpdateFinishSyncInfo(queryKey, storeInfo.syncId, E_ERROR); + Report({ storeInfo.user, storeInfo.bundleName, prepareTraceId, SyncStage::END, E_ERROR }); } bool SyncManager::InitDefaultUser(int32_t &user) @@ -768,10 +834,10 @@ bool SyncManager::InitDefaultUser(int32_t &user) return true; } -std::function SyncManager::RetryCallback( - const StoreInfo &storeInfo, Retryer retryer, int32_t triggerMode) +std::function SyncManager::RetryCallback(const StoreInfo &storeInfo, + Retryer retryer, int32_t triggerMode, const std::string &prepareTraceId, int32_t user) { - return [this, retryer, storeInfo, triggerMode](const GenDetails &details) { + return [this, retryer, storeInfo, triggerMode, prepareTraceId, user](const GenDetails &details) { if (details.empty()) { ZLOGE("retry, details empty"); return; @@ -784,10 +850,12 @@ std::function SyncManager::Retr if (code == E_OK) { RadarReporter::Report({ storeInfo.bundleName.c_str(), CLOUD_SYNC, FINISH_SYNC, storeInfo.syncId, triggerMode, details.begin()->second.changeCount }, - "RetryCallback", END); + "RetryCallback", BizState::END); + Report({ user, storeInfo.bundleName, prepareTraceId, SyncStage::END, + dbCode == GenStore::DB_ERR_OFFSET ? 0 : dbCode }); } } - retryer(GetInterval(code), code, dbCode); + retryer(GetInterval(code), code, dbCode, prepareTraceId); }; } @@ -799,4 +867,27 @@ void SyncManager::BatchUpdateFinishState(const std::vector SyncManager::GetMetaData(const StoreInfo &storeInfo) +{ + StoreMetaData meta(storeInfo); + meta.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true)) { + meta.user = "0"; // check if it is a public store. + StoreMetaDataLocal localMetaData; + if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKeyLocal(), localMetaData, true) || + !localMetaData.isPublic || !MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true)) { + ZLOGE("failed, no store meta. bundleName:%{public}s, storeId:%{public}s", meta.bundleName.c_str(), + meta.GetStoreAlias().c_str()); + return { false, meta }; + } + } + return { true, meta }; +} } // namespace OHOS::CloudData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/cloud/sync_manager.h b/datamgr_service/services/distributeddataservice/service/cloud/sync_manager.h index 2aed28defc06b6dec157b01af17ffc9e6c6d575a..1c7eb993fc08df138e6ff46ae62305454429978a 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/sync_manager.h +++ b/datamgr_service/services/distributeddataservice/service/cloud/sync_manager.h @@ -39,17 +39,29 @@ public: using AutoCache = DistributedData::AutoCache; using StoreMetaData = DistributedData::StoreMetaData; using SchemaMeta = DistributedData::SchemaMeta; + using TraceIds = std::map; + using SyncStage = DistributedData::SyncStage; + using ReportParam = DistributedData::ReportParam; static AutoCache::Store GetStore(const StoreMetaData &meta, int32_t user, bool mustBind = true); class SyncInfo final { public: using Store = std::string; using Stores = std::vector; using Tables = std::vector; + struct Param { + int32_t user; + std::string bundleName; + Store store; + Tables tables; + int32_t triggerMode = 0; + std::string prepareTraceId; + }; using MutliStoreTables = std::map; explicit SyncInfo(int32_t user, const std::string &bundleName = "", const Store &store = "", const Tables &tables = {}, int32_t triggerMode = 0); SyncInfo(int32_t user, const std::string &bundleName, const Stores &stores); SyncInfo(int32_t user, const std::string &bundleName, const MutliStoreTables &tables); + explicit SyncInfo(const Param ¶m); void SetMode(int32_t mode); void SetWait(int32_t wait); void SetAsyncDetail(GenAsync asyncDetail); @@ -57,6 +69,7 @@ public: void SetError(int32_t code) const; void SetCompensation(bool isCompensation); void SetTriggerMode(int32_t triggerMode); + void SetPrepareTraceId(const std::string &prepareTraceId); std::shared_ptr GenerateQuery(const std::string &store, const Tables &tables); bool Contains(const std::string &storeName); inline static constexpr const char *DEFAULT_ID = "default"; @@ -74,6 +87,7 @@ public: std::shared_ptr query_; bool isCompensation_ = false; int32_t triggerMode_ = 0; + std::string prepareTraceId_; }; SyncManager(); ~SyncManager(); @@ -81,13 +95,15 @@ public: int32_t DoCloudSync(SyncInfo syncInfo); int32_t StopCloudSync(int32_t user = 0); int32_t QueryLastSyncInfo(const std::vector &queryKeys, QueryLastResults &results); + void Report(const ReportParam &reportParam); private: using Event = DistributedData::Event; using Task = ExecutorPool::Task; using TaskId = ExecutorPool::TaskId; using Duration = ExecutorPool::Duration; - using Retryer = std::function; + using Retryer = + std::function; using CloudInfo = DistributedData::CloudInfo; using StoreInfo = DistributedData::StoreInfo; using SyncStrategy = DistributedData::SyncStrategy; @@ -107,35 +123,39 @@ private: static uint64_t GenerateId(int32_t user); static ExecutorPool::Duration GetInterval(int32_t code); - static std::map GetBindInfos(const StoreMetaData &meta, - const std::vector &users, const DistributedData::Database &schemaDatabase); + static std::map GetBindInfos( + const StoreMetaData &meta, const std::vector &users, const DistributedData::Database &schemaDatabase); static std::string GetAccountId(int32_t user); static std::vector> GetCloudSyncInfo(const SyncInfo &info, CloudInfo &cloud); static std::vector GetSchemaMeta(const CloudInfo &cloud, const std::string &bundleName); static bool NeedGetCloudInfo(CloudInfo &cloud); + static GeneralError IsValid(SyncInfo &info, CloudInfo &cloud); Task GetSyncTask(int32_t times, bool retry, RefCount ref, SyncInfo &&syncInfo); void UpdateSchema(const SyncInfo &syncInfo); std::function GetSyncHandler(Retryer retryer); std::function GetClientChangeHandler(); - Retryer GetRetryer(int32_t times, const SyncInfo &syncInfo); + Retryer GetRetryer(int32_t times, const SyncInfo &syncInfo, int32_t user); RefCount GenSyncRef(uint64_t syncId); int32_t Compare(uint64_t syncId, int32_t user); - GeneralError IsValid(SyncInfo &info, CloudInfo &cloud); void UpdateStartSyncInfo(const std::vector> &cloudSyncInfos); void UpdateFinishSyncInfo(const QueryKey &queryKey, uint64_t syncId, int32_t code); std::function GetCallback(const GenAsync &async, - const StoreInfo &storeInfo, int32_t triggerMode); - std::function GetPostEventTask(const std::vector &schemas, CloudInfo &cloud, SyncInfo &info, - bool retry); - void DoExceptionalCallback(const GenAsync &async, GenDetails &details, const StoreInfo &storeInfo); + const StoreInfo &storeInfo, int32_t triggerMode, const std::string &prepareTraceId, int32_t user); + std::function GetPostEventTask(const std::vector &schemas, CloudInfo &cloud, SyncInfo &info, + bool retry, const TraceIds &traceIds); + void DoExceptionalCallback( + const GenAsync &async, GenDetails &details, const StoreInfo &storeInfo, const std::string &prepareTraceId); bool InitDefaultUser(int32_t &user); - std::function RetryCallback( - const StoreInfo &storeInfo, Retryer retryer, int32_t triggerMode); + std::function RetryCallback(const StoreInfo &storeInfo, + Retryer retryer, int32_t triggerMode, const std::string &prepareTraceId, int32_t user); static void GetLastResults( const std::string &storeId, std::map &infos, QueryLastResults &results); void BatchUpdateFinishState(const std::vector> &cloudSyncInfos, int32_t code); bool NeedSaveSyncInfo(const QueryKey &queryKey); std::function GetLockChangeHandler(); + void BatchReport(int32_t userId, const TraceIds &traceIds, SyncStage syncStage, int32_t errCode); + TraceIds GetPrepareTraceId(const SyncInfo &info, const CloudInfo &cloud); + std::pair GetMetaData(const StoreInfo &storeInfo); static std::atomic genId_; std::shared_ptr executor_; diff --git a/datamgr_service/services/distributeddataservice/service/cloud/sync_strategies/network_sync_strategy.cpp b/datamgr_service/services/distributeddataservice/service/cloud/sync_strategies/network_sync_strategy.cpp index d7b6f74df148a1a278f1dab20bfba1f7dea97d4c..cb8a86f17b992066742701d62e38b31124578bf8 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/sync_strategies/network_sync_strategy.cpp +++ b/datamgr_service/services/distributeddataservice/service/cloud/sync_strategies/network_sync_strategy.cpp @@ -27,8 +27,7 @@ using namespace OHOS::DistributedData; NetworkSyncStrategy::NetworkSyncStrategy() { MetaDataManager::GetInstance().Subscribe( - StrategyInfo::PREFIX, - [this](const std::string &key, const std::string &value, int32_t flag) -> auto { + StrategyInfo::PREFIX, [this](const std::string &key, const std::string &value, int32_t flag) -> auto { StrategyInfo info; StrategyInfo::Unmarshall(value, info); ZLOGI("flag:%{public}d, value:%{public}s", flag, value.c_str()); @@ -43,8 +42,7 @@ NetworkSyncStrategy::NetworkSyncStrategy() ZLOGE("ignored operation"); } return true; - }, - true); + }, true); } NetworkSyncStrategy::~NetworkSyncStrategy() diff --git a/datamgr_service/services/distributeddataservice/service/data_share/BUILD.gn b/datamgr_service/services/distributeddataservice/service/data_share/BUILD.gn index ff8b1a46d30ffea7d77ab2c638ee722a73520382..f2992608080489e995759c42151fa88eae32933d 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/data_share/BUILD.gn @@ -87,7 +87,10 @@ ohos_shared_library("data_share_service") { "subscriber_managers/rdb_subscriber_manager.cpp", "sys_event_subscriber.cpp", ] - cflags = [ "-Wno-multichar" ] + cflags = [ + "-Wno-multichar", + "-D_LIBCPP_HAS_COND_CLOCKWAIT", + ] cflags_cc = [ "-fvisibility=hidden" ] diff --git a/datamgr_service/services/distributeddataservice/service/data_share/common/bundle_mgr_proxy.cpp b/datamgr_service/services/distributeddataservice/service/data_share/common/bundle_mgr_proxy.cpp index dec8551caa0b349d709dd9a97ff697e9fdc60dc4..03e91f19bacd6af3b5bd88a9c06b37fcb9f743c0 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/common/bundle_mgr_proxy.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/common/bundle_mgr_proxy.cpp @@ -62,9 +62,12 @@ sptr BundleMgrProxy::CheckBMS() } int BundleMgrProxy::GetBundleInfoFromBMS( - const std::string &bundleName, int32_t userId, BundleConfig &bundleConfig) + const std::string &bundleName, int32_t userId, BundleConfig &bundleConfig, int32_t appIndex) { - auto bundleKey = bundleName + std::to_string(userId); + std::string bundleKey = bundleName + std::to_string(userId); + if (appIndex != 0) { + bundleKey += "appIndex" + std::to_string(appIndex); + } auto it = bundleCache_.Find(bundleKey); if (it.first) { bundleConfig = it.second; @@ -78,8 +81,24 @@ int BundleMgrProxy::GetBundleInfoFromBMS( return E_BMS_NOT_READY; } AppExecFwk::BundleInfo bundleInfo; - bool ret = bmsClient->GetBundleInfo( - bundleName, AppExecFwk::BundleFlag::GET_BUNDLE_WITH_EXTENSION_INFO, bundleInfo, userId); + bool ret; + if (appIndex == 0) { + ret = bmsClient->GetBundleInfo( + bundleName, AppExecFwk::BundleFlag::GET_BUNDLE_WITH_EXTENSION_INFO, bundleInfo, userId); + } else { + ret = bmsClient->GetCloneBundleInfo( + bundleName, static_cast(AppExecFwk::GetBundleInfoFlag::GET_BUNDLE_INFO_WITH_EXTENSION_ABILITY) | + static_cast(AppExecFwk::GetBundleInfoFlag::GET_BUNDLE_INFO_WITH_HAP_MODULE), + appIndex, bundleInfo, userId); + // when there is no error, the former function returns 1 while the new function returns 0 + ret = !ret; + for (auto &item : bundleInfo.hapModuleInfos) { + for (auto &item2 : item.extensionInfos) { + bundleInfo.extensionInfos.push_back(item2); + } + } + } + if (!ret) { RADAR_REPORT(__FUNCTION__, RadarReporter::SILENT_ACCESS, RadarReporter::GET_BMS, RadarReporter::FAILED, RadarReporter::ERROR_CODE, RadarReporter::GET_BUNDLE_INFP_FAILED); @@ -115,9 +134,13 @@ BundleMgrProxy::~BundleMgrProxy() } } -void BundleMgrProxy::Delete(const std::string &bundleName, int32_t userId) +void BundleMgrProxy::Delete(const std::string &bundleName, int32_t userId, int32_t appIndex) { - bundleCache_.Erase(bundleName + std::to_string(userId)); + if (appIndex != 0) { + bundleCache_.Erase(bundleName + std::to_string(userId) + "appIndex" + std::to_string(appIndex)); + } else { + bundleCache_.Erase(bundleName + std::to_string(userId)); + } return; } diff --git a/datamgr_service/services/distributeddataservice/service/data_share/common/bundle_mgr_proxy.h b/datamgr_service/services/distributeddataservice/service/data_share/common/bundle_mgr_proxy.h index 9b4b325cac565a22567387de6bb53d57d6a3b898..75edf5bbfd6ca0d05563f6104a56dc6d7a829162 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/common/bundle_mgr_proxy.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/common/bundle_mgr_proxy.h @@ -65,8 +65,9 @@ class BundleMgrProxy final : public std::enable_shared_from_this public: ~BundleMgrProxy(); static std::shared_ptr GetInstance(); - int GetBundleInfoFromBMS(const std::string &bundleName, int32_t userId, BundleConfig &bundleConfig); - void Delete(const std::string &bundleName, int32_t userId); + int GetBundleInfoFromBMS(const std::string &bundleName, int32_t userId, + BundleConfig &bundleConfig, int32_t appIndex = 0); + void Delete(const std::string &bundleName, int32_t userId, int32_t appIndex); sptr CheckBMS(); private: diff --git a/datamgr_service/services/distributeddataservice/service/data_share/common/context.h b/datamgr_service/services/distributeddataservice/service/data_share/common/context.h index 25995eaa064c8741f80251cfc2e80874f6fa15d8..71988eb20eedd5323afde3da7a7307b7a15a3d1f 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/common/context.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/common/context.h @@ -37,6 +37,7 @@ public: virtual ~Context() = default; std::string uri; int32_t currentUserId = -1; + int32_t appIndex = 0; std::string permission; uint32_t callerTokenId = 0; std::string callerBundleName; diff --git a/datamgr_service/services/distributeddataservice/service/data_share/common/rdb_delegate.cpp b/datamgr_service/services/distributeddataservice/service/data_share/common/rdb_delegate.cpp index 013ce8b05cd1971d7f9994d3ef3a0201ec52d6ea..df25e90185d125390d86d026c290c2a66658406f 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/common/rdb_delegate.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/common/rdb_delegate.cpp @@ -64,7 +64,8 @@ std::string RemindTimerFunc(const std::vector &args) return args[ARG_TIME]; } -RdbStoreConfig RdbDelegate::GetConfig(const DistributedData::StoreMetaData &meta, bool registerFunction) +std::pair RdbDelegate::GetConfig(const DistributedData::StoreMetaData &meta, + bool registerFunction) { RdbStoreConfig config(meta.dataDir); config.SetCreateNecessary(false); @@ -72,16 +73,20 @@ RdbStoreConfig RdbDelegate::GetConfig(const DistributedData::StoreMetaData &meta config.SetBundleName(meta.bundleName); if (meta.isEncrypt) { DistributedData::SecretKeyMetaData secretKeyMeta; - DistributedData::MetaDataManager::GetInstance().LoadMeta(meta.GetSecretKey(), secretKeyMeta, true); + if (!DistributedData::MetaDataManager::GetInstance().LoadMeta(meta.GetSecretKey(), secretKeyMeta, true)) { + return std::make_pair(E_DB_NOT_EXIST, config); + } std::vector decryptKey; - DistributedData::CryptoManager::GetInstance().Decrypt(secretKeyMeta.sKey, decryptKey); + if (!DistributedData::CryptoManager::GetInstance().Decrypt(secretKeyMeta.sKey, decryptKey)) { + return std::make_pair(E_ERROR, config); + }; config.SetEncryptKey(decryptKey); std::fill(decryptKey.begin(), decryptKey.end(), 0); } if (registerFunction) { config.SetScalarFunction("remindTimer", ARGS_SIZE, RemindTimerFunc); } - return config; + return std::make_pair(E_OK, config); } RdbDelegate::RdbDelegate(const DistributedData::StoreMetaData &meta, int version, @@ -94,7 +99,12 @@ RdbDelegate::RdbDelegate(const DistributedData::StoreMetaData &meta, int version haMode_ = meta.haMode; backup_ = backup; - RdbStoreConfig config = GetConfig(meta, registerFunction); + auto [err, config] = GetConfig(meta, registerFunction); + if (err != E_OK) { + ZLOGW("Get rdbConfig failed, errCode is %{public}d, dir is %{public}s", err, + DistributedData::Anonymous::Change(meta.dataDir).c_str()); + return; + } DefaultOpenCallback callback; store_ = RdbHelper::GetRdbStore(config, version, callback, errCode_); if (errCode_ != E_OK) { diff --git a/datamgr_service/services/distributeddataservice/service/data_share/common/rdb_delegate.h b/datamgr_service/services/distributeddataservice/service/data_share/common/rdb_delegate.h index adb3d3b133980e7a7aa5cadab78faee3ec1831be..b73ac308939ff1750eb6cc2f9b328072df6c1788 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/common/rdb_delegate.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/common/rdb_delegate.h @@ -47,7 +47,7 @@ public: const DataSharePredicates &predicate) override; private: void TryAndSend(int errCode); - RdbStoreConfig GetConfig(const DistributedData::StoreMetaData &meta, bool registerFunction); + std::pair GetConfig(const DistributedData::StoreMetaData &meta, bool registerFunction); bool IsLimit(int count, const int32_t callingPid); static std::atomic resultSetCount; static ConcurrentMap resultSetCallingPids; diff --git a/datamgr_service/services/distributeddataservice/service/data_share/data/template_data.cpp b/datamgr_service/services/distributeddataservice/service/data_share/data/template_data.cpp index eb63f4111728c95a87a6c3dfd8129d855af7d828..f99bec09c24f851811f1371be7302f2260bb8426 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/data/template_data.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/data/template_data.cpp @@ -59,7 +59,14 @@ bool TemplateRootNode::Unmarshal(const DistributedData::Serializable::json &node { bool ret = GetValue(node, GET_NAME(uri), uri); ret = ret && GetValue(node, GET_NAME(bundleName), bundleName); - ret = ret && GetValue(node, GET_NAME(subscriberId), subscriberId); + if (!GetValue(node, GET_NAME(subscriberId), subscriberId)) { + int64_t subId; + if (GetValue(node, GET_NAME(subscriberId), subId)) { + subscriberId = std::to_string(subId); + } else { + ret = false; + } + } ret = ret && GetValue(node, GET_NAME(userId), userId); ret = ret && GetValue(node, GET_NAME(templat), tpl); return ret; @@ -67,7 +74,7 @@ bool TemplateRootNode::Unmarshal(const DistributedData::Serializable::json &node TemplateRootNode::TemplateRootNode(const std::string &uri, const std::string &bundleName, const int64_t subscriberId, const int32_t userId, const Template &tpl) - : uri(uri), bundleName(bundleName), subscriberId(subscriberId), userId(userId), tpl(tpl) + : uri(uri), bundleName(bundleName), subscriberId(std::to_string(subscriberId)), userId(userId), tpl(tpl) { } diff --git a/datamgr_service/services/distributeddataservice/service/data_share/data/template_data.h b/datamgr_service/services/distributeddataservice/service/data_share/data/template_data.h index 06b482b51bc1f573126f8d8e191716fe7e5fe8d3..859f0d2d3fe02515bc87390246e7ed48249788dd 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/data/template_data.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/data/template_data.h @@ -50,7 +50,7 @@ struct TemplateRootNode final: public DistributedData::Serializable { private: std::string uri; std::string bundleName; - int64_t subscriberId; + std::string subscriberId; int32_t userId; TemplateNode tpl; }; 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 98783ade7fe562899cf3adffe406f973356b793a..4b8aca96517d5038f4dda9da90644941c1c2cf42 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,6 +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); if (providerInfo_.currentUserId == 0) { LoadConfigCommonStrategy::GetInfoFromProxyURI(providerInfo_.uri, providerInfo_.currentUserId, callerTokenId, providerInfo_.bundleName); @@ -52,7 +53,7 @@ std::pair DataProviderConfig::GetBundleInfo() providerInfo_.bundleName = uriConfig_.pathSegments[0]; } auto ret = BundleMgrProxy::GetInstance()->GetBundleInfoFromBMS( - providerInfo_.bundleName, providerInfo_.currentUserId, bundleInfo); + providerInfo_.bundleName, providerInfo_.currentUserId, bundleInfo, providerInfo_.appIndex); return std::make_pair(ret, bundleInfo); } @@ -144,7 +145,7 @@ int DataProviderConfig::GetFromExtension() } BundleConfig bundleInfo; auto ret = BundleMgrProxy::GetInstance()->GetBundleInfoFromBMS( - providerInfo_.bundleName, providerInfo_.currentUserId, bundleInfo); + providerInfo_.bundleName, providerInfo_.currentUserId, bundleInfo, providerInfo_.appIndex); if (ret != E_OK) { ZLOGE("BundleInfo failed! bundleName: %{public}s", providerInfo_.bundleName.c_str()); return ret; @@ -202,6 +203,9 @@ void DataProviderConfig::GetMetaDataFromUri() std::pair DataProviderConfig::GetProviderInfo() { + if (providerInfo_.appIndex == -1) { + return std::make_pair(E_APPINDEX_INVALID, providerInfo_); + } auto ret = GetFromProxyData(); if (ret == E_OK) { GetMetaDataFromUri(); diff --git a/datamgr_service/services/distributeddataservice/service/data_share/data_provider_config.h b/datamgr_service/services/distributeddataservice/service/data_share/data_provider_config.h index 794cfe0650ca6c77fed175d507520afd7ff74bf3..a58a78f3a9535c886284a417a02ba94e69823ffb 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/data_provider_config.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/data_provider_config.h @@ -34,6 +34,7 @@ public: struct ProviderInfo { std::string uri; int32_t currentUserId = -1; + int32_t appIndex = 0; // appIndex is in [1, 1000], and original app's index is 0 std::string bundleName; std::string moduleName; std::string storeName; diff --git a/datamgr_service/services/distributeddataservice/service/data_share/data_share_db_config.cpp b/datamgr_service/services/distributeddataservice/service/data_share/data_share_db_config.cpp index b8c2927a025c75b811e99c5d66a3cc94668157c8..79a2f4629ba388611e675ae0ec7b0edc33fbd366 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/data_share_db_config.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/data_share_db_config.cpp @@ -30,29 +30,30 @@ namespace OHOS::DataShare { std::pair DataShareDbConfig::QueryMetaData( - const std::string &bundleName, const std::string &storeName, int32_t userId) + const std::string &bundleName, const std::string &storeName, int32_t userId, int32_t appIndex) { DistributedData::StoreMetaData meta; meta.deviceId = DistributedData::DeviceManagerAdapter::GetInstance().GetLocalDevice().uuid; meta.user = std::to_string(userId); meta.bundleName = bundleName; meta.storeId = storeName; + meta.instanceId = appIndex; DistributedData::StoreMetaData metaData; bool isCreated = DistributedData::MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), metaData, true); return std::make_pair(isCreated, metaData); } -std::pair DataShareDbConfig::GetMetaData(const std::string &uri, - const std::string &bundleName, const std::string &storeName, int32_t userId, bool hasExtension) +std::pair DataShareDbConfig::GetMetaData(const DbConfig &dbConfig) { - auto [success, metaData] = QueryMetaData(bundleName, storeName, userId); + auto [success, metaData] = QueryMetaData( + dbConfig.bundleName, dbConfig.storeName, dbConfig.userId, dbConfig.appIndex); if (!success) { - if (!hasExtension) { + if (!dbConfig.hasExtension) { return std::pair(NativeRdb::E_DB_NOT_EXIST, metaData); } AAFwk::WantParams wantParams; - ExtensionConnectAdaptor::TryAndWait(uri, bundleName, wantParams); - auto [succ, meta] = QueryMetaData(bundleName, storeName, userId); + ExtensionConnectAdaptor::TryAndWait(dbConfig.uri, dbConfig.bundleName, wantParams); + auto [succ, meta] = QueryMetaData(dbConfig.bundleName, dbConfig.storeName, dbConfig.userId, dbConfig.appIndex); if (!succ) { return std::pair(NativeRdb::E_DB_NOT_EXIST, meta); } @@ -64,8 +65,7 @@ std::pair DataShareDbConfig::GetMetaData(co std::tuple> DataShareDbConfig::GetDbConfig( DbConfig &dbConfig) { - auto [errCode, metaData] = GetMetaData(dbConfig.uri, dbConfig.bundleName, dbConfig.storeName, - dbConfig.userId, dbConfig.hasExtension); + auto [errCode, metaData] = GetMetaData(dbConfig); if (errCode != E_OK) { ZLOGE("DB not exist,bundleName:%{public}s,storeName:%{public}s,user:%{public}d,err:%{public}d,uri:%{public}s", dbConfig.bundleName.c_str(), dbConfig.storeName.c_str(), dbConfig.userId, errCode, diff --git a/datamgr_service/services/distributeddataservice/service/data_share/data_share_db_config.h b/datamgr_service/services/distributeddataservice/service/data_share/data_share_db_config.h index c038a4cbd62d5148d98beb169ea335908774230e..88efe930efe5fd4e58b9db46d822ad5f0f97d081 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/data_share_db_config.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/data_share_db_config.h @@ -35,14 +35,14 @@ public: std::string storeName; std::string backup; int32_t userId; + int32_t appIndex; bool hasExtension; }; std::tuple> GetDbConfig(DbConfig &dbConfig); - std::pair GetMetaData(const std::string &uri, - const std::string &bundleName, const std::string &storeName, int32_t userId, bool hasExtension); + std::pair GetMetaData(const DbConfig &dbConfig); private: static std::pair QueryMetaData(const std::string &bundleName, - const std::string &storeName, int32_t userId); + const std::string &storeName, int32_t userId, int32_t appIndex); }; } // namespace OHOS::DataShare #endif diff --git a/datamgr_service/services/distributeddataservice/service/data_share/data_share_profile_config.cpp b/datamgr_service/services/distributeddataservice/service/data_share/data_share_profile_config.cpp index fde20bd1128af33f4e3bb2496aac5c778fc91e38..302fbebd35d85fd3138c2ce92f6327f1b1581935 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/data_share_profile_config.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/data_share_profile_config.cpp @@ -251,6 +251,7 @@ bool DataShareProfileConfig::GetProfileInfo(const std::string &calledBundleName, std::map &profileInfos) { BundleConfig bundleInfo; + // profile is the same when app clone if (BundleMgrProxy::GetInstance()->GetBundleInfoFromBMS(calledBundleName, currentUserId, bundleInfo) != E_OK) { ZLOGE("data share GetBundleInfoFromBMS failed! bundleName: %{public}s, currentUserId = %{public}d", 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 c57d403dcb636a09d88f13c11509feecdca1b22b..f36d3800de6c17372f9d43890e36718cecd0a053 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 @@ -671,7 +671,7 @@ int32_t DataShareServiceImpl::DataShareStatic::OnAppUninstall(const std::string PublishedData::ClearAging(); TemplateData::Delete(bundleName, user); NativeRdb::RdbHelper::ClearCache(); - BundleMgrProxy::GetInstance()->Delete(bundleName, user); + BundleMgrProxy::GetInstance()->Delete(bundleName, user, index); uint32_t tokenId = Security::AccessToken::AccessTokenKit::GetHapTokenID(user, bundleName, index); DBDelegate::EraseStoreCache(tokenId); return E_OK; @@ -690,7 +690,7 @@ int32_t DataShareServiceImpl::DataShareStatic::OnAppUpdate(const std::string &bu int32_t index) { ZLOGI("%{public}s updated", bundleName.c_str()); - BundleMgrProxy::GetInstance()->Delete(bundleName, user); + BundleMgrProxy::GetInstance()->Delete(bundleName, user, index); std::string prefix = StoreMetaData::GetPrefix( { DeviceManagerAdapter::GetInstance().GetLocalDevice().uuid, std::to_string(user), "default", bundleName }); std::vector storeMetaData; @@ -715,7 +715,7 @@ int32_t DataShareServiceImpl::OnAppUninstall(const std::string &bundleName, int3 { ZLOGI("AppUninstall user=%{public}d, index=%{public}d, bundleName=%{public}s", user, index, bundleName.c_str()); - BundleMgrProxy::GetInstance()->Delete(bundleName, user); + BundleMgrProxy::GetInstance()->Delete(bundleName, user, index); return E_OK; } @@ -723,7 +723,7 @@ int32_t DataShareServiceImpl::OnAppUpdate(const std::string &bundleName, int32_t { ZLOGI("AppUpdate user=%{public}d, index=%{public}d, bundleName=%{public}s", user, index, bundleName.c_str()); - BundleMgrProxy::GetInstance()->Delete(bundleName, user); + BundleMgrProxy::GetInstance()->Delete(bundleName, user, index); return E_OK; } @@ -950,7 +950,7 @@ std::pair DataShareServiceImpl::ExecuteEx(const std::string &u } DataShareDbConfig::DbConfig config {providerInfo.uri, extensionUri, providerInfo.bundleName, providerInfo.storeName, providerInfo.backup, - providerInfo.singleton ? 0 : providerInfo.currentUserId, providerInfo.hasExtension}; + providerInfo.singleton ? 0 : providerInfo.currentUserId, providerInfo.appIndex, providerInfo.hasExtension}; auto [code, metaData, dbDelegate] = dbConfig.GetDbConfig(config); if (code != E_OK) { ZLOGE("Get dbConfig fail,bundleName:%{public}s,tableName:%{public}s,tokenId:0x%{public}x, uri:%{public}s", @@ -967,7 +967,7 @@ int32_t DataShareServiceImpl::GetBMSAndMetaDataStatus(const std::string &uri, co auto [errCode, calledInfo] = calledConfig.GetProviderInfo(); if (errCode == E_URI_NOT_EXIST) { ZLOGE("Create helper invalid uri, token:0x%{public}x, uri:%{public}s", tokenId, - URIUtils::Anonymous(calledInfo.uri).c_str()); + URIUtils::Anonymous(calledInfo.uri).c_str()); return E_OK; } if (errCode != E_OK) { @@ -976,8 +976,14 @@ int32_t DataShareServiceImpl::GetBMSAndMetaDataStatus(const std::string &uri, co return errCode; } DataShareDbConfig dbConfig; - auto [code, metaData] = dbConfig.GetMetaData(calledInfo.uri, calledInfo.bundleName, - calledInfo.storeName, calledInfo.singleton ? 0 : calledInfo.currentUserId, calledInfo.hasExtension); + DataShareDbConfig::DbConfig dbArg; + dbArg.uri = calledInfo.uri; + dbArg.bundleName = calledInfo.bundleName; + dbArg.storeName = calledInfo.storeName; + dbArg.userId = calledInfo.singleton ? 0 : calledInfo.currentUserId; + dbArg.hasExtension = calledInfo.hasExtension; + dbArg.appIndex = calledInfo.appIndex; + auto [code, metaData] = dbConfig.GetMetaData(dbArg); if (code != E_OK) { ZLOGE("Get metaData fail,bundleName:%{public}s,tableName:%{public}s,tokenId:0x%{public}x, uri:%{public}s", calledInfo.bundleName.c_str(), calledInfo.tableName.c_str(), tokenId, 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 3cc60cdb7fc6406e68f21777c17d943b38421513..80cf59a7d33106ef1ca637cda015c0865968ae98 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,12 +26,16 @@ 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)) { + return false; + } // sa, userId is in uri, caller token id is from first caller tokenId if (context->currentUserId == 0) { GetInfoFromProxyURI( @@ -73,4 +77,19 @@ 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 cf6ddfcbdb1caaafa4ee8f6416e590bb48cf33f8..5b633a15cf1064b1376d8ea4b9b6651c8f293289 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,6 +23,7 @@ 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/data_share/strategies/general/load_config_data_info_strategy.cpp b/datamgr_service/services/distributeddataservice/service/data_share/strategies/general/load_config_data_info_strategy.cpp index a48ad89a8b816ac787683b9bb4c7f8c4eddf3f62..ee18ab8a769cf2faa5ac38cb1d4a1be58e7c336a 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/strategies/general/load_config_data_info_strategy.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/strategies/general/load_config_data_info_strategy.cpp @@ -31,7 +31,7 @@ LoadConfigDataInfoStrategy::LoadConfigDataInfoStrategy() { } static bool QueryMetaData(const std::string &bundleName, const std::string &storeName, - DistributedData::StoreMetaData &metaData, const int32_t userId) + DistributedData::StoreMetaData &metaData, const int32_t userId, const int32_t appIndex) { DistributedData::StoreMetaData meta; meta.deviceId = DistributedData::DeviceManagerAdapter::GetInstance().GetLocalDevice().uuid; @@ -52,11 +52,13 @@ bool LoadConfigNormalDataInfoStrategy::operator()(std::shared_ptr conte return true; } DistributedData::StoreMetaData metaData; - if (!QueryMetaData(context->calledBundleName, context->calledStoreName, metaData, context->currentUserId)) { + if (!QueryMetaData( + context->calledBundleName, context->calledStoreName, metaData, context->currentUserId, context->appIndex)) { // connect extension and retry AAFwk::WantParams wantParams; ExtensionConnectAdaptor::TryAndWait(context->uri, context->calledBundleName, wantParams); - if (!QueryMetaData(context->calledBundleName, context->calledStoreName, metaData, context->currentUserId)) { + if (!QueryMetaData( + context->calledBundleName, context->calledStoreName, metaData, context->currentUserId, context->appIndex)) { ZLOGE("QueryMetaData fail, %{public}s", DistributedData::Anonymous::Change(context->uri).c_str()); context->errCode = NativeRdb::E_DB_NOT_EXIST; return false; @@ -73,11 +75,11 @@ bool LoadConfigNormalDataInfoStrategy::operator()(std::shared_ptr conte bool LoadConfigSingleDataInfoStrategy::operator()(std::shared_ptr context) { DistributedData::StoreMetaData metaData; - if (!QueryMetaData(context->calledBundleName, context->calledStoreName, metaData, 0)) { + if (!QueryMetaData(context->calledBundleName, context->calledStoreName, metaData, 0, context->appIndex)) { // connect extension and retry AAFwk::WantParams wantParams; ExtensionConnectAdaptor::TryAndWait(context->uri, context->calledBundleName, wantParams); - if (!QueryMetaData(context->calledBundleName, context->calledStoreName, metaData, 0)) { + if (!QueryMetaData(context->calledBundleName, context->calledStoreName, metaData, 0, context->appIndex)) { ZLOGE("QueryMetaData fail, %{public}s", DistributedData::Anonymous::Change(context->uri).c_str()); context->errCode = NativeRdb::E_DB_NOT_EXIST; return false; diff --git a/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/rdb_subscriber_manager.cpp b/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/rdb_subscriber_manager.cpp index 3ad175de106b39a0bd6a852a84ad1fd1cb8090f6..630e721fcc1fd09539dd9506a1f267aa0058a961 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/rdb_subscriber_manager.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/rdb_subscriber_manager.cpp @@ -344,7 +344,8 @@ int RdbSubscriberManager::Notify(const Key &key, int32_t userId, const std::vect changeNode.data_.emplace_back("{\"" + predicate.key_ + "\":" + result + "}"); } - ZLOGI("emit, size %{public}zu %{private}s", val.size(), changeNode.uri_.c_str()); + ZLOGI("emit, valSize: %{public}zu, dataSize:%{public}zu, uri:%{public}s,", + val.size(), changeNode.data_.size(), DistributedData::Anonymous::Change(changeNode.uri_).c_str()); for (const auto &callback : val) { if (callback.enabled && callback.observer != nullptr) { callback.observer->OnChangeFromRdb(changeNode); diff --git a/datamgr_service/services/distributeddataservice/service/kvdb/kv_radar_reporter.h b/datamgr_service/services/distributeddataservice/service/kvdb/kv_radar_reporter.h index b1ea96b8011c6249963473969e502dfdd6444eba..d93fc955df10d9b536ef48d743999b0d745d261c 100644 --- a/datamgr_service/services/distributeddataservice/service/kvdb/kv_radar_reporter.h +++ b/datamgr_service/services/distributeddataservice/service/kvdb/kv_radar_reporter.h @@ -76,11 +76,11 @@ constexpr const char* DATA_TYPE = "DATA_TYPE"; constexpr const char* WATER_VERSION = "WATER_VERSION"; constexpr const char* SCREEN_STATUS = "SCREEN_STATUS"; -#define RADAR_REPORT(bizScene, bizStage, stageRes, ...) \ -({ \ - HiSysEventWrite(DistributedKv::DOMAIN, DistributedKv::EVENT_NAME, DistributedKv::TYPE, \ - "ORG_PKG", DistributedKv::ORG_PKG, "FUNC", __FUNCTION__, \ - "BIZ_SCENE", bizScene, "BIZ_STAGE", bizStage, "STAGE_RES", stageRes, ##__VA_ARGS__); \ -}) +#define RADAR_REPORT(bizScene, bizStage, stageRes, ...) \ + ({ \ + HiSysEventWrite(DistributedKv::DOMAIN, DistributedKv::EVENT_NAME, DistributedKv::TYPE, "ORG_PKG", \ + DistributedKv::ORG_PKG, "FUNC", __FUNCTION__, "BIZ_SCENE", bizScene, "BIZ_STAGE", bizStage, "STAGE_RES", \ + stageRes, ##__VA_ARGS__); \ + }) } // namespace OHOS::DistributedKv #endif // KV_RADAR_REPORTER_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_exporter.h b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_exporter.h index 06a18017ca1c9c41c9162230915d344c4508527f..2e856e5d817289ec5d70c825cc5c6f060658df03 100644 --- a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_exporter.h +++ b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_exporter.h @@ -27,6 +27,7 @@ public: KVDBExporter() noexcept; ~KVDBExporter() {} static void Exporter(const StoreMetaData &meta, const std::string &backupPath, bool &result); + private: static KVDBExporter instance_; }; 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 9d24138d4fc87b52eb7c5ebd08371f3f5e6ee817..308938dbfb50373d628440c21c81cbbf9ec54ff8 100644 --- a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_general_store.cpp +++ b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_general_store.cpp @@ -16,11 +16,14 @@ #include "kvdb_general_store.h" #include + +#include "app_id_mapping/app_id_mapping_config_manager.h" #include "bootstrap.h" #include "checker/checker_manager.h" #include "cloud/cloud_sync_finished_event.h" #include "cloud/schema_meta.h" #include "crypto_manager.h" +#include "device_manager_adapter.h" #include "device_matrix.h" #include "directory/directory_manager.h" #include "eventcenter/event_center.h" @@ -36,8 +39,6 @@ #include "user_delegate.h" #include "utils/anonymous.h" #include "water_version_manager.h" -#include "device_manager_adapter.h" -#include "app_id_mapping/app_id_mapping_config_manager.h" namespace OHOS::DistributedKv { using namespace DistributedData; @@ -223,8 +224,8 @@ int32_t KVDBGeneralStore::BindSnapshots(std::shared_ptr &bindInfos, - const CloudConfig &config) +int32_t KVDBGeneralStore::Bind( + Database &database, const std::map &bindInfos, const CloudConfig &config) { if (bindInfos.empty()) { ZLOGW("No cloudDB!"); @@ -250,7 +251,7 @@ int32_t KVDBGeneralStore::Bind(Database &database, const std::map lock(rwMutex_); + std::shared_lock lock(rwMutex_); if (delegate_ == nullptr) { return GeneralError::E_ALREADY_CLOSED; } @@ -350,13 +351,14 @@ KVDBGeneralStore::DBSyncCallback KVDBGeneralStore::GetDBSyncCompleteCB(DetailAsy }; } -DBStatus KVDBGeneralStore::CloudSync( - const Devices &devices, DistributedDB::SyncMode cloudSyncMode, DetailAsync async, int64_t wait) +DBStatus KVDBGeneralStore::CloudSync(const Devices &devices, DistributedDB::SyncMode cloudSyncMode, DetailAsync async, + int64_t wait, const std::string &prepareTraceId) { DistributedDB::CloudSyncOption syncOption; syncOption.devices = devices; syncOption.mode = cloudSyncMode; syncOption.waitTime = wait; + syncOption.prepareTraceId = prepareTraceId; syncOption.lockAction = DistributedDB::LockAction::NONE; if (storeInfo_.user == 0) { std::vector users; @@ -368,13 +370,13 @@ DBStatus KVDBGeneralStore::CloudSync( return delegate_->Sync(syncOption, GetDBProcessCB(async)); } -int32_t KVDBGeneralStore::Sync(const Devices &devices, GenQuery &query, DetailAsync async, SyncParam &syncParm) +int32_t KVDBGeneralStore::Sync(const Devices &devices, GenQuery &query, DetailAsync async, SyncParam &syncParam) { - auto syncMode = GeneralStore::GetSyncMode(syncParm.mode); + auto syncMode = GeneralStore::GetSyncMode(syncParam.mode); std::shared_lock lock(rwMutex_); if (delegate_ == nullptr) { ZLOGE("store already closed! devices count:%{public}zu, the 1st:%{public}s, mode:%{public}d", devices.size(), - devices.empty() ? "null" : Anonymous::Change(*devices.begin()).c_str(), syncParm.mode); + devices.empty() ? "null" : Anonymous::Change(*devices.begin()).c_str(), syncParam.mode); return GeneralError::E_ALREADY_CLOSED; } DBStatus dbStatus; @@ -383,10 +385,10 @@ int32_t KVDBGeneralStore::Sync(const Devices &devices, GenQuery &query, DetailAs if (!enableCloud_) { return GeneralError::E_NOT_SUPPORT; } - dbStatus = CloudSync(devices, dbMode, async, syncParm.wait); + dbStatus = CloudSync(devices, dbMode, async, syncParam.wait, syncParam.prepareTraceId); } else { if (devices.empty()) { - ZLOGE("Devices is empty! mode:%{public}d", syncParm.mode); + ZLOGE("Devices is empty! mode:%{public}d", syncParam.mode); return GeneralError::E_INVALID_ARGS; } KVDBQuery *kvQuery = nullptr; @@ -424,8 +426,8 @@ void KVDBGeneralStore::SetEqualIdentifier(const std::string &appId, const std::s Anonymous::Change(storeId).c_str()); return; } - std::vector sameAccountDevs {}; - std::vector defaultAccountDevs {}; + std::vector sameAccountDevs{}; + std::vector defaultAccountDevs{}; auto uuids = DMAdapter::ToUUID(DMAdapter::GetInstance().GetRemoteDevices()); GetIdentifierParams(sameAccountDevs, uuids, IDENTICAL_ACCOUNT); GetIdentifierParams(defaultAccountDevs, uuids, NO_ACCOUNT); @@ -441,15 +443,14 @@ void KVDBGeneralStore::SetEqualIdentifier(const std::string &appId, const std::s if (!defaultAccountDevs.empty()) { auto convertedIds = AppIdMappingConfigManager::GetInstance().Convert(appId, defaultAccountId); auto identifier = KvManager::GetKvStoreIdentifier(convertedIds.second, convertedIds.first, storeId); - ZLOGI("no account store:%{public}s, device:%{public}.10s, appId:%{public}s", - Anonymous::Change(storeId).c_str(), + ZLOGI("no account store:%{public}s, device:%{public}.10s, appId:%{public}s", Anonymous::Change(storeId).c_str(), DistributedData::Serializable::Marshall(defaultAccountDevs).c_str(), convertedIds.first.c_str()); delegate_->SetEqualIdentifier(identifier, defaultAccountDevs); } } -void KVDBGeneralStore::GetIdentifierParams(std::vector &devices, - const std::vector &uuids, int32_t authType) +void KVDBGeneralStore::GetIdentifierParams( + std::vector &devices, const std::vector &uuids, int32_t authType) { for (const auto &devId : uuids) { if (DMAdapter::GetInstance().IsOHOSType(devId)) { @@ -555,8 +556,8 @@ int32_t KVDBGeneralStore::SetDistributedTables( return GeneralError::E_OK; } -int32_t KVDBGeneralStore::SetTrackerTable( - const std::string &tableName, const std::set &trackerColNames, const std::string &extendColName) +int32_t KVDBGeneralStore::SetTrackerTable(const std::string &tableName, const std::set &trackerColNames, + const std::string &extendColName, bool isForceUpgrade) { return GeneralError::E_OK; } @@ -676,9 +677,9 @@ KVDBGeneralStore::DBProcessCB KVDBGeneralStore::GetDBProcessCB(DetailAsync async table.download.failed = value.downLoadInfo.failCount; table.download.untreated = table.download.total - table.download.success - table.download.failed; detail.changeCount = (process.process == FINISHED) - ? value.downLoadInfo.insertCount + value.downLoadInfo.updateCount + - value.downLoadInfo.deleteCount - : 0; + ? value.downLoadInfo.insertCount + value.downLoadInfo.updateCount + + value.downLoadInfo.deleteCount + : 0; } } if (async) { @@ -713,8 +714,7 @@ void KVDBGeneralStore::SetDBPushDataInterceptor(int32_t storeType) } } return errCode; - } - ); + }); } void KVDBGeneralStore::SetDBReceiveDataInterceptor(int32_t storeType) @@ -751,8 +751,7 @@ void KVDBGeneralStore::SetDBReceiveDataInterceptor(int32_t storeType) } } return errCode; - } - ); + }); } std::vector KVDBGeneralStore::GetNewKey(std::vector &key, const std::string &uuid) 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 a21efc30b45c819dd77736605c39120880aaba7a..6bb4ddc7bbc012874db9801f3089765a1ec42de0 100644 --- a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_general_store.h +++ b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_general_store.h @@ -43,22 +43,21 @@ public: explicit KVDBGeneralStore(const StoreMetaData &meta); ~KVDBGeneralStore(); - int32_t Bind(Database &database, const std::map &bindInfos, - const CloudConfig &config) override; + int32_t Bind(Database &database, const std::map &bindInfos, const CloudConfig &config) override; bool IsBound() override; bool IsValid(); int32_t Execute(const std::string &table, const std::string &sql) override; 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) 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; int32_t Replace(const std::string &table, VBucket &&value) override; int32_t Delete(const std::string &table, const std::string &sql, Values &&args) override; - std::pair> Query(const std::string &table, const std::string &sql, - Values &&args) override; + std::pair> Query( + const std::string &table, const std::string &sql, Values &&args) override; std::pair> Query(const std::string &table, GenQuery &query) override; int32_t Sync(const Devices &devices, GenQuery &query, DetailAsync async, SyncParam &syncParm) override; std::pair> PreSharing(GenQuery &query) override; @@ -94,9 +93,10 @@ private: std::vector GetNewKey(std::vector &key, const std::string &uuid); DBSyncCallback GetDBSyncCompleteCB(DetailAsync async); DBProcessCB GetDBProcessCB(DetailAsync async); - DBStatus CloudSync(const Devices &devices, DistributedDB::SyncMode cloudSyncMode, DetailAsync async, int64_t wait); - void GetIdentifierParams(std::vector &devices, - const std::vector &uuids, int32_t authType); + DBStatus CloudSync(const Devices &devices, DistributedDB::SyncMode cloudSyncMode, DetailAsync async, int64_t wait, + const std::string &prepareTraceId); + void GetIdentifierParams( + std::vector &devices, const std::vector &uuids, int32_t authType); class ObserverProxy : public DistributedDB::KvStoreObserver { public: using DBOrigin = DistributedDB::Origin; diff --git a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_impl.cpp b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_impl.cpp index 8e6bb5248748bbe529457bd74c26ef23b8f64773..00911ffe635c05be515fed300b1ecdb24142a86a 100644 --- a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_impl.cpp @@ -33,9 +33,9 @@ #include "dump/dump_manager.h" #include "eventcenter/event_center.h" #include "ipc_skeleton.h" +#include "kv_radar_reporter.h" #include "kvdb_general_store.h" #include "kvdb_query.h" -#include "kv_radar_reporter.h" #include "log_print.h" #include "matrix_event.h" #include "metadata/appid_meta_data.h" @@ -85,9 +85,7 @@ KVDBServiceImpl::Factory::~Factory() product_ = nullptr; } -KVDBServiceImpl::KVDBServiceImpl() -{ -} +KVDBServiceImpl::KVDBServiceImpl() {} KVDBServiceImpl::~KVDBServiceImpl() { @@ -153,8 +151,7 @@ void KVDBServiceImpl::DumpKvServiceInfo(int fd, std::map &storeIds) @@ -224,8 +221,8 @@ Status KVDBServiceImpl::CloudSync(const AppId &appId, const StoreId &storeId, co { StoreMetaData metaData = GetStoreMetaData(appId, storeId); if (!MetaDataManager::GetInstance().LoadMeta(metaData.GetKey(), metaData, true)) { - ZLOGE("invalid, appId:%{public}s storeId:%{public}s", - appId.appId.c_str(), Anonymous::Change(storeId.storeId).c_str()); + ZLOGE("invalid, appId:%{public}s storeId:%{public}s", appId.appId.c_str(), + Anonymous::Change(storeId.storeId).c_str()); return Status::INVALID_ARGUMENT; } return DoCloudSync(metaData, syncInfo); @@ -269,8 +266,8 @@ Status KVDBServiceImpl::NotifyDataChange(const AppId &appId, const StoreId &stor { StoreMetaData meta = GetStoreMetaData(appId, storeId); if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta)) { - ZLOGE("invalid, appId:%{public}s storeId:%{public}s", - appId.appId.c_str(), Anonymous::Change(storeId.storeId).c_str()); + ZLOGE("invalid, appId:%{public}s storeId:%{public}s", appId.appId.c_str(), + Anonymous::Change(storeId.storeId).c_str()); return Status::INVALID_ARGUMENT; } if (DeviceMatrix::GetInstance().IsSupportMatrix() && @@ -594,10 +591,21 @@ Status KVDBServiceImpl::Unsubscribe(const AppId &appId, const StoreId &storeId, return SUCCESS; } -Status KVDBServiceImpl::GetBackupPassword(const AppId &appId, const StoreId &storeId, std::vector &password) +Status KVDBServiceImpl::GetBackupPassword(const AppId &appId, const StoreId &storeId, std::vector &password, + int32_t passwordType) { StoreMetaData metaData = GetStoreMetaData(appId, storeId); - return (BackupManager::GetInstance().GetPassWord(metaData, password)) ? SUCCESS : ERROR; + if (passwordType == KVDBService::PasswordType::BACKUP_SECRET_KEY) { + return BackupManager::GetInstance().GetPassWord(metaData, password) ? SUCCESS : ERROR; + } + if (passwordType == KVDBService::PasswordType::SECRET_KEY) { + SecretKeyMetaData secretKey; + MetaDataManager::GetInstance().LoadMeta(metaData.GetSecretKey(), secretKey, true); + return CryptoManager::GetInstance().Decrypt(secretKey.sKey, password) ? SUCCESS : ERROR; + } + ZLOGE("passwordType is invalid, appId:%{public}s, storeId:%{public}s, passwordType:%{public}d", + appId.appId.c_str(), Anonymous::Change(storeId.storeId).c_str(), passwordType); + return ERROR; } Status KVDBServiceImpl::SetConfig(const AppId &appId, const StoreId &storeId, const StoreConfig &storeConfig) @@ -675,8 +683,8 @@ Status KVDBServiceImpl::BeforeCreate(const AppId &appId, const StoreId &storeId, return dbStatus == DBStatus::OK ? SUCCESS : DB_ERROR; } -Status KVDBServiceImpl::AfterCreate(const AppId &appId, const StoreId &storeId, const Options &options, - const std::vector &password) +Status KVDBServiceImpl::AfterCreate( + const AppId &appId, const StoreId &storeId, const Options &options, const std::vector &password) { if (!appId.IsValid() || !storeId.IsValid() || !options.IsValidType()) { ZLOGE("failed please check type:%{public}d appId:%{public}s storeId:%{public}s dataType:%{public}d", @@ -734,14 +742,14 @@ int32_t KVDBServiceImpl::OnAppExit(pid_t uid, pid_t pid, uint32_t tokenId, const MetaDataManager::GetInstance().Unsubscribe(SwitchesMetaData::GetPrefix({})); } agent.watchers_.clear(); - auto stores = AutoCache::GetInstance().GetStoresIfPresent(key); - for (auto store : stores) { - if (store != nullptr) { - store->UnregisterDetailProgressObserver(); - } - } return true; }); + auto stores = AutoCache::GetInstance().GetStoresIfPresent(tokenId); + for (auto store : stores) { + if (store != nullptr) { + store->UnregisterDetailProgressObserver(); + } + } return SUCCESS; } @@ -1333,8 +1341,8 @@ AutoCache::Watchers KVDBServiceImpl::GetWatchers(uint32_t tokenId, const std::st void KVDBServiceImpl::SyncAgent::ReInit(pid_t pid, const AppId &appId) { - ZLOGW("pid:%{public}d->%{public}d appId:%{public}s notifier:%{public}d", pid, pid_, - appId_.appId.c_str(), notifier_ == nullptr); + ZLOGW("pid:%{public}d->%{public}d appId:%{public}s notifier:%{public}d", pid, pid_, appId_.appId.c_str(), + notifier_ == nullptr); pid_ = pid; appId_ = appId; notifier_ = nullptr; diff --git a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_impl.h b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_impl.h index 38038ba2813c1851dc7cd87d3c1cc837bbe9cfe9..c2fcef042d06a7e32c883d0098b2e12c796d93dd 100644 --- a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_impl.h +++ b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_impl.h @@ -61,7 +61,8 @@ public: Status RmvSubscribeInfo(const AppId &appId, const StoreId &storeId, const SyncInfo &syncInfo) override; Status Subscribe(const AppId &appId, const StoreId &storeId, sptr observer) override; Status Unsubscribe(const AppId &appId, const StoreId &storeId, sptr observer) override; - Status GetBackupPassword(const AppId &appId, const StoreId &storeId, std::vector &password) override; + Status GetBackupPassword(const AppId &appId, const StoreId &storeId, std::vector &password, + int32_t passwordType) override; Status NotifyDataChange(const AppId &appId, const StoreId &storeId, uint64_t delay) override; Status PutSwitch(const AppId &appId, const SwitchData &data) override; Status GetSwitch(const AppId &appId, const std::string &networkId, SwitchData &data) override; @@ -108,6 +109,7 @@ private: public: Factory(); ~Factory(); + private: std::shared_ptr product_; }; @@ -123,8 +125,8 @@ private: void DoCloudSync(bool statics, bool dynamic); Status DoSync(const StoreMetaData &meta, const SyncInfo &info, const SyncEnd &complete, int32_t type); Status DoSyncInOrder(const StoreMetaData &meta, const SyncInfo &info, const SyncEnd &complete, int32_t type); - Status DoSyncBegin(const std::vector &devices, const StoreMetaData &meta, - const SyncInfo &info, const SyncEnd &complete, int32_t type); + Status DoSyncBegin(const std::vector &devices, const StoreMetaData &meta, const SyncInfo &info, + const SyncEnd &complete, int32_t type); Status DoComplete(const StoreMetaData &meta, const SyncInfo &info, RefCount refCount, const DBResult &dbResult); uint32_t GetSyncDelayTime(uint32_t delay, const StoreId &storeId); Status ConvertDbStatus(DBStatus status) const; diff --git a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_stub.cpp b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_stub.cpp index cf7761ae8ed4f6928f343032f4937e3249e2b091..5921553c4cc754a26a285cdbd21dd51b8d064db2 100644 --- a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_stub.cpp +++ b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_stub.cpp @@ -421,8 +421,14 @@ int32_t KVDBServiceStub::OnUnsubscribe( int32_t KVDBServiceStub::OnGetBackupPassword( const AppId &appId, const StoreId &storeId, MessageParcel &data, MessageParcel &reply) { + int32_t passwordType; + if (!ITypesUtil::Unmarshal(data, passwordType)) { + ZLOGE("Unmarshal type failed, appId:%{public}s storeId:%{public}s", appId.appId.c_str(), + Anonymous::Change(storeId.storeId).c_str()); + return IPC_STUB_INVALID_DATA_ERR; + } std::vector password; - int32_t status = GetBackupPassword(appId, storeId, password); + int32_t status = GetBackupPassword(appId, storeId, password, passwordType); if (!ITypesUtil::Marshal(reply, status, password)) { ZLOGE("Marshal status:0x%{public}x appId:%{public}s storeId:%{public}s", status, appId.appId.c_str(), Anonymous::Change(storeId.storeId).c_str()); diff --git a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_stub.h b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_stub.h index a5deeaf1b28c7fe0cc648f0d9def3bfae2a5356b..f26cb7c8325dfb1d5348c1f426379d8c340e7708 100644 --- a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_stub.h +++ b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_stub.h @@ -17,9 +17,9 @@ #define OHOS_DISTRIBUTED_DATA_SERVICE_KVDB_SERVICE_STUB_H #include "checker/checker_manager.h" #include "distributeddata_kvdb_ipc_interface_code.h" +#include "feature/feature_system.h" #include "iremote_stub.h" #include "kvdb_service.h" -#include "feature/feature_system.h" namespace OHOS::DistributedKv { class KVDBServiceStub : public KVDBService, public DistributedData::FeatureSystem::Feature { public: @@ -36,8 +36,7 @@ private: int32_t OnClose(const AppId &appId, const StoreId &storeId, MessageParcel &data, MessageParcel &reply); int32_t OnSync(const AppId &appId, const StoreId &storeId, MessageParcel &data, MessageParcel &reply); int32_t OnCloudSync(const AppId &appId, const StoreId &storeId, MessageParcel &data, MessageParcel &reply); - int32_t OnRegServiceNotifier( - const AppId &appId, const StoreId &storeId, MessageParcel &data, MessageParcel &reply); + int32_t OnRegServiceNotifier(const AppId &appId, const StoreId &storeId, MessageParcel &data, MessageParcel &reply); int32_t OnUnregServiceNotifier( const AppId &appId, const StoreId &storeId, MessageParcel &data, MessageParcel &reply); int32_t OnSetSyncParam(const AppId &appId, const StoreId &storeId, MessageParcel &data, MessageParcel &reply); @@ -53,10 +52,10 @@ private: int32_t OnNotifyDataChange(const AppId &appId, const StoreId &storeId, MessageParcel &data, MessageParcel &reply); int32_t OnPutSwitch(const AppId &appId, const StoreId &storeId, MessageParcel &data, MessageParcel &reply); int32_t OnGetSwitch(const AppId &appId, const StoreId &storeId, MessageParcel &data, MessageParcel &reply); - int32_t OnSubscribeSwitchData(const AppId &appId, const StoreId &storeId, MessageParcel &data, - MessageParcel &reply); - int32_t OnUnsubscribeSwitchData(const AppId &appId, const StoreId &storeId, MessageParcel &data, - MessageParcel &reply); + int32_t OnSubscribeSwitchData( + const AppId &appId, const StoreId &storeId, MessageParcel &data, MessageParcel &reply); + int32_t OnUnsubscribeSwitchData( + const AppId &appId, const StoreId &storeId, MessageParcel &data, MessageParcel &reply); int32_t OnSetConfig(const AppId &appId, const StoreId &storeId, MessageParcel &data, MessageParcel &reply); int32_t OnRemoveDeviceData(const AppId &appId, const StoreId &storeId, MessageParcel &data, MessageParcel &reply); static const Handler HANDLERS[static_cast(KVDBServiceInterfaceCode::TRANS_BUTT)]; diff --git a/datamgr_service/services/distributeddataservice/service/kvdb/kvstore_sync_manager.cpp b/datamgr_service/services/distributeddataservice/service/kvdb/kvstore_sync_manager.cpp index 4a41de5d244ae90823140cad33ec222ac4af38f3..c4dad02f6e9679871a894b91a42185033d7598e5 100644 --- a/datamgr_service/services/distributeddataservice/service/kvdb/kvstore_sync_manager.cpp +++ b/datamgr_service/services/distributeddataservice/service/kvdb/kvstore_sync_manager.cpp @@ -69,11 +69,9 @@ uint32_t KvStoreSyncManager::GetExpireTimeRange(uint32_t delayMs) const Status KvStoreSyncManager::RemoveSyncOperation(uintptr_t syncId) { auto pred = [syncId](const KvSyncOperation &op) -> bool { return syncId == op.syncId; }; - std::lock_guard lock(syncOpsMutex_); uint32_t count = DoRemoveSyncingOp(pred, realtimeSyncingOps_); count += DoRemoveSyncingOp(pred, delaySyncingOps_); - auto &syncOps = scheduleSyncOps_; for (auto it = syncOps.begin(); it != syncOps.end();) { if (pred(it->second)) { @@ -102,9 +100,8 @@ uint32_t KvStoreSyncManager::DoRemoveSyncingOp(OpPred pred, std::list &syncingOps) { - auto pred = [opSeq](const KvSyncOperation &op) -> bool { return opSeq == op.opSeq; }; - ZLOGD("remove op %u", opSeq); + auto pred = [opSeq](const KvSyncOperation &op) -> bool { return opSeq == op.opSeq; }; std::lock_guard lock(syncOpsMutex_); uint32_t count = DoRemoveSyncingOp(pred, syncingOps); return (count == 1) ? Status::SUCCESS : Status::ERROR; @@ -138,7 +135,6 @@ bool KvStoreSyncManager::GetTimeoutSyncOps(const TimePoint ¤tTime, std::li if (currentTime + std::chrono::milliseconds(GetExpireTimeRange(op.delayMs)) < expireTime) { break; } - syncOps.push_back(op); if (op.syncEnd != nullptr) { delaySyncingOps_.push_back(op); @@ -153,7 +149,6 @@ void KvStoreSyncManager::DoCheckSyncingTimeout(std::list &synci auto syncingTimeoutPred = [](const KvSyncOperation &op) -> bool { return op.beginTime + std::chrono::milliseconds(SYNCING_TIMEOUT_MS) < std::chrono::steady_clock::now(); }; - uint32_t count = DoRemoveSyncingOp(syncingTimeoutPred, syncingOps); if (count > 0) { ZLOGI("remove %u syncing ops by timeout", count); @@ -181,6 +176,7 @@ void KvStoreSyncManager::Schedule(const TimePoint &time) AddTimer(nextTime); } } + void KvStoreSyncManager::SetThreadPool(std::shared_ptr executors) { executors_ = executors; diff --git a/datamgr_service/services/distributeddataservice/service/kvdb/upgrade.h b/datamgr_service/services/distributeddataservice/service/kvdb/upgrade.h index 5e98238026688e45db76f2bbcda2dd5d4b8fca7f..7d4e9686ca2307005ac8cd23c07ad5ce12312158 100644 --- a/datamgr_service/services/distributeddataservice/service/kvdb/upgrade.h +++ b/datamgr_service/services/distributeddataservice/service/kvdb/upgrade.h @@ -18,11 +18,11 @@ #include #include +#include "concurrent_map.h" #include "kv_store_delegate_manager.h" #include "kv_store_nb_delegate.h" #include "metadata/store_meta_data.h" #include "types.h" -#include "concurrent_map.h" namespace OHOS::DistributedKv { class Upgrade { diff --git a/datamgr_service/services/distributeddataservice/service/kvdb/user_delegate.cpp b/datamgr_service/services/distributeddataservice/service/kvdb/user_delegate.cpp index a40202e3c6a3472b8f454530ee92058af49ca1b0..cdb2991afc5955c813dbb7984e8efe55b86b0350 100644 --- a/datamgr_service/services/distributeddataservice/service/kvdb/user_delegate.cpp +++ b/datamgr_service/services/distributeddataservice/service/kvdb/user_delegate.cpp @@ -15,9 +15,11 @@ #define LOG_TAG "UserDelegate" #include "user_delegate.h" + #include #include #include + #include "communicator/device_manager_adapter.h" #include "log_print.h" #include "metadata/meta_data_manager.h" @@ -91,8 +93,7 @@ std::vector UserDelegate::GetUsers(const std::string &deviceId) } return !users.empty(); }); - auto time = - static_cast(duration_cast(system_clock::now().time_since_epoch()).count()); + auto time = static_cast(duration_cast(system_clock::now().time_since_epoch()).count()); ZLOGI("device:%{public}s, users:%{public}s times %{public}" PRIu64 ".", Anonymous::Change(deviceId).c_str(), Serializable::Marshall(userStatus).c_str(), time); return userStatus; @@ -147,7 +148,7 @@ UserDelegate &UserDelegate::GetInstance() return instance; } -void UserDelegate::Init(const std::shared_ptr& executors) +void UserDelegate::Init(const std::shared_ptr &executors) { auto ret = AccountDelegate::GetInstance()->Subscribe(std::make_shared(*this)); MetaDataManager::GetInstance().Subscribe( @@ -171,7 +172,7 @@ void UserDelegate::Init(const std::shared_ptr& executors) ZLOGD("ignored operation"); } return true; - }); + }); if (!executors_) { executors_ = executors; } @@ -193,13 +194,11 @@ ExecutorPool::Task UserDelegate::GeTask() bool UserDelegate::NotifyUserEvent(const UserDelegate::UserEvent &userEvent) { // update all local user status - (void) userEvent; + (void)userEvent; return InitLocalUserMeta(); } -UserDelegate::LocalUserObserver::LocalUserObserver(UserDelegate &userDelegate) : userDelegate_(userDelegate) -{ -} +UserDelegate::LocalUserObserver::LocalUserObserver(UserDelegate &userDelegate) : userDelegate_(userDelegate) {} void UserDelegate::LocalUserObserver::OnAccountChanged(const DistributedKv::AccountEventInfo &eventInfo) { diff --git a/datamgr_service/services/distributeddataservice/service/kvdb/user_delegate.h b/datamgr_service/services/distributeddataservice/service/kvdb/user_delegate.h index 67009804580c361d442bccc6dd5cc2f7e272b877..3a7a7b319159fb078472678457f900a085338b16 100644 --- a/datamgr_service/services/distributeddataservice/service/kvdb/user_delegate.h +++ b/datamgr_service/services/distributeddataservice/service/kvdb/user_delegate.h @@ -18,6 +18,7 @@ #include #include + #include "account/account_delegate.h" #include "concurrent_map.h" #include "executor_pool.h" @@ -35,13 +36,14 @@ public: }; API_EXPORT static UserDelegate &GetInstance(); - API_EXPORT void Init(const std::shared_ptr& executors); + API_EXPORT void Init(const std::shared_ptr &executors); API_EXPORT std::vector GetLocalUserStatus(); API_EXPORT std::set GetLocalUsers(); API_EXPORT std::vector GetRemoteUserStatus(const std::string &deviceId); API_EXPORT bool InitLocalUserMeta(); API_EXPORT static constexpr const int SYSTEM_USER = 0; + private: class LocalUserObserver : public AccountDelegate::Observer { public: diff --git a/datamgr_service/services/distributeddataservice/service/object/object_asset_machine.cpp b/datamgr_service/services/distributeddataservice/service/object/object_asset_machine.cpp index b15277a6cedaa221bbd1157cedf0cb36b1d27a79..dcb034ad95eaa4f57291a174169edf9d19d75fe7 100644 --- a/datamgr_service/services/distributeddataservice/service/object/object_asset_machine.cpp +++ b/datamgr_service/services/distributeddataservice/service/object/object_asset_machine.cpp @@ -259,7 +259,7 @@ static void MergeAssetData(VBucket& record, const Asset& newAsset, const AssetBi auto* asset = Traits::get_if(&value); if (asset->name != newAsset.name) { ZLOGD("Asset not same, old uri: %{public}s, new uri: %{public}s", - Anonymous::Change(asset->uri, true).c_str(), Anonymous::Change(newAsset.uri, true).c_str()); + Anonymous::Change(asset->uri).c_str(), Anonymous::Change(newAsset.uri).c_str()); return; } } diff --git a/datamgr_service/services/distributeddataservice/service/object/object_dms_handler.cpp b/datamgr_service/services/distributeddataservice/service/object/object_dms_handler.cpp index 8dbfeea9532a99effab8b3d7ceb0819b60e8e2e7..7ec88aca2eaa6542b5697a2f68c3d72fc803fe15 100644 --- a/datamgr_service/services/distributeddataservice/service/object/object_dms_handler.cpp +++ b/datamgr_service/services/distributeddataservice/service/object/object_dms_handler.cpp @@ -17,11 +17,13 @@ #include "object_dms_handler.h" +#include "device_manager_adapter.h" #include "dms_handler.h" #include "log_print.h" #include "utils/anonymous.h" namespace OHOS::DistributedObject { +constexpr const char *PKG_NAME = "ohos.distributeddata.service"; void DmsEventListener::DSchedEventNotify(DistributedSchedule::EventNotify ¬ify) { ObjectDmsHandler::GetInstance().ReceiveDmsEvent(notify); @@ -41,10 +43,12 @@ void ObjectDmsHandler::ReceiveDmsEvent(DistributedSchedule::EventNotify &event) DistributedData::Anonymous::Change(event.dstNetworkId_).c_str(), event.destBundleName_.c_str()); } -bool ObjectDmsHandler::IsContinue(const std::string &networkId, const std::string &bundleName) +bool ObjectDmsHandler::IsContinue(const std::string &bundleName) { std::lock_guard lock(mutex_); auto validityTime = std::chrono::steady_clock::now() - std::chrono::seconds(VALIDITY); + DistributedHardware::DmDeviceInfo localDeviceInfo; + DistributedHardware::DeviceManager::GetInstance().GetLocalDeviceInfo(PKG_NAME, localDeviceInfo); for (auto it = dmsEvents_.rbegin(); it != dmsEvents_.rend(); ++it) { if (it->second < validityTime) { continue; @@ -52,22 +56,47 @@ bool ObjectDmsHandler::IsContinue(const std::string &networkId, const std::strin if (it->first.dSchedEventType_ != DistributedSchedule::DMS_CONTINUE) { continue; } - if (it->first.srcNetworkId_ == networkId && it->first.srcBundleName_ == bundleName) { + if (it->first.srcNetworkId_ == localDeviceInfo.networkId && it->first.srcBundleName_ == bundleName) { ZLOGI("Continue source, networkId: %{public}s, bundleName: %{public}s", - DistributedData::Anonymous::Change(networkId).c_str(), bundleName.c_str()); + DistributedData::Anonymous::Change(localDeviceInfo.networkId).c_str(), bundleName.c_str()); return true; } - if (it->first.dstNetworkId_ == networkId && it->first.destBundleName_ == bundleName) { + if (it->first.dstNetworkId_ == localDeviceInfo.networkId && it->first.destBundleName_ == bundleName) { ZLOGI("Continue destination, networkId: %{public}s, bundleName: %{public}s", - DistributedData::Anonymous::Change(networkId).c_str(), bundleName.c_str()); + DistributedData::Anonymous::Change(localDeviceInfo.networkId).c_str(), bundleName.c_str()); return true; } } ZLOGW("Not in continue, networkId: %{public}s, bundleName: %{public}s", - DistributedData::Anonymous::Change(networkId).c_str(), bundleName.c_str()); + DistributedData::Anonymous::Change(localDeviceInfo.networkId).c_str(), bundleName.c_str()); return false; } +std::string ObjectDmsHandler::GetDstBundleName(const std::string &srcBundleName, const std::string &dstNetworkId) +{ + std::lock_guard lock(mutex_); + auto validityTime = std::chrono::steady_clock::now() - std::chrono::seconds(VALIDITY); + DistributedHardware::DmDeviceInfo localDeviceInfo; + DistributedHardware::DeviceManager::GetInstance().GetLocalDeviceInfo(PKG_NAME, localDeviceInfo); + for (auto it = dmsEvents_.rbegin(); it != dmsEvents_.rend(); ++it) { + if (it->second < validityTime) { + continue; + } + if (it->first.dSchedEventType_ != DistributedSchedule::DMS_CONTINUE) { + continue; + } + if (it->first.srcNetworkId_ == localDeviceInfo.networkId && it->first.srcBundleName_ == srcBundleName && + it->first.dstNetworkId_ == dstNetworkId) { + ZLOGI("In continue, srcBundleName: %{public}s, dstBundleName: %{public}s", + srcBundleName.c_str(), it->first.destBundleName_.c_str()); + return it->first.destBundleName_; + } + } + ZLOGW("Not in continue, srcBundleName: %{public}s, srcNetworkId: %{public}s", + srcBundleName.c_str(), DistributedData::Anonymous::Change(localDeviceInfo.networkId).c_str()); + return srcBundleName; +} + void ObjectDmsHandler::RegisterDmsEvent() { ZLOGI("Start register dms event"); diff --git a/datamgr_service/services/distributeddataservice/service/object/object_dms_handler.h b/datamgr_service/services/distributeddataservice/service/object/object_dms_handler.h index c1804e172a64f510212397efe8e32245333c9d1a..ee4208a2798901d63f84f781595f62cbee99a74b 100644 --- a/datamgr_service/services/distributeddataservice/service/object/object_dms_handler.h +++ b/datamgr_service/services/distributeddataservice/service/object/object_dms_handler.h @@ -38,7 +38,8 @@ public: } void ReceiveDmsEvent(DistributedSchedule::EventNotify &event); - bool IsContinue(const std::string &networkId, const std::string &bundleName); + bool IsContinue(const std::string &bundleName); + std::string GetDstBundleName(const std::string &srcBundleName, const std::string &dstNetworkId); void RegisterDmsEvent(); private: diff --git a/datamgr_service/services/distributeddataservice/service/object/object_manager.cpp b/datamgr_service/services/distributeddataservice/service/object/object_manager.cpp index 9be54bc853935644ea5aeae952d7bac77e8387f7..d1353a9bcceb246557655baadbb40cb7cb661752 100644 --- a/datamgr_service/services/distributeddataservice/service/object/object_manager.cpp +++ b/datamgr_service/services/distributeddataservice/service/object/object_manager.cpp @@ -17,24 +17,22 @@ #include "object_manager.h" #include -#include -#include #include "accesstoken_kit.h" #include "account/account_delegate.h" #include "block_data.h" #include "bootstrap.h" -#include "checker/checker_manager.h" #include "common/bytes.h" #include "common/string_utils.h" #include "datetime_ex.h" #include "distributed_file_daemon_manager.h" -#include "ipc_skeleton.h" #include "kvstore_utils.h" #include "log_print.h" #include "metadata/meta_data_manager.h" #include "metadata/store_meta_data.h" +#include "object_dms_handler.h" #include "object_radar_reporter.h" +#include "utils/anonymous.h" namespace OHOS { namespace DistributedObject { @@ -42,7 +40,6 @@ using namespace OHOS::DistributedKv; using namespace Security::AccessToken; using StoreMetaData = OHOS::DistributedData::StoreMetaData; using AccountDelegate = DistributedKv::AccountDelegate; -using OHOS::DistributedKv::AccountDelegate; using Account = OHOS::DistributedKv::AccountDelegate; using AccessTokenKit = Security::AccessToken::AccessTokenKit; using ValueProxy = OHOS::DistributedData::ValueProxy; @@ -132,64 +129,63 @@ void ObjectStoreManager::ProcessSyncCallback(const std::map> &data, const std::string &deviceId, - sptr callback) + const ObjectRecord &data, const std::string &deviceId, sptr callback) { auto proxy = iface_cast(callback); if (deviceId.size() == 0) { - ZLOGE("deviceId empty"); + ZLOGE("DeviceId empty, appId: %{public}s, sessionId: %{public}s", appId.c_str(), sessionId.c_str()); proxy->Completed(std::map()); return INVALID_ARGUMENT; } int32_t result = Open(); if (result != OBJECT_SUCCESS) { - ZLOGE("Open failed, errCode = %{public}d", result); - proxy->Completed(std::map()); + ZLOGE("Open object kvstore failed, result: %{public}d", result); ObjectStore::RadarReporter::ReportStateError(std::string(__FUNCTION__), ObjectStore::SAVE, ObjectStore::SAVE_TO_STORE, ObjectStore::RADAR_FAILED, ObjectStore::GETKV_FAILED, ObjectStore::FINISHED); + proxy->Completed(std::map()); return STORE_NOT_OPEN; } - - ZLOGD("start SaveToStore"); SaveUserToMeta(); - result = SaveToStore(appId, sessionId, deviceId, data); + std::string dstBundleName = ObjectDmsHandler::GetInstance().GetDstBundleName(appId, deviceId); + result = SaveToStore(dstBundleName, sessionId, deviceId, data); if (result != OBJECT_SUCCESS) { - ZLOGE("Save failed, errCode = %{public}d", result); + ZLOGE("Save to store failed, result: %{public}d", result); ObjectStore::RadarReporter::ReportStateError(std::string(__FUNCTION__), ObjectStore::SAVE, ObjectStore::SAVE_TO_STORE, ObjectStore::RADAR_FAILED, result, ObjectStore::FINISHED); Close(); proxy->Completed(std::map()); return result; } - SyncCallBack tmp = [proxy, appId, sessionId, deviceId, this](const std::map &results) { - proxy->Completed(results); - ProcessSyncCallback(results, appId, sessionId, deviceId); - }; - ZLOGI("Sync data, bundleName: %{public}s, sessionId: %{public}s, deviceId: %{public}s", appId.c_str(), + ZLOGI("Sync data, bundleName: %{public}s, sessionId: %{public}s, deviceId: %{public}s", dstBundleName.c_str(), sessionId.c_str(), Anonymous::Change(deviceId).c_str()); - std::vector deviceList = {deviceId}; - result = SyncOnStore(GetPropertyPrefix(appId, sessionId, deviceId), deviceList, tmp); + SyncCallBack syncCallback = + [proxy, dstBundleName, sessionId, deviceId, this](const std::map &results) { + ProcessSyncCallback(results, dstBundleName, sessionId, deviceId); + proxy->Completed(results); + }; + result = SyncOnStore(GetPropertyPrefix(dstBundleName, sessionId, deviceId), {deviceId}, syncCallback); if (result != OBJECT_SUCCESS) { - ZLOGE("sync failed, errCode = %{public}d", result); - proxy->Completed(std::map()); + ZLOGE("Sync data failed, result: %{public}d", result); ObjectStore::RadarReporter::ReportStateError(std::string(__FUNCTION__), ObjectStore::SAVE, ObjectStore::SYNC_DATA, ObjectStore::RADAR_FAILED, result, ObjectStore::FINISHED); + Close(); + proxy->Completed(std::map()); + return result; } - result = PushAssets(std::stoi(GetCurrentUser()), appId, sessionId, data, deviceId); Close(); - return result; + return PushAssets(appId, dstBundleName, sessionId, data, deviceId); } -int32_t ObjectStoreManager::PushAssets(int32_t userId, const std::string &appId, const std::string &sessionId, - const std::map> &data, const std::string &deviceId) +int32_t ObjectStoreManager::PushAssets(const std::string &srcBundleName, const std::string &dstBundleName, + const std::string &sessionId, const ObjectRecord &data, const std::string &deviceId) { Assets assets = GetAssetsFromDBRecords(data); if (assets.empty() || data.find(ObjectStore::FIELDS_PREFIX + ObjectStore::DEVICEID_KEY) == data.end()) { return OBJECT_SUCCESS; } sptr assetObj = new AssetObj(); - assetObj->dstBundleName_ = appId; - assetObj->srcBundleName_ = appId; + assetObj->dstBundleName_ = dstBundleName; + assetObj->srcBundleName_ = srcBundleName; assetObj->dstNetworkId_ = deviceId; assetObj->sessionId_ = sessionId; for (const auto& asset : assets) { @@ -198,6 +194,7 @@ int32_t ObjectStoreManager::PushAssets(int32_t userId, const std::string &appId, if (objectAssetsSendListener_ == nullptr) { objectAssetsSendListener_ = new ObjectAssetsSendListener(); } + int userId = std::atoi(GetCurrentUser().c_str()); auto status = ObjectAssetLoader::GetInstance()->PushAsset(userId, assetObj, objectAssetsSendListener_); return status; } @@ -245,19 +242,18 @@ int32_t ObjectStoreManager::Retrieve( const std::string &bundleName, const std::string &sessionId, sptr callback, uint32_t tokenId) { auto proxy = iface_cast(callback); - ZLOGI("enter"); int32_t result = Open(); if (result != OBJECT_SUCCESS) { - ZLOGE("Open failed, errCode = %{public}d", result); - proxy->Completed(std::map>(), false); + ZLOGE("Open object kvstore failed, result: %{public}d", result); + proxy->Completed(ObjectRecord(), false); return ObjectStore::GETKV_FAILED; } - std::map> results{}; + ObjectRecord results{}; int32_t status = RetrieveFromStore(bundleName, sessionId, results); if (status != OBJECT_SUCCESS) { - ZLOGI("Retrieve failed, status = %{public}d", status); + ZLOGI("Retrieve from store failed, status: %{public}d", status); Close(); - proxy->Completed(std::map>(), false); + proxy->Completed(ObjectRecord(), false); return status; } bool allReady = false; @@ -277,12 +273,11 @@ int32_t ObjectStoreManager::Retrieve( return true; }); } - // delete local data status = RevokeSaveToStore(GetPrefixWithoutDeviceId(bundleName, sessionId)); if (status != OBJECT_SUCCESS) { - ZLOGE("revoke save failed, status = %{public}d", status); + ZLOGE("Revoke save failed, status: %{public}d", status); Close(); - proxy->Completed(std::map>(), false); + proxy->Completed(ObjectRecord(), false); return status; } Close(); @@ -330,26 +325,26 @@ int32_t ObjectStoreManager::Clear() return result; } -int32_t ObjectStoreManager::DeleteByAppId(const std::string &appId) +int32_t ObjectStoreManager::DeleteByAppId(const std::string &appId, int32_t user) { - ZLOGI("enter, %{public}s", appId.c_str()); int32_t result = Open(); if (result != OBJECT_SUCCESS) { - ZLOGE("Open failed, errCode = %{public}d", result); + ZLOGE("Open store failed, result: %{public}d, appId: %{public}s, user: %{public}d", result, + appId.c_str(), user); return STORE_NOT_OPEN; } result = RevokeSaveToStore(appId); if (result != OBJECT_SUCCESS) { - ZLOGE("RevokeSaveToStore failed"); + ZLOGE("Revoke save failed, result: %{public}d, appId: %{public}s, user: %{public}d", result, + appId.c_str(), user); } Close(); - - std::string userId = GetCurrentUser(); - if (userId.empty()) { - return OBJECT_INNER_ERROR; - } + std::string userId = std::to_string(user); std::string metaKey = GetMetaUserIdKey(userId, appId); - DistributedData::MetaDataManager::GetInstance().DelMeta(metaKey, true); + auto status = DistributedData::MetaDataManager::GetInstance().DelMeta(metaKey, true); + if (!status) { + ZLOGE("Delete meta failed, userId: %{public}s, appId: %{public}s", userId.c_str(), appId.c_str()); + } return result; } @@ -399,7 +394,7 @@ void ObjectStoreManager::UnregisterRemoteCallback(const std::string &bundleName, })); } -void ObjectStoreManager::NotifyChange(std::map> &changedData) +void ObjectStoreManager::NotifyChange(ObjectRecord &changedData) { ZLOGI("OnChange start, size:%{public}zu", changedData.size()); bool hasAsset = false; @@ -424,10 +419,10 @@ void ObjectStoreManager::NotifyChange(std::map SaveUserToMeta(); } -std::map>> ObjectStoreManager::GetObjectData( - const std::map>& changedData, SaveInfo& saveInfo, bool& hasAsset) +std::map ObjectStoreManager::GetObjectData(const ObjectRecord& changedData, + SaveInfo& saveInfo, bool& hasAsset) { - std::map>> data; + std::map data; std::string keyPrefix = saveInfo.ToPropertyPrefix(); if (!keyPrefix.empty()) { std::string observerKey = saveInfo.bundleName + saveInfo.sessionId; @@ -465,7 +460,7 @@ std::map>> ObjectStoreMa } void ObjectStoreManager::ComputeStatus(const std::string& objectKey, const SaveInfo& saveInfo, - const std::map>>& data) + const std::map& data) { restoreStatus_.Compute(objectKey, [this, &data, saveInfo] (const auto &key, auto &value) { if (value == RestoreStatus::ASSETS_READY) { @@ -490,8 +485,7 @@ void ObjectStoreManager::ComputeStatus(const std::string& objectKey, const SaveI }); } -void ObjectStoreManager::NotifyDataChanged( - const std::map>>& data, const SaveInfo& saveInfo) +void ObjectStoreManager::NotifyDataChanged(const std::map& data, const SaveInfo& saveInfo) { for (auto const& [objectKey, results] : data) { restoreStatus_.ComputeIfAbsent( @@ -503,7 +497,7 @@ void ObjectStoreManager::NotifyDataChanged( } int32_t ObjectStoreManager::WaitAssets(const std::string& objectKey, const SaveInfo& saveInfo, - const std::map>>& data) + const std::map& data) { auto taskId = executors_->Schedule(std::chrono::seconds(WAIT_TIME), [this, objectKey, data, saveInfo]() { ZLOGE("wait assets finisehd timeout, try pull assets, objectKey:%{public}s", objectKey.c_str()); @@ -518,8 +512,7 @@ int32_t ObjectStoreManager::WaitAssets(const std::string& objectKey, const SaveI return OBJECT_SUCCESS; } -void ObjectStoreManager::PullAssets(const std::map>>& data, - const SaveInfo& saveInfo) +void ObjectStoreManager::PullAssets(const std::map& data, const SaveInfo& saveInfo) { std::map changedAssets; for (auto const& [objectId, result] : data) { @@ -585,8 +578,7 @@ bool ObjectStoreManager::IsAssetKey(const std::string& key) return key.find(ObjectStore::ASSET_DOT) != std::string::npos; } -bool ObjectStoreManager::IsAssetComplete(const std::map>& result, - const std::string& assetPrefix) +bool ObjectStoreManager::IsAssetComplete(const ObjectRecord& result, const std::string& assetPrefix) { if (result.find(assetPrefix + ObjectStore::NAME_SUFFIX) == result.end() || result.find(assetPrefix + ObjectStore::URI_SUFFIX) == result.end() || @@ -599,7 +591,7 @@ bool ObjectStoreManager::IsAssetComplete(const std::map>& result) +Assets ObjectStoreManager::GetAssetsFromDBRecords(const ObjectRecord& result) { Assets assets{}; std::set assetKey; @@ -639,7 +631,7 @@ Assets ObjectStoreManager::GetAssetsFromDBRecords(const std::map>>& data, bool allReady) + const std::map& data, bool allReady) { for (const auto& observer : value.observers_) { auto it = data.find(observer.first); @@ -667,7 +659,7 @@ void ObjectStoreManager::DoNotifyAssetsReady(uint32_t tokenId, const CallbackInf if (objectKey != observer.first) { continue; } - observer.second->Completed(std::map>(), allReady); + observer.second->Completed(ObjectRecord(), allReady); if (allReady) { restoreStatus_.Erase(objectKey); ObjectStore::RadarReporter::ReportStateFinished(std::string(__FUNCTION__), ObjectStore::DATA_RESTORE, @@ -690,7 +682,7 @@ void ObjectStoreManager::DoNotifyWaitAssetTimeout(const std::string &objectKey) if (objectKey != observer.first) { continue; } - observer.second->Completed(std::map>(), true); + observer.second->Completed(ObjectRecord(), true); restoreStatus_.Erase(objectKey); auto [has, taskId] = objectTimer_.Find(objectKey); if (has) { @@ -717,21 +709,21 @@ void ObjectStoreManager::SetData(const std::string &dataDir, const std::string & int32_t ObjectStoreManager::Open() { if (kvStoreDelegateManager_ == nullptr) { - ZLOGE("not init"); + ZLOGE("Kvstore delegate manager not init"); return OBJECT_INNER_ERROR; } std::lock_guard lock(kvStoreMutex_); if (delegate_ == nullptr) { - ZLOGI("open store"); delegate_ = OpenObjectKvStore(); if (delegate_ == nullptr) { - ZLOGE("open failed,please check DB status"); + ZLOGE("Open object kvstore failed"); return OBJECT_DBSTATUS_ERROR; } syncCount_ = 1; + ZLOGI("Open object kvstore success"); } else { syncCount_++; - ZLOGI("syncCount = %{public}d", syncCount_); + ZLOGI("Object kvstore syncCount: %{public}d", syncCount_); } return OBJECT_SUCCESS; } @@ -765,11 +757,11 @@ void ObjectStoreManager::SyncCompleted( } for (const auto &item : results) { if (item.second == DistributedDB::DBStatus::OK) { - ZLOGI("Sync success, sequenceId: 0x%{public}" PRIx64 "", sequenceId); + ZLOGI("Sync data success, sequenceId: 0x%{public}" PRIx64 "", sequenceId); ObjectStore::RadarReporter::ReportStateFinished(std::string(__FUNCTION__), ObjectStore::SAVE, ObjectStore::SYNC_DATA, ObjectStore::RADAR_SUCCESS, ObjectStore::FINISHED); } else { - ZLOGE("Sync failed, sequenceId: 0x%{public}" PRIx64 ", status: %{public}d", sequenceId, item.second); + ZLOGE("Sync data failed, sequenceId: 0x%{public}" PRIx64 ", status: %{public}d", sequenceId, item.second); ObjectStore::RadarReporter::ReportStateError(std::string(__FUNCTION__), ObjectStore::SAVE, ObjectStore::SYNC_DATA, ObjectStore::RADAR_FAILED, item.second, ObjectStore::FINISHED); } @@ -802,11 +794,14 @@ void ObjectStoreManager::ProcessOldEntry(const std::string &appId) { std::vector entries; auto status = delegate_->GetEntries(std::vector(appId.begin(), appId.end()), entries); + if (status != DistributedDB::DBStatus::NOT_FOUND) { + ZLOGI("Get old entries empty, bundleName: %{public}s", appId.c_str()); + return; + } if (status != DistributedDB::DBStatus::OK) { - ZLOGE("GetEntries fail %{public}d", status); + ZLOGE("Get old entries failed, bundleName: %{public}s, status %{public}d", appId.c_str(), status); return; } - std::map sessionIds; int64_t oldestTime = 0; std::string deleteKey; @@ -830,40 +825,45 @@ void ObjectStoreManager::ProcessOldEntry(const std::string &appId) if (sessionIds.size() < MAX_OBJECT_SIZE_PER_APP) { return; } - ZLOGI("app object is full, delete oldest one %{public}s", deleteKey.c_str()); int32_t result = RevokeSaveToStore(deleteKey); if (result != OBJECT_SUCCESS) { - ZLOGE("RevokeSaveToStore fail %{public}d", result); + ZLOGE("Delete old entries failed, deleteKey: %{public}s, status: %{public}d", deleteKey.c_str(), result); return; } + ZLOGI("Delete old entries success, deleteKey: %{public}s", deleteKey.c_str()); } int32_t ObjectStoreManager::SaveToStore(const std::string &appId, const std::string &sessionId, - const std::string &toDeviceId, const std::map> &data) + const std::string &toDeviceId, const ObjectRecord &data) { ProcessOldEntry(appId); RevokeSaveToStore(GetPropertyPrefix(appId, sessionId, toDeviceId)); std::string timestamp = std::to_string(GetSecondsSince1970ToNow()); - std::vector entries; + std::string prefix = GetPropertyPrefix(appId, sessionId, toDeviceId) + timestamp + SEPERATOR; DistributedDB::Entry saveInfoEntry; - std::string saveInfoKey = GetPropertyPrefix(appId, sessionId, toDeviceId) + timestamp + SEPERATOR + SAVE_INFO; + std::string saveInfoKey = prefix + SAVE_INFO; saveInfoEntry.key = std::vector(saveInfoKey.begin(), saveInfoKey.end()); SaveInfo saveInfo(appId, sessionId, DmAdaper::GetInstance().GetLocalDevice().udid, toDeviceId, timestamp); std::string saveInfoValue = DistributedData::Serializable::Marshall(saveInfo); saveInfoEntry.value = std::vector(saveInfoValue.begin(), saveInfoValue.end()); + std::vector entries; entries.emplace_back(saveInfoEntry); for (auto &item : data) { DistributedDB::Entry entry; - std::string tmp = GetPropertyPrefix(appId, sessionId, toDeviceId) + timestamp + SEPERATOR + item.first; - entry.key = std::vector(tmp.begin(), tmp.end()); + std::string key = GetPropertyPrefix(appId, sessionId, toDeviceId) + timestamp + SEPERATOR + item.first; + entry.key = std::vector(key.begin(), key.end()); entry.value = item.second; entries.emplace_back(entry); } auto status = delegate_->PutBatch(entries); if (status != DistributedDB::DBStatus::OK) { - ZLOGE("putBatch fail %{public}d", status); + ZLOGE("PutBatch failed, bundleName: %{public}s, sessionId: %{public}s, dstNetworkId: %{public}s, " + "status: %{public}d", appId.c_str(), sessionId.c_str(), Anonymous::Change(toDeviceId).c_str(), status); + return status; } - return status; + ZLOGI("PutBatch success, bundleName: %{public}s, sessionId: %{public}s, dstNetworkId: %{public}s, " + "count: %{public}zu", appId.c_str(), sessionId.c_str(), Anonymous::Change(toDeviceId).c_str(), entries.size()); + return OBJECT_SUCCESS; } int32_t ObjectStoreManager::SyncOnStore( @@ -871,43 +871,39 @@ int32_t ObjectStoreManager::SyncOnStore( { std::vector syncDevices; for (auto &device : deviceList) { - // save to local, do not need sync if (device == LOCAL_DEVICE) { - ZLOGI("save to local successful"); - std::map result; - result[LOCAL_DEVICE] = OBJECT_SUCCESS; - callback(result); + ZLOGI("Save to local, do not need sync, prefix: %{public}s", prefix.c_str()); + callback({{LOCAL_DEVICE, OBJECT_SUCCESS}}); return OBJECT_SUCCESS; } syncDevices.emplace_back(DmAdaper::GetInstance().GetUuidByNetworkId(device)); } - if (!syncDevices.empty()) { - uint64_t sequenceId = SequenceSyncManager::GetInstance()->AddNotifier(userId_, callback); - DistributedDB::Query dbQuery = DistributedDB::Query::Select(); - dbQuery.PrefixKey(std::vector(prefix.begin(), prefix.end())); - ZLOGI("Start sync, sequenceId: 0x%{public}" PRIx64 "", sequenceId); - auto status = delegate_->Sync( - syncDevices, DistributedDB::SyncMode::SYNC_MODE_PUSH_ONLY, - [this, sequenceId](const std::map &devicesMap) { - ZLOGI("objectstore sync finished"); - std::map result; - for (auto &item : devicesMap) { - result[DmAdaper::GetInstance().ToNetworkID(item.first)] = item.second; - } - SyncCompleted(result, sequenceId); - }, - dbQuery, false); - if (status != DistributedDB::DBStatus::OK) { - ZLOGE("sync error %{public}d", status); - std::string tmp; - SequenceSyncManager::GetInstance()->DeleteNotifier(sequenceId, tmp); - return status; - } - SetSyncStatus(true); - } else { - ZLOGI("single device"); + if (syncDevices.empty()) { + ZLOGI("Device list is empty, prefix: %{public}s", Anonymous::Change(prefix).c_str()); callback(std::map()); + return OBJECT_SUCCESS; } + uint64_t sequenceId = SequenceSyncManager::GetInstance()->AddNotifier(userId_, callback); + DistributedDB::Query dbQuery = DistributedDB::Query::Select(); + dbQuery.PrefixKey(std::vector(prefix.begin(), prefix.end())); + ZLOGI("Start sync data, sequenceId: 0x%{public}" PRIx64 "", sequenceId); + auto status = delegate_->Sync(syncDevices, DistributedDB::SyncMode::SYNC_MODE_PUSH_ONLY, + [this, sequenceId](const std::map &devicesMap) { + ZLOGI("Sync data finished, sequenceId: 0x%{public}" PRIx64 "", sequenceId); + std::map result; + for (auto &item : devicesMap) { + result[DmAdaper::GetInstance().ToNetworkID(item.first)] = item.second; + } + SyncCompleted(result, sequenceId); + }, dbQuery, false); + if (status != DistributedDB::DBStatus::OK) { + ZLOGE("Sync data failed, prefix: %{public}s, sequenceId: 0x%{public}" PRIx64 ", status: %{public}d", + Anonymous::Change(prefix).c_str(), sequenceId, status); + std::string tmp; + SequenceSyncManager::GetInstance()->DeleteNotifier(sequenceId, tmp); + return status; + } + SetSyncStatus(true); return OBJECT_SUCCESS; } @@ -923,41 +919,46 @@ int32_t ObjectStoreManager::RevokeSaveToStore(const std::string &prefix) std::vector entries; auto status = delegate_->GetEntries(std::vector(prefix.begin(), prefix.end()), entries); if (status == DistributedDB::DBStatus::NOT_FOUND) { - ZLOGI("not found entry"); + ZLOGI("Get entries empty, prefix: %{public}s", Anonymous::Change(prefix).c_str()); return OBJECT_SUCCESS; } if (status != DistributedDB::DBStatus::OK) { - ZLOGE("GetEntries failed, status = %{public}d", status); + ZLOGE("Get entries failed, prefix: %{public}s, status: %{public}d", Anonymous::Change(prefix).c_str(), status); return DB_ERROR; } std::vector> keys; - std::for_each( - entries.begin(), entries.end(), [&keys](const DistributedDB::Entry &entry) { keys.emplace_back(entry.key); }); - if (!keys.empty()) { - status = delegate_->DeleteBatch(keys); - if (status != DistributedDB::DBStatus::OK) { - ZLOGE("DeleteBatch failed, status = %{public}d", status); - return DB_ERROR; - } + std::for_each(entries.begin(), entries.end(), [&keys](const DistributedDB::Entry &entry) { + keys.emplace_back(entry.key); + }); + if (keys.empty()) { + return OBJECT_SUCCESS; + } + status = delegate_->DeleteBatch(keys); + if (status != DistributedDB::DBStatus::OK) { + ZLOGE("Delete entries failed, prefix: %{public}s, status: %{public}d", Anonymous::Change(prefix).c_str(), + status); + return DB_ERROR; } + ZLOGI("Delete entries success, prefix: %{public}s, count: %{public}zu", Anonymous::Change(prefix).c_str(), + keys.size()); return OBJECT_SUCCESS; } -int32_t ObjectStoreManager::RetrieveFromStore( - const std::string &appId, const std::string &sessionId, std::map> &results) +int32_t ObjectStoreManager::RetrieveFromStore(const std::string &appId, const std::string &sessionId, + ObjectRecord &results) { std::vector entries; std::string prefix = GetPrefixWithoutDeviceId(appId, sessionId); auto status = delegate_->GetEntries(std::vector(prefix.begin(), prefix.end()), entries); if (status == DistributedDB::DBStatus::NOT_FOUND) { - ZLOGW("key not found, status = %{public}d", status); + ZLOGI("Get entries empty, prefix: %{public}s, status: %{public}d", prefix.c_str(), status); return KEY_NOT_FOUND; } if (status != DistributedDB::DBStatus::OK) { - ZLOGE("GetEntries failed, status = %{public}d", status); + ZLOGE("Get entries failed, prefix: %{public}s, status: %{public}d", prefix.c_str(), status); return DB_ERROR; } - ZLOGI("GetEntries successfully"); + ZLOGI("Get entries success, prefix: %{public}s, count: %{public}zu", prefix.c_str(), entries.size()); for (const auto &entry : entries) { std::string key(entry.key.begin(), entry.key.end()); if (key.find(SAVE_INFO) != std::string::npos) { diff --git a/datamgr_service/services/distributeddataservice/service/object/object_manager.h b/datamgr_service/services/distributeddataservice/service/object/object_manager.h index e927912387a4edeba01b472d4841207b5eae8455..c750c61345f125e0c4396d03a3a59238cc9ba184 100644 --- a/datamgr_service/services/distributeddataservice/service/object/object_manager.h +++ b/datamgr_service/services/distributeddataservice/service/object/object_manager.h @@ -34,7 +34,7 @@ namespace OHOS { namespace DistributedObject { using SyncCallBack = std::function &results)>; - +using ObjectRecord = std::map>; class SequenceSyncManager { public: enum Result { @@ -81,22 +81,21 @@ public: static ObjectStoreManager *manager = new ObjectStoreManager(); return manager; } - int32_t Save(const std::string &appId, const std::string &sessionId, - const std::map> &data, const std::string &deviceId, - sptr callback); + int32_t Save(const std::string &appId, const std::string &sessionId, const ObjectRecord &data, + const std::string &deviceId, sptr callback); int32_t RevokeSave( const std::string &appId, const std::string &sessionId, sptr callback); int32_t Retrieve(const std::string &bundleName, const std::string &sessionId, sptr callback, uint32_t tokenId); void SetData(const std::string &dataDir, const std::string &userId); int32_t Clear(); - int32_t DeleteByAppId(const std::string &appId); + int32_t DeleteByAppId(const std::string &appId, int32_t user); void RegisterRemoteCallback(const std::string &bundleName, const std::string &sessionId, pid_t pid, uint32_t tokenId, sptr callback); void UnregisterRemoteCallback(const std::string &bundleName, pid_t pid, uint32_t tokenId, const std::string &sessionId = ""); - void NotifyChange(std::map> &changedData); + void NotifyChange(ObjectRecord &changedData); void NotifyAssetsReady(const std::string& objectKey, const std::string& bundleName, const std::string& srcNetworkId = ""); void NotifyAssetsStart(const std::string& objectKey, const std::string& srcNetworkId = ""); @@ -153,11 +152,10 @@ private: void Close(); int32_t SetSyncStatus(bool status); int32_t SaveToStore(const std::string &appId, const std::string &sessionId, const std::string &toDeviceId, - const std::map> &data); + const ObjectRecord &data); int32_t SyncOnStore(const std::string &prefix, const std::vector &deviceList, SyncCallBack &callback); int32_t RevokeSaveToStore(const std::string &prefix); - int32_t RetrieveFromStore( - const std::string &appId, const std::string &sessionId, std::map> &results); + int32_t RetrieveFromStore(const std::string &appId, const std::string &sessionId, ObjectRecord &results); void SyncCompleted(const std::map &results, uint64_t sequenceId); std::vector SplitEntryKey(const std::string &key); void ProcessOldEntry(const std::string &appId); @@ -165,30 +163,25 @@ private: const std::string &sessionId, const std::string &deviceId); void SaveUserToMeta(); std::string GetCurrentUser(); - void DoNotify(uint32_t tokenId, const CallbackInfo& value, - const std::map>>& data, bool allReady); + void DoNotify(uint32_t tokenId, const CallbackInfo& value, const std::map& data, + bool allReady); void DoNotifyAssetsReady(uint32_t tokenId, const CallbackInfo& value, const std::string& objectKey, bool allReady); void DoNotifyWaitAssetTimeout(const std::string &objectKey); - std::map> GetAssetsFromStore( - const std::map>& changedData); + std::map> GetAssetsFromStore(const ObjectRecord& changedData); static bool IsAssetKey(const std::string& key); - static bool IsAssetComplete(const std::map>& result, - const std::string& assetPrefix); - Assets GetAssetsFromDBRecords(const std::map>& result); + static bool IsAssetComplete(const ObjectRecord& result, const std::string& assetPrefix); + Assets GetAssetsFromDBRecords(const ObjectRecord& result); bool RegisterAssetsLister(); void ComputeStatus(const std::string& objectKey, const SaveInfo& saveInfo, - const std::map>>& data); - void NotifyDataChanged(const std::map>>& data, - const SaveInfo& saveInfo); - int32_t PushAssets(int32_t userId, const std::string &appId, const std::string &sessionId, - const std::map> &data, const std::string &deviceId); + const std::map& data); + void NotifyDataChanged(const std::map& data, const SaveInfo& saveInfo); + int32_t PushAssets(const std::string &srcBundleName, const std::string &dstBundleName, const std::string &sessionId, + const ObjectRecord &data, const std::string &deviceId); int32_t WaitAssets(const std::string& objectKey, const SaveInfo& saveInfo, - const std::map>>& data); - void PullAssets(const std::map>>& data, - const SaveInfo& saveInfo); - std::map>> GetObjectData( - const std::map>& changedData, SaveInfo& saveInfo, bool& hasAsset); - + const std::map& data); + void PullAssets(const std::map& data, const SaveInfo& saveInfo); + std::map GetObjectData(const ObjectRecord& changedData, SaveInfo& saveInfo, + bool& hasAsset); inline std::string GetPropertyPrefix(const std::string &appId, const std::string &sessionId) { return appId + SEPERATOR + sessionId + SEPERATOR + DmAdaper::GetInstance().GetLocalDevice().udid + SEPERATOR; diff --git a/datamgr_service/services/distributeddataservice/service/object/object_service_impl.cpp b/datamgr_service/services/distributeddataservice/service/object/object_service_impl.cpp index a47b74864043cb67113fd50b1ab15d35cad95ebf..1a3182fcc1d9f9496b05f47436c54913c8cb2976 100644 --- a/datamgr_service/services/distributeddataservice/service/object/object_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/object/object_service_impl.cpp @@ -44,7 +44,6 @@ using StoreMetaData = OHOS::DistributedData::StoreMetaData; using FeatureSystem = OHOS::DistributedData::FeatureSystem; using DumpManager = OHOS::DistributedData::DumpManager; __attribute__((used)) ObjectServiceImpl::Factory ObjectServiceImpl::factory_; -constexpr const char *PKG_NAME = "ohos.distributeddata.service"; ObjectServiceImpl::Factory::Factory() { FeatureSystem::GetInstance().RegisterCreator( @@ -122,10 +121,7 @@ int32_t ObjectServiceImpl::IsContinue(bool &result) ZLOGE("Get hap token info failed, tokenId: %{public}u, status: %{public}d", tokenId, status); return status; } - DistributedHardware::DmDeviceInfo info; - DistributedHardware::DeviceManager::GetInstance().GetLocalDeviceInfo(PKG_NAME, info); - std::string networkId = info.networkId; - result = ObjectDmsHandler::GetInstance().IsContinue(networkId, tokenInfo.bundleName); + result = ObjectDmsHandler::GetInstance().IsContinue(tokenInfo.bundleName); return OBJECT_SUCCESS; } @@ -288,13 +284,14 @@ void ObjectServiceImpl::Clear() int32_t ObjectServiceImpl::ObjectStatic::OnAppUninstall(const std::string &bundleName, int32_t user, int32_t index) { - ZLOGI("begin. %{public}s", bundleName.c_str()); - int32_t result = ObjectStoreManager::GetInstance()->DeleteByAppId(bundleName); + int32_t result = ObjectStoreManager::GetInstance()->DeleteByAppId(bundleName, user); if (result != OBJECT_SUCCESS) { - pid_t uid = IPCSkeleton::GetCallingUid(); - ZLOGE("Delete fail %{public}d, bundleName = %{public}s, uid = %{public}d", - result, bundleName.c_str(), uid); + ZLOGE("Delete object data failed, result:%{public}d, bundleName:%{public}s, user:%{public}d, index:%{public}d", + result, bundleName.c_str(), user, index); + return result; } + ZLOGI("Delete object data, bundleName:%{public}s, userId:%{public}d, index:%{public}d", bundleName.c_str(), user, + index); return result; } diff --git a/datamgr_service/services/distributeddataservice/service/object/object_snapshot.cpp b/datamgr_service/services/distributeddataservice/service/object/object_snapshot.cpp index 29c7fc8729957038fbe497181eb10dc03cf522fb..14775b73024ecf4f9c78c89c7e57ef2ab62a4393 100644 --- a/datamgr_service/services/distributeddataservice/service/object/object_snapshot.cpp +++ b/datamgr_service/services/distributeddataservice/service/object/object_snapshot.cpp @@ -85,7 +85,7 @@ int32_t ObjectSnapshot::BindAsset(const Asset& asset, const DistributedData::Ass const StoreInfo& storeInfo) { if (IsBoundAsset(asset)) { - ZLOGD("Asset is bound. asset.uri:%{public}s :", Anonymous::Change(asset.uri, true).c_str()); + ZLOGD("Asset is bound. asset.uri:%{public}s :", Anonymous::Change(asset.uri).c_str()); return E_OK; } changedAssets_[asset.uri] = ChangedAssetInfo(asset, bindInfo, storeInfo); diff --git a/datamgr_service/services/distributeddataservice/service/rdb/cache_cursor.cpp b/datamgr_service/services/distributeddataservice/service/rdb/cache_cursor.cpp index 1bbdcf07d14f24e7d42092c36c2a33e01c6b6937..4c3b04d3ce9d2602735adcf60d3ffd68b4e04efe 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/cache_cursor.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/cache_cursor.cpp @@ -14,6 +14,7 @@ */ #include "cache_cursor.h" + #include "value_proxy.h" namespace OHOS::DistributedRdb { diff --git a/datamgr_service/services/distributeddataservice/service/rdb/cache_cursor.h b/datamgr_service/services/distributeddataservice/service/rdb/cache_cursor.h index d18607a055823856f341f0fd06e4616030e38211..3b783359123b89bf248c8fe40d676dff6190bbea 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/cache_cursor.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/cache_cursor.h @@ -46,4 +46,3 @@ private: }; } // namespace OHOS::DistributedRdb #endif // OHOS_DISTRIBUTED_DATA_DATAMGR_SERVICE_CACHE_CURSOR_H - 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 76e73a0b844f123ecf629bd510dc80d00f262f1f..5c24452365e3de3d7d3a21dfd4c724a2cc89fce9 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_asset_loader.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_asset_loader.h @@ -16,11 +16,11 @@ #ifndef OHOS_DISTRIBUTED_DATA_DATAMGR_SERVICE_RDB_ASSET_LOADER_H #define OHOS_DISTRIBUTED_DATA_DATAMGR_SERVICE_RDB_ASSET_LOADER_H -#include "snapshot/snapshot.h" #include "cloud/asset_loader.h" #include "cloud/cloud_store_types.h" #include "cloud/iAssetLoader.h" #include "error/general_error.h" +#include "snapshot/snapshot.h" namespace OHOS::DistributedRdb { class RdbAssetLoader : public DistributedDB::IAssetLoader { diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_cloud.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_cloud.cpp index 096d3fc638ac2b81f9eadbdde288b26e16e9e1c0..a26a6dbf73bbb8905eaf518168ab59247c33f532 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_cloud.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_cloud.cpp @@ -20,8 +20,8 @@ #include "log_print.h" #include "rdb_query.h" #include "relational_store_manager.h" -#include "value_proxy.h" #include "utils/anonymous.h" +#include "value_proxy.h" namespace OHOS::DistributedRdb { using namespace DistributedDB; @@ -345,4 +345,12 @@ void RdbCloud::ConvertErrorField(DistributedData::VBuckets& extends) errorField->second = ConvertStatus(static_cast(*errCode)); } } + +void RdbCloud::SetPrepareTraceId(const std::string &traceId) +{ + if (cloudDB_ == nullptr) { + return; + } + cloudDB_->SetPrepareTraceId(traceId); +} } // namespace OHOS::DistributedRdb \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_cloud.h b/datamgr_service/services/distributeddataservice/service/rdb/rdb_cloud.h index 0478110cb0a2cfacfe8d3cbf0b6c4bd291c45735..ac93e253d3c22618ea75faad8164d3b935bbbda9 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_cloud.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_cloud.h @@ -56,6 +56,7 @@ public: uint8_t GetLockFlag() const; std::pair LockCloudDB(FLAG flag); GeneralError UnLockCloudDB(FLAG flag); + void SetPrepareTraceId(const std::string &traceId) override; private: static constexpr const char *TYPE_FIELD = "#_type"; diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_cloud_data_translate.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_cloud_data_translate.cpp index 833474bd410f5f8f0d8cb55bf1e5b33447f22b8e..6f4723c4f3325fd6961f811f3ad38d2b200c074c 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_cloud_data_translate.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_cloud_data_translate.cpp @@ -23,7 +23,7 @@ using Asset = DistributedDB::Asset; using Assets = DistributedDB::Assets; using DataAsset = NativeRdb::ValueObject::Asset; using DataAssets = NativeRdb::ValueObject::Assets; -using ValueProxy = DistributedData::ValueProxy; +using ValueProxy = DistributedData::ValueProxy; std::vector RdbCloudDataTranslate::AssetToBlob(const Asset &asset) { std::vector rawData; diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_cursor.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_cursor.cpp index afa0c82728956a262b1b3b6eebf0e6c64e67291b..a8a70919314a1c098849ad1dd6a4d55211af9f94 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_cursor.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_cursor.cpp @@ -16,15 +16,12 @@ #include "rdb_cursor.h" #include "result_set.h" -#include "value_proxy.h" #include "store_types.h" +#include "value_proxy.h" namespace OHOS::DistributedRdb { using namespace OHOS::DistributedData; using namespace DistributedDB; -RdbCursor::RdbCursor(std::shared_ptr resultSet) - : resultSet_(std::move(resultSet)) -{ -} +RdbCursor::RdbCursor(std::shared_ptr resultSet) : resultSet_(std::move(resultSet)) {} RdbCursor::~RdbCursor() { diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_cursor.h b/datamgr_service/services/distributeddataservice/service/rdb/rdb_cursor.h index 3aa01820b162a4913fbf7e7610375e7952f44336..adb54af8273d6c017d3fba73ece2463cbd7f1605 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_cursor.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_cursor.h @@ -15,8 +15,8 @@ #ifndef OHOS_DISTRIBUTED_DATA_DATAMGR_SERVICE_RDB_CURSOR_H #define OHOS_DISTRIBUTED_DATA_DATAMGR_SERVICE_RDB_CURSOR_H -#include "store/cursor.h" #include "distributeddb/result_set.h" +#include "store/cursor.h" namespace OHOS::DistributedRdb { class RdbCursor : public DistributedData::Cursor { public: 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 c4866bfe8363726e39b6b945766c55ca5f4635d1..c326a86d3f3a279349ab110c519255596414505e 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.cpp @@ -59,9 +59,9 @@ constexpr const char *INSERT = "INSERT INTO "; constexpr const char *REPLACE = "REPLACE INTO "; constexpr const char *VALUES = " VALUES "; constexpr const char *LOGOUT_DELETE_FLAG = "DELETE#ALL_CLOUDDATA"; -constexpr const LockAction LOCK_ACTION = static_cast(static_cast(LockAction::INSERT) | - static_cast(LockAction::UPDATE) | static_cast(LockAction::DELETE) | - static_cast(LockAction::DOWNLOAD)); +constexpr const LockAction LOCK_ACTION = + static_cast(static_cast(LockAction::INSERT) | static_cast(LockAction::UPDATE) | + static_cast(LockAction::DELETE) | static_cast(LockAction::DOWNLOAD)); constexpr uint32_t CLOUD_SYNC_FLAG = 1; constexpr uint32_t SEARCHABLE_FLAG = 2; constexpr uint32_t LOCK_TIMEOUT = 3600; // second @@ -198,7 +198,7 @@ int32_t RdbGeneralStore::Bind(Database &database, const std::map lock(rwMutex_); + std::shared_lock lock(rwMutex_); if (delegate_ == nullptr) { ZLOGE("database:%{public}s already closed!", Anonymous::Change(database.name).c_str()); return GeneralError::E_ALREADY_CLOSED; @@ -517,14 +517,13 @@ int32_t RdbGeneralStore::Sync(const Devices &devices, GenQuery &query, DetailAsy } else if (syncMode > NEARBY_END && syncMode < CLOUD_END) { auto callback = GetDBProcessCB(std::move(async), syncMode, syncId, highMode); if (executor_ != nullptr && tasks_ != nullptr) { - auto id = executor_->Schedule(GetFinishTask(syncId), std::chrono::minutes(INTERVAL), - std::chrono::minutes(INTERVAL)); + auto id = executor_->Schedule(std::chrono::minutes(INTERVAL), GetFinishTask(syncId)); tasks_->Insert(syncId, { id, callback }); } - dbStatus = - delegate_->Sync({ devices, dbMode, dbQuery, syncParam.wait, (isPriority || highMode == MANUAL_SYNC_MODE), - syncParam.isCompensation, {}, highMode == AUTO_SYNC_MODE, LOCK_ACTION }, - tasks_ != nullptr ? GetCB(syncId) : callback, syncId); + dbStatus = delegate_->Sync({ devices, dbMode, dbQuery, syncParam.wait, + (isPriority || highMode == MANUAL_SYNC_MODE), syncParam.isCompensation, {}, + highMode == AUTO_SYNC_MODE, LOCK_ACTION, syncParam.prepareTraceId }, + tasks_ != nullptr ? GetCB(syncId) : callback, syncId); if (dbStatus == DBStatus::OK || tasks_ == nullptr) { return ConvertStatus(dbStatus); } @@ -812,8 +811,8 @@ int32_t RdbGeneralStore::SetDistributedTables(const std::vector &ta return GeneralError::E_OK; } -int32_t RdbGeneralStore::SetTrackerTable( - const std::string &tableName, const std::set &trackerColNames, const std::string &extendColName) +int32_t RdbGeneralStore::SetTrackerTable(const std::string &tableName, const std::set &trackerColNames, + const std::string &extendColName, bool isForceUpgrade) { std::shared_lock lock(rwMutex_); if (delegate_ == nullptr) { @@ -821,7 +820,7 @@ int32_t RdbGeneralStore::SetTrackerTable( Anonymous::Change(storeInfo_.storeName).c_str(), Anonymous::Change(tableName).c_str()); return GeneralError::E_ALREADY_CLOSED; } - auto status = delegate_->SetTrackerTable({ tableName, extendColName, trackerColNames }); + auto status = delegate_->SetTrackerTable({ tableName, extendColName, trackerColNames, isForceUpgrade }); if (status == DBStatus::WITH_INVENTORY_DATA) { ZLOGI("Set tracker table with inventory data, database:%{public}s, tables name:%{public}s", Anonymous::Change(storeInfo_.storeName).c_str(), Anonymous::Change(tableName).c_str()); @@ -963,7 +962,8 @@ std::vector RdbGeneralStore::GetIntersection(std::vector res; for (auto &it : syncTables) { - if (localTables.count(it)) { + if (localTables.count(it) && + localTables.count(RelationalStoreManager::GetDistributedLogTableName(it))) { res.push_back(std::move(it)); } } @@ -1085,21 +1085,27 @@ bool RdbGeneralStore::IsFinished(SyncId syncId) const Executor::Task RdbGeneralStore::GetFinishTask(SyncId syncId) { - return [this, syncId]() { + return [this, executor = executor_, task = tasks_, syncId]() { + auto [exist, finishTask] = task->Find(syncId); + if (!exist || finishTask.cb == nullptr) { + task->Erase(syncId); + return; + } if (!IsFinished(syncId)) { + task->ComputeIfPresent(syncId, [executor = executor_, this](SyncId syncId, FinishTask &task) { + task.taskId = executor->Schedule(std::chrono::minutes(INTERVAL), GetFinishTask(syncId)); + return true; + }); return; } DBProcessCB cb; - ZLOGW("database:%{public}s syncId:%{public}" PRIu64 " miss finished. ", - Anonymous::Change(storeInfo_.storeName).c_str(), syncId); - tasks_->ComputeIfPresent(syncId, [&cb, executor = executor_](SyncId syncId, const FinishTask &task) { + task->ComputeIfPresent(syncId, [&cb, executor = executor_](SyncId syncId, const FinishTask &task) { cb = task.cb; - if (executor != nullptr) { - executor->Remove(task.taskId); - } return false; }); if (cb != nullptr) { + ZLOGW("database:%{public}s syncId:%{public}" PRIu64 " miss finished. ", + Anonymous::Change(storeInfo_.storeName).c_str(), syncId); std::map result; result.insert({ "", { DistributedDB::FINISHED, DBStatus::DB_ERROR } }); cb(result); @@ -1120,16 +1126,21 @@ void RdbGeneralStore::RemoveTasks() return; } std::list cbs; - tasks_->ForEach([&cbs, executor = executor_, store = storeInfo_.storeName](SyncId syncId, const FinishTask &task) { - cbs.push_back(std::move(task.cb)); - ZLOGW("database:%{public}s syncId:%{public}" PRIu64 " miss finished. ", - Anonymous::Change(store).c_str(), syncId); - if (executor != nullptr) { - executor->Remove(task.taskId); + std::list taskIds; + tasks_->EraseIf([&cbs, &taskIds, store = storeInfo_.storeName](SyncId syncId, const FinishTask &task) { + if (task.cb != nullptr) { + ZLOGW("database:%{public}s syncId:%{public}" PRIu64 " miss finished. ", Anonymous::Change(store).c_str(), + syncId); } - return false; + cbs.push_back(std::move(task.cb)); + taskIds.push_back(task.taskId); + return true; }); - tasks_->Clear(); + if (executor_ != nullptr) { + for (auto taskId : taskIds) { + executor_->Remove(taskId, true); + } + } std::map result; result.insert({ "", { DistributedDB::FINISHED, DBStatus::DB_ERROR } }); for (auto &cb : cbs) { @@ -1146,13 +1157,13 @@ RdbGeneralStore::DBProcessCB RdbGeneralStore::GetCB(SyncId syncId) return; } DBProcessCB cb; - task->ComputeIfPresent(syncId, [&cb, &progress, executor](SyncId syncId, const FinishTask &finishTask) { + task->ComputeIfPresent(syncId, [&cb, &progress, executor](SyncId syncId, FinishTask &finishTask) { cb = finishTask.cb; bool isFinished = !progress.empty() && progress.begin()->second.process == DistributedDB::FINISHED; - if (isFinished && executor != nullptr) { - executor->Remove(finishTask.taskId); + if (isFinished) { + finishTask.cb = nullptr; } - return !isFinished; + return true; }); if (cb != nullptr) { cb(progress); 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 f096b6c31f111f87865242a6aef944a101c3d102..b61d01c6609cb9fc4f6ad7735d2803e581ea32a3 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.h @@ -26,9 +26,9 @@ #include "rdb_store.h" #include "relational_store_delegate.h" #include "relational_store_manager.h" +#include "snapshot/snapshot.h" #include "store/general_store.h" #include "store/general_value.h" -#include "snapshot/snapshot.h" namespace OHOS::DistributedRdb { class RdbGeneralStore : public DistributedData::GeneralStore { public: @@ -62,7 +62,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) 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; diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_notifier_proxy.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_notifier_proxy.cpp index ceb200a3777656b880950fe6c4925d6974b44caa..517a9ec789f48afabdac5f185ba61a2d1be51006 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_notifier_proxy.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_notifier_proxy.cpp @@ -14,19 +14,16 @@ */ #define LOG_TAG "RdbNotifierProxy" #include "rdb_notifier_proxy.h" + #include "itypes_util.h" #include "log_print.h" #include "utils/anonymous.h" namespace OHOS::DistributedRdb { using NotifierIFCode = RelationalStore::IRdbNotifierInterfaceCode; -RdbNotifierProxy::RdbNotifierProxy(const sptr &object) : IRemoteProxy(object) -{ -} +RdbNotifierProxy::RdbNotifierProxy(const sptr &object) : IRemoteProxy(object) {} -RdbNotifierProxy::~RdbNotifierProxy() noexcept -{ -} +RdbNotifierProxy::~RdbNotifierProxy() noexcept {} int32_t RdbNotifierProxy::OnComplete(uint32_t seqNum, Details &&result) { diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_notifier_proxy.h b/datamgr_service/services/distributeddataservice/service/rdb/rdb_notifier_proxy.h index d9b1d66a745539da6c4bfbae157627e28df82269..cad4e24f221971f780f9f24131ddf934968a3a10 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_notifier_proxy.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_notifier_proxy.h @@ -17,6 +17,7 @@ #define OHOS_DISTRIBUTED_DATA_KV_STORE_FRAMEWORKS_INNERKITSIMPL_RDB_RDB_NOTIFIER_PROXY_H #include #include + #include "rdb_notifier.h" namespace OHOS::DistributedRdb { class RdbNotifierProxyBroker : public IRdbNotifier, public IRemoteBroker { diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_query.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_query.cpp index 28a85ff8a6d653735f1678320abdff5102b4dc62..5c47d453478811cc63f4bff77f31078afda4ff7b 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_query.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_query.cpp @@ -14,6 +14,7 @@ */ #define LOG_TAG "RdbQuery" #include "rdb_query.h" + #include "log_print.h" #include "utils/anonymous.h" #include "value_proxy.h" @@ -29,7 +30,7 @@ std::vector RdbQuery::GetTables() return tables_; } -void RdbQuery::MakeRemoteQuery(const std::string& devices, const std::string& sql, Values&& args) +void RdbQuery::MakeRemoteQuery(const std::string &devices, const std::string &sql, Values &&args) { isRemote_ = true; devices_ = { devices }; diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_query.h b/datamgr_service/services/distributeddataservice/service/rdb/rdb_query.h index 22346b9c424516d34e198760f84428879e5fa8aa..bf8cd381aa6a44842cb0229d76cffa2a47719d3a 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_query.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_query.h @@ -15,19 +15,17 @@ #ifndef OHOS_DISTRIBUTED_DATA_DATAMGR_SERVICE_RDB_QUERY_H #define OHOS_DISTRIBUTED_DATA_DATAMGR_SERVICE_RDB_QUERY_H +#include "query.h" #include "rdb_predicates.h" #include "store/general_value.h" #include "store_types.h" -#include "query.h" namespace OHOS::DistributedRdb { class RdbQuery : public DistributedData::GenQuery { public: using Predicates = NativeRdb::RdbPredicates; static constexpr uint64_t TYPE_ID = 0x20000001; RdbQuery() = default; - ~RdbQuery() override = default; - bool IsEqual(uint64_t tid) override; std::vector GetTables() override; void SetQueryNodes(const std::string& tableName, DistributedData::QueryNodes&& nodes) override; diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_result_set_impl.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_result_set_impl.cpp index 8fd00e9cd1938c055dc3e85b08539286573cdc14..f6e7d4dd5658db2f2988eac85851cadd4391056b 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_result_set_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_result_set_impl.cpp @@ -15,11 +15,13 @@ #define LOG_TAG "RdbResultSetImpl" +#include "rdb_result_set_impl.h" + #include + #include "log_print.h" -#include "store_types.h" #include "store/cursor.h" -#include "rdb_result_set_impl.h" +#include "store_types.h" using DistributedDB::DBStatus; using OHOS::NativeRdb::ColumnType; diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_result_set_impl.h b/datamgr_service/services/distributeddataservice/service/rdb/rdb_result_set_impl.h index 49d0c9fe2941c7691f75a346e42135568d28d4ca..388bdc308016269108c0578fba61a546829c1c8a 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_result_set_impl.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_result_set_impl.h @@ -18,6 +18,7 @@ #include #include + #include "result_set.h" #include "rdb_errno.h" #include "store/cursor.h" diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_result_set_stub.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_result_set_stub.cpp index aead0cfb03d863c0d7732e35ba813b7935c013d5..06537d67c1b99c18d1f505404e3dc649ec27cb2a 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_result_set_stub.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_result_set_stub.cpp @@ -15,17 +15,19 @@ #define LOG_TAG "RdbResultSetStub" +#include "rdb_result_set_stub.h" + #include + #include "itypes_util.h" #include "log_print.h" -#include "rdb_result_set_stub.h" namespace OHOS::DistributedRdb { RdbResultSetStub::RdbResultSetStub(std::shared_ptr resultSet) : resultSet_(std::move(resultSet)) { } -int RdbResultSetStub::OnRemoteRequest(uint32_t code, MessageParcel& data, MessageParcel& reply, MessageOption& option) +int RdbResultSetStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) { ZLOGD("code:%{public}u, callingPid:%{public}d", code, IPCSkeleton::GetCallingPid()); if (!CheckInterfaceToken(data) || resultSet_ == nullptr) { 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 487b28b0c2166b92a35a20071b81e4fa034c2b77..eeb4d3795d6ee6cd9b758d79f0ce39aafe26c272 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp @@ -25,8 +25,6 @@ #include "cloud/cloud_share_event.h" #include "cloud/make_query_event.h" #include "cloud/schema_meta.h" -#include "commonevent/data_change_event.h" -#include "commonevent/set_searchable_event.h" #include "communicator/device_manager_adapter.h" #include "crypto_manager.h" #include "device_matrix.h" @@ -53,11 +51,11 @@ #include "utils/constant.h" #include "utils/converter.h" #include "xcollie.h" -using OHOS::DistributedKv::AccountDelegate; +using OHOS::DistributedData::Anonymous; using OHOS::DistributedData::CheckerManager; using OHOS::DistributedData::MetaDataManager; using OHOS::DistributedData::StoreMetaData; -using OHOS::DistributedData::Anonymous; +using OHOS::DistributedKv::AccountDelegate; using namespace OHOS::DistributedData; using namespace OHOS::Security::AccessToken; using DistributedDB::RelationalStoreManager; @@ -221,10 +219,6 @@ bool RdbServiceImpl::CheckAccess(const std::string& bundleName, const std::strin storeInfo.tokenId = IPCSkeleton::GetCallingTokenID(); storeInfo.bundleName = bundleName; storeInfo.storeId = RemoveSuffix(storeName); - auto [instanceId, user] = GetInstIndexAndUser(storeInfo.tokenId, storeInfo.bundleName); - if (instanceId != 0) { - return false; - } return !CheckerManager::GetInstance().GetAppId(storeInfo).empty(); } @@ -279,13 +273,18 @@ std::shared_ptr RdbServiceImpl::GetStore(const Rd } int32_t RdbServiceImpl::SetDistributedTables(const RdbSyncerParam ¶m, const std::vector &tables, - const std::vector &references, int32_t type) + const std::vector &references, bool isRebuild, int32_t type) { if (!CheckAccess(param.bundleName_, param.storeName_)) { ZLOGE("bundleName:%{public}s, storeName:%{public}s. Permission error", param.bundleName_.c_str(), Anonymous::Change(param.storeName_).c_str()); return RDB_ERROR; } + if (type == DistributedRdb::DistributedTableType::DISTRIBUTED_SEARCH) { + DistributedData::SetSearchableEvent::EventInfo eventInfo; + eventInfo.isRebuild = isRebuild; + return PostSearchEvent(CloudEvent::SET_SEARCH_TRIGGER, param, eventInfo); + } auto meta = GetStoreMetaData(param); if (type == DistributedRdb::DistributedTableType::DISTRIBUTED_DEVICE) { @@ -771,7 +770,7 @@ int32_t RdbServiceImpl::AfterOpen(const RdbSyncerParam ¶m) auto isCreated = MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), old, true); if (!isCreated || meta != old) { Upgrade(param, old); - ZLOGD("meta bundle:%{public}s store:%{public}s type:%{public}d->%{public}d encrypt:%{public}d->%{public}d " + ZLOGI("meta bundle:%{public}s store:%{public}s type:%{public}d->%{public}d encrypt:%{public}d->%{public}d " "area:%{public}d->%{public}d", meta.bundleName.c_str(), meta.GetStoreAlias().c_str(), old.storeType, meta.storeType, old.isEncrypt, meta.isEncrypt, old.area, meta.area); @@ -1083,15 +1082,32 @@ int32_t RdbServiceImpl::NotifyDataChange(const RdbSyncerParam ¶m, const RdbC eventInfo.tableProperties.insert_or_assign(key, std::move(tableChangeProperties)); } + if (IsPostImmediately(IPCSkeleton::GetCallingPid(), rdbNotifyConfig, storeInfo, eventInfo, param.storeName_)) { + auto evt = std::make_unique(std::move(storeInfo), std::move(eventInfo)); + EventCenter::GetInstance().PostEvent(std::move(evt)); + } + + return RDB_OK; +} + +bool RdbServiceImpl::IsPostImmediately(const int32_t callingPid, const RdbNotifyConfig &rdbNotifyConfig, + StoreInfo &storeInfo, DataChangeEvent::EventInfo &eventInfo, const std::string &storeName) +{ bool postImmediately = false; - heartbeatTaskIds_.Compute(param.storeName_, [this, &postImmediately, &rdbNotifyConfig, &storeInfo, &eventInfo] - (const std::string &key, ExecutorPool::TaskId &value) { + heartbeatTaskIds_.Compute(callingPid, [this, &postImmediately, &rdbNotifyConfig, &storeInfo, &eventInfo, + &storeName](const int32_t &key, std::map &tasks) { + auto iter = tasks.find(storeName); + ExecutorPool::TaskId taskId; + if (iter != tasks.end()) { + taskId = iter->second; + } if (rdbNotifyConfig.delay_ == 0) { - if (value != ExecutorPool::INVALID_TASK_ID && executors_ != nullptr) { - executors_->Remove(value); + if (taskId != ExecutorPool::INVALID_TASK_ID && executors_ != nullptr) { + executors_->Remove(taskId); } postImmediately = true; - return false; + tasks.erase(storeName); + return !tasks.empty(); } if (executors_ != nullptr) { @@ -1099,21 +1115,16 @@ int32_t RdbServiceImpl::NotifyDataChange(const RdbSyncerParam ¶m, const RdbC auto evt = std::make_unique(std::move(storeInfoInner), std::move(eventInfoInner)); EventCenter::GetInstance().PostEvent(std::move(evt)); }; - if (value == ExecutorPool::INVALID_TASK_ID) { - value = executors_->Schedule(std::chrono::milliseconds(rdbNotifyConfig.delay_), task); + if (taskId == ExecutorPool::INVALID_TASK_ID) { + taskId = executors_->Schedule(std::chrono::milliseconds(rdbNotifyConfig.delay_), task); } else { - value = executors_->Reset(value, std::chrono::milliseconds(rdbNotifyConfig.delay_)); + taskId = executors_->Reset(taskId, std::chrono::milliseconds(rdbNotifyConfig.delay_)); } } + tasks.insert_or_assign(storeName, taskId); return true; }); - - if (postImmediately) { - auto evt = std::make_unique(std::move(storeInfo), std::move(eventInfo)); - EventCenter::GetInstance().PostEvent(std::move(evt)); - } - - return RDB_OK; + return postImmediately; } int32_t RdbServiceImpl::SetSearchable(const RdbSyncerParam& param, bool isSearchable) @@ -1124,6 +1135,14 @@ int32_t RdbServiceImpl::SetSearchable(const RdbSyncerParam& param, bool isSearch Anonymous::Change(param.storeName_).c_str()); return RDB_ERROR; } + SetSearchableEvent::EventInfo eventInfo; + eventInfo.isSearchable = isSearchable; + return PostSearchEvent(CloudEvent::SET_SEARCHABLE, param, eventInfo); +} + +int32_t RdbServiceImpl::PostSearchEvent(int32_t evtId, const RdbSyncerParam& param, + SetSearchableEvent::EventInfo &eventInfo) +{ StoreInfo storeInfo; storeInfo.tokenId = IPCSkeleton::GetCallingTokenID(); storeInfo.bundleName = param.bundleName_; @@ -1133,11 +1152,8 @@ int32_t RdbServiceImpl::SetSearchable(const RdbSyncerParam& param, bool isSearch storeInfo.user = user; storeInfo.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; - SetSearchableEvent::EventInfo eventInfo; - eventInfo.isSearchable = isSearchable; - auto evt = std::make_unique(std::move(storeInfo), std::move(eventInfo)); + auto evt = std::make_unique(std::move(storeInfo), std::move(eventInfo), evtId); EventCenter::GetInstance().PostEvent(std::move(evt)); - return RDB_OK; } 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 5b82ac7c8b9e2b1a498d1e8b2c34495bff88e090..4b7312b6f6666e0a78851c03f66af57122ef3cfe 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h @@ -16,25 +16,27 @@ #ifndef DISTRIBUTEDDATASERVICE_RDB_SERVICE_H #define DISTRIBUTEDDATASERVICE_RDB_SERVICE_H -#include "rdb_service_stub.h" - #include #include #include + #include "cloud/cloud_event.h" +#include "commonevent/data_change_event.h" +#include "commonevent/set_searchable_event.h" #include "concurrent_map.h" #include "feature/static_acts.h" #include "metadata/secret_key_meta_data.h" #include "metadata/store_meta_data.h" #include "rdb_notifier_proxy.h" -#include "rdb_watcher.h" #include "rdb_query.h" +#include "rdb_service_stub.h" +#include "rdb_watcher.h" +#include "snapshot/bind_event.h" #include "store/auto_cache.h" #include "store/general_store.h" +#include "store/general_value.h" #include "store_observer.h" #include "visibility.h" -#include "store/general_value.h" -#include "snapshot/bind_event.h" namespace OHOS::DistributedRdb { class RdbServiceImpl : public RdbServiceStub { @@ -53,7 +55,7 @@ public: int32_t InitNotifier(const RdbSyncerParam ¶m, sptr notifier) override; int32_t SetDistributedTables(const RdbSyncerParam ¶m, const std::vector &tables, - const std::vector &references, int32_t type = DISTRIBUTED_DEVICE) override; + const std::vector &references, bool isRebuild, int32_t type = DISTRIBUTED_DEVICE) override; std::pair> RemoteQuery(const RdbSyncerParam& param, const std::string& device, const std::string& sql, const std::vector& selectionArgs) override; @@ -200,10 +202,16 @@ private: int32_t SaveDebugInfo(const StoreMetaData &metaData, const RdbSyncerParam ¶m); + int32_t PostSearchEvent(int32_t evtId, const RdbSyncerParam& param, + DistributedData::SetSearchableEvent::EventInfo &eventInfo); + + bool IsPostImmediately(const int32_t callingPid, const RdbNotifyConfig &rdbNotifyConfig, StoreInfo &storeInfo, + DistributedData::DataChangeEvent::EventInfo &eventInfo, const std::string &storeName); + static Factory factory_; ConcurrentMap syncAgents_; std::shared_ptr executors_; - ConcurrentMap heartbeatTaskIds_; + ConcurrentMap> heartbeatTaskIds_; }; } // namespace OHOS::DistributedRdb #endif \ No newline at end of file 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 dea28b890ddd5bc771e062fdec2fbb9102175ed1..6f6d0cf40f2d1f9556fa961bbc375739bf70e4f9 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.cpp @@ -16,11 +16,13 @@ #define LOG_TAG "RdbServiceStub" #include "rdb_service_stub.h" + #include -#include "log_print.h" + #include "itypes_util.h" -#include "utils/anonymous.h" +#include "log_print.h" #include "rdb_result_set_stub.h" +#include "utils/anonymous.h" namespace OHOS::DistributedRdb { using Anonymous = DistributedData::Anonymous; @@ -111,13 +113,14 @@ int32_t RdbServiceStub::OnRemoteSetDistributedTables(MessageParcel &data, Messag std::vector tables; std::vector references; int32_t type; - if (!ITypesUtil::Unmarshal(data, param, tables, references, type)) { + bool isRebuild; + if (!ITypesUtil::Unmarshal(data, param, tables, references, type, isRebuild)) { ZLOGE("Unmarshal bundleName_:%{public}s storeName_:%{public}s tables size:%{public}zu type:%{public}d", param.bundleName_.c_str(), Anonymous::Change(param.storeName_).c_str(), tables.size(), type); return IPC_STUB_INVALID_DATA_ERR; } - auto status = SetDistributedTables(param, tables, references, type); + auto status = SetDistributedTables(param, tables, references, isRebuild, type); if (!ITypesUtil::Marshal(reply, status)) { ZLOGE("Marshal status:0x%{public}x", status); return IPC_STUB_WRITE_PARCEL_ERR; diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_watcher.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_watcher.cpp index 1791f649a132406c14a092aef0257df4f0a418e6..0a6ac6c498339c82cd6358002b6a3b0fa6a04c15 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_watcher.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_watcher.cpp @@ -24,9 +24,7 @@ namespace OHOS::DistributedRdb { using namespace DistributedData; using Error = DistributedData::GeneralError; -RdbWatcher::RdbWatcher() -{ -} +RdbWatcher::RdbWatcher() {} int32_t RdbWatcher::OnChange(const Origin &origin, const PRIFields &primaryFields, ChangeInfo &&values) { diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_watcher.h b/datamgr_service/services/distributeddataservice/service/rdb/rdb_watcher.h index c6e95dd94e3928c9f89933997c1db823678ff07a..57cf8d4967275e9ff9f7e7eace7e1da4b5d2a1cd 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_watcher.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_watcher.h @@ -17,6 +17,7 @@ #define OHOS_DISTRIBUTED_DATA_DATAMGR_SERVICE_RDB_GENERAL_WATCHER_H #include #include + #include "rdb_notifier_proxy.h" #include "store/general_value.h" #include "store/general_watcher.h" diff --git a/datamgr_service/services/distributeddataservice/service/test/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/BUILD.gn index 0181a183cee49508de046be86c2be1cf33358428..0cf3ca1a0f71b35625b004552ced4c1953e0cca0 100644 --- a/datamgr_service/services/distributeddataservice/service/test/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/test/BUILD.gn @@ -646,6 +646,7 @@ ohos_unittest("ObjectDmsHandlerTest") { ] deps = [ + "${data_service_path}/adapter:distributeddata_adapter", "${data_service_path}/framework:distributeddatasvcfwk", "//third_party/googletest:gtest_main", ] @@ -685,6 +686,7 @@ ohos_unittest("ObjectManagerTest") { "c_utils:utils", "dfs_service:cloudsync_asset_kit_inner", "dfs_service:distributed_file_daemon_kit_inner", + "dmsfwk:distributed_sdk", "hilog:libhilog", "hisysevent:libhisysevent", "ipc:ipc_core", diff --git a/datamgr_service/services/distributeddataservice/service/test/cache_cursor_test.cpp b/datamgr_service/services/distributeddataservice/service/test/cache_cursor_test.cpp index ac8efd48a8f92dd2481346c70b1b0a25147c0d8c..da62bccbdd47eb537bdff829aa06c2f68b542b8b 100644 --- a/datamgr_service/services/distributeddataservice/service/test/cache_cursor_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/cache_cursor_test.cpp @@ -15,6 +15,7 @@ #define LOG_TAG "CacheCursorTest" #include "cache_cursor.h" + #include "gtest/gtest.h" #include "log_print.h" #include "store/cursor.h" @@ -38,6 +39,7 @@ public: void SetUp(){}; void TearDown(){}; static std::shared_ptr GetCursor(); + protected: CacheCursorTest(); static std::shared_ptr cursor_; @@ -77,7 +79,7 @@ HWTEST_F(CacheCursorTest, CacheCursorTest001, TestSize.Level1) { auto cursor = CacheCursorTest::GetCursor(); EXPECT_NE(cursor, nullptr); - std::vector expectedNames = {"age", "identifier", "name", "phoneNumber"}; + std::vector expectedNames = { "age", "identifier", "name", "phoneNumber" }; std::vector names; auto result = cursor->GetColumnNames(names); EXPECT_EQ(result, GeneralError::E_OK); @@ -127,7 +129,7 @@ HWTEST_F(CacheCursorTest, UnCacheCursorTest001, TestSize.Level1) { auto cursor = CacheCursorTest::GetCursor(); EXPECT_NE(cursor, nullptr); - std::vector expectedNames = {"age", "identifier", "name", "phoneNumber"}; + std::vector expectedNames = { "age", "identifier", "name", "phoneNumber" }; std::vector names; auto result = cursor->GetColumnNames(names); EXPECT_EQ(result, GeneralError::E_OK); 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 be76bb4d20bf46c5c8bd6358ce699c66c42c0fd4..b576ac0e302bea84ab15826fa8310b7e7cd9fdbf 100644 --- a/datamgr_service/services/distributeddataservice/service/test/cloud_data_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/cloud_data_test.cpp @@ -240,8 +240,9 @@ void CloudDataTest::InitCloudInfo() void CloudDataTest::SetUpTestCase(void) { MetaDataManager::GetInstance().Initialize(dbStoreMock_, nullptr); - MetaDataManager::GetInstance().SetSyncer( - [](const auto &, auto) { DeviceMatrix::GetInstance().OnChanged(DeviceMatrix::META_STORE_MASK); }); + MetaDataManager::GetInstance().SetSyncer([](const auto &, auto) { + DeviceMatrix::GetInstance().OnChanged(DeviceMatrix::META_STORE_MASK); + }); auto cloudServerMock = new CloudServerMock(); CloudServer::RegisterCloudInstance(cloudServerMock); @@ -366,7 +367,7 @@ HWTEST_F(CloudDataTest, QueryStatistics003, TestSize.Level0) { ZLOGI("CloudDataTest QueryStatistics003 start"); // Construct the statisticInfo data - auto creator = [](const StoreMetaData &metaData) -> GeneralStore * { + auto creator = [](const StoreMetaData &metaData) -> GeneralStore* { auto store = new (std::nothrow) GeneralStoreMock(); if (store != nullptr) { std::map entry = { { "inserted", 1 }, { "updated", 2 }, { "normal", 3 } }; @@ -403,7 +404,7 @@ HWTEST_F(CloudDataTest, QueryStatistics004, TestSize.Level0) ZLOGI("CloudDataTest QueryStatistics004 start"); // Construct the statisticInfo data - auto creator = [](const StoreMetaData &metaData) -> GeneralStore * { + auto creator = [](const StoreMetaData &metaData) -> GeneralStore* { auto store = new (std::nothrow) GeneralStoreMock(); if (store != nullptr) { std::map entry = { { "inserted", 1 }, { "updated", 2 }, { "normal", 3 } }; @@ -672,8 +673,8 @@ HWTEST_F(CloudDataTest, AllocResourceAndShare001, TestSize.Level0) CloudData::Participants participants; auto [ret, _] = cloudServiceImpl_->AllocResourceAndShare(TEST_CLOUD_STORE, predicates, columns, participants); EXPECT_EQ(ret, E_ERROR); - EventCenter::GetInstance().Subscribe(CloudEvent::MAKE_QUERY, [](const Event& event) { - auto& evt = static_cast(event); + EventCenter::GetInstance().Subscribe(CloudEvent::MAKE_QUERY, [](const Event &event) { + auto &evt = static_cast(event); auto callback = evt.GetCallback(); if (!callback) { return; @@ -1173,7 +1174,8 @@ HWTEST_F(CloudDataTest, OnAllocResourceAndShare, TestSize.Level0) MessageParcel reply; MessageParcel data; data.WriteInterfaceToken(cloudServiceImpl_->GetDescriptor()); - auto ret = cloudServiceImpl_->OnRemoteRequest(CloudData::CloudService::TRANS_ALLOC_RESOURCE_AND_SHARE, data, reply); + auto ret = cloudServiceImpl_->OnRemoteRequest( + CloudData::CloudService::TRANS_ALLOC_RESOURCE_AND_SHARE, data, reply); EXPECT_EQ(ret, IPC_STUB_INVALID_DATA_ERR); data.WriteInterfaceToken(cloudServiceImpl_->GetDescriptor()); std::string storeId = "storeId"; @@ -1507,9 +1509,10 @@ HWTEST_F(CloudDataTest, GetPostEventTask, TestSize.Level0) info.tables_.insert_or_assign(TEST_CLOUD_STORE, value); CloudData::SyncManager sync; - auto task = sync.GetPostEventTask(schemas, cloudInfo_, info, true); - auto ret = task(); - EXPECT_TRUE(ret); + std::map traceIds; + auto task = sync.GetPostEventTask(schemas, cloudInfo_, info, true, traceIds); + task(); + EXPECT_TRUE(sync.lastSyncInfos_.Empty()); } /** @@ -1524,13 +1527,15 @@ HWTEST_F(CloudDataTest, GetRetryer, TestSize.Level0) CloudData::SyncManager::SyncInfo info(user); CloudData::SyncManager sync; CloudData::SyncManager::Duration duration; - auto ret = sync.GetRetryer(CloudData::SyncManager::RETRY_TIMES, info)(duration, E_OK, E_OK); + std::string prepareTraceId; + auto ret = sync.GetRetryer(CloudData::SyncManager::RETRY_TIMES, info, user)(duration, E_OK, E_OK, prepareTraceId); EXPECT_TRUE(ret); - ret = sync.GetRetryer(CloudData::SyncManager::RETRY_TIMES, info)(duration, E_SYNC_TASK_MERGED, E_SYNC_TASK_MERGED); + ret = sync.GetRetryer(CloudData::SyncManager::RETRY_TIMES, info, user)( + duration, E_SYNC_TASK_MERGED, E_SYNC_TASK_MERGED, prepareTraceId); EXPECT_TRUE(ret); - ret = sync.GetRetryer(0, info)(duration, E_OK, E_OK); + ret = sync.GetRetryer(0, info, user)(duration, E_OK, E_OK, prepareTraceId); EXPECT_TRUE(ret); - ret = sync.GetRetryer(0, info)(duration, E_SYNC_TASK_MERGED, E_SYNC_TASK_MERGED); + ret = sync.GetRetryer(0, info, user)(duration, E_SYNC_TASK_MERGED, E_SYNC_TASK_MERGED, prepareTraceId); EXPECT_TRUE(ret); } @@ -1550,21 +1555,24 @@ HWTEST_F(CloudDataTest, GetCallback, TestSize.Level0) storeInfo.user = user; storeInfo.bundleName = "testBundleName"; int32_t triggerMode = MODE_DEFAULT; + std::string prepareTraceId; GenAsync async = nullptr; - sync.GetCallback(async, storeInfo, triggerMode)(result); + sync.GetCallback(async, storeInfo, triggerMode, prepareTraceId, user)(result); int32_t process = 0; - async = [&process](const GenDetails &details) { process = details.begin()->second.progress; }; + async = [&process](const GenDetails &details) { + process = details.begin()->second.progress; + }; GenProgressDetail detail; detail.progress = GenProgress::SYNC_IN_PROGRESS; result.insert_or_assign("test", detail); - sync.GetCallback(async, storeInfo, triggerMode)(result); + sync.GetCallback(async, storeInfo, triggerMode, prepareTraceId, user)(result); EXPECT_EQ(process, GenProgress::SYNC_IN_PROGRESS); detail.progress = GenProgress::SYNC_FINISH; result.insert_or_assign("test", detail); storeInfo.user = -1; - sync.GetCallback(async, storeInfo, triggerMode)(result); + sync.GetCallback(async, storeInfo, triggerMode, prepareTraceId, user)(result); storeInfo.user = user; - sync.GetCallback(async, storeInfo, triggerMode)(result); + sync.GetCallback(async, storeInfo, triggerMode, prepareTraceId, user)(result); EXPECT_EQ(process, GenProgress::SYNC_FINISH); } @@ -1613,22 +1621,24 @@ HWTEST_F(CloudDataTest, GetCloudSyncInfo, TestSize.Level0) */ HWTEST_F(CloudDataTest, RetryCallback, TestSize.Level0) { + int32_t user = 100; + std::string prepareTraceId; CloudData::SyncManager sync; StoreInfo storeInfo; int32_t retCode = -1; CloudData::SyncManager::Retryer retry = [&retCode](CloudData::SyncManager::Duration interval, int32_t code, - int32_t dbCode) { + int32_t dbCode, const std::string &prepareTraceId) { retCode = code; return true; }; DistributedData::GenDetails result; - auto task = sync.RetryCallback(storeInfo, retry, MODE_DEFAULT); + auto task = sync.RetryCallback(storeInfo, retry, MODE_DEFAULT, prepareTraceId, user); task(result); GenProgressDetail detail; detail.progress = GenProgress::SYNC_IN_PROGRESS; detail.code = 100; result.insert_or_assign("test", detail); - task = sync.RetryCallback(storeInfo, retry, MODE_DEFAULT); + task = sync.RetryCallback(storeInfo, retry, MODE_DEFAULT, prepareTraceId, user); task(result); EXPECT_EQ(retCode, detail.code); } @@ -1671,7 +1681,9 @@ HWTEST_F(CloudDataTest, SubTask, TestSize.Level0) MetaDataManager::GetInstance().LoadMeta(Subscription::GetKey(cloudInfo_.user), sub, true); cloudServiceImpl_->InitSubTask(sub, 0); int32_t userId = 0; - CloudData::CloudServiceImpl::Task task = [&userId]() { userId = cloudInfo_.user; }; + CloudData::CloudServiceImpl::Task task = [&userId]() { + userId = cloudInfo_.user; + }; cloudServiceImpl_->GenSubTask(task, cloudInfo_.user)(); EXPECT_EQ(userId, cloudInfo_.user); } diff --git a/datamgr_service/services/distributeddataservice/service/test/cloud_service_impl_test.cpp b/datamgr_service/services/distributeddataservice/service/test/cloud_service_impl_test.cpp index 16c3bc7a1499af99c1ebe2c451b0f038f0fb8d2b..c16d535e326a7359fa23dd2dc895686d1c6cfa84 100644 --- a/datamgr_service/services/distributeddataservice/service/test/cloud_service_impl_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/cloud_service_impl_test.cpp @@ -81,17 +81,11 @@ void CloudServiceImplTest::SetUpTestCase(void) DeviceManagerAdapter::GetInstance().Init(executor); } -void CloudServiceImplTest::TearDownTestCase() -{ -} +void CloudServiceImplTest::TearDownTestCase() {} -void CloudServiceImplTest::SetUp() -{ -} +void CloudServiceImplTest::SetUp() {} -void CloudServiceImplTest::TearDown() -{ -} +void CloudServiceImplTest::TearDown() {} /** * @tc.name: EnableCloud001 diff --git a/datamgr_service/services/distributeddataservice/service/test/config_factory_test.cpp b/datamgr_service/services/distributeddataservice/service/test/config_factory_test.cpp index d92ccf2e39ca03c9f16452df1a1b0e168e691b44..1f8b057c42746a2e57a908e84fb1def7e48ae107 100644 --- a/datamgr_service/services/distributeddataservice/service/test/config_factory_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/config_factory_test.cpp @@ -13,23 +13,16 @@ * limitations under the License. */ #include "config_factory.h" + #include "gtest/gtest.h" using namespace testing::ext; using namespace OHOS::DistributedData; class ConfigFactoryTest : public testing::Test { public: - static void SetUpTestCase(void) - { - } - static void TearDownTestCase(void) - { - } - void SetUp() - { - } - void TearDown() - { - } + static void SetUpTestCase(void) {} + static void TearDownTestCase(void) {} + void SetUp() {} + void TearDown() {} }; /** diff --git a/datamgr_service/services/distributeddataservice/service/test/crypto_manager_test.cpp b/datamgr_service/services/distributeddataservice/service/test/crypto_manager_test.cpp index a78020761ca1deef628312729da7642591afd3ca..3e935ff94392e65636981dba1cf5414201a9bb35 100644 --- a/datamgr_service/services/distributeddataservice/service/test/crypto_manager_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/crypto_manager_test.cpp @@ -16,6 +16,7 @@ #include "crypto_manager.h" #include + #include "gtest/gtest.h" #include "types.h" using namespace testing::ext; @@ -24,8 +25,8 @@ class CryptoManagerTest : public testing::Test { public: static void SetUpTestCase(void); static void TearDownTestCase(void); - void SetUp() {}; - void TearDown() {}; + void SetUp(){}; + void TearDown(){}; protected: static std::vector randomKey; diff --git a/datamgr_service/services/distributeddataservice/service/test/data_share_profile_config_test.cpp b/datamgr_service/services/distributeddataservice/service/test/data_share_profile_config_test.cpp index c8454845ddd875261ec074303e7433ccdd88296a..83119d1df2f29f9393a93ccfaa9d868571926baf 100644 --- a/datamgr_service/services/distributeddataservice/service/test/data_share_profile_config_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/data_share_profile_config_test.cpp @@ -14,13 +14,14 @@ */ #define LOG_TAG "DataShareProfileConfigTest" +#include "data_share_profile_config.h" + #include #include -#include "datashare_errno.h" #include "data_share_db_config.h" -#include "data_share_profile_config.h" #include "data_share_service_impl.h" +#include "datashare_errno.h" #include "log_print.h" namespace OHOS::Test { diff --git a/datamgr_service/services/distributeddataservice/service/test/data_share_service_impl_test.cpp b/datamgr_service/services/distributeddataservice/service/test/data_share_service_impl_test.cpp index 9d7648f9361bd661dcc43d4e6c48775b9d5273ce..f9aaed5ef97275b57b949817d90e105c27b7cc8c 100644 --- a/datamgr_service/services/distributeddataservice/service/test/data_share_service_impl_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/data_share_service_impl_test.cpp @@ -14,18 +14,20 @@ */ #define LOG_TAG "DataShareServiceImplTest" +#include "data_share_service_impl.h" + #include #include -#include "log_print.h" -#include "ipc_skeleton.h" + +#include "accesstoken_kit.h" #include "data_share_service_stub.h" #include "dump/dump_manager.h" -#include "accesstoken_kit.h" #include "hap_token_info.h" +#include "ipc_skeleton.h" #include "iservice_registry.h" +#include "log_print.h" #include "system_ability_definition.h" #include "token_setproc.h" -#include "data_share_service_impl.h" using namespace testing::ext; using namespace OHOS::DataShare; @@ -34,7 +36,7 @@ using namespace OHOS::Security::AccessToken; std::string SLIENT_ACCESS_URI = "datashareproxy://com.acts.ohos.data.datasharetest/test"; std::string TBL_NAME0 = "name0"; std::string TBL_NAME1 = "name1"; -std::string BUNDLE_NAME = "ohos.datasharetest.demo"; +std::string BUNDLE_NAME = "ohos.datasharetest.demo"; namespace OHOS::Test { class DataShareServiceImplTest : public testing::Test { public: diff --git a/datamgr_service/services/distributeddataservice/service/test/data_share_service_stub_test.cpp b/datamgr_service/services/distributeddataservice/service/test/data_share_service_stub_test.cpp index d006a70be73b307e22916d471ae3ca0ad7926224..9e3a5514d312efa7fdd39cc0033a4beede8bea00 100644 --- a/datamgr_service/services/distributeddataservice/service/test/data_share_service_stub_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/data_share_service_stub_test.cpp @@ -14,12 +14,14 @@ */ #define LOG_TAG "DataShareServiceStubTest" +#include "data_share_service_stub.h" + #include #include -#include "log_print.h" -#include "ipc_skeleton.h" + #include "data_share_service_impl.h" -#include "data_share_service_stub.h" +#include "ipc_skeleton.h" +#include "log_print.h" using namespace testing::ext; using namespace OHOS::DataShare; diff --git a/datamgr_service/services/distributeddataservice/service/test/data_share_subscriber_managers_test.cpp b/datamgr_service/services/distributeddataservice/service/test/data_share_subscriber_managers_test.cpp index eedf4ba159ec0143f6439b03e8a364b05a42a381..0746d85a1455dc51cc2380b2ae6370121e2c8de6 100644 --- a/datamgr_service/services/distributeddataservice/service/test/data_share_subscriber_managers_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/data_share_subscriber_managers_test.cpp @@ -18,8 +18,8 @@ #include #include "accesstoken_kit.h" -#include "datashare_errno.h" #include "data_share_service_impl.h" +#include "datashare_errno.h" #include "hap_token_info.h" #include "ipc_skeleton.h" #include "iservice_registry.h" diff --git a/datamgr_service/services/distributeddataservice/service/test/device_matrix_test.cpp b/datamgr_service/services/distributeddataservice/service/test/device_matrix_test.cpp index f72ffc5676763092954985f00f6124aaf9e7b5ad..43e162a7f6edaebed2e127f29fc5c26c82d91e59 100644 --- a/datamgr_service/services/distributeddataservice/service/test/device_matrix_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/device_matrix_test.cpp @@ -40,6 +40,7 @@ public: static void TearDownTestCase(void); void SetUp(); void TearDown(); + protected: struct Result { uint16_t mask_ = DeviceMatrix::INVALID_LEVEL; diff --git a/datamgr_service/services/distributeddataservice/service/test/directory_manager_test.cpp b/datamgr_service/services/distributeddataservice/service/test/directory_manager_test.cpp index fd57b50c89814217eb09c62e8f8c6d6e6e9d109e..ce979c4fb33722da5127c852bf565fbff8f4edfa 100644 --- a/datamgr_service/services/distributeddataservice/service/test/directory_manager_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/directory_manager_test.cpp @@ -13,13 +13,15 @@ * limitations under the License. */ +#include "directory/directory_manager.h" + +#include #include + #include "accesstoken_kit.h" #include "bootstrap.h" -#include "directory/directory_manager.h" #include "nativetoken_kit.h" #include "types.h" -#include using namespace testing::ext; using namespace OHOS::DistributedData; diff --git a/datamgr_service/services/distributeddataservice/service/test/dump_helper_test.cpp b/datamgr_service/services/distributeddataservice/service/test/dump_helper_test.cpp index 86ce2efb7db433e6e076b9eb81ff6b7dbeb8b2a2..58134080242e3a7d26bef66b339bb6c5284f3966 100644 --- a/datamgr_service/services/distributeddataservice/service/test/dump_helper_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/dump_helper_test.cpp @@ -14,10 +14,11 @@ */ #define LOG_TAG "DumpHelperTest " -#include "gtest/gtest.h" -#include "log_print.h" #include "dump_helper.h" + #include "dump/dump_manager.h" +#include "gtest/gtest.h" +#include "log_print.h" #include "types.h" using namespace OHOS; @@ -26,7 +27,7 @@ using namespace testing::ext; using namespace OHOS::DistributedData; namespace OHOS::Test { namespace DistributedDataTest { -class DumpHelperTest : public testing::Test { +class DumpHelperTest : public testing::Test { public: static void SetUpTestCase(void){}; static void TearDownTestCase(void){}; diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/fuzztest/BUILD.gn index 5a9c822976e76a9150d975c7eba25c00473701cf..6686a1d01f9846051d975d02d513ed167b0f5c61 100644 --- a/datamgr_service/services/distributeddataservice/service/test/fuzztest/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/BUILD.gn @@ -20,7 +20,6 @@ group("fuzztest") { deps = [ "cloudservicestub_fuzzer:fuzztest", - "customutdinstaller_fuzzer:fuzztest", "datashareservicestub_fuzzer:fuzztest", "dumphelper_fuzzer:fuzztest", "kvdbservicestub_fuzzer:fuzztest", diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/customutdinstaller_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/fuzztest/customutdinstaller_fuzzer/BUILD.gn deleted file mode 100644 index c495c98f2507352fc7be8f2af14896936221f078..0000000000000000000000000000000000000000 --- a/datamgr_service/services/distributeddataservice/service/test/fuzztest/customutdinstaller_fuzzer/BUILD.gn +++ /dev/null @@ -1,112 +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. -##############################hydra-fuzz######################################## -import("//build/config/features.gni") -import("//build/test.gni") -import("//foundation/distributeddatamgr/datamgr_service/datamgr_service.gni") - -##############################fuzztest########################################## -ohos_fuzztest("CustomUtdInstallerFuzzTest") { - module_out_path = "datamgr_service/datamgr_service" - - include_dirs = [ - "${data_service_path}/service/udmf/utd", - "${udmf_path}/framework/common", - "${udmf_path}/interfaces/innerkits/common", - "${udmf_path}/interfaces/innerkits/data", - "${data_service_path}/framework/include", - "${data_service_path}/service/udmf/lifecycle", - "${data_service_path}/service/udmf/permission", - "${data_service_path}/service/udmf/preprocess", - "${data_service_path}/service/udmf/store", - "${data_service_path}/service/udmf", - "${kv_store_path}/frameworks/common", - "${kv_store_common_path}", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatafwk/include", - "${kv_store_path}/frameworks/innerkitsimpl/distributeddatasvc/include", - "${kv_store_path}/frameworks/innerkitsimpl/kvdb/include", - "${kv_store_distributeddb_path}", - "${kv_store_distributeddb_path}/include/", - "${kv_store_distributeddb_path}/interfaces/include/", - "${kv_store_distributeddb_path}/interfaces/include/relational", - "${dataobject_path}/frameworks/innerkitsimpl/include", - "${relational_store_path}/interfaces/inner_api/cloud_data/include", - "${relational_store_path}/interfaces/inner_api/rdb/include", - "${relational_store_path}/interfaces/inner_api/common_type/include", - "//third_party/json/single_include", - "${data_service_path}/framework/include", - "${data_service_path}/adapter/include/communicator", - "${data_service_path}/adapter/include/dfx", - "${data_service_path}/service/bootstrap/include", - "${device_manager_path}/interfaces/inner_kits/native_cpp/include", - "${file_service_path}/interfaces/innerkits/native/remote_file_share/include", - "${kv_store_path}/interfaces/innerkits/distributeddata/include", - "${kv_store_path}/framework/libs/distributeddb/interfaces/include", - "${kv_store_common_path}", - "${udmf_path}/framework/common", - "${udmf_path}/interfaces/innerkits/common", - "${udmf_path}/interfaces/innerkits/data", - ] - - fuzz_config_file = - "${data_service_path}/service/test/fuzztest/customutdinstaller_fuzzer" - - cflags = [ - "-g", - "-O0", - "-Wno-unused-variable", - "-fno-omit-frame-pointer", - ] - - sources = [ - "${data_service_path}/service/udmf/utd/custom_utd_installer.cpp", - "customutdinstaller_fuzzer.cpp", - ] - - deps = [ - "${data_service_path}/adapter:distributeddata_adapter", - "${data_service_path}/adapter/utils:distributeddata_utils_static", - "${data_service_path}/framework:distributeddatasvcfwk", - "${data_service_path}/service:distributeddatasvc", - "${data_service_path}/service/udmf:udmf_server", - "${kv_store_distributeddb_path}:distributeddb", - ] - - external_deps = [ - "ability_base:zuri", - "ability_runtime:uri_permission_mgr", - "access_token:libaccesstoken_sdk", - "app_file_service:remote_file_share_native", - "bundle_framework:appexecfwk_base", - "bundle_framework:appexecfwk_core", - "c_utils:utils", - "hilog:libhilog", - "image_framework:image", - "ipc:ipc_core", - "kv_store:distributeddata_inner", - "kv_store:distributeddata_mgr", - "kv_store:distributeddb", - "safwk:system_ability_fwk", - "samgr:samgr_proxy", - "udmf:udmf_client", - "udmf:utd_client", - ] -} - -############################################################################### -group("fuzztest") { - testonly = true - - deps = [ ":CustomUtdInstallerFuzzTest" ] -} -############################################################################### diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/customutdinstaller_fuzzer/project.xml b/datamgr_service/services/distributeddataservice/service/test/fuzztest/customutdinstaller_fuzzer/project.xml deleted file mode 100644 index e3791389ecf624d1b851a1ef1a3dcdee48a38b7b..0000000000000000000000000000000000000000 --- a/datamgr_service/services/distributeddataservice/service/test/fuzztest/customutdinstaller_fuzzer/project.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - 1000 - - 300 - - 4096 - - \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/kvdb_general_store_test.cpp b/datamgr_service/services/distributeddataservice/service/test/kvdb_general_store_test.cpp index 1cc1334419b1714439fa8284dc5e9c89f796a79f..b8c4568324e1cfd9980bf2a1234a8e489964e828 100644 --- a/datamgr_service/services/distributeddataservice/service/test/kvdb_general_store_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/kvdb_general_store_test.cpp @@ -21,12 +21,12 @@ #include #include "bootstrap.h" -#include "cloud/schema_meta.h" #include "cloud/asset_loader.h" #include "cloud/cloud_db.h" +#include "cloud/schema_meta.h" #include "crypto_manager.h" -#include "kvdb_query.h" #include "kv_store_nb_delegate_mock.h" +#include "kvdb_query.h" #include "log_print.h" #include "metadata/meta_data_manager.h" #include "metadata/secret_key_meta_data.h" @@ -50,6 +50,7 @@ public: static void TearDownTestCase(void); void SetUp(); void TearDown(); + protected: static constexpr const char *bundleName = "test_distributeddata"; static constexpr const char *storeName = "test_service_meta"; @@ -89,9 +90,7 @@ std::vector KVDBGeneralStoreTest::Random(uint32_t len) return key; } -void KVDBGeneralStoreTest::SetUpTestCase(void) -{ -} +void KVDBGeneralStoreTest::SetUpTestCase(void) {} void KVDBGeneralStoreTest::TearDownTestCase() {} @@ -124,17 +123,17 @@ public: std::list entriesUpdated = {}; std::list entriesDeleted = {}; bool isCleared = true; - const std::list& GetEntriesInserted() const override + const std::list &GetEntriesInserted() const override { return entriesInserted; } - const std::list& GetEntriesUpdated() const override + const std::list &GetEntriesUpdated() const override { return entriesUpdated; } - const std::list& GetEntriesDeleted() const override + const std::list &GetEntriesDeleted() const override { return entriesDeleted; } @@ -325,8 +324,7 @@ HWTEST_F(KVDBGeneralStoreTest, SyncTest, TestSize.Level0) DistributedKv::KVDBQuery query(kvQuery); SyncParam syncParam{}; syncParam.mode = mixMode; - auto ret = store->Sync( - {}, query, [](const GenDetails &result) {}, syncParam); + auto ret = store->Sync({}, query, [](const GenDetails &result) {}, syncParam); EXPECT_NE(ret, GeneralError::E_OK); ret = store->Close(); EXPECT_EQ(ret, GeneralError::E_OK); @@ -413,17 +411,18 @@ HWTEST_F(KVDBGeneralStoreTest, CloudSync, TestSize.Level0) store->SetEqualIdentifier(bundleName, storeName); KvStoreNbDelegateMock mockDelegate; store->delegate_ = &mockDelegate; - std::vector devices = {"device1", "device2"}; + std::vector devices = { "device1", "device2" }; auto asyncs = [](const GenDetails &result) {}; store->storeInfo_.user = 0; auto cloudSyncMode = DistributedDB::SyncMode::SYNC_MODE_PUSH_ONLY; store->SetEqualIdentifier(bundleName, storeName); - auto ret = store->CloudSync(devices, cloudSyncMode, asyncs, 0); + std::string prepareTraceId; + auto ret = store->CloudSync(devices, cloudSyncMode, asyncs, 0, prepareTraceId); EXPECT_EQ(ret, DBStatus::OK); store->storeInfo_.user = 1; cloudSyncMode = DistributedDB::SyncMode::SYNC_MODE_CLOUD_FORCE_PUSH; - ret = store->CloudSync(devices, cloudSyncMode, asyncs, 0); + ret = store->CloudSync(devices, cloudSyncMode, asyncs, 0, prepareTraceId); EXPECT_EQ(ret, DBStatus::OK); } @@ -463,7 +462,7 @@ HWTEST_F(KVDBGeneralStoreTest, Sync, TestSize.Level0) ret = store->Sync({}, query, [](const GenDetails &result) {}, syncParam); EXPECT_EQ(ret, GeneralError::E_INVALID_ARGS); - std::vector devices = {"device1", "device2"}; + std::vector devices = { "device1", "device2" }; syncMode = GeneralStore::SyncMode::NEARBY_SUBSCRIBE_REMOTE; mixMode = GeneralStore::MixMode(syncMode, highMode); syncParam.mode = mixMode; @@ -500,7 +499,7 @@ HWTEST_F(KVDBGeneralStoreTest, Clean, TestSize.Level0) { auto store = new (std::nothrow) KVDBGeneralStore(metaData_); ASSERT_NE(store, nullptr); - std::vector devices = {"device1", "device2"}; + std::vector devices = { "device1", "device2" }; std::string tableName = "tableName"; auto ret = store->Clean(devices, -1, tableName); EXPECT_EQ(ret, GeneralError::E_INVALID_ARGS); @@ -632,7 +631,7 @@ HWTEST_F(KVDBGeneralStoreTest, GetWaterVersion, TestSize.Level0) EXPECT_EQ(ret, res); ret = store->GetWaterVersion("device"); EXPECT_EQ(ret, res); - res = {"deviceId"}; + res = { "deviceId" }; ret = store->GetWaterVersion(deviceId); EXPECT_EQ(ret, res); } diff --git a/datamgr_service/services/distributeddataservice/service/test/kvdb_service_impl_test.cpp b/datamgr_service/services/distributeddataservice/service/test/kvdb_service_impl_test.cpp index 2fb8c1861498c822b262e714aba05a6a8d0fe72a..cdb512aa7fbfcba883f214f613e78ec5472bf52b 100644 --- a/datamgr_service/services/distributeddataservice/service/test/kvdb_service_impl_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/kvdb_service_impl_test.cpp @@ -13,24 +13,26 @@ * limitations under the License. */ #define LOG_TAG "KvdbServiceImplTest" +#include "kvdb_service_impl.h" + #include -#include "log_print.h" +#include + #include "accesstoken_kit.h" #include "bootstrap.h" #include "checker/checker_manager.h" -#include "distributed_kv_data_manager.h" #include "device_manager_adapter.h" +#include "distributed_kv_data_manager.h" #include "ipc_skeleton.h" -#include "nativetoken_kit.h" -#include "kvdb_service_impl.h" #include "kvdb_service_stub.h" #include "kvstore_death_recipient.h" #include "kvstore_meta_manager.h" -#include "utils/constant.h" -#include "utils/anonymous.h" +#include "log_print.h" +#include "nativetoken_kit.h" #include "token_setproc.h" #include "types.h" -#include +#include "utils/anonymous.h" +#include "utils/constant.h" using namespace testing::ext; using namespace OHOS::DistributedData; @@ -76,6 +78,7 @@ public: void TearDown(); KvdbServiceImplTest(); + protected: std::shared_ptr kvdbServiceImpl_; }; @@ -132,8 +135,7 @@ void KvdbServiceImplTest::TearDown(void) RemoveAllStore(manager); } -KvdbServiceImplTest::KvdbServiceImplTest(void) -{} +KvdbServiceImplTest::KvdbServiceImplTest(void) {} /** * @tc.name: KvdbServiceImpl001 @@ -475,13 +477,9 @@ HWTEST_F(KvdbServiceImplTest, UnsubscribeTest001, TestSize.Level0) HWTEST_F(KvdbServiceImplTest, GetBackupPasswordTest001, TestSize.Level0) { ZLOGI("GetBackupPasswordTest001 start"); - Status status1 = manager.GetSingleKvStore(create, appId, storeId, kvStore); + auto status = manager.GetSingleKvStore(create, appId, storeId, kvStore); ASSERT_NE(kvStore, nullptr); - ASSERT_EQ(status1, Status::SUCCESS); - std::vector password; - auto status = kvdbServiceImpl_->GetBackupPassword(appId, storeId, password); - ZLOGI("GetBackupPasswordTest001 status = :%{public}d", status); - ASSERT_NE(status, Status::SUCCESS); + ASSERT_EQ(status, Status::SUCCESS); } /** @@ -667,7 +665,7 @@ HWTEST_F(KvdbServiceImplTest, DoCloudSync, TestSize.Level0) SyncInfo syncInfo; status = kvdbServiceImpl_->DoCloudSync(metaData, syncInfo); EXPECT_EQ(status, Status::NOT_SUPPORT); - syncInfo.devices = {"device1", "device2"}; + syncInfo.devices = { "device1", "device2" }; syncInfo.query = "query"; metaData.enableCloud = true; status = kvdbServiceImpl_->DoCloudSync(metaData, syncInfo); diff --git a/datamgr_service/services/distributeddataservice/service/test/kvdb_service_test.cpp b/datamgr_service/services/distributeddataservice/service/test/kvdb_service_test.cpp index 026b9c039349a5cf5d5544bdc8b270d98d0d45b9..5e7d61594d605967ead41ab479aa0dc99a42b6b2 100644 --- a/datamgr_service/services/distributeddataservice/service/test/kvdb_service_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/kvdb_service_test.cpp @@ -14,13 +14,19 @@ */ #include -#include "log_print.h" + #include "accesstoken_kit.h" #include "auth_delegate.h" #include "bootstrap.h" #include "crypto_manager.h" #include "device_manager_adapter.h" #include "directory/directory_manager.h" +#include "kvdb_general_store.h" +#include "kvdb_notifier_proxy.h" +#include "kvdb_watcher.h" +#include "kvstore_meta_manager.h" +#include "kvstore_sync_manager.h" +#include "log_print.h" #include "metadata/meta_data_manager.h" #include "metadata/secret_key_meta_data.h" #include "metadata/store_meta_data.h" @@ -28,11 +34,6 @@ #include "query_helper.h" #include "upgrade.h" #include "user_delegate.h" -#include "kvdb_general_store.h" -#include "kvdb_watcher.h" -#include "kvdb_notifier_proxy.h" -#include "kvstore_sync_manager.h" -#include "kvstore_meta_manager.h" using namespace testing::ext; using namespace DistributedDB; diff --git a/datamgr_service/services/distributeddataservice/service/test/meta_data_test.cpp b/datamgr_service/services/distributeddataservice/service/test/meta_data_test.cpp index 1d7e649ef185da26d02f88756ee66fd7a0c429b9..1476b51da173f08faecbd5dddc7b7194ab80c5a6 100644 --- a/datamgr_service/services/distributeddataservice/service/test/meta_data_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/meta_data_test.cpp @@ -14,20 +14,21 @@ */ #define LOG_TAG "MetaDataTest" #include -#include "log_print.h" -#include "ipc_skeleton.h" -#include "device_matrix.h" -#include "executor_pool.h" + #include "accesstoken_kit.h" #include "bootstrap.h" -#include "token_setproc.h" -#include "nativetoken_kit.h" -#include "kvstore_meta_manager.h" #include "device_manager_adapter.h" +#include "device_matrix.h" +#include "executor_pool.h" +#include "ipc_skeleton.h" +#include "kvdb_service_impl.h" +#include "kvstore_meta_manager.h" +#include "log_print.h" #include "metadata/meta_data_manager.h" #include "metadata/store_meta_data.h" -#include "kvdb_service_impl.h" #include "metadata/store_meta_data_local.h" +#include "nativetoken_kit.h" +#include "token_setproc.h" using namespace testing::ext; using namespace OHOS::DistributedData; using namespace OHOS::Security::AccessToken; diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/checker_mock.cpp b/datamgr_service/services/distributeddataservice/service/test/mock/checker_mock.cpp index e30210794b17c6caff5de123b77d0826061a9633..22a2e748e70e572a9a93a3a23c773700e2c96a67 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/checker_mock.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/mock/checker_mock.cpp @@ -20,45 +20,56 @@ CheckerMock::CheckerMock() noexcept CheckerManager::GetInstance().RegisterPlugin( "SystemChecker", [this]() -> auto { return this; }); } + CheckerMock::~CheckerMock() {} + void CheckerMock::SetDynamic(const std::vector &dynamicStores) { dynamicInfos_ = dynamicStores; } + void CheckerMock::SetStatic(const std::vector &staticStores) { staticInfos_ = staticStores; } + void CheckerMock::Initialize() {} + bool CheckerMock::SetTrustInfo(const CheckerManager::Trust &trust) { return true; } + std::string CheckerMock::GetAppId(const CheckerManager::StoreInfo &info) { return info.bundleName; } + bool CheckerMock::IsValid(const CheckerManager::StoreInfo &info) { return true; } + bool CheckerMock::SetDistrustInfo(const CheckerManager::Distrust &distrust) { return true; -}; +} bool CheckerMock::IsDistrust(const CheckerManager::StoreInfo &info) { return true; } + std::vector CheckerMock::GetDynamicStores() { return dynamicInfos_; } + std::vector CheckerMock::GetStaticStores() { return staticInfos_; } + bool CheckerMock::IsDynamic(const CheckerManager::StoreInfo &info) { for (const auto &store : dynamicInfos_) { @@ -68,6 +79,7 @@ bool CheckerMock::IsDynamic(const CheckerManager::StoreInfo &info) } return false; } + bool CheckerMock::IsStatic(const CheckerManager::StoreInfo &info) { for (const auto &store : staticInfos_) { @@ -77,18 +89,22 @@ bool CheckerMock::IsStatic(const CheckerManager::StoreInfo &info) } return false; } + bool CheckerMock::AddDynamicStore(const CheckerManager::StoreInfo &storeInfo) { return false; } + bool CheckerMock::AddStaticStore(const CheckerManager::StoreInfo &storeInfo) { return false; } + bool CheckerMock::IsSwitches(const CheckerManager::StoreInfo &info) { return false; } + bool CheckerMock::SetSwitchesInfo(const CheckerManager::Switches &switches) { return true; diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/cursor_mock.cpp b/datamgr_service/services/distributeddataservice/service/test/mock/cursor_mock.cpp index 78d4936094dd60b6dc415780df17d8979ee58246..48ce40ebdea7daf930aebdf0f66330a15aaa126b 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/cursor_mock.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/mock/cursor_mock.cpp @@ -13,6 +13,7 @@ * limitations under the License. */ #include "cursor_mock.h" + #include "store/general_value.h" namespace OHOS { namespace DistributedData { diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/cursor_mock.h b/datamgr_service/services/distributeddataservice/service/test/mock/cursor_mock.h index ca487f1409689f97df0839ffbb33f1ad3587a6c6..c63bdacc07e7f0ecb790e23e8a881339105c97d3 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/cursor_mock.h +++ b/datamgr_service/services/distributeddataservice/service/test/mock/cursor_mock.h @@ -17,6 +17,7 @@ #include #include #include + #include "store/cursor.h" #include "store/general_value.h" namespace OHOS { 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 07b36a03027f85963884826e587850f93998c30f..d4f2c2aef400bc0bce75adbde441b59287b2e8e4 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 @@ -14,8 +14,8 @@ */ #ifndef OHOS_DISTRIBUTEDDATA_SERVICE_TEST_DB_STORE_MOCK_H #define OHOS_DISTRIBUTEDDATA_SERVICE_TEST_DB_STORE_MOCK_H -#include "kv_store_nb_delegate.h" #include "concurrent_map.h" +#include "kv_store_nb_delegate.h" #include "store_types.h" namespace OHOS { namespace DistributedData { 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 a3d3b7f93ee0920c46d0d35f3f6cbb6c4e598d22..62c31e848204bd918da1424ead595d2b71bf9a1a 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) +int32_t GeneralStoreMock::SetTrackerTable(const std::string &tableName, const std::set &trackerColNames, + const std::string &extendColName, bool isForceUpgrade) { return 0; } 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 bf16a2c8f1724d46e91ff0d6df3c08f01f7e7d4e..86f2c4ca0ab0d1afbb7df0819b50062fba32e2ad 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) override; + const std::string &extendColName, bool isForceUpgrade) 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; 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 8c402f961d30586660275353a1a088c02ec8e1b8..9ab67e8b11ad2f55070ba9a73efda7bdb106abef 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 @@ -14,6 +14,7 @@ */ #include "kv_store_nb_delegate_mock.h" + #include "store_types.h" namespace DistributedDB { DBStatus KvStoreNbDelegateMock::Get(const Key &key, Value &value) const 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 83d935fbf26be9904f7c7301f2343ded34541ccd..a7483b7a5d9c5fbaba3043551c31ef4a06e911f7 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 @@ -24,8 +24,8 @@ #include "cloud/icloud_db.h" #include "intercepted_data.h" #include "iprocess_system_api_adapter.h" -#include "kv_store_nb_delegate.h" #include "kv_store_nb_conflict_data.h" +#include "kv_store_nb_delegate.h" #include "kv_store_observer.h" #include "kv_store_result_set.h" #include "query.h" diff --git a/datamgr_service/services/distributeddataservice/service/test/object_asset_loader_test.cpp b/datamgr_service/services/distributeddataservice/service/test/object_asset_loader_test.cpp index ab44449262ffef3f7615f91296eddeae55b9c6b1..57aa68b6f3963c30a9dd1d9a877804a7fb99ee4e 100644 --- a/datamgr_service/services/distributeddataservice/service/test/object_asset_loader_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/object_asset_loader_test.cpp @@ -16,9 +16,11 @@ #define LOG_TAG "ObjectAssetLoaderTest" #include "object_asset_loader.h" + #include -#include "snapshot/machine_status.h" + #include "executor_pool.h" +#include "snapshot/machine_status.h" using namespace testing::ext; using namespace OHOS::DistributedObject; diff --git a/datamgr_service/services/distributeddataservice/service/test/object_asset_machine_test.cpp b/datamgr_service/services/distributeddataservice/service/test/object_asset_machine_test.cpp index c6e34358179beee37619d8a457254b96c197c77c..0405b829469e604611e5848df3acb6d1d67d7fea 100644 --- a/datamgr_service/services/distributeddataservice/service/test/object_asset_machine_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/object_asset_machine_test.cpp @@ -19,9 +19,9 @@ #include -#include "snapshot/machine_status.h" -#include "object_asset_loader.h" #include "executor_pool.h" +#include "object_asset_loader.h" +#include "snapshot/machine_status.h" using namespace testing::ext; using namespace OHOS::DistributedObject; @@ -41,6 +41,7 @@ protected: std::map changedAssets_; std::string sessionId = "123"; StoreInfo storeInfo_; + std::shared_ptr machine; }; void ObjectAssetMachineTest::SetUp() @@ -74,8 +75,11 @@ void ObjectAssetMachineTest::SetUp() storeInfo_ = storeInfo; ChangedAssetInfo changedAssetInfo(asset, AssetBindInfo, storeInfo); changedAssets_[uri_] = changedAssetInfo; - auto executors = std::make_shared(1, 0); - ObjectAssetLoader::GetInstance()->SetThreadPool(executors); + if (machine == nullptr) { + machine = std::make_shared(); + auto executors = std::make_shared(2, 1); + ObjectAssetLoader::GetInstance()->SetThreadPool(executors); + } } void ObjectAssetMachineTest::TearDown() {} @@ -89,7 +93,6 @@ void ObjectAssetMachineTest::TearDown() {} */ HWTEST_F(ObjectAssetMachineTest, StatusTransfer001, TestSize.Level0) { - auto machine = std::make_shared(); Asset asset{ .name = "test_name", .uri = uri_, @@ -114,7 +117,6 @@ HWTEST_F(ObjectAssetMachineTest, StatusTransfer001, TestSize.Level0) */ HWTEST_F(ObjectAssetMachineTest, StatusTransfer002, TestSize.Level0) { - auto machine = std::make_shared(); Asset asset{ .name = "test_name", .uri = uri_, @@ -137,7 +139,6 @@ HWTEST_F(ObjectAssetMachineTest, StatusTransfer002, TestSize.Level0) */ HWTEST_F(ObjectAssetMachineTest, StatusTransfer003, TestSize.Level0) { - auto machine = std::make_shared(); Asset asset{ .name = "test_name", .uri = uri_, @@ -162,7 +163,6 @@ HWTEST_F(ObjectAssetMachineTest, StatusTransfer003, TestSize.Level0) */ HWTEST_F(ObjectAssetMachineTest, StatusUpload001, TestSize.Level0) { - auto machine = std::make_shared(); Asset asset{ .name = "test_name", .uri = uri_, @@ -187,24 +187,41 @@ HWTEST_F(ObjectAssetMachineTest, StatusUpload001, TestSize.Level0) */ HWTEST_F(ObjectAssetMachineTest, StatusUpload002, TestSize.Level0) { - auto machine = std::make_shared(); + auto time = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); + auto timestamp = std::to_string(time); Asset asset{ - .name = "test_name", - .uri = uri_, - .modifyTime = "modifyTime1", - .size = "size1", - .hash = "modifyTime1_size1", + .name = "name_" + timestamp, + .uri = "uri_" + timestamp, + .modifyTime = "modifyTime_" + timestamp, + .size = "size_" + timestamp, + .hash = "modifyTime_size_" + timestamp, }; - std::pair changedAsset{ "device_1", asset }; - machine->DFAPostEvent(UPLOAD, changedAssets_[uri_], asset); - ASSERT_EQ(changedAssets_[uri_].status, STATUS_UPLOADING); + AssetBindInfo bindInfo{ + .storeName = "store_" + timestamp, + .tableName = "table_" + timestamp, + .primaryKey = {{ "key_" + timestamp, "value_" + timestamp }}, + .field = "attachment_" + timestamp, + .assetName = "asset_" + timestamp + ".jpg", + }; + StoreInfo storeInfo { + .tokenId = time, + .bundleName = "bundleName_" + timestamp, + .storeName = "store_" + timestamp, + .instanceId = time, + .user = time, + }; + ChangedAssetInfo changedAssetInfo(asset, bindInfo, storeInfo); + std::pair changedAsset{ "device_" + timestamp, asset }; - machine->DFAPostEvent(REMOTE_CHANGED, changedAssets_[uri_], asset, changedAsset); - ASSERT_EQ(changedAssets_[uri_].status, STATUS_WAIT_TRANSFER); - ASSERT_EQ(changedAssets_[uri_].asset.hash, asset.hash); + machine->DFAPostEvent(UPLOAD, changedAssetInfo, asset); + ASSERT_EQ(changedAssetInfo.status, STATUS_UPLOADING); - machine->DFAPostEvent(UPLOAD_FINISHED, changedAssets_[uri_], asset); - ASSERT_EQ(changedAssets_[uri_].status, STATUS_TRANSFERRING); + machine->DFAPostEvent(REMOTE_CHANGED, changedAssetInfo, asset, changedAsset); + ASSERT_EQ(changedAssetInfo.status, STATUS_WAIT_TRANSFER); + ASSERT_EQ(changedAssetInfo.asset.hash, asset.hash); + + machine->DFAPostEvent(UPLOAD_FINISHED, changedAssetInfo, asset); + ASSERT_EQ(changedAssetInfo.status, STATUS_TRANSFERRING); } /** @@ -216,7 +233,6 @@ HWTEST_F(ObjectAssetMachineTest, StatusUpload002, TestSize.Level0) */ HWTEST_F(ObjectAssetMachineTest, StatusDownload001, TestSize.Level0) { - auto machine = std::make_shared(); Asset asset{ .name = "name_006", .uri = "uri_006", diff --git a/datamgr_service/services/distributeddataservice/service/test/object_dms_handler_test.cpp b/datamgr_service/services/distributeddataservice/service/test/object_dms_handler_test.cpp index 37fc4e3ae2d0b8450321e08a4e4aa9a91ba4b958..8bc94030e4c2ddec6081f22caece8384aa8ef3d9 100644 --- a/datamgr_service/services/distributeddataservice/service/test/object_dms_handler_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/object_dms_handler_test.cpp @@ -19,11 +19,13 @@ #include +#include "device_manager_adapter.h" #include "dms_listener_stub.h" using namespace testing::ext; using namespace OHOS::DistributedObject; namespace OHOS::Test { +constexpr const char *PKG_NAME = "ohos.distributeddata.service"; class ObjectDmsHandlerTest : public testing::Test { public: void SetUp() {} @@ -38,20 +40,47 @@ public: HWTEST_F(ObjectDmsHandlerTest, IsContinue_001, TestSize.Level0) { ObjectDmsHandler::GetInstance().RegisterDmsEvent(); - DmsEventListener listener; + DistributedHardware::DmDeviceInfo localDeviceInfo; + DistributedHardware::DeviceManager::GetInstance().GetLocalDeviceInfo(PKG_NAME, localDeviceInfo); + std::string localNetworkId = localDeviceInfo.networkId; DistributedSchedule::EventNotify notify; notify.dSchedEventType_ = DistributedSchedule::DSchedEventType::DMS_CONTINUE; - notify.srcNetworkId_ = "srcNetworkId"; - notify.dstNetworkId_ = "dstNetworkId"; - notify.srcBundleName_ = "srcBundleName"; - notify.destBundleName_ = "destBundleName"; + notify.srcNetworkId_ = localNetworkId; + notify.dstNetworkId_ = "networkId2"; + notify.srcBundleName_ = "bundleName1"; + notify.destBundleName_ = "bundleName2"; + DmsEventListener listener; listener.DSchedEventNotify(notify); - auto res = ObjectDmsHandler::GetInstance().IsContinue("srcNetworkId", "srcBundleName"); - EXPECT_TRUE(res); - res = ObjectDmsHandler::GetInstance().IsContinue("dstNetworkId", "destBundleName"); + auto res = ObjectDmsHandler::GetInstance().IsContinue("bundleName1"); EXPECT_TRUE(res); - res = ObjectDmsHandler::GetInstance().IsContinue("srcNetworkId", "destBundleName"); + res = ObjectDmsHandler::GetInstance().IsContinue("bundleName2"); + EXPECT_FALSE(res); + ObjectDmsHandler::GetInstance().dmsEvents_.clear(); +} + +/** +* @tc.name: IsContinueTest_002 +* @tc.desc: IsContinue test. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectDmsHandlerTest, IsContinue_002, TestSize.Level0) +{ + ObjectDmsHandler::GetInstance().RegisterDmsEvent(); + DistributedHardware::DmDeviceInfo localDeviceInfo; + DistributedHardware::DeviceManager::GetInstance().GetLocalDeviceInfo(PKG_NAME, localDeviceInfo); + std::string localNetworkId = localDeviceInfo.networkId; + DistributedSchedule::EventNotify notify; + notify.dSchedEventType_ = DistributedSchedule::DSchedEventType::DMS_CONTINUE; + notify.srcNetworkId_ = "networkId1"; + notify.dstNetworkId_ = localNetworkId; + notify.srcBundleName_ = "bundleName1"; + notify.destBundleName_ = "bundleName2"; + DmsEventListener listener; + listener.DSchedEventNotify(notify); + auto res = ObjectDmsHandler::GetInstance().IsContinue("bundleName1"); EXPECT_FALSE(res); + res = ObjectDmsHandler::GetInstance().IsContinue("bundleName2"); + EXPECT_TRUE(res); ObjectDmsHandler::GetInstance().dmsEvents_.clear(); } @@ -78,4 +107,45 @@ HWTEST_F(ObjectDmsHandlerTest, ReceiveDmsEvent_001, TestSize.Level0) EXPECT_EQ(ObjectDmsHandler::GetInstance().dmsEvents_.back().first.srcNetworkId_, "srcNetworkId20"); ObjectDmsHandler::GetInstance().dmsEvents_.clear(); } + +/** +* @tc.name: GetDstBundleName_001 +* @tc.desc: IsContinue test. +* @tc.type: FUNC +*/ +HWTEST_F(ObjectDmsHandlerTest, GetDstBundleName_001, TestSize.Level0) +{ + DistributedHardware::DmDeviceInfo localDeviceInfo; + DistributedHardware::DeviceManager::GetInstance().GetLocalDeviceInfo(PKG_NAME, localDeviceInfo); + std::string localNetworkId = localDeviceInfo.networkId; + + std::string srcNetworkId = localNetworkId; + std::string srcBundleName = "bundleName1"; + std::string dstNetworkId = "networkId2"; + std::string destBundleName = "bundleName2"; + + auto res = ObjectDmsHandler::GetInstance().GetDstBundleName(srcBundleName, dstNetworkId); + EXPECT_EQ(res, srcBundleName); + + DistributedSchedule::EventNotify notify; + notify.dSchedEventType_ = DistributedSchedule::DSchedEventType::DMS_CONTINUE; + notify.srcNetworkId_ = srcNetworkId; + notify.dstNetworkId_ = dstNetworkId; + notify.srcBundleName_ = srcBundleName; + notify.destBundleName_ = destBundleName; + ObjectDmsHandler::GetInstance().ReceiveDmsEvent(notify); + + res = ObjectDmsHandler::GetInstance().GetDstBundleName(srcBundleName, dstNetworkId); + EXPECT_EQ(res, destBundleName); + + ObjectDmsHandler::GetInstance().dmsEvents_.clear(); + + auto timestamp = std::chrono::steady_clock::now() - std::chrono::seconds(20); + ObjectDmsHandler::GetInstance().dmsEvents_.push_back({notify, timestamp}); + + res = ObjectDmsHandler::GetInstance().GetDstBundleName(srcBundleName, dstNetworkId); + EXPECT_EQ(res, srcBundleName); + + ObjectDmsHandler::GetInstance().dmsEvents_.clear(); +} } // namespace OHOS::Test diff --git a/datamgr_service/services/distributeddataservice/service/test/object_manager_test.cpp b/datamgr_service/services/distributeddataservice/service/test/object_manager_test.cpp index bccbc22e28dddaa98d1d2f07f9261a49b8261297..5d25fc0b1d94796dddd8fae403a3b97ccd13a065 100644 --- a/datamgr_service/services/distributeddataservice/service/test/object_manager_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/object_manager_test.cpp @@ -16,12 +16,14 @@ #define LOG_TAG "ObjectManagerTest" #include "object_manager.h" + #include -#include "snapshot/machine_status.h" +#include + #include "executor_pool.h" -#include "object_types.h" #include "kv_store_nb_delegate_mock.h" -#include +#include "object_types.h" +#include "snapshot/machine_status.h" using namespace testing::ext; using namespace OHOS::DistributedObject; @@ -838,7 +840,7 @@ HWTEST_F(ObjectManagerTest, PushAssets001, TestSize.Level0) completes.push_back(1); // for testing completes.push_back(2); // for testing data.insert({assetPrefix, completes}); - auto result = manager->PushAssets(100, appId_, sessionId_, data, deviceId_); + auto result = manager->PushAssets(appId_, appId_, sessionId_, data, deviceId_); ASSERT_EQ(result, DistributedObject::OBJECT_SUCCESS); } diff --git a/datamgr_service/services/distributeddataservice/service/test/object_snapshot_test.cpp b/datamgr_service/services/distributeddataservice/service/test/object_snapshot_test.cpp index 90cdc9daf4852c6f521e6104ec59eb004b0bc2b9..37cee3e9cc447305c8b345428a5c6b5309332284 100644 --- a/datamgr_service/services/distributeddataservice/service/test/object_snapshot_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/object_snapshot_test.cpp @@ -16,9 +16,11 @@ #define LOG_TAG "ObjectSnapshotTest" #include "object_snapshot.h" + #include -#include "snapshot/machine_status.h" + #include "executor_pool.h" +#include "snapshot/machine_status.h" using namespace testing::ext; using namespace OHOS::DistributedObject; 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 91b54fb417965db1fc7bac83474ee52434e78c08..165a766ae74270f188961c5d97f4bf55d5eb43ef 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 @@ -14,9 +14,10 @@ */ #define LOG_TAG "RdbAssetLoaderTest" +#include "rdb_asset_loader.h" + #include "gtest/gtest.h" #include "log_print.h" -#include "rdb_asset_loader.h" #include "rdb_notifier_proxy.h" #include "rdb_watcher.h" #include "store/cursor.h" @@ -28,8 +29,7 @@ using namespace testing::ext; using namespace OHOS::DistributedRdb; using namespace OHOS::DistributedData; using Type = DistributedDB::Type; -const DistributedDB::Asset g_rdbAsset = { - .version = 1, +const DistributedDB::Asset g_rdbAsset = { .version = 1, .name = "Phone", .assetId = "0", .subpath = "/local/sync", @@ -37,8 +37,7 @@ const DistributedDB::Asset g_rdbAsset = { .modifyTime = "123456", .createTime = "createTime", .size = "256", - .hash = "ASE" -}; + .hash = "ASE" }; namespace OHOS::Test { namespace DistributedRDBTest { class RdbAssetLoaderTest : public testing::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 0646e6ff9a77baa0ecd474bd5533cdebec549f57..3000a5d68259e7e963f24039fe29975a010324e9 100644 --- a/datamgr_service/services/distributeddataservice/service/test/rdb_cloud_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/rdb_cloud_test.cpp @@ -25,16 +25,9 @@ using namespace OHOS::DistributedData; using namespace OHOS::DistributedRdb; using DBVBucket = DistributedDB::VBucket; using DBStatus = DistributedDB::DBStatus; -std::vector g_DBVBucket = { - { - {"#gid", {"0000000"}}, - {"#flag", {true}}, - {"#value", {int64_t(100)}}, - {"#float", {double(100)}}, - {"#_type", {int64_t(1)}}, - {"#_query", {Bytes({ 1, 2, 3, 4 })}} - } -}; +std::vector g_DBVBucket = { { { "#gid", { "0000000" } }, { "#flag", { true } }, + { "#value", { int64_t(100) } }, { "#float", { double(100) } }, { "#_type", { int64_t(1) } }, + { "#_query", { Bytes({ 1, 2, 3, 4 }) } } } }; namespace OHOS::Test { namespace DistributedRDBTest { class RdbCloudTest : public testing::Test { @@ -43,7 +36,6 @@ public: static void TearDownTestCase(void){}; void SetUp(){}; void TearDown(){}; -protected: }; /** diff --git a/datamgr_service/services/distributeddataservice/service/test/rdb_cursor_test.cpp b/datamgr_service/services/distributeddataservice/service/test/rdb_cursor_test.cpp index 02f36f3ca6dc9cbd553e2b12f5f5610b871f3fbf..4c14b80a44fc8868eb7018c5868b9976f8775a6c 100644 --- a/datamgr_service/services/distributeddataservice/service/test/rdb_cursor_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/rdb_cursor_test.cpp @@ -14,9 +14,10 @@ */ #define LOG_TAG "RdbCursorTest" +#include "rdb_cursor.h" + #include "gtest/gtest.h" #include "log_print.h" -#include "rdb_cursor.h" #include "result_set.h" #include "store/general_value.h" @@ -34,9 +35,7 @@ public: MockResultSet() {} virtual ~MockResultSet() {} - void Close() override - { - } + void Close() override {} int GetCount() const override { @@ -110,7 +109,7 @@ public: void GetColumnNames(std::vector &columnNames) const override { - columnNames = {"age", "identifier", "name", "phoneNumber"}; + columnNames = { "age", "identifier", "name", "phoneNumber" }; } DBStatus GetColumnType(int columnIndex, DistributedDB::ResultSet::ColumnType &columnType) const override @@ -189,6 +188,7 @@ public: static void TearDownTestCase(void){}; void SetUp(){}; void TearDown(){}; + protected: static std::shared_ptr resultSet; static std::shared_ptr rdbCursor; diff --git a/datamgr_service/services/distributeddataservice/service/test/rdb_query_test.cpp b/datamgr_service/services/distributeddataservice/service/test/rdb_query_test.cpp index 618f7dcfffea036229bea9552dcca6ddf31124fa..72572e9d31296d6c23fc8493c623ac3e5580d6a0 100644 --- a/datamgr_service/services/distributeddataservice/service/test/rdb_query_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/rdb_query_test.cpp @@ -14,9 +14,10 @@ */ #define LOG_TAG "RdbQueryTest" +#include "rdb_query.h" + #include "gtest/gtest.h" #include "log_print.h" -#include "rdb_query.h" #include "utils/anonymous.h" #include "value_proxy.h" @@ -32,7 +33,6 @@ public: static void TearDownTestCase(void){}; void SetUp(){}; void TearDown(){}; -protected: }; /** diff --git a/datamgr_service/services/distributeddataservice/service/test/rdb_result_set_impl_test.cpp b/datamgr_service/services/distributeddataservice/service/test/rdb_result_set_impl_test.cpp index 3275efb5ee4d10c80d49e19747071bcc265129be..390048b80c6ab61c29ebe7c2d660a60e18acdafd 100644 --- a/datamgr_service/services/distributeddataservice/service/test/rdb_result_set_impl_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/rdb_result_set_impl_test.cpp @@ -13,9 +13,10 @@ * limitations under the License. */ +#include "rdb_result_set_impl.h" + #include "gtest/gtest.h" #include "mock/cursor_mock.h" -#include "rdb_result_set_impl.h" #include "store/cursor.h" using namespace testing::ext; using namespace OHOS; diff --git a/datamgr_service/services/distributeddataservice/service/test/rdb_result_set_stub_test.cpp b/datamgr_service/services/distributeddataservice/service/test/rdb_result_set_stub_test.cpp index 981ca6ed35149b1532fdf0bb2f1e238d805e34ed..49282237b0a2046406d28d5d3ad95c545032d54a 100644 --- a/datamgr_service/services/distributeddataservice/service/test/rdb_result_set_stub_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/rdb_result_set_stub_test.cpp @@ -14,13 +14,14 @@ */ #define LOG_TAG "RdbResultSetStubTest" +#include "rdb_result_set_stub.h" + #include "gtest/gtest.h" #include "log_print.h" #include "message_parcel.h" #include "rdb_result_set_impl.h" -#include "rdb_result_set_stub.h" -#include "store/cursor.h" #include "securec.h" +#include "store/cursor.h" using namespace testing::ext; using namespace OHOS; @@ -35,7 +36,6 @@ public: static void TearDownTestCase(void){}; void SetUp(){}; void TearDown(){}; -protected: }; /** diff --git a/datamgr_service/services/distributeddataservice/service/test/value_proxy_test.cpp b/datamgr_service/services/distributeddataservice/service/test/value_proxy_test.cpp index bdedc60489f88adeb9b268f253ba3c4d257b513e..8ada4d4c9607cfd49fc88bb1d6f198937a613377 100644 --- a/datamgr_service/services/distributeddataservice/service/test/value_proxy_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/value_proxy_test.cpp @@ -14,9 +14,11 @@ */ #define LOG_TAG "ValueProxyServiceTest" +#include "value_proxy.h" + #include + #include "log_print.h" -#include "value_proxy.h" namespace OHOS::Test { using namespace testing::ext; using namespace OHOS::DistributedData; diff --git a/datamgr_service/services/distributeddataservice/service/udmf/BUILD.gn b/datamgr_service/services/distributeddataservice/service/udmf/BUILD.gn index 65d462e1d34b85819a1a08e5d43303e3275ec41f..9824c5be0998860f2810b558181c7671c091fa0a 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/udmf/BUILD.gn @@ -60,11 +60,12 @@ ohos_shared_library("udmf_server") { "store/store_cache.cpp", "udmf_service_impl.cpp", "udmf_service_stub.cpp", - "utd/custom_utd_installer.cpp", ] configs = [ ":module_public_config" ] + cflags = [ "-D_LIBCPP_HAS_COND_CLOCKWAIT" ] + deps = [ "${data_service_path}/adapter:distributeddata_adapter", "${data_service_path}/framework:distributeddatasvcfwk", diff --git a/datamgr_service/services/distributeddataservice/service/udmf/store/runtime_store.cpp b/datamgr_service/services/distributeddataservice/service/udmf/store/runtime_store.cpp index 179b49fe30def802c950890477a420f83fc31f6a..3d1cc59f47a13833b84cc3f8745d10719d5b8fa3 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/store/runtime_store.cpp +++ b/datamgr_service/services/distributeddataservice/service/udmf/store/runtime_store.cpp @@ -18,7 +18,7 @@ #include #include -#include +#include #include #include "log_print.h" 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 b47e61b2f29e2f9272ae639046d445954a00cfc1..939453cfd0c30e3af904976363aa48d0a5f9e1b9 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_impl.cpp @@ -32,7 +32,6 @@ #include "reporter.h" #include "uri_permission_manager.h" #include "uri.h" -#include "utd/custom_utd_installer.h" #include "udmf_conversion.h" #include "udmf_radar_reporter.h" #include "securec.h" @@ -63,8 +62,6 @@ UdmfServiceImpl::Factory::Factory() } return product_; }, FeatureSystem::BIND_NOW); - staticActs_ = std::make_shared(); - FeatureSystem::GetInstance().RegisterStaticActs("udmf", staticActs_); auto observer = std::make_shared(); DistributedKv::AccountDelegate::GetInstance()->Subscribe(observer); } @@ -722,44 +719,6 @@ int32_t UdmfServiceImpl::OnBind(const BindInfo &bindInfo) return 0; } -int32_t UdmfServiceImpl::UdmfStatic::OnAppInstall(const std::string &bundleName, int32_t user, - int32_t index) -{ - ZLOGD("Bundle: %{public}s installed.", bundleName.c_str()); - auto status = CustomUtdInstaller::GetInstance().InstallUtd(bundleName, user); - if (status != E_OK) { - ZLOGE("Install Utd failed, bundleName: %{public}s, status: %{public}d", bundleName.c_str(), status); - } - return status; -} - -int32_t UdmfServiceImpl::UdmfStatic::OnAppUpdate(const std::string &bundleName, int32_t user, - int32_t index) -{ - ZLOGD("Bundle: %{public}s Update.", bundleName.c_str()); - auto status = CustomUtdInstaller::GetInstance().UninstallUtd(bundleName, user); - if (status != E_OK) { - ZLOGE("Uninstall utd failed, bundleName: %{public}s, status: %{public}d.", bundleName.c_str(), status); - return status; - } - status = CustomUtdInstaller::GetInstance().InstallUtd(bundleName, user); - if (status != E_OK) { - ZLOGE("Install utd failed, bundleName: %{public}s, status: %{public}d.", bundleName.c_str(), status); - } - return status; -} - -int32_t UdmfServiceImpl::UdmfStatic::OnAppUninstall(const std::string &bundleName, int32_t user, - int32_t index) -{ - ZLOGD("Bundle: %{public}s uninstalled.", bundleName.c_str()); - auto status = CustomUtdInstaller::GetInstance().UninstallUtd(bundleName, user); - if (status != E_OK) { - ZLOGE("Uninstall utd failed, bundleName: %{public}s, status: %{public}d.", bundleName.c_str(), status); - } - return status; -} - int32_t UdmfServiceImpl::ObtainAsynProcess(AsyncProcessInfo &processInfo) { processInfo = asyncProcessInfo_; diff --git a/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_impl.h b/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_impl.h index ca9a11071ccb4267a7509b965c43c77510ab6d62..a3095c9c1c99df3765b017adfcd90cb13f6bd8ff 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_impl.h +++ b/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_impl.h @@ -63,14 +63,6 @@ private: bool IsPermissionInCache(const QueryOption &query); bool IsReadAndKeep(const std::vector &privileges, const QueryOption &query); - using StaticActs = DistributedData::StaticActs; - class UdmfStatic : public StaticActs { - public: - ~UdmfStatic() override {}; - int32_t OnAppInstall(const std::string &bundleName, int32_t user, int32_t index) override; - int32_t OnAppUpdate(const std::string &bundleName, int32_t user, int32_t index) override; - int32_t OnAppUninstall(const std::string &bundleName, int32_t user, int32_t index) override; - }; class Factory { public: Factory(); @@ -78,7 +70,6 @@ private: private: std::shared_ptr product_; - std::shared_ptr staticActs_; }; static Factory factory_; std::map privilegeCache_; diff --git a/datamgr_service/services/distributeddataservice/service/udmf/utd/custom_utd_installer.cpp b/datamgr_service/services/distributeddataservice/service/udmf/utd/custom_utd_installer.cpp deleted file mode 100644 index 548472b9c76a28421626b9319444bd6016a84a28..0000000000000000000000000000000000000000 --- a/datamgr_service/services/distributeddataservice/service/udmf/utd/custom_utd_installer.cpp +++ /dev/null @@ -1,223 +0,0 @@ -/* - * 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. - */ -#define LOG_TAG "CustomUtdInstaller" - -#include -#include -#include - -#include "error_code.h" -#include "log_print.h" -#include "if_system_ability_manager.h" -#include "iservice_registry.h" -#include "system_ability_definition.h" -#include "utd_graph.h" -#include "custom_utd_json_parser.h" -#include "custom_utd_store.h" -#include "preset_type_descriptors.h" -#include "custom_utd_installer.h" - -namespace OHOS { -namespace UDMF { -constexpr const char *CUSTOM_UTD_PATH = "/data/service/el1/"; -constexpr const char *CUSTOM_UTD_FILE = "/distributeddata/utd/utd-adt.json"; -CustomUtdInstaller::CustomUtdInstaller() -{ -} - -CustomUtdInstaller::~CustomUtdInstaller() -{ -} - -CustomUtdInstaller &CustomUtdInstaller::GetInstance() -{ - static CustomUtdInstaller instance; - return instance; -} - -sptr CustomUtdInstaller::GetBundleManager() -{ - auto samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); - if (samgrProxy == nullptr) { - ZLOGE("samgrProxy is null."); - return nullptr; - } - auto bmsProxy = samgrProxy->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID); - if (bmsProxy == nullptr) { - ZLOGE("failed to get bms from samgrProxy."); - return nullptr; - } - return iface_cast(bmsProxy); -} - -int32_t CustomUtdInstaller::InstallUtd(const std::string &bundleName, int32_t user) -{ - std::string path = CUSTOM_UTD_PATH + std::to_string(user) + CUSTOM_UTD_FILE; - std::vector customTyepCfgs = CustomUtdStore::GetInstance().GetTypeCfgs(path); - std::vector presetTypes = PresetTypeDescriptors::GetInstance().GetPresetTypes(); - std::vector modules = GetHapModules(bundleName, user); - bool isSucc = true; - for (std::string module : modules) { - auto utdTypes = GetModuleCustomUtdTypes(bundleName, module, user); - if (utdTypes.first.empty() && utdTypes.second.empty()) { - ZLOGD("Module custom utd types is empty."); - continue; - } - if (!UtdCfgsChecker::GetInstance().CheckTypeDescriptors(utdTypes, presetTypes, customTyepCfgs, bundleName)) { - ZLOGE("Parse json failed, moduleName: %{public}s, bundleName: %{public}s.", module.c_str(), - bundleName.c_str()); - isSucc = false; - continue; - } - if (SaveCustomUtds(utdTypes, customTyepCfgs, bundleName, path) != E_OK) { - ZLOGE("Install save custom utds failed, moduleName: %{public}s, bundleName: %{public}s.", module.c_str(), - bundleName.c_str()); - isSucc = false; - continue; - } - } - if (!isSucc) { - return E_ERROR; - } - return E_OK; -} - -int32_t CustomUtdInstaller::UninstallUtd(const std::string &bundleName, int32_t user) -{ - std::string path = CUSTOM_UTD_PATH + std::to_string(user) + CUSTOM_UTD_FILE; - std::vector customTyepCfgs = CustomUtdStore::GetInstance().GetTypeCfgs(path); - std::vector deletionMock; - if (!customTyepCfgs.empty()) { - deletionMock.insert(deletionMock.end(), customTyepCfgs.begin(), customTyepCfgs.end()); - } - for (auto iter = deletionMock.begin(); iter != deletionMock.end();) { - auto it = find (iter->installerBundles.begin(), iter->installerBundles.end(), bundleName); - if (it != iter->installerBundles.end()) { - iter->installerBundles.erase(it); - } - if (iter->installerBundles.empty()) { - iter = deletionMock.erase(iter); - } else { - iter++; - } - } - std::vector presetTypes = PresetTypeDescriptors::GetInstance().GetPresetTypes(); - if (!UtdCfgsChecker::GetInstance().CheckBelongingToTypes(deletionMock, presetTypes)) { - ZLOGW("Uninstall error, because of belongingToTypes check failed."); - return E_ERROR; - } - for (auto customIter = customTyepCfgs.begin(); customIter != customTyepCfgs.end();) { - auto InstallerIter = find (customIter->installerBundles.begin(), customIter->installerBundles.end(), - bundleName); - if (InstallerIter != customIter->installerBundles.end()) { - customIter->installerBundles.erase(InstallerIter); - } - if (customIter->installerBundles.empty()) { - customIter = customTyepCfgs.erase(customIter); - } else { - customIter++; - } - } - if (CustomUtdStore::GetInstance().SaveTypeCfgs(customTyepCfgs, path) != E_OK) { - ZLOGE("Save type cfgs failed, bundleName: %{public}s.", bundleName.c_str()); - return E_ERROR; - } - return E_OK; -} - -std::vector CustomUtdInstaller::GetHapModules(const std::string &bundleName, int32_t user) -{ - auto bundlemgr = GetBundleManager(); - if (bundlemgr == nullptr) { - ZLOGE("Get bms service failed, bundleName: %{public}s.", bundleName.c_str()); - return {}; - } - AppExecFwk::BundleInfo bundleInfo; - if (!bundlemgr->GetBundleInfo(bundleName, AppExecFwk::BundleFlag::GET_BUNDLE_DEFAULT, bundleInfo, user)) { - ZLOGE("Get local bundle info failed, bundleName: %{public}s.", bundleName.c_str()); - } - return bundleInfo.hapModuleNames; -} - -CustomUtdCfgs CustomUtdInstaller::GetModuleCustomUtdTypes(const std::string &bundleName, - const std::string &moduleName, int32_t user) -{ - auto bundlemgr = GetBundleManager(); - std::string jsonStr; - CustomUtdCfgs typeCfgs; - if (bundlemgr == nullptr) { - ZLOGE("Get bms service failed, bundleName: %{public}s.", bundleName.c_str()); - return typeCfgs; - } - auto status = bundlemgr->GetJsonProfile(AppExecFwk::ProfileType::UTD_SDT_PROFILE, bundleName, moduleName, jsonStr, - user); - if (status != NO_ERROR) { - ZLOGD("get json profile failed, bundleName: %{public}s.", bundleName.c_str()); - return typeCfgs; - } - if (jsonStr.empty()) { - ZLOGE("JsonStr is empty, bundleName: %{public}s.", bundleName.c_str()); - return typeCfgs; - } - std::vector declarationType; - std::vector referenceType; - - CustomUtdJsonParser customUtdJsonParser_; - bool res = customUtdJsonParser_.ParseUserCustomUtdJson(jsonStr, declarationType, referenceType); - if (!jsonStr.empty() && res) { - typeCfgs.first = declarationType; - typeCfgs.second = referenceType; - } - return typeCfgs; -} - -int32_t CustomUtdInstaller::SaveCustomUtds(const CustomUtdCfgs &utdTypes, std::vector customTyepCfgs, - const std::string &bundleName, const std::string &path) -{ - for (TypeDescriptorCfg declarationType : utdTypes.first) { - for (auto iter = customTyepCfgs.begin(); iter != customTyepCfgs.end();) { - if (iter->typeId == declarationType.typeId) { - declarationType.installerBundles = iter->installerBundles; - iter = customTyepCfgs.erase(iter); - } else { - iter ++; - } - } - declarationType.installerBundles.emplace(bundleName); - declarationType.ownerBundle = bundleName; - customTyepCfgs.push_back(declarationType); - } - for (TypeDescriptorCfg referenceType : utdTypes.second) { - bool found = false; - for (auto &typeCfg : customTyepCfgs) { - if (typeCfg.typeId == referenceType.typeId) { - typeCfg.installerBundles.emplace(bundleName); - found = true; - break; - } - } - if (!found) { - referenceType.installerBundles.emplace(bundleName); - customTyepCfgs.push_back(referenceType); - } - } - if (CustomUtdStore::GetInstance().SaveTypeCfgs(customTyepCfgs, path) != E_OK) { - ZLOGE("Save type cfgs failed, bundleName: %{public}s.", bundleName.c_str()); - return E_ERROR; - } - return E_OK; -} -} -} \ No newline at end of file diff --git a/interface_sdk/api/@ohos.data.relationalStore.d.ts b/interface_sdk/api/@ohos.data.relationalStore.d.ts index 16e4ce632f3b0ee7235a9ca7fe64d7f376cb3e81..da96b2ad02fd940bd08e7d207365fed9db7ca453 100644 --- a/interface_sdk/api/@ohos.data.relationalStore.d.ts +++ b/interface_sdk/api/@ohos.data.relationalStore.d.ts @@ -407,6 +407,15 @@ declare namespace relationalStore { * @since 12 */ haMode?: HAMode; + + /** + * Specifies the cryptographic parameters used when opening an encrypted database. + * + * @type { ?CryptoParam } + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 14 + */ + cryptoParam?: CryptoParam; } /** @@ -437,6 +446,167 @@ declare namespace relationalStore { MAIN_REPLICA } + /** + * Specifies the cryptographic parameters used when opening an encrypted database. + * + * @typedef CryptoParam + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 14 + */ + interface CryptoParam { + /** + * Specifies the key used when opening an encrypted database. + * When finished passing the key to the database, its content should be set to all-zero. + * + * @type { Uint8Array } + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 14 + */ + encryptionKey: Uint8Array; + + /** + * Specifies the number of KDF iterations used when opening an encrypted database. + * Default number is 10000. + * When the number is set to 0, use default iteration number and encryption algorithm. + * + * @type { ?number } + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 14 + */ + iterationCount?: number; + + /** + * Specifies the encryption algorithm when opening an encrypted database. + * Default encryption algorithm is AES_256_GCM. + * + * @type { ?EncryptionAlgo } + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 14 + */ + encryptionAlgo?: EncryptionAlgo; + + /** + * Specifies the HMAC algorithm when opening an encrypted database. + * Default HMAC algorithm is SHA256. + * + * @type { ?HmacAlgo } + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 14 + */ + hmacAlgo?: HmacAlgo; + + /** + * Specifies the KDF algorithm when opening an encrypted database. + * Default KDF SHA algorithm is the same as HMAC algorithm. + * + * @type { ?KdfAlgo } + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 14 + */ + kdfAlgo?: KdfAlgo; + + /** + * Specifies the page size used when opening an encrypted database. + * Default crypto page size is 1024. + * + * @type { ?number } + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 14 + */ + cryptoPageSize?: number; + } + + /** + * Enumerates the supported encryption algorithm when opening a database. + * + * @enum { number } + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 14 + */ + enum EncryptionAlgo { + /** + * AES_256_GCM: Database is encrypted using AES_256_GCM. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 14 + */ + AES_256_GCM = 0, + + /** + * AES_256_CBC: Database is encrypted using AES_256_CBC. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 14 + */ + AES_256_CBC + } + + /** + * Enumerates the supported HMAC algorithm when opening a database. + * + * @enum { number } + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 14 + */ + enum HmacAlgo { + /** + * SHA1: HMAC_SHA1 algorithm. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 14 + */ + SHA1 = 0, + + /** + * SHA256: HMAC_SHA256 algorithm. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 14 + */ + SHA256, + + /** + * SHA512: HMAC_SHA512 algorithm. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 14 + */ + SHA512 + } + + /** + * Enumerates the supported KDF algorithm when opening a database. + * + * @enum { number } + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 14 + */ + enum KdfAlgo { + /** + * KDF_SHA1: PBKDF2_HMAC_SHA1 algorithm. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 14 + */ + KDF_SHA1 = 0, + + /** + * KDF_SHA256: PBKDF2_HMAC_SHA256 algorithm. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 14 + */ + KDF_SHA256, + + /** + * KDF_SHA512: PBKDF2_HMAC_SHA512 algorithm. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 14 + */ + KDF_SHA512 + } + /** * The cloud sync progress * @@ -1258,6 +1428,56 @@ declare namespace relationalStore { REPAIRED } + /** + * Enumerates the type of transaction. + * + * @enum { number } + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 14 + */ + enum TransactionType { + /** + * The DEFERRED transaction. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 14 + */ + DEFERRED, + + /** + * The IMMEDIATE transaction. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 14 + */ + IMMEDIATE, + + /** + * The EXCLUSIVE transaction. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 14 + */ + EXCLUSIVE + } + + /** + * Create transaction option. + * + * @interface TransactionOption + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 14 + */ + interface TransactionOption { + /** + * The type of transaction. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 14 + */ + transactionType: TransactionType; + } + /** * Manages relational database configurations. * @@ -3827,10 +4047,10 @@ declare namespace relationalStore { * @since 12 */ update( - values: ValuesBucket, - predicates: RdbPredicates, - conflict: ConflictResolution, - callback: AsyncCallback + values: ValuesBucket, + predicates: RdbPredicates, + conflict: ConflictResolution, + callback: AsyncCallback ): void; /** @@ -4055,10 +4275,10 @@ declare namespace relationalStore { * @since 12 */ update( - table: string, - values: ValuesBucket, - predicates: dataSharePredicates.DataSharePredicates, - callback: AsyncCallback + table: string, + values: ValuesBucket, + predicates: dataSharePredicates.DataSharePredicates, + callback: AsyncCallback ): void; /** @@ -4602,10 +4822,10 @@ declare namespace relationalStore { * @since 12 */ query( - table: string, - predicates: dataSharePredicates.DataSharePredicates, - columns: Array, - callback: AsyncCallback + table: string, + predicates: dataSharePredicates.DataSharePredicates, + columns: Array, + callback: AsyncCallback ): void; /** @@ -4645,9 +4865,9 @@ declare namespace relationalStore { * @since 12 */ query( - table: string, - predicates: dataSharePredicates.DataSharePredicates, - columns?: Array + table: string, + predicates: dataSharePredicates.DataSharePredicates, + columns?: Array ): Promise; /** @@ -4893,10 +5113,10 @@ declare namespace relationalStore { * @since 12 */ getModifyTime( - table: string, - columnName: string, - primaryKeys: PRIKeyType[], - callback: AsyncCallback + table: string, + columnName: string, + primaryKeys: PRIKeyType[], + callback: AsyncCallback ): void; /** @@ -5497,6 +5717,8 @@ declare namespace relationalStore { * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform * @since 12 + * @deprecated since 14 + * @useinstead ohos.data.relationalStore.RdbStore.createTransaction */ beginTransaction(): void; @@ -5570,6 +5792,8 @@ declare namespace relationalStore { * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform * @since 12 + * @deprecated since 14 + * @useinstead ohos.data.relationalStore.Transaction.commit */ commit(): void; @@ -5643,6 +5867,8 @@ declare namespace relationalStore { * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @crossplatform * @since 12 + * @deprecated since 14 + * @useinstead ohos.data.relationalStore.Transaction.rollback */ rollBack(): void; @@ -6050,10 +6276,10 @@ declare namespace relationalStore { * @since 12 */ setDistributedTables( - tables: Array, - type: DistributedType, - config: DistributedConfig, - callback: AsyncCallback + tables: Array, + type: DistributedType, + config: DistributedConfig, + callback: AsyncCallback ): void; /** @@ -6309,10 +6535,10 @@ declare namespace relationalStore { * @since 12 */ cloudSync( - mode: SyncMode, - tables: string[], - progress: Callback, - callback: AsyncCallback + mode: SyncMode, + tables: string[], + progress: Callback, + callback: AsyncCallback ): void; /** @@ -6378,10 +6604,10 @@ declare namespace relationalStore { * @since 12 */ cloudSync( - mode: SyncMode, - predicates: RdbPredicates, - progress: Callback, - callback: AsyncCallback + mode: SyncMode, + predicates: RdbPredicates, + progress: Callback, + callback: AsyncCallback ): void; /** @@ -6451,11 +6677,11 @@ declare namespace relationalStore { * @since 12 */ remoteQuery( - device: string, - table: string, - predicates: RdbPredicates, - columns: Array, - callback: AsyncCallback + device: string, + table: string, + predicates: RdbPredicates, + columns: Array, + callback: AsyncCallback ): void; /** @@ -6690,9 +6916,9 @@ declare namespace relationalStore { * @since 12 */ off( - event: 'dataChange', - type: SubscribeType, - observer?: Callback> | Callback> + event: 'dataChange', + type: SubscribeType, + observer?: Callback> | Callback> ): void; /** @@ -7023,6 +7249,458 @@ declare namespace relationalStore { * @since 12 */ unlockCloudContainer(): Promise; + + /** + * create a transaction instance and begin. + * + * @param { TransactionOption } 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. + * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800015 - The database is busy. + * @throws { BusinessError } 14800023 - SQLite: Access permission denied. + * @throws { BusinessError } 14800024 - SQLite: The database file is locked. + * @throws { BusinessError } 14800025 - SQLite: A table in the database is locked. + * @throws { BusinessError } 14800026 - SQLite: The database is out of memory. + * @throws { BusinessError } 14800028 - SQLite: Some kind of disk I/O error occurred. + * @throws { BusinessError } 14800029 - SQLite: The database is full. + * @throws { BusinessError } 14800030 - SQLite: Unable to open the database file. + * @throws { BusinessError } 14800032 - SQLite: Abort due to constraint violation. + * @throws { BusinessError } 14800033 - SQLite: Data type mismatch. + * @throws { BusinessError } 14800034 - SQLite: Library used incorrectly. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 14 + */ + createTransaction(option?: TransactionOption): Promise; + } + + interface Transaction { + /** + * commit the transaction. + * + * @throws { BusinessError } 14800000 - Inner error. + * @throws { BusinessError } 14800011 - Database corrupted. + * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800021 - SQLite: Generic error. + * @throws { BusinessError } 14800023 - SQLite: Access permission denied. + * @throws { BusinessError } 14800024 - SQLite: The database file is locked. + * @throws { BusinessError } 14800025 - SQLite: A table in the database is locked. + * @throws { BusinessError } 14800026 - SQLite: The database is out of memory. + * @throws { BusinessError } 14800027 - SQLite: Attempt to write a readonly database. + * @throws { BusinessError } 14800028 - SQLite: Some kind of disk I/O error occurred. + * @throws { BusinessError } 14800029 - SQLite: The database is full. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 14 + */ + commit(): Promise; + + /** + * rollback the transaction. + * + * @throws { BusinessError } 14800000 - Inner error. + * @throws { BusinessError } 14800011 - Database corrupted. + * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800021 - SQLite: Generic error. + * @throws { BusinessError } 14800023 - SQLite: Access permission denied. + * @throws { BusinessError } 14800024 - SQLite: The database file is locked. + * @throws { BusinessError } 14800025 - SQLite: A table in the database is locked. + * @throws { BusinessError } 14800026 - SQLite: The database is out of memory. + * @throws { BusinessError } 14800027 - SQLite: Attempt to write a readonly database. + * @throws { BusinessError } 14800028 - SQLite: Some kind of disk I/O error occurred. + * @throws { BusinessError } 14800029 - SQLite: The database is full. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 14 + */ + rollback(): Promise; + + /** + * Inserts a row of data into the target table. + * + * @param { string } table - Indicates the target table. + * @param { ValuesBucket } values - Indicates the row of data {@link ValuesBucket} to be inserted into the table. + * @param { ConflictResolution } conflict - Indicates the {@link ConflictResolution} to insert data into the table. + * @returns { Promise } The row ID if the operation is successful. return -1 otherwise. + * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; + *
2. Incorrect parameter types. + * @throws { BusinessError } 14800000 - Inner error. + * @throws { BusinessError } 14800011 - Database corrupted. + * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800021 - SQLite: Generic error. + * @throws { BusinessError } 14800023 - SQLite: Access permission denied. + * @throws { BusinessError } 14800024 - SQLite: The database file is locked. + * @throws { BusinessError } 14800025 - SQLite: A table in the database is locked. + * @throws { BusinessError } 14800026 - SQLite: The database is out of memory. + * @throws { BusinessError } 14800027 - SQLite: Attempt to write a readonly database. + * @throws { BusinessError } 14800028 - SQLite: Some kind of disk I/O error occurred. + * @throws { BusinessError } 14800029 - SQLite: The database is full. + * @throws { BusinessError } 14800031 - SQLite: TEXT or BLOB exceeds size limit. + * @throws { BusinessError } 14800033 - SQLite: Data type mismatch. + * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 14 + */ + insert(table: string, values: ValuesBucket, conflict?: ConflictResolution): Promise; + + /** + * Inserts a row of data into the target table with sync interface, just use in TaskPool or Worker. + * + * @param { string } table - Indicates the target table. + * @param { ValuesBucket } values - Indicates the row of data {@link ValuesBucket} to be inserted into the table. + * @param { ConflictResolution } conflict - Indicates the {@link ConflictResolution} to insert data into the table. + * @returns { number } The row ID if the operation is successful. return -1 otherwise. + * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; + *
2. Incorrect parameter types. + * @throws { BusinessError } 14800000 - Inner error. + * @throws { BusinessError } 14800011 - Database corrupted. + * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800021 - SQLite: Generic error. + * @throws { BusinessError } 14800023 - SQLite: Access permission denied. + * @throws { BusinessError } 14800024 - SQLite: The database file is locked. + * @throws { BusinessError } 14800025 - SQLite: A table in the database is locked. + * @throws { BusinessError } 14800026 - SQLite: The database is out of memory. + * @throws { BusinessError } 14800027 - SQLite: Attempt to write a readonly database. + * @throws { BusinessError } 14800028 - SQLite: Some kind of disk I/O error occurred. + * @throws { BusinessError } 14800029 - SQLite: The database is full. + * @throws { BusinessError } 14800031 - SQLite: TEXT or BLOB exceeds size limit. + * @throws { BusinessError } 14800033 - SQLite: Data type mismatch. + * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 14 + */ + insertSync(table: string, values: ValuesBucket | sendableRelationalStore.ValuesBucket, conflict?: ConflictResolution): number; + + /** + * Inserts a batch of data into the target table. + * + * @param { string } table - Indicates the target table. + * @param { Array } values - Indicates the rows of data {@link ValuesBucket} to be inserted into the table. + * @returns { Promise } The number of values that were inserted if the operation is successful. returns -1 otherwise. + * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; + *
2. Incorrect parameter types. + * @throws { BusinessError } 14800000 - Inner error. + * @throws { BusinessError } 14800011 - Database corrupted. + * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800021 - SQLite: Generic error. + * @throws { BusinessError } 14800023 - SQLite: Access permission denied. + * @throws { BusinessError } 14800024 - SQLite: The database file is locked. + * @throws { BusinessError } 14800025 - SQLite: A table in the database is locked. + * @throws { BusinessError } 14800026 - SQLite: The database is out of memory. + * @throws { BusinessError } 14800027 - SQLite: Attempt to write a readonly database. + * @throws { BusinessError } 14800028 - SQLite: Some kind of disk I/O error occurred. + * @throws { BusinessError } 14800029 - SQLite: The database is full. + * @throws { BusinessError } 14800031 - SQLite: TEXT or BLOB exceeds size limit. + * @throws { BusinessError } 14800033 - SQLite: Data type mismatch. + * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 14 + */ + batchInsert(table: string, values: Array): Promise; + + /** + * Inserts a batch of data into the target table. + * + * @param { string } table - Indicates the target table. + * @param { Array } values - Indicates the rows of data {@link ValuesBucket} to be inserted into the table. + * @returns { number } The number of values that were inserted if the operation is successful. returns -1 otherwise. + * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; + *
2. Incorrect parameter types. + * @throws { BusinessError } 14800000 - Inner error. + * @throws { BusinessError } 14800011 - Database corrupted. + * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800021 - SQLite: Generic error. + * @throws { BusinessError } 14800023 - SQLite: Access permission denied. + * @throws { BusinessError } 14800024 - SQLite: The database file is locked. + * @throws { BusinessError } 14800025 - SQLite: A table in the database is locked. + * @throws { BusinessError } 14800026 - SQLite: The database is out of memory. + * @throws { BusinessError } 14800027 - SQLite: Attempt to write a readonly database. + * @throws { BusinessError } 14800028 - SQLite: Some kind of disk I/O error occurred. + * @throws { BusinessError } 14800029 - SQLite: The database is full. + * @throws { BusinessError } 14800031 - SQLite: TEXT or BLOB exceeds size limit. + * @throws { BusinessError } 14800033 - SQLite: Data type mismatch. + * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 14 + */ + batchInsertSync(table: string, values: Array): number; + + /** + * Updates data in the database based on a specified instance object of RdbPredicates. + * + * @param { ValuesBucket } values - Indicates the row of data to be updated in the database. + * The key-value pairs are associated with column names of the database table. + * @param { RdbPredicates } predicates - Indicates the specified update condition by the instance object of {@link RdbPredicates}. + * @param { ConflictResolution } conflict - Indicates the {@link ConflictResolution} to insert data into the table. + * @returns { Promise } The number of affected rows. + * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; + *
2. Incorrect parameter types. + * @throws { BusinessError } 14800000 - Inner error. + * @throws { BusinessError } 14800011 - Database corrupted. + * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800021 - SQLite: Generic error. + * @throws { BusinessError } 14800023 - SQLite: Access permission denied. + * @throws { BusinessError } 14800024 - SQLite: The database file is locked. + * @throws { BusinessError } 14800025 - SQLite: A table in the database is locked. + * @throws { BusinessError } 14800026 - SQLite: The database is out of memory. + * @throws { BusinessError } 14800027 - SQLite: Attempt to write a readonly database. + * @throws { BusinessError } 14800028 - SQLite: Some kind of disk I/O error occurred. + * @throws { BusinessError } 14800029 - SQLite: The database is full. + * @throws { BusinessError } 14800031 - SQLite: TEXT or BLOB exceeds size limit. + * @throws { BusinessError } 14800033 - SQLite: Data type mismatch. + * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 14 + */ + update(values: ValuesBucket, predicates: RdbPredicates, conflict?: ConflictResolution): Promise; + + /** + * Updates data in the database based on a specified instance object of RdbPredicates with sync interface. + * + * @param { ValuesBucket } values - Indicates the row of data to be updated in the database. + * The key-value pairs are associated with column names of the database table. + * @param { RdbPredicates } predicates - Indicates the specified update condition by the instance object of {@link RdbPredicates}. + * @param { ConflictResolution } conflict - Indicates the {@link ConflictResolution} to insert data into the table. + * @returns { number } The number of affected rows. + * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; + *
2. Incorrect parameter types. + * @throws { BusinessError } 14800000 - Inner error. + * @throws { BusinessError } 14800011 - Database corrupted. + * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800021 - SQLite: Generic error. + * @throws { BusinessError } 14800023 - SQLite: Access permission denied. + * @throws { BusinessError } 14800024 - SQLite: The database file is locked. + * @throws { BusinessError } 14800025 - SQLite: A table in the database is locked. + * @throws { BusinessError } 14800026 - SQLite: The database is out of memory. + * @throws { BusinessError } 14800027 - SQLite: Attempt to write a readonly database. + * @throws { BusinessError } 14800028 - SQLite: Some kind of disk I/O error occurred. + * @throws { BusinessError } 14800029 - SQLite: The database is full. + * @throws { BusinessError } 14800031 - SQLite: TEXT or BLOB exceeds size limit. + * @throws { BusinessError } 14800033 - SQLite: Data type mismatch. + * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 14 + */ + updateSync(values: ValuesBucket, predicates: RdbPredicates, conflict?: ConflictResolution): number; + + /** + * Deletes data from the database based on a specified instance object of RdbPredicates. + * + * @param { RdbPredicates } predicates - The specified delete condition by the instance object of {@link RdbPredicates}. + * @returns { Promise } return the number of affected rows. + * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; + *
2. Incorrect parameter types. + * @throws { BusinessError } 14800000 - Inner error. + * @throws { BusinessError } 14800011 - Database corrupted. + * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800021 - SQLite: Generic error. + * @throws { BusinessError } 14800023 - SQLite: Access permission denied. + * @throws { BusinessError } 14800024 - SQLite: The database file is locked. + * @throws { BusinessError } 14800025 - SQLite: A table in the database is locked. + * @throws { BusinessError } 14800026 - SQLite: The database is out of memory. + * @throws { BusinessError } 14800027 - SQLite: Attempt to write a readonly database. + * @throws { BusinessError } 14800028 - SQLite: Some kind of disk I/O error occurred. + * @throws { BusinessError } 14800029 - SQLite: The database is full. + * @throws { BusinessError } 14800031 - SQLite: TEXT or BLOB exceeds size limit. + * @throws { BusinessError } 14800033 - SQLite: Data type mismatch. + * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 14 + */ + delete(predicates: RdbPredicates): Promise; + + /** + * Deletes data from the database based on a specified instance object of RdbPredicates with sync interface. + * + * @param { RdbPredicates } predicates - The specified delete condition by the instance object of {@link RdbPredicates}. + * @returns { number } return the number of affected rows. + * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; + *
2. Incorrect parameter types. + * @throws { BusinessError } 14800000 - Inner error. + * @throws { BusinessError } 14800011 - Database corrupted. + * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800021 - SQLite: Generic error. + * @throws { BusinessError } 14800023 - SQLite: Access permission denied. + * @throws { BusinessError } 14800024 - SQLite: The database file is locked. + * @throws { BusinessError } 14800025 - SQLite: A table in the database is locked. + * @throws { BusinessError } 14800026 - SQLite: The database is out of memory. + * @throws { BusinessError } 14800027 - SQLite: Attempt to write a readonly database. + * @throws { BusinessError } 14800028 - SQLite: Some kind of disk I/O error occurred. + * @throws { BusinessError } 14800029 - SQLite: The database is full. + * @throws { BusinessError } 14800031 - SQLite: TEXT or BLOB exceeds size limit. + * @throws { BusinessError } 14800033 - SQLite: Data type mismatch. + * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 14 + */ + deleteSync(predicates: RdbPredicates): number; + + /** + * Queries data in the database based on specified conditions. + * + * @param { RdbPredicates } predicates - The specified query condition by the instance object of {@link RdbPredicates}. + * @param { Array } columns - The columns to query. If the value is null, the query applies to all columns. + * @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. + * @throws { BusinessError } 14800000 - Inner error. + * @throws { BusinessError } 14800011 - Database corrupted. + * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800021 - SQLite: Generic error. + * @throws { BusinessError } 14800023 - SQLite: Access permission denied. + * @throws { BusinessError } 14800024 - SQLite: The database file is locked. + * @throws { BusinessError } 14800025 - SQLite: A table in the database is locked. + * @throws { BusinessError } 14800026 - SQLite: The database is out of memory. + * @throws { BusinessError } 14800028 - SQLite: Some kind of disk I/O error occurred. + * @throws { BusinessError } 14800029 - SQLite: The database is full. + * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 14 + */ + query(predicates: RdbPredicates, columns?: Array): Promise; + + /** + * Queries data in the database based on specified conditions with sync function. + * + * @param { RdbPredicates } predicates - The specified query condition by the instance object of {@link RdbPredicates}. + * @param { Array } columns - The columns to query. If the value is empty array, the query applies to all columns. + * @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. + * @throws { BusinessError } 14800000 - Inner error. + * @throws { BusinessError } 14800011 - Database corrupted. + * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800021 - SQLite: Generic error. + * @throws { BusinessError } 14800023 - SQLite: Access permission denied. + * @throws { BusinessError } 14800024 - SQLite: The database file is locked. + * @throws { BusinessError } 14800025 - SQLite: A table in the database is locked. + * @throws { BusinessError } 14800026 - SQLite: The database is out of memory. + * @throws { BusinessError } 14800028 - SQLite: Some kind of disk I/O error occurred. + * @throws { BusinessError } 14800029 - SQLite: The database is full. + * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 14 + */ + querySync(predicates: RdbPredicates, columns?: Array): ResultSet; + + /** + * 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. + * @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. + * @throws { BusinessError } 14800000 - Inner error. + * @throws { BusinessError } 14800011 - Database corrupted. + * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800021 - SQLite: Generic error. + * @throws { BusinessError } 14800023 - SQLite: Access permission denied. + * @throws { BusinessError } 14800024 - SQLite: The database file is locked. + * @throws { BusinessError } 14800025 - SQLite: A table in the database is locked. + * @throws { BusinessError } 14800026 - SQLite: The database is out of memory. + * @throws { BusinessError } 14800028 - SQLite: Some kind of disk I/O error occurred. + * @throws { BusinessError } 14800029 - SQLite: The database is full. + * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 14 + */ + querySql(sql: string, bindArgs?: 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. + * @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. + * @throws { BusinessError } 14800000 - Inner error. + * @throws { BusinessError } 14800011 - Database corrupted. + * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800021 - SQLite: Generic error. + * @throws { BusinessError } 14800023 - SQLite: Access permission denied. + * @throws { BusinessError } 14800024 - SQLite: The database file is locked. + * @throws { BusinessError } 14800025 - SQLite: A table in the database is locked. + * @throws { BusinessError } 14800026 - SQLite: The database is out of memory. + * @throws { BusinessError } 14800028 - SQLite: Some kind of disk I/O error occurred. + * @throws { BusinessError } 14800029 - SQLite: The database is full. + * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 14 + */ + querySqlSync(sql: string, bindArgs?: Array): ResultSet; + + /** + * Executes a SQL statement that contains specified parameters and returns a value of ValueType. + * + * @param { string } sql - Indicates the SQL statement to execute. + * @param { Array } args - Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. + * @returns { Promise } The promise returned by the function. + * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; + *
2. Incorrect parameter types. + * @throws { BusinessError } 801 - Capability not supported the sql(attach,begin,commit,rollback etc.). + * @throws { BusinessError } 14800000 - Inner error. + * @throws { BusinessError } 14800011 - Database corrupted. + * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800021 - SQLite: Generic error. + * @throws { BusinessError } 14800023 - SQLite: Access permission denied. + * @throws { BusinessError } 14800024 - SQLite: The database file is locked. + * @throws { BusinessError } 14800025 - SQLite: A table in the database is locked. + * @throws { BusinessError } 14800026 - SQLite: The database is out of memory. + * @throws { BusinessError } 14800027 - SQLite: Attempt to write a readonly database. + * @throws { BusinessError } 14800028 - SQLite: Some kind of disk I/O error occurred. + * @throws { BusinessError } 14800029 - SQLite: The database is full. + * @throws { BusinessError } 14800031 - SQLite: TEXT or BLOB exceeds size limit. + * @throws { BusinessError } 14800033 - SQLite: Data type mismatch. + * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 14 + */ + execute(sql: string, args?: Array): Promise; + + /** + * Executes a SQL statement that contains specified parameters and returns a value of ValueType with sync interface. + * + * @param { string } sql - Indicates the SQL statement to execute. + * @param { Array } args - Indicates the {@link ValueType} values of the parameters in the SQL statement. The values are strings. + * @returns { ValueType } The promise returned by the function. + * @throws { BusinessError } 401 - Parameter error. Possible causes: 1. Mandatory parameters are left unspecified; + *
2. Incorrect parameter types. + * @throws { BusinessError } 801 - Capability not supported the sql(attach,begin,commit,rollback etc.). + * @throws { BusinessError } 14800000 - Inner error. + * @throws { BusinessError } 14800011 - Database corrupted. + * @throws { BusinessError } 14800014 - Already closed. + * @throws { BusinessError } 14800021 - SQLite: Generic error. + * @throws { BusinessError } 14800023 - SQLite: Access permission denied. + * @throws { BusinessError } 14800024 - SQLite: The database file is locked. + * @throws { BusinessError } 14800025 - SQLite: A table in the database is locked. + * @throws { BusinessError } 14800026 - SQLite: The database is out of memory. + * @throws { BusinessError } 14800027 - SQLite: Attempt to write a readonly database. + * @throws { BusinessError } 14800028 - SQLite: Some kind of disk I/O error occurred. + * @throws { BusinessError } 14800029 - SQLite: The database is full. + * @throws { BusinessError } 14800031 - SQLite: TEXT or BLOB exceeds size limit. + * @throws { BusinessError } 14800033 - SQLite: Data type mismatch. + * @throws { BusinessError } 14800047 - The WAL file size exceeds the default limit. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 14 + */ + executeSync(sql: string, args?: Array): ValueType; } /** diff --git a/kv_store/frameworks/common/block_data.h b/kv_store/frameworks/common/block_data.h index 9c148b4687dde84cb2ba23b97c4013155d68e5fe..839df28720fa4e2215d13efa4d09946b7013b282 100644 --- a/kv_store/frameworks/common/block_data.h +++ b/kv_store/frameworks/common/block_data.h @@ -18,14 +18,13 @@ #include namespace OHOS { -template +template class BlockData { public: explicit BlockData(uint32_t interval, const T &invalid = T()) : INTERVAL(interval), data_(invalid) {} ~BlockData() {} -public: void SetValue(const T &data) { std::lock_guard lock(mutex_); @@ -37,7 +36,7 @@ public: T GetValue() { std::unique_lock lock(mutex_); - cv_.wait_for(lock, std::chrono::seconds(INTERVAL), [this]() { + cv_.wait_for(lock, Dur(INTERVAL), [this]() { return isSet_; }); T data = data_; diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/include/kv_hiview_reporter.h b/kv_store/frameworks/innerkitsimpl/kvdb/include/kv_hiview_reporter.h index dd13958591e0308c9880ddeb2b913c445e11d8e3..446eff1bafdd339973a55e23cee1e67ad58d75c1 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/include/kv_hiview_reporter.h +++ b/kv_store/frameworks/innerkitsimpl/kvdb/include/kv_hiview_reporter.h @@ -20,32 +20,43 @@ #include "types.h" namespace OHOS::DistributedKv { -constexpr const char* OPEN_STORE = "OPEN_STORE"; -constexpr const char* PUT = "PUT"; -constexpr const char* PUTBATCH = "PUTBATCH"; -constexpr const char* DEL = "DELETE"; -constexpr const char* DELETEBATCH = "DELETEBATCH"; -constexpr const char* STARTTRANSACTION = "STARTTRANSACTION"; -constexpr const char* COMMIT = "COMMIT"; -constexpr const char* ROLLBACK = "ROLLBACK"; -constexpr const char* GET = "GET"; -constexpr const char* GETDEVICEENTRIES = "GETDEVICEENTRIES"; -constexpr const char* GETCOUNT = "GETCOUNT"; -constexpr const char* GETSECURITYLEVEL = "GETSECURITYLEVEL"; -constexpr const char* REMOVEDEVICEDATA = "REMOVEDEVICEDATA"; -constexpr const char* GETENTRIES = "GETENTRIES"; - +constexpr const char* DATABASE_REBUILD = "RestoreType:Rebuild"; +struct Suffix { + const char *suffix_ = nullptr; + const char *name_ = nullptr; +}; +static constexpr Suffix FILE_SUFFIXES[] = { + {"", "DB"}, + {"-shm", "SHM"}, + {"-wal", "WAL"}, +}; +static constexpr const char *defaultPath = "single_ver/main/gen_natural_store.db"; struct KVDBCorruptedEvent; class KVDBFaultHiViewReporter { public: static void ReportKVDBCorruptedFault( const Options &options, uint32_t errorCode, int32_t systemErrorNo, const KvStoreTuple &storeTuple, const std::string &appendix); + + static void ReportKVDBRebuild( + const Options &options, uint32_t errorCode, int32_t systemErrorNo, + const KvStoreTuple &storeTuple, const std::string &appendix); + static std::string GetDBPath(const std::string &path, const std::string &storeId); + + static void DeleteCorruptedFlag(const std::string &dbPath, const std::string &storeId); private: static void ReportCommonFault(const KVDBCorruptedEvent &eventInfo); static std::string GetCurrentMicrosecondTimeFormat(); + + static bool IsReportCorruptedFault(const std::string &dbPath, const std::string &storeId); + + static void CreateCorruptedFlag(const std::string &dbPath, const std::string &storeId); + + static std::string GetFileStatInfo(const std::string &dbPath); + + static std::string GetTimeWithMilliseconds(time_t sec, int64_t nsec); }; } // namespace OHOS::DistributedKv #endif //KV_HIVIEW_REPORTER_H \ No newline at end of file diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/include/kvdb_service.h b/kv_store/frameworks/innerkitsimpl/kvdb/include/kvdb_service.h index 6f18deeed1fa122820b97cead159b77c4884192a..7777bc5b035b07275eef51675fca22daefb0380b 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/include/kvdb_service.h +++ b/kv_store/frameworks/innerkitsimpl/kvdb/include/kvdb_service.h @@ -35,6 +35,11 @@ public: uint64_t syncId = 0; int32_t triggerMode = 0; }; + enum PasswordType { + BACKUP_SECRET_KEY = 0, + SECRET_KEY = 1, + BUTTON, + }; DECLARE_INTERFACE_DESCRIPTOR(u"OHOS.DistributedKv.KVFeature"); API_EXPORT KVDBService() = default; @@ -61,7 +66,7 @@ public: virtual Status Subscribe(const AppId &appId, const StoreId &storeId, sptr observer) = 0; virtual Status Unsubscribe(const AppId &appId, const StoreId &storeId, sptr observer) = 0; virtual Status GetBackupPassword( - const AppId &appId, const StoreId &storeId, std::vector &password) = 0; + const AppId &appId, const StoreId &storeId, std::vector &password, int32_t passwordType) = 0; virtual Status CloudSync(const AppId &appId, const StoreId &storeId, const SyncInfo &syncInfo) = 0; virtual Status NotifyDataChange(const AppId &appId, const StoreId &storeId, uint64_t delay) = 0; virtual Status PutSwitch(const AppId &appId, const SwitchData &data) = 0; diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/include/kvdb_service_client.h b/kv_store/frameworks/innerkitsimpl/kvdb/include/kvdb_service_client.h index 2bbf5131a96f10bd7de56efea3038f16dc41b5c4..e2e01baf6aa5aa20f8e473d00fe1d2d4513d0d3e 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/include/kvdb_service_client.h +++ b/kv_store/frameworks/innerkitsimpl/kvdb/include/kvdb_service_client.h @@ -49,7 +49,8 @@ public: Status RmvSubscribeInfo(const AppId &appId, const StoreId &storeId, const SyncInfo &syncInfo) override; Status Subscribe(const AppId &appId, const StoreId &storeId, sptr observer) override; Status Unsubscribe(const AppId &appId, const StoreId &storeId, sptr observer) override; - Status GetBackupPassword(const AppId &appId, const StoreId &storeId, std::vector &password) override; + Status GetBackupPassword(const AppId &appId, const StoreId &storeId, std::vector &password, + int32_t passwordType) override; Status CloudSync(const AppId &appId, const StoreId &storeId, const SyncInfo &syncInfo) override; Status NotifyDataChange(const AppId &appId, const StoreId &storeId, uint64_t delay) override; Status PutSwitch(const AppId &appId, const SwitchData &data) override; diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/include/observer_bridge.h b/kv_store/frameworks/innerkitsimpl/kvdb/include/observer_bridge.h index d16b7fffabbc2e009732c166582b30e646f97861..0450ba91eae9e1af5b54c3bb6814a58b5de9fa42 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/include/observer_bridge.h +++ b/kv_store/frameworks/innerkitsimpl/kvdb/include/observer_bridge.h @@ -55,6 +55,7 @@ private: std::shared_ptr observer_; sptr remote_; const Convertor &convert_; + std::mutex mutex_; }; } // namespace OHOS::DistributedKv #endif // OHOS_DISTRIBUTED_DATA_FRAMEWORKS_KVDB_OBSERVER_BRIDGE_H 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 11c37a47766530312c281e466c57ee7ba03d5c66..2d7a0f2c5cfa5aca355d8adc9dd316f47e7d5ffd 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/include/single_store_impl.h +++ b/kv_store/frameworks/innerkitsimpl/kvdb/include/single_store_impl.h @@ -77,7 +77,7 @@ public: Status DeleteBackup(const std::vector &files, const std::string &baseDir, std::map &status) override; void OnRemoteDied() override; - + bool IsRebuild() override; // normal function int32_t Close(bool isForce = false); int32_t AddRef(); @@ -132,7 +132,7 @@ private: bool IsRemoteChanged(const std::string &deviceId); void DoNotifyChange(); void Register(); - void ReportDBCorruptedFault(Status status, const std::string &appendIX) const; + void ReportDBCorruptedFault(Status status) const; bool isApplication_ = false; bool autoSync_ = false; @@ -151,6 +151,7 @@ private: int32_t securityLevel_ = -1; int32_t area_ = 1; std::string hapName_ = ""; + std::string path_ = ""; std::mutex notifyMutex_; uint64_t notifyExpiredTime_ = 0; diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/include/store_manager.h b/kv_store/frameworks/innerkitsimpl/kvdb/include/store_manager.h index 8a0b0202be3ce6e5ef01e5aa82ac771709782bba..c33721af0335f862fff6e113e626fd306c2fb14d 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/include/store_manager.h +++ b/kv_store/frameworks/innerkitsimpl/kvdb/include/store_manager.h @@ -29,7 +29,9 @@ public: std::pair GetSwitch(const AppId &appId, const std::string &networkId); Status SubscribeSwitchData(const AppId &appId, std::shared_ptr observer); Status UnsubscribeSwitchData(const AppId &appId, std::shared_ptr observer); + +private: + Status GetSecretKeyFromService(const AppId &appId, const StoreId &storeId, const std::string &path); }; } - #endif // OHOS_DISTRIBUTED_DATA_FRAMEWORKS_KVDB_STORE_MANAGER_H diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/src/backup_manager.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/src/backup_manager.cpp index f21796e4edd1fe7ed9c18b30f74e85c9c15f807a..46e3047828459e6a2a95a4220454450650f58f92 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/src/backup_manager.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/src/backup_manager.cpp @@ -205,7 +205,7 @@ BackupManager::DBPassword BackupManager::GetRestorePassword( return dbPassword; } std::vector pwd; - service->GetBackupPassword({ appId }, { storeId }, pwd); + service->GetBackupPassword({ appId }, { storeId }, pwd, KVDBService::PasswordType::BACKUP_SECRET_KEY); dbPassword.SetValue(pwd.data(), pwd.size()); pwd.assign(pwd.size(), 0); } else { diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/src/kv_hiview_reporter.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/src/kv_hiview_reporter.cpp index 7c86da91dacaa3a0a4ee69dd244199b1833d249a..e0cb2860bfc2d707014fc1be9e63256bf9218fdd 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/src/kv_hiview_reporter.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/src/kv_hiview_reporter.cpp @@ -20,14 +20,22 @@ #include #include #include +#include +#include +#include #include "hisysevent_c.h" #include "log_print.h" #include "types.h" +#include "store_util.h" namespace OHOS::DistributedKv { - +static constexpr int MAX_TIME_BUF_LEN = 32; +static constexpr int MILLISECONDS_LEN = 3; +static constexpr int NANO_TO_MILLI = 1000000; +static constexpr int MILLI_PRE_SEC = 1000; static constexpr const char *EVENT_NAME = "DATABASE_CORRUPTED"; static constexpr const char *DISTRIBUTED_DATAMGR = "DISTDATAMGR"; +constexpr const char *DB_CORRUPTED_POSTFIX = ".corruptedflg"; struct KVDBCorruptedEvent { std::string bundleName; std::string moduleName; @@ -62,7 +70,34 @@ void KVDBFaultHiViewReporter::ReportKVDBCorruptedFault( eventInfo.storeName = storeTuple.storeId; eventInfo.bundleName = storeTuple.appId; eventInfo.errorOccurTime = GetCurrentMicrosecondTimeFormat(); - ReportCommonFault(eventInfo); + if (IsReportCorruptedFault(eventInfo.appendix, storeTuple.storeId)) { + CreateCorruptedFlag(eventInfo.appendix, storeTuple.storeId); + auto corruptedTime = GetFileStatInfo(eventInfo.appendix); + eventInfo.appendix = corruptedTime; + ZLOGI("db corrupted report:storeId:%{public}s", StoreUtil::Anonymous(storeTuple.storeId).c_str()); + ReportCommonFault(eventInfo); + } +} + +void KVDBFaultHiViewReporter::ReportKVDBRebuild( + const Options &options, uint32_t errorCode, int32_t systemErrorNo, + const KvStoreTuple &storeTuple, const std::string &appendix) +{ + KVDBCorruptedEvent eventInfo(options); + eventInfo.errorCode = errorCode; + eventInfo.systemErrorNo = systemErrorNo; + eventInfo.appendix = appendix; + eventInfo.storeName = storeTuple.storeId; + eventInfo.bundleName = storeTuple.appId; + eventInfo.errorOccurTime = GetCurrentMicrosecondTimeFormat(); + if (errorCode == 0) { + ZLOGI("db rebuild report:storeId:%{public}s", StoreUtil::Anonymous(storeTuple.storeId).c_str()); + DeleteCorruptedFlag(eventInfo.appendix, storeTuple.storeId); + auto corruptedTime = GetFileStatInfo(eventInfo.appendix); + corruptedTime += "\n" + std::string(DATABASE_REBUILD); + eventInfo.appendix = corruptedTime; + ReportCommonFault(eventInfo); + } } std::string KVDBFaultHiViewReporter::GetCurrentMicrosecondTimeFormat() @@ -88,6 +123,41 @@ std::string KVDBFaultHiViewReporter::GetCurrentMicrosecondTimeFormat() return oss.str(); } +std::string KVDBFaultHiViewReporter::GetFileStatInfo(const std::string &dbPath) +{ + std::string fileTimeInfo; + const uint32_t permission = 0777; + for (auto &suffix : FILE_SUFFIXES) { + if (suffix.name_ == nullptr) { + continue; + } + auto file = dbPath + defaultPath + suffix.suffix_; + struct stat fileStat; + if (stat(file.c_str(), &fileStat) != 0) { + continue; + } + std::stringstream oss; + oss << " dev:0x" << std::hex << fileStat.st_dev << " ino:0x" << std::hex << fileStat.st_ino; + oss << " mode:0" << std::oct << (fileStat.st_mode & permission) << " size:" << std::dec << fileStat.st_size + << " atime:" << GetTimeWithMilliseconds(fileStat.st_atime, fileStat.st_atim.tv_nsec) + << " mtime:" << GetTimeWithMilliseconds(fileStat.st_mtime, fileStat.st_mtim.tv_nsec) + << " ctime:" << GetTimeWithMilliseconds(fileStat.st_ctime, fileStat.st_ctim.tv_nsec); + fileTimeInfo += "\n" + std::string(suffix.name_) + " :" + oss.str(); + } + return fileTimeInfo; +} + +std::string KVDBFaultHiViewReporter::GetTimeWithMilliseconds(time_t sec, int64_t nsec) +{ + std::stringstream oss; + char buffer[MAX_TIME_BUF_LEN] = { 0 }; + std::tm local_time; + localtime_r(&sec, &local_time); + std::strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", &local_time); + oss << buffer << "." << std::setfill('0') << std::setw(MILLISECONDS_LEN) << (nsec / NANO_TO_MILLI) % MILLI_PRE_SEC; + return oss.str(); +} + void KVDBFaultHiViewReporter::ReportCommonFault(const KVDBCorruptedEvent &eventInfo) { char *bundleName = const_cast(eventInfo.bundleName.c_str()); @@ -114,4 +184,58 @@ void KVDBFaultHiViewReporter::ReportCommonFault(const KVDBCorruptedEvent &eventI OH_HiSysEvent_Write(DISTRIBUTED_DATAMGR, EVENT_NAME, HISYSEVENT_FAULT, params, sizeof(params) / sizeof(params[0])); } -} // namespace OHOS::NativeRdb \ No newline at end of file + +bool KVDBFaultHiViewReporter::IsReportCorruptedFault(const std::string &dbPath, const std::string &storeId) +{ + if (dbPath.empty()) { + ZLOGW("dbPath path is empty"); + return false; + } + + std::string flagFilename = dbPath + storeId + DB_CORRUPTED_POSTFIX; + if (access(flagFilename.c_str(), F_OK) == 0) { + ZLOGW("corrupted flag already exit"); + return false; + } + return true; +} + +void KVDBFaultHiViewReporter::CreateCorruptedFlag(const std::string &dbPath, const std::string &storeId) +{ + if (dbPath.empty()) { + ZLOGW("dbPath path is empty"); + return; + } + std::string flagFilename = dbPath + storeId + DB_CORRUPTED_POSTFIX; + int fd = creat(flagFilename.c_str(), S_IRWXU | S_IRWXG); + if (fd == -1) { + ZLOGW("creat corrupted flg fail, flgname=%{public}s, errno=%{public}d", + StoreUtil::Anonymous(flagFilename).c_str(), errno); + return; + + } + close(fd); +} + +void KVDBFaultHiViewReporter::DeleteCorruptedFlag(const std::string &dbPath, const std::string &storeId) +{ + if (dbPath.empty()) { + ZLOGW("dbPath path is empty"); + return; + } + std::string flagFilename = dbPath + storeId + DB_CORRUPTED_POSTFIX; + int result = remove(flagFilename.c_str()); + if (result != 0) { + ZLOGW("remove corrupted flg fail, flgname=%{public}s, errno=%{public}d", + StoreUtil::Anonymous(flagFilename).c_str(), errno); + } +} + +std::string KVDBFaultHiViewReporter::GetDBPath(const std::string &path, const std::string &storeId) +{ + std::string reporterDir = ""; + DistributedDB::KvStoreDelegateManager::GetDatabaseDir(storeId, reporterDir); + reporterDir = path + "/kvdb/" + reporterDir + "/"; + return reporterDir; +} +} // namespace OHOS::DistributedKv \ No newline at end of file diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/src/kv_hiview_reporter_mock.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/src/kv_hiview_reporter_mock.cpp index d5d2a70b507d2be80b3f4df62ad934d86a831aaa..ed7400008a925a960b835d383b2baae035bdbd8a 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/src/kv_hiview_reporter_mock.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/src/kv_hiview_reporter_mock.cpp @@ -42,17 +42,17 @@ struct KVDBCorruptedEvent { }; void KVDBFaultHiViewReporter::ReportKVDBCorruptedFault( + const Options &options, uint32_t errorCode, int32_t systemErrorNo, + const KvStoreTuple &storeTuple, const std::string &path) +{ + return; +} + +void KVDBFaultHiViewReporter::ReportKVDBRebuild( const Options &options, uint32_t errorCode, int32_t systemErrorNo, const KvStoreTuple &storeTuple, const std::string &appendix) { - KVDBCorruptedEvent eventInfo(options); - eventInfo.errorCode = errorCode; - eventInfo.systemErrorNo = systemErrorNo; - eventInfo.appendix = appendix; - eventInfo.storeName = storeTuple.storeId; - eventInfo.bundleName = storeTuple.appId; - eventInfo.errorOccurTime = GetCurrentMicrosecondTimeFormat(); - ReportCommonFault(eventInfo); + return; } std::string KVDBFaultHiViewReporter::GetCurrentMicrosecondTimeFormat() @@ -65,4 +65,24 @@ void KVDBFaultHiViewReporter::ReportCommonFault(__attribute__((unused)) { return; } -} // namespace OHOS::NativeRdb \ No newline at end of file + +bool KVDBFaultHiViewReporter::IsReportCorruptedFault(const std::string &dbPath, const std::string &storeId) +{ + return false; +} + +void KVDBFaultHiViewReporter::CreateCorruptedFlag(const std::string &dbPath, const std::string &storeId) +{ + return; +} + +void KVDBFaultHiViewReporter::DeleteCorruptedFlag(const std::string &dbPath, const std::string &storeId) +{ + return; +} + +std::string KVDBFaultHiViewReporter::GetDBPath(const std::string &path, const std::string &storeId) +{ + return ""; +} +} // namespace OHOS::DistributedKv \ No newline at end of file diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/src/kvdb_service_client.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/src/kvdb_service_client.cpp index 2360c771239768c0c006684d22d999b32ad6d1a2..6e3d0772867f6251e80142528233a9db557f1c8b 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/src/kvdb_service_client.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/src/kvdb_service_client.cpp @@ -339,11 +339,11 @@ Status KVDBServiceClient::Unsubscribe(const AppId &appId, const StoreId &storeId } Status KVDBServiceClient::GetBackupPassword( - const AppId &appId, const StoreId &storeId, std::vector &password) + const AppId &appId, const StoreId &storeId, std::vector &password, int32_t passwordType) { MessageParcel reply; int32_t status = IPC_SEND(static_cast(KVDBServiceInterfaceCode::TRANS_GET_PASSWORD), - reply, appId, storeId); + reply, appId, storeId, passwordType); if (status != SUCCESS) { ZLOGE("status:0x%{public}x appId:%{public}s, storeId:%{public}s", status, appId.appId.c_str(), StoreUtil::Anonymous(storeId.storeId).c_str()); diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/src/observer_bridge.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/src/observer_bridge.cpp index e5015d0c56f6b025e6cd58e11cd17fa7a60da981..8a466243ad8871c654f9a2133d9dea9d417a824b 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/src/observer_bridge.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/src/observer_bridge.cpp @@ -36,6 +36,7 @@ ObserverBridge::~ObserverBridge() Status ObserverBridge::RegisterRemoteObserver(uint32_t realType) { + std::lock_guard lockGuard(mutex_); if (remote_ != nullptr) { remote_->realType_ |= realType; return SUCCESS; @@ -58,6 +59,7 @@ Status ObserverBridge::RegisterRemoteObserver(uint32_t realType) Status ObserverBridge::UnregisterRemoteObserver(uint32_t realType) { + std::lock_guard lockGuard(mutex_); if (remote_ == nullptr) { return SUCCESS; } @@ -129,6 +131,7 @@ std::vector ObserverBridge::ConvertDB(const T &dbEntries, std::string &de void ObserverBridge::OnServiceDeath() { + std::lock_guard lockGuard(mutex_); if (remote_ == nullptr) { return; } 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 eb8a6323d29e4393df8196ea9aae5c6bec76ddfd..682f13e4585c7bc8837d22b1570ceada63b73e81 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/src/single_store_impl.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/src/single_store_impl.cpp @@ -38,6 +38,7 @@ SingleStoreImpl::SingleStoreImpl( : convertor_(cvt), dbStore_(std::move(dbStore)) { std::string path = options.GetDatabaseDir(); + path_ = path; appId_ = appId.appId; storeId_ = dbStore_->GetStoreId(); autoSync_ = options.autoSync; @@ -100,7 +101,7 @@ Status SingleStoreImpl::Put(const Key &key, const Value &value) } auto status = RetryWithCheckPoint([this, &dbKey, &value]() { return dbStore_->Put(dbKey, value); }); - ReportDBCorruptedFault(status, PUT); + ReportDBCorruptedFault(status); if (status != SUCCESS) { ZLOGE("status:0x%{public}x key:%{public}s, value size:%{public}zu", status, StoreUtil::Anonymous(key.ToString()).c_str(), value.Size()); @@ -133,7 +134,7 @@ Status SingleStoreImpl::PutBatch(const std::vector &entries) } auto status = RetryWithCheckPoint([this, &dbEntries]() { return dbStore_->PutBatch(dbEntries); }); - ReportDBCorruptedFault(status, PUTBATCH); + ReportDBCorruptedFault(status); if (status != SUCCESS) { ZLOGE("status:0x%{public}x entries size:%{public}zu", status, entries.size()); } @@ -158,7 +159,7 @@ Status SingleStoreImpl::Delete(const Key &key) } auto status = RetryWithCheckPoint([this, &dbKey]() { return dbStore_->Delete(dbKey); }); - ReportDBCorruptedFault(status, DEL); + ReportDBCorruptedFault(status); if (status != SUCCESS) { ZLOGE("status:0x%{public}x key:%{public}s", status, StoreUtil::Anonymous(key.ToString()).c_str()); } @@ -187,7 +188,7 @@ Status SingleStoreImpl::DeleteBatch(const std::vector &keys) } auto status = RetryWithCheckPoint([this, &dbKeys]() { return dbStore_->DeleteBatch(dbKeys); }); - ReportDBCorruptedFault(status, DELETEBATCH); + ReportDBCorruptedFault(status); if (status != SUCCESS) { ZLOGE("status:0x%{public}x keys size:%{public}zu", status, keys.size()); } @@ -206,7 +207,7 @@ Status SingleStoreImpl::StartTransaction() } auto status = RetryWithCheckPoint([this]() { return dbStore_->StartTransaction(); }); - ReportDBCorruptedFault(status, STARTTRANSACTION); + ReportDBCorruptedFault(status); if (status != SUCCESS) { ZLOGE("status:0x%{public}x storeId:%{public}s", status, StoreUtil::Anonymous(storeId_).c_str()); } @@ -224,7 +225,7 @@ Status SingleStoreImpl::Commit() auto dbStatus = dbStore_->Commit(); auto status = StoreUtil::ConvertStatus(dbStatus); - ReportDBCorruptedFault(status, COMMIT); + ReportDBCorruptedFault(status); if (status != SUCCESS) { ZLOGE("status:0x%{public}x storeId:%{public}s", status, StoreUtil::Anonymous(storeId_).c_str()); } @@ -242,7 +243,7 @@ Status SingleStoreImpl::Rollback() auto dbStatus = dbStore_->Rollback(); auto status = StoreUtil::ConvertStatus(dbStatus); - ReportDBCorruptedFault(status, ROLLBACK); + ReportDBCorruptedFault(status); if (status != SUCCESS) { ZLOGE("status:0x%{public}x storeId:%{public}s", status, StoreUtil::Anonymous(storeId_).c_str()); } @@ -355,7 +356,7 @@ Status SingleStoreImpl::Get(const Key &key, Value &value) auto dbStatus = dbStore_->Get(dbKey, dbValue); value = std::move(dbValue); auto status = StoreUtil::ConvertStatus(dbStatus); - ReportDBCorruptedFault(status, GET); + ReportDBCorruptedFault(status); if (status != SUCCESS) { ZLOGE("status:0x%{public}x key:%{public}s", status, StoreUtil::Anonymous(key.ToString()).c_str()); } @@ -479,7 +480,7 @@ Status SingleStoreImpl::GetDeviceEntries(const std::string &device, std::vector< } auto status = StoreUtil::ConvertStatus(dbStatus); - ReportDBCorruptedFault(status, GETDEVICEENTRIES); + ReportDBCorruptedFault(status); if (status == NOT_FOUND) { status = SUCCESS; } @@ -525,7 +526,7 @@ Status SingleStoreImpl::GetCount(const DataQuery &query, int &result) const DBQuery dbQuery = convertor_.GetDBQuery(query); auto dbStatus = dbStore_->GetCount(dbQuery, result); auto status = StoreUtil::ConvertStatus(dbStatus); - ReportDBCorruptedFault(status, GETCOUNT); + ReportDBCorruptedFault(status); if (status != SUCCESS) { ZLOGE("status:0x%{public}x query:%{public}s", status, StoreUtil::Anonymous(query.ToString()).c_str()); } @@ -545,7 +546,7 @@ Status SingleStoreImpl::GetSecurityLevel(SecurityLevel &secLevel) const auto dbStatus = dbStore_->GetSecurityOption(option); secLevel = static_cast(StoreUtil::GetSecLevel(option)); auto status = StoreUtil::ConvertStatus(dbStatus); - ReportDBCorruptedFault(status, GETSECURITYLEVEL); + ReportDBCorruptedFault(status); if (status != SUCCESS) { ZLOGE("status:0x%{public}x security:[%{public}d]", status, option.securityLabel); } @@ -566,7 +567,7 @@ Status SingleStoreImpl::RemoveDeviceData(const std::string &device) } Status status = service->RemoveDeviceData({ appId_ }, { storeId_ }, device); - ReportDBCorruptedFault(status, REMOVEDEVICEDATA); + ReportDBCorruptedFault(status); if (status != SUCCESS) { ZLOGE("status:%{public}d device:%{public}s", status, StoreUtil::Anonymous(device).c_str()); } @@ -774,6 +775,13 @@ Status SingleStoreImpl::Restore(const std::string &file, const std::string &base ZLOGE("status:0x%{public}x storeId:%{public}s backup:%{public}s ", status, StoreUtil::Anonymous(storeId_).c_str(), file.c_str()); } + if (status == SUCCESS) { + Options options = { .encrypt = encrypt_, .autoSync = autoSync_, .securityLevel = securityLevel_, + .area = area_, .hapName = hapName_ }; + KvStoreTuple tuple = { .appId = appId_, .storeId = storeId_ }; + auto repoterDir = KVDBFaultHiViewReporter::GetDBPath(path_, storeId_); + KVDBFaultHiViewReporter::ReportKVDBRebuild(options, status, errno, tuple, repoterDir); + } return status; } @@ -898,7 +906,7 @@ Status SingleStoreImpl::GetEntries(const DBQuery &query, std::vector &ent } auto status = StoreUtil::ConvertStatus(dbStatus); - ReportDBCorruptedFault(status, GETENTRIES); + ReportDBCorruptedFault(status); if (status == NOT_FOUND) { status = SUCCESS; } @@ -907,6 +915,11 @@ Status SingleStoreImpl::GetEntries(const DBQuery &query, std::vector &ent Status SingleStoreImpl::DoClientSync(SyncInfo &syncInfo, std::shared_ptr observer) { + std::shared_lock lock(rwMutex_); + if (dbStore_ == nullptr) { + ZLOGE("db:%{public}s already closed!", StoreUtil::Anonymous(storeId_).c_str()); + return ALREADY_CLOSED; + } auto complete = [observer](const std::map &devicesMap) { if (observer == nullptr) { return; @@ -1048,6 +1061,11 @@ void SingleStoreImpl::Register() Status SingleStoreImpl::SetIdentifier(const std::string &accountId, const std::string &appId, const std::string &storeId, const std::vector &tagretDev) { + std::shared_lock lock(rwMutex_); + if (dbStore_ == nullptr) { + ZLOGE("db:%{public}s already closed!", StoreUtil::Anonymous(storeId_).c_str()); + return ALREADY_CLOSED; + } auto syncIdentifier = DistributedDB::KvStoreDelegateManager::GetKvStoreIdentifier(accountId, appId, storeId); auto dbStatus = dbStore_->SetEqualIdentifier(syncIdentifier, tagretDev); auto status = StoreUtil::ConvertStatus(dbStatus); @@ -1057,13 +1075,25 @@ Status SingleStoreImpl::SetIdentifier(const std::string &accountId, const std::s return status; } -void SingleStoreImpl::ReportDBCorruptedFault(Status status, const std::string &appendIX) const +bool SingleStoreImpl::IsRebuild() +{ + std::shared_lock lock(rwMutex_); + if (dbStore_ == nullptr) { + ZLOGE("db:%{public}s already closed!", StoreUtil::Anonymous(storeId_).c_str()); + return false; + } + auto databaseStatus = dbStore_->GetDatabaseStatus(); + return databaseStatus.isRebuild; +} + +void SingleStoreImpl::ReportDBCorruptedFault(Status status) const { if (status == CRYPT_ERROR) { Options options = { .encrypt = encrypt_, .autoSync = autoSync_, .securityLevel = securityLevel_, .area = area_, .hapName = hapName_ }; KvStoreTuple tuple = { .appId = appId_, .storeId = storeId_ }; - KVDBFaultHiViewReporter::ReportKVDBCorruptedFault(options, status, errno, tuple, appendIX); + auto repoterDir = KVDBFaultHiViewReporter::GetDBPath(path_, storeId_); + KVDBFaultHiViewReporter::ReportKVDBCorruptedFault(options, status, errno, tuple, repoterDir); } } } // namespace OHOS::DistributedKv \ No newline at end of file diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/src/store_factory.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/src/store_factory.cpp index 77c7dba363d8b6871ca90da5fd6324696c6f4494..daa0e51ae7b0191bf7d23e5cc5f0b08560507151 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/src/store_factory.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/src/store_factory.cpp @@ -79,14 +79,14 @@ std::shared_ptr StoreFactory::GetOrOpenStore(const AppId &appId, StoreUtil::Anonymous(storeId.storeId).c_str(), static_cast(status)); return !stores.empty(); } - if (options.encrypt) { + if (options.encrypt && options.autoRekey) { status = RekeyRecover(storeId, path, dbPassword, dbManager, options); if (status != SUCCESS) { ZLOGE("KvStore password error, storeId is %{public}s, error is %{public}d", StoreUtil::Anonymous(storeId.storeId).c_str(), static_cast(status)); return !stores.empty(); } - if (dbPassword.isKeyOutdated && options.autoRekey) { + if (dbPassword.isKeyOutdated) { ReKey(storeId, path, dbPassword, dbManager, options); } } @@ -103,7 +103,11 @@ std::shared_ptr StoreFactory::GetOrOpenStore(const AppId &appId, const Convertor &convertor = *(convertors_[options.kvStoreType]); kvStore = std::make_shared(dbStore, appId, options, convertor); }); - status = StoreUtil::ConvertStatus(dbStatus); + if (dbStatus == DBStatus::INVALID_PASSWD_OR_CORRUPTED_DB) { + status = DATA_CORRUPTED; + } else { + 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 b34d220f9e00ad93a6aaffe89329b075b0f3dbe4..e4e65af27a75a1d6d1ed453a4a39fcc7515f57af 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/src/store_manager.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/src/store_manager.cpp @@ -41,23 +41,33 @@ std::shared_ptr StoreManager::GetKVStore(const AppId &appId, cons status = INVALID_ARGUMENT; return nullptr; } - auto service = KVDBServiceClient::GetInstance(); if (service != nullptr) { status = service->BeforeCreate(appId, storeId, options); } - if (status == STORE_META_CHANGED) { ZLOGE("appId:%{public}s, storeId:%{public}s type:%{public}d encrypt:%{public}d", appId.appId.c_str(), StoreUtil::Anonymous(storeId.storeId).c_str(), options.kvStoreType, options.encrypt); return nullptr; } - bool isCreate = false; auto kvStore = StoreFactory::GetInstance().GetOrOpenStore(appId, storeId, options, status, isCreate); - if (status == CRYPT_ERROR) { + 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; + } + } + if (kvStore != nullptr && status == SUCCESS && kvStore->IsRebuild()) { + ZLOGI("rebuild store success, storeId:%{public}s", StoreUtil::Anonymous(storeId.storeId).c_str()); KvStoreTuple tuple = { .appId = appId.appId, .storeId = storeId.storeId }; - KVDBFaultHiViewReporter::ReportKVDBCorruptedFault(options, status, errno, tuple, OPEN_STORE); + auto repoterDir = KVDBFaultHiViewReporter::GetDBPath(path, storeId.storeId); + KVDBFaultHiViewReporter::ReportKVDBRebuild(options, status, errno, tuple, repoterDir); } if (isCreate && options.persistent) { auto dbPassword = SecurityManager::GetInstance().GetDBPassword(storeId.storeId, @@ -72,6 +82,34 @@ std::shared_ptr StoreManager::GetKVStore(const AppId &appId, cons return kvStore; } +Status StoreManager::GetSecretKeyFromService(const AppId &appId, const StoreId &storeId, const std::string &path) +{ + auto service = KVDBServiceClient::GetInstance(); + if (service == nullptr) { + ZLOGE("get service failed! appId:%{public}s, storeId:%{public}s", + appId.appId.c_str(), StoreUtil::Anonymous(storeId.storeId).c_str()); + return Status::SERVER_UNAVAILABLE; + } + std::vector key; + auto status = service->GetBackupPassword(appId, storeId, key, KVDBService::PasswordType::SECRET_KEY); + if (status != Status::SUCCESS) { + key.assign(key.size(), 0); + ZLOGE("get password from service failed! status:%{public}d, appId:%{public}s storeId:%{public}s", + status, appId.appId.c_str(), StoreUtil::Anonymous(storeId.storeId).c_str()); + return status; + } + if (key.empty()) { + ZLOGE("service secret key is empty! status:%{public}d, appId:%{public}s storeId:%{public}s", + status, appId.appId.c_str(), StoreUtil::Anonymous(storeId.storeId).c_str()); + return Status::ERROR; + } + SecurityManager::DBPassword dbPassword; + dbPassword.SetValue(key.data(), key.size()); + key.assign(key.size(), 0); + SecurityManager::GetInstance().SaveDBPassword(storeId.storeId, path, dbPassword.password); + return Status::SUCCESS; +} + Status StoreManager::CloseKVStore(const AppId &appId, const StoreId &storeId) { ZLOGD("appId:%{public}s, storeId:%{public}s", appId.appId.c_str(), StoreUtil::Anonymous(storeId.storeId).c_str()); @@ -118,6 +156,8 @@ Status StoreManager::Delete(const AppId &appId, const StoreId &storeId, const st if (service != nullptr) { service->Delete(appId, storeId); } + auto repoterDir = KVDBFaultHiViewReporter::GetDBPath(path, storeId.storeId); + KVDBFaultHiViewReporter::DeleteCorruptedFlag(repoterDir, storeId.storeId); return StoreFactory::GetInstance().Delete(appId, storeId, path); } diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/test/BUILD.gn b/kv_store/frameworks/innerkitsimpl/kvdb/test/BUILD.gn index ee7b787312ed89d484d51e7597be50c330e0dc14..a39cb3ec808e6e85f1e0c3e1b675886fb3c0f2a1 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/test/BUILD.gn +++ b/kv_store/frameworks/innerkitsimpl/kvdb/test/BUILD.gn @@ -218,6 +218,38 @@ ohos_unittest("DevManagerTest") { ] } +ohos_unittest("DevManagerMockTest") { + module_out_path = module_output_path + include_dirs = [ "${kv_store_base_path}/frameworks/innerkitsimpl/kvdb/test" ] + sources = [ + "${kv_store_base_path}/frameworks/innerkitsimpl/kvdb/test/device_manager_mock.cpp", + "../../kvdb/src/kv_hiview_reporter_mock.cpp", + "dev_manager_mock_test.cpp", + ] + + configs = [ ":module_private_config" ] + + cflags = [ + "-Dprivate=public", + "-Dprotected=public", + ] + + external_deps = [ + "c_utils:utils", + "device_manager:devicemanagersdk", + "hilog:libhilog", + "ipc:ipc_single", + "safwk:system_ability_fwk", + "samgr:samgr_proxy", + ] + + deps = [ + ":kvdb_src_file", + "${kv_store_base_path}/frameworks/libs/distributeddb/:distributeddb", + "//third_party/googletest:gtest", + ] +} + ohos_unittest("SingleStoreImplGetTopTest") { module_out_path = module_output_path @@ -275,6 +307,7 @@ group("unittest") { deps = [] deps += [ ":BackupManagerTest", + ":DevManagerMockTest", ":DevManagerTest", ":SingleStoreImplGetTopTest", ":SingleStoreImplTest", diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/test/dev_manager_mock_test.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/test/dev_manager_mock_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fe825aadca15b7b5f2ecb7897590b5bb8982a8e7 --- /dev/null +++ b/kv_store/frameworks/innerkitsimpl/kvdb/test/dev_manager_mock_test.cpp @@ -0,0 +1,133 @@ +/* + * 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 "DevManagerMockTest" +#include +#include "dev_manager.h" +#include "device_manager_mock.h" +#include "types.h" +#include "log_print.h" +namespace OHOS::Test { +using namespace testing; +using namespace testing::ext; +using namespace OHOS; +using namespace OHOS::DistributedKv; +using namespace OHOS::DistributedHardware; +using DmDeviceInfo = OHOS::DistributedHardware::DmDeviceInfo; +class DevManagerMockTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + + void SetUp(); + void TearDown(); +}; + +void DevManagerMockTest::SetUpTestCase(void) +{} + +void DevManagerMockTest::TearDownTestCase(void) +{} + +void DevManagerMockTest::SetUp(void) +{} + +void DevManagerMockTest::TearDown(void) +{} + +/** +* @tc.name: GetUnEncryptedUuid +* @tc.desc: test GetUnEncryptedUuid get local device info fail +* @tc.type: FUNC +* @tc.require: +* @tc.author: SQL +*/ +HWTEST_F(DevManagerMockTest, GetUnEncryptedUuid001, TestSize.Level1) +{ + ZLOGI("GetUnEncryptedUuid001 begin."); + auto uuid = DevManager::GetInstance().GetUnEncryptedUuid(); + EXPECT_EQ(uuid, ""); +} + +/** +* @tc.name: GetUnEncryptedUuid +* @tc.desc: test GetUnEncryptedUuid networkid empty +* @tc.type: FUNC +* @tc.require: +* @tc.author: SQL +*/ +HWTEST_F(DevManagerMockTest, GetUnEncryptedUuid002, TestSize.Level1) +{ + ZLOGI("GetUnEncryptedUuid002 begin."); + auto uuid = DevManager::GetInstance().GetUnEncryptedUuid(); + EXPECT_EQ(uuid, ""); +} + +/** +* @tc.name: GetUnEncryptedUuid +* @tc.desc: test GetUnEncryptedUuid get uuid by networkid fail +* @tc.type: FUNC +* @tc.require: +* @tc.author: SQL +*/ +HWTEST_F(DevManagerMockTest, GetUnEncryptedUuid003, TestSize.Level1) +{ + ZLOGI("GetUnEncryptedUuid003 begin."); + auto uuid = DevManager::GetInstance().GetUnEncryptedUuid(); + EXPECT_EQ(uuid, ""); +} + +/** +* @tc.name: GetLocalDevice +* @tc.desc: test GetLocalDevice get local device info fail +* @tc.type: FUNC +* @tc.require: +* @tc.author: SQL +*/ +HWTEST_F(DevManagerMockTest, GetLocalDevice, TestSize.Level1) +{ + ZLOGI("GetLocalDevice begin."); + auto devInfo = DevManager::GetInstance().GetLocalDevice(); + EXPECT_EQ(devInfo.uuid, ""); +} + +/** +* @tc.name: GetRemoteDevices001 +* @tc.desc: test GetRemoteDevices get trusted device fail +* @tc.type: FUNC +* @tc.require: +* @tc.author: SQL +*/ +HWTEST_F(DevManagerMockTest, GetRemoteDevices001, TestSize.Level1) +{ + ZLOGI("GetRemoteDevices001 begin."); + auto detailInfo = DevManager::GetInstance().GetRemoteDevices(); + EXPECT_TRUE(detailInfo.empty()); +} + +/** +* @tc.name: GetRemoteDevices002 +* @tc.desc: test GetRemoteDevices get trusted device no remote device +* @tc.type: FUNC +* @tc.require: +* @tc.author: SQL +*/ +HWTEST_F(DevManagerMockTest, GetRemoteDevices002, TestSize.Level1) +{ + ZLOGI("GetRemoteDevices002 begin."); + auto detailInfo = DevManager::GetInstance().GetRemoteDevices(); + EXPECT_TRUE(detailInfo.empty()); +} +} // namespace OHOS::Test \ No newline at end of file diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/test/device_manager_mock.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/test/device_manager_mock.cpp new file mode 100644 index 0000000000000000000000000000000000000000..18c735a8f785a4856aeb5016fc1410f803a479c2 --- /dev/null +++ b/kv_store/frameworks/innerkitsimpl/kvdb/test/device_manager_mock.cpp @@ -0,0 +1,102 @@ +/* + * 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 "device_manager_mock.h" +#include "dm_constants.h" + +namespace OHOS { +namespace DistributedHardware { +DeviceManager &DeviceManager::GetInstance() +{ + static DeviceManager instance; + return instance; +} + +int32_t DeviceManager::InitDeviceManager(const std::string &pkgName, + std::shared_ptr dmInitCallback) +{ + return ERR_DM_INPUT_PARA_INVALID; +} + +int32_t DeviceManager::UnInitDeviceManager(const std::string &pkgName) +{ + return ERR_DM_INPUT_PARA_INVALID; +} + +int32_t DeviceManager::GetTrustedDeviceList(const std::string &pkgName, const std::string &extra, + std::vector &deviceList) +{ + if (testDemo == 0) { + testDemo = 1; + return ERR_DM_IPC_SEND_REQUEST_FAILED; + } else { + testDemo = 0; + return DM_OK; + } +} + +int32_t DeviceManager::GetTrustedDeviceList(const std::string &pkgName, const std::string &extra, + bool isRefresh, std::vector &deviceList) +{ + return ERR_DM_INPUT_PARA_INVALID; +} + +int32_t DeviceManager::GetAvailableDeviceList(const std::string &pkgName, + std::vector &deviceList) +{ + return ERR_DM_INPUT_PARA_INVALID; +} + +int32_t DeviceManager::GetLocalDeviceInfo(const std::string &pkgName, DmDeviceInfo &deviceInfo) +{ + if (testDemo == 0) { + testDemo = 1; + return ERR_DM_IPC_SEND_REQUEST_FAILED; + } else if (testDemo == 1) { + testDemo = -1; + return DM_OK; + } else { + testDemo = 0; + deviceInfo.networkId[0] = 'a'; + return DM_OK; + } +} + +int32_t DeviceManager::RegisterDevStateCallback(const std::string &pkgName, const std::string &extra, + std::shared_ptr callback) +{ + return ERR_DM_INPUT_PARA_INVALID; +} + +int32_t DeviceManager::RegisterDevStatusCallback(const std::string &pkgName, const std::string &extra, + std::shared_ptr callback) +{ + return ERR_DM_INPUT_PARA_INVALID; +} + +int32_t DeviceManager::GetUuidByNetworkId(const std::string &pkgName, const std::string &netWorkId, + std::string &uuid) +{ + uuid = ""; + return ERR_DM_INPUT_PARA_INVALID; +} + +int32_t DeviceManager::GetEncryptedUuidByNetworkId(const std::string &pkgName, const std::string &networkId, + std::string &uuid) +{ + return ERR_DM_INPUT_PARA_INVALID; +} +} // namespace DistributedHardware +} // namespace OHOS diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/test/device_manager_mock.h b/kv_store/frameworks/innerkitsimpl/kvdb/test/device_manager_mock.h new file mode 100644 index 0000000000000000000000000000000000000000..229b28c79916d9f41ccc7fbe1c7bd566807a480f --- /dev/null +++ b/kv_store/frameworks/innerkitsimpl/kvdb/test/device_manager_mock.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2022-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. + */ + +#ifndef OHOS_DEVICE_MANAGER_H +#define OHOS_DEVICE_MANAGER_H + +#include +#include +#include +#include +#include "device_manager_callback.h" +#include "dm_device_info.h" +#include "dm_publish_info.h" +#include "dm_subscribe_info.h" + +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); + + virtual int32_t UnInitDeviceManager(const std::string &pkgName); + + virtual int32_t GetTrustedDeviceList(const std::string &pkgName, const std::string &extra, + std::vector &deviceList); + + virtual int32_t GetTrustedDeviceList(const std::string &pkgName, const std::string &extra, + bool isRefresh, std::vector &deviceList); + + virtual int32_t GetAvailableDeviceList(const std::string &pkgName, + std::vector &deviceList); + + virtual int32_t GetLocalDeviceInfo(const std::string &pkgName, DmDeviceInfo &deviceInfo); + + virtual int32_t RegisterDevStateCallback(const std::string &pkgName, const std::string &extra, + std::shared_ptr callback); + + virtual int32_t RegisterDevStatusCallback(const std::string &pkgName, const std::string &extra, + std::shared_ptr callback); + + virtual int32_t GetUuidByNetworkId(const std::string &pkgName, const std::string &netWorkId, std::string &uuid); + + virtual int32_t GetEncryptedUuidByNetworkId(const std::string &pkgName, const std::string &networkId, + std::string &uuid); +private: + DeviceManager() = default; + ~DeviceManager() = default; + DeviceManager(const DeviceManager &) = delete; + DeviceManager &operator=(const DeviceManager &) = delete; + DeviceManager(DeviceManager &&) = delete; + DeviceManager &operator=(DeviceManager &&) = delete; +}; +} // namespace DistributedHardware +} // namespace OHOS +#endif // DEVICE_MANAGER_H \ No newline at end of file diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/test/store_factory_test.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/test/store_factory_test.cpp index f69b0cf80a7443812ff7ca09f4060f5394958ed1..6eb7faf78ed857299e5a38e1aee75e5309d0778a 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/test/store_factory_test.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/test/store_factory_test.cpp @@ -341,6 +341,7 @@ HWTEST_F(StoreFactoryTest, RekeyInterruptedBeforeChangeKeyFile, TestSize.Level1) HWTEST_F(StoreFactoryTest, RekeyNoPwdFile, TestSize.Level1) { Status status = DB_ERROR; + options.autoRekey = false; StoreManager::GetInstance().GetKVStore(appId, storeId, options, status); ASSERT_EQ(status, SUCCESS); @@ -353,6 +354,9 @@ HWTEST_F(StoreFactoryTest, RekeyNoPwdFile, TestSize.Level1) ASSERT_EQ(isKeyExist, false); StoreManager::GetInstance().GetKVStore(appId, storeId, options, status); - ASSERT_EQ(status, CRYPT_ERROR); + ASSERT_EQ(status, SUCCESS); + + isKeyExist = StoreUtil::IsFileExist(keyFileName); + ASSERT_EQ(isKeyExist, true); } } \ No newline at end of file diff --git a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_field_node.cpp b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_field_node.cpp index 8cf2576552477865a3664fdb9628e62bc58030d0..10b7d4234304846de9e875fc9a6fa3d696586138 100644 --- a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_field_node.cpp +++ b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_field_node.cpp @@ -100,7 +100,7 @@ napi_value JsFieldNode::New(napi_env env, napi_callback_info info) ASSERT_ERR(env, fieldNode != nullptr, Status::INVALID_ARGUMENT, "Parameter error:fieldNode is nullptr"); auto finalize = [](napi_env env, void* data, void* hint) { - ZLOGD("fieldNode finalize."); + ZLOGI("fieldNode finalize."); auto* fieldNode = reinterpret_cast(data); ASSERT_VOID(fieldNode != nullptr, "fieldNode is null!"); delete fieldNode; diff --git a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_schema.cpp b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_schema.cpp index afa2bd2ae4ec2f963319406960793dac38a20dd1..79a1337d2e159d0816876717efaa9b93a6e76f18 100644 --- a/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_schema.cpp +++ b/kv_store/frameworks/jskitsimpl/distributedkvstore/src/js_schema.cpp @@ -72,7 +72,7 @@ napi_value JsSchema::New(napi_env env, napi_callback_info info) NAPI_ASSERT(env, schema !=nullptr, "no memory for schema"); auto finalize = [](napi_env env, void* data, void* hint) { - ZLOGD("Schema finalize."); + ZLOGI("Schema finalize."); auto* schema = reinterpret_cast(data); ASSERT_VOID(schema != nullptr, "schema is null!"); delete schema; 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 788ea9c4da27c35270b2c42f3fcf3d9bfe6a7937..c20e5a7fb06dfad811613ec9984985acca614f4c 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 @@ -58,6 +58,7 @@ public: static constexpr const char *CLOUD_KV_FIELD_ORI_DEVICE = "ori_device"; static constexpr const char *CLOUD_KV_FIELD_DEVICE_CREATE_TIME = "device_create_time"; static constexpr const char *CLOUD_KV_TABLE_NAME = "sync_data"; + static constexpr const char *CLOUD_KV_FIELD_USERID = "userid"; // data status changes to lock_change static constexpr const char *TO_LOCAL_CHANGE = "status = CASE WHEN status == 2 THEN 3 ELSE status END"; @@ -74,6 +75,8 @@ public: static constexpr const char *FLAG_AND_DATA_MODE_NOTIFY = "DELETE#ALL_CLOUDDATA"; + static constexpr const char *FLAG_ONLY_MODE_NOTIFY = "RESERVE#ALL_CLOUDDATA"; + // cloud data timestamp is utc ms precision // used for 100ns to ms when handle cloud data timestamp static constexpr uint32_t TEN_THOUSAND = 10000; diff --git a/kv_store/frameworks/libs/distributeddb/common/include/cloud/cloud_db_types.h b/kv_store/frameworks/libs/distributeddb/common/include/cloud/cloud_db_types.h index e57916ddc44d01e78320309dbab32f3fbaa1329f..5c031f74d19e0edc7eb6f75e36a4e64c69c6b560 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/cloud/cloud_db_types.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/cloud/cloud_db_types.h @@ -36,12 +36,19 @@ struct CloudSyncBatch { std::vector hashKey; }; +struct ReviseModTimeInfo { + Bytes hashKey; + int64_t curTime; + int64_t invalidTime; +}; + struct CloudSyncData { std::string tableName; CloudSyncBatch insData; CloudSyncBatch updData; CloudSyncBatch delData; CloudSyncBatch lockData; + std::vector revisedData; bool isCloudForcePushStrategy = false; bool isCompensatedTask = false; bool isShared = false; diff --git a/kv_store/frameworks/libs/distributeddb/common/include/concurrent_adapter.h b/kv_store/frameworks/libs/distributeddb/common/include/concurrent_adapter.h index ff09c7a7efd48133728384ff8953d327a5b0e0e6..a6aaeca91157bf10a1f8c25f1ff87f0df4df7eb1 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/concurrent_adapter.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/concurrent_adapter.h @@ -23,13 +23,14 @@ namespace DistributedDB { #ifdef USE_FFRT +using TaskHandle = ffrt::task_handle; #define ADAPTER_AUTO_LOCK(n, m) #define ADAPTER_WAIT(x) ffrt::wait({x}) #else +using TaskHandle = void *; #define ADAPTER_AUTO_LOCK(n, m) std::lock_guard n(m) #define ADAPTER_WAIT(x) (void)(x) #endif -using TaskHandle = void *; using Dependence = void *; class ConcurrentAdapter { public: 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 94e5a895db3e8a40dfe5e813e2d2eb31c5cff635..134ce2fe91c26bca5c2e577773688ec16f80e127 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/db_common.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/db_common.h @@ -135,6 +135,8 @@ public: static bool IsNeedCompensatedForUpload(const VBucket &uploadExtend, const CloudWaterType &type); + static bool IsRecordIgnoredForReliability(const VBucket &uploadExtend, const CloudWaterType &type); + static bool IsRecordSuccess(const VBucket &record); static std::string GenerateHashLabel(const DBInfo &dbInfo); @@ -149,6 +151,8 @@ public: static std::string GetCursorKey(const std::string &tableName); + static bool ConvertToUInt(const std::string &str, uint64_t &value); + static void RemoveDuplicateAssetsData(std::vector &assets); private: static void InsertNodesByScore(const std::map> &graph, diff --git a/kv_store/frameworks/libs/distributeddb/common/include/db_types.h b/kv_store/frameworks/libs/distributeddb/common/include/db_types.h index 28cdad4dd1215f801df68adb8b48b499ddcfd1a0..e9f240d851eeb3c401912ed12df6c1f2f6c2ecf6 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/db_types.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/db_types.h @@ -48,6 +48,7 @@ struct DataItem { Timestamp writeTimestamp = 0; std::string dev; bool neglect = false; + bool dataDelete = false; Key hashKey{}; Timestamp modifyTime = 0; Timestamp createTime = 0; diff --git a/kv_store/frameworks/libs/distributeddb/common/include/query_utils.h b/kv_store/frameworks/libs/distributeddb/common/include/query_utils.h index 4161a36e86b41495899ef26b19adafb01b6c812b..94df27ac3d8d4a41fc7ec300f025bc6a089a04c2 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/query_utils.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/query_utils.h @@ -26,6 +26,10 @@ public: static void FillQueryInKeys(const std::map> &syncPk, std::map dataIndex, Query &query); +private: + static void FillStringQueryKeys(std::set &keys, const std::vector &pkList); + + static void FillByteQueryKeys(std::set &keys, const std::vector &pkList); }; } // DistributedDB #endif // QUERY_UTILS_H 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 fe7251c2e417a0e9014a62fdff0c0b9f4674086c..65d12d595e9ca3f8a233ed4b22b63e86e9f1e951 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 @@ -42,12 +42,12 @@ public: const std::string GetExtendName() const; std::string ToString() const; const std::vector GetDropTempTriggerSql() const; - const std::string GetTempInsertTriggerSql() const; + const std::string GetTempInsertTriggerSql(bool incFlag = false) const; const std::string GetDropTempTriggerSql(TriggerMode::TriggerModeEnum mode) const; const std::string GetCreateTempTriggerSql(TriggerMode::TriggerModeEnum mode) const; const std::string GetTempTriggerName(TriggerMode::TriggerModeEnum mode) const; - const std::string GetTempUpdateTriggerSql() const; - const std::string GetTempDeleteTriggerSql() const; + const std::string GetTempUpdateTriggerSql(bool incFlag = false) const; + const std::string GetTempDeleteTriggerSql(bool incFlag = false) const; void SetTableName(const std::string &tableName); void SetExtendName(const std::string &colName); void SetTrackerNames(const std::set &trackerNames); 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 32e6cdedc42c359935f282abc81f50ea48e11440..3a5056e2dba817750c58d9b69ef1f4cb7d67f8a1 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 &identifierExt, const std::string &userId) { - ExtConnectionLifeCycleCallback(identifierExt, userId); + notifier = [this](const std::string &identifier, const std::string &userId) { + ExtConnectionLifeCycleCallback(identifier, userId); }; } else { - notifier = [this](const std::string &identifierExt, const std::string &userId) { - ConnectionLifeCycleCallback(identifierExt, userId); + notifier = [this](const std::string &identifier, const std::string &userId) { + ConnectionLifeCycleCallback(identifier, 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 d5558a332a0bb39425e86922ece1f9dd68d27eb1..853e33dd8990fe2703f28ad2e973af34c45aefdb 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 @@ -209,7 +209,7 @@ AssetOperationUtils::AssetOpType AssetOperationUtils::HandleIfExistAndSameStatus if (dbAsset.name != cacheAsset.name) { continue; } - if (dbAsset.status == cacheAsset.status) { + if (dbAsset.status == cacheAsset.status && dbAsset.hash == cacheAsset.hash) { return AssetOpType::HANDLE; } return AssetOpType::NOT_HANDLE; diff --git a/kv_store/frameworks/libs/distributeddb/common/src/data_value.cpp b/kv_store/frameworks/libs/distributeddb/common/src/data_value.cpp index 6ac0ad91f034b09053fa79cf391633908caf4cd1..bc2861218ea40c29678f91f0338630bdb8acf985 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/data_value.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/data_value.cpp @@ -76,6 +76,8 @@ int Blob::WriteBlob(const uint8_t *ptrArray, const uint32_t &size) } errno_t errCode = memcpy_s(ptr_, size, ptrArray, size); if (errCode != EOK) { + delete[] ptr_; + ptr_ = nullptr; return -E_SECUREC_ERROR; } size_ = size; 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 e543a1b5371301417b8536e197b64624e15aa3ad..5f2b11eef62497d395d047cd78db54a6d16ac5f7 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/db_common.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/db_common.cpp @@ -16,6 +16,7 @@ #include "db_common.h" #include +#include #include #include #ifndef _WIN32 @@ -642,7 +643,8 @@ bool DBCommon::IsRecordError(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_RECORD_ALREADY_EXISTED) && - status != static_cast(DBStatus::CLOUD_RECORD_NOT_FOUND); + status != static_cast(DBStatus::CLOUD_RECORD_NOT_FOUND) && + status != static_cast(DBStatus::LOCAL_ASSET_NOT_FOUND); } bool DBCommon::IsIntTypeRecordError(const VBucket &record) @@ -662,7 +664,8 @@ bool DBCommon::IsRecordIgnored(const VBucket &record) return false; } auto status = std::get(record.at(CloudDbConstant::ERROR_FIELD)); - return status == static_cast(DBStatus::CLOUD_RECORD_EXIST_CONFLICT); + return status == static_cast(DBStatus::CLOUD_RECORD_EXIST_CONFLICT) || + status == static_cast(DBStatus::CLOUD_VERSION_CONFLICT); } bool DBCommon::IsRecordVersionConflict(const VBucket &record) @@ -730,6 +733,13 @@ bool DBCommon::IsNeedCompensatedForUpload(const VBucket &uploadExtend, const Clo (DBCommon::IsCloudRecordNotFound(uploadExtend) && type == CloudWaterType::UPDATE); } +bool DBCommon::IsRecordIgnoredForReliability(const VBucket &uploadExtend, const CloudWaterType &type) +{ + return (DBCommon::IsCloudRecordAlreadyExisted(uploadExtend) && type == CloudWaterType::INSERT) || + (DBCommon::IsCloudRecordNotFound(uploadExtend) && + (type == CloudWaterType::UPDATE || type == CloudWaterType::DELETE)); +} + bool DBCommon::IsRecordSuccess(const VBucket &record) { return record.find(CloudDbConstant::ERROR_FIELD) == record.end(); @@ -752,15 +762,15 @@ void DBCommon::LoadGrdLib(void) { static std::once_flag loadOnceFlag; std::call_once(loadOnceFlag, []() { - if (!g_isGrdLoaded) { #ifndef _WIN32 + if (!g_isGrdLoaded) { if (dlopen("libarkdata_db_core.z.so", RTLD_LAZY) != NULL) { g_isGrdLoaded = true; } else { LOGW("[DBCommon] unable to load grd lib, errno: %d, %s", errno, dlerror()); } -#endif } +#endif }); } @@ -793,6 +803,12 @@ 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) +{ + auto [ptr, errCode] = std::from_chars(str.data(), str.data() + str.size(), value); + return errCode == std::errc{} && ptr == str.data() + str.size(); +} + void DBCommon::RemoveDuplicateAssetsData(std::vector &assets) { std::unordered_map indexMap; @@ -817,11 +833,10 @@ void DBCommon::RemoveDuplicateAssetsData(std::vector &assets) indexMap[asset.name] = prevIndex; continue; } - if (std::all_of(asset.modifyTime.begin(), asset.modifyTime.end(), ::isdigit) && - std::all_of(prevAsset.modifyTime.begin(), prevAsset.modifyTime.end(), ::isdigit) && + uint64_t modifyTime = 0; + uint64_t prevModifyTime = 0; + if (ConvertToUInt(asset.modifyTime, modifyTime) && ConvertToUInt(prevAsset.modifyTime, prevModifyTime) && !asset.modifyTime.empty() && !prevAsset.modifyTime.empty()) { - auto modifyTime = std::stoll(asset.modifyTime); - auto prevModifyTime = std::stoll(prevAsset.modifyTime); arr[modifyTime > prevModifyTime ? prevIndex : i] = 1; indexMap[asset.name] = modifyTime > prevModifyTime ? i : prevIndex; continue; 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 2652b3659646a53df195b4081c55d8764a06bc83..ff608c703b5974062384a875213547f5c985484b 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,7 +91,7 @@ void DBDfxAdapter::ReportBehavior(const ReportTask &reportTask) .arraySize = 0}, {.name = {"FUNC"}, .t = HISYSEVENT_STRING, - .v = {.s = const_cast(reportTask.funcName.c_str())}, + .v = {.s = const_cast(ORG_PKG_NAME.c_str())}, .arraySize = 0}, {.name = {"BIZ_SCENE"}, .t = HISYSEVENT_INT32, @@ -111,7 +111,7 @@ void DBDfxAdapter::ReportBehavior(const ReportTask &reportTask) .arraySize = 0 }, {.name = {"ERROR_CODE"}, .t = HISYSEVENT_INT32, - .v = { .i32 = static_cast(dbDfxErrCode)}, + .v = { .i32 = static_cast(reportTask.result)}, .arraySize = 0 }, }; RuntimeContext::GetInstance()->ScheduleTask([=]() { diff --git a/kv_store/frameworks/libs/distributeddb/common/src/evloop/src/event_loop_epoll.cpp b/kv_store/frameworks/libs/distributeddb/common/src/evloop/src/event_loop_epoll.cpp index 21d1aae2110b4f040d9a23490c424c711fa558aa..18486aa6a33d466543ceec8ed515faa995bbffed 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/evloop/src/event_loop_epoll.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/evloop/src/event_loop_epoll.cpp @@ -171,13 +171,13 @@ void EventLoopEpoll::EpollWokenUp() uint32_t EventLoopEpoll::CalEpollEvents(EventsMask events) const { uint32_t epollEvents = 0; - if (events & IEvent::ET_READ) { // LCOV_EXCL_BR_LINE + if ((events & static_cast(IEvent::ET_READ)) != 0) { // LCOV_EXCL_BR_LINE epollEvents |= EPOLLIN; } - if (events & IEvent::ET_WRITE) { // LCOV_EXCL_BR_LINE + if ((events & static_cast(IEvent::ET_WRITE)) != 0) { // LCOV_EXCL_BR_LINE epollEvents |= EPOLLOUT; } - if (events & IEvent::ET_ERROR) { // LCOV_EXCL_BR_LINE + if ((events & static_cast(IEvent::ET_ERROR)) != 0) { // LCOV_EXCL_BR_LINE epollEvents |= EPOLLERR; } return epollEvents; @@ -186,13 +186,13 @@ uint32_t EventLoopEpoll::CalEpollEvents(EventsMask events) const EventsMask EventLoopEpoll::CalEventsMask(uint32_t epollEvents) { EventsMask events = 0; - if (epollEvents & EPOLLIN) { // LCOV_EXCL_BR_LINE + if ((epollEvents & EPOLLIN) != 0) { // LCOV_EXCL_BR_LINE events |= IEvent::ET_READ; } - if (epollEvents & EPOLLOUT) { // LCOV_EXCL_BR_LINE + if ((epollEvents & EPOLLOUT) != 0) { // LCOV_EXCL_BR_LINE events |= IEvent::ET_WRITE; } - if (epollEvents & EPOLLERR) { // LCOV_EXCL_BR_LINE + if ((epollEvents & EPOLLERR) != 0) { // LCOV_EXCL_BR_LINE events |= IEvent::ET_ERROR; } return events; 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 0667fc681bba5f6650f397e94a979f9eec45803f..40945cc0b03b36c5eae211858c4f4c9409c4df0b 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/platform_specific.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/platform_specific.cpp @@ -619,7 +619,7 @@ int OpenFile(const std::string &fileName, FileHandle *&fileHandle) } fileHandle->handle = open(fileName.c_str(), (O_WRONLY | O_CREAT), (S_IRUSR | S_IWUSR | S_IRGRP)); if (fileHandle->handle < 0) { - LOGE("[FileLock] can not open file when lock it:[%d], filename: %s", errno, fileName.c_str()); + LOGE("[FileLock] can not open file when lock it:[%d]", errno); delete fileHandle; fileHandle = nullptr; return -E_SYSTEM_API_FAIL; diff --git a/kv_store/frameworks/libs/distributeddb/common/src/query_utils.cpp b/kv_store/frameworks/libs/distributeddb/common/src/query_utils.cpp index e9877197b3626ee93742b26aaaacf626e05f0048..111511fcf9cc517e9a171863e16db0fc7d582111 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/query_utils.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/query_utils.cpp @@ -64,15 +64,10 @@ void QueryUtils::FillQueryInKeys(const std::map> for (const auto &[col, pkList] : syncPk) { switch (dataIndex[col]) { case TYPE_INDEX: - for (const auto &pk : pkList) { - std::string keyStr = std::get(pk); - keys.insert(Key(keyStr.begin(), keyStr.end())); - } + FillStringQueryKeys(keys, pkList); break; case TYPE_INDEX: - for (const auto &pk : pkList) { - keys.insert(std::get(pk)); - } + FillByteQueryKeys(keys, pkList); break; default: break; @@ -82,4 +77,25 @@ void QueryUtils::FillQueryInKeys(const std::map> query.InKeys(keys); } } + +void QueryUtils::FillStringQueryKeys(std::set &keys, const std::vector &pkList) +{ + for (const auto &pk : pkList) { + const std::string *keyStrPtr = std::get_if(&pk); + if (keyStrPtr == nullptr) { + continue; + } + keys.insert(Key((*keyStrPtr).begin(), (*keyStrPtr).end())); + } +} + +void QueryUtils::FillByteQueryKeys(std::set &keys, const std::vector &pkList) +{ + for (const auto &pk : pkList) { + if (std::get_if(&pk) == nullptr) { + continue; + } + keys.insert(std::get(pk)); + } +} } // DistributedDB \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/common/src/relational/relational_row_data_set.cpp b/kv_store/frameworks/libs/distributeddb/common/src/relational/relational_row_data_set.cpp index ffed14cd5c0ce302637098c16928293ee6c69dd0..81bda77fd0fb7043aeb9ce2d88e8a943347c3f8e 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/relational/relational_row_data_set.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/relational/relational_row_data_set.cpp @@ -79,12 +79,14 @@ int RelationalRowDataSet::DeSerialize(Parcel &parcel) uint32_t size = 0; parcel.ReadUInt32(size); if (parcel.IsError() || size > DBConstant::MAX_REMOTEDATA_SIZE / parcel.GetStringLen(std::string {})) { + LOGE("parcel size is wrong when get string, errcode: %d, size: %" PRIu32, -E_PARSE_FAIL, size); return -E_PARSE_FAIL; } while (size-- > 0) { std::string str; parcel.ReadString(str); if (parcel.IsError()) { + LOGE("parcel read string wrong, errcode: %d", -E_PARSE_FAIL); return -E_PARSE_FAIL; } colNames_.emplace_back(std::move(str)); @@ -92,21 +94,27 @@ int RelationalRowDataSet::DeSerialize(Parcel &parcel) parcel.ReadUInt32(size); if (parcel.IsError() || size > DBConstant::MAX_REMOTEDATA_SIZE / parcel.GetUInt32Len()) { + LOGE("parcel size is wrong when get int, errcode: %d, size: %" PRIu32, -E_PARSE_FAIL, size); return -E_PARSE_FAIL; } while (size-- > 0) { auto rowData = new (std::nothrow) RelationalRowDataImpl(); if (rowData == nullptr) { + LOGE("alloc rowData wrong, errcode: %d", -E_OUT_OF_MEMORY); return -E_OUT_OF_MEMORY; } if (rowData->DeSerialize(parcel) != E_OK) { + delete rowData; + rowData = nullptr; + LOGE("rowData deserialize wrong, errcode: %d", -E_PARSE_FAIL); return -E_PARSE_FAIL; } data_.push_back(rowData); } parcel.EightByteAlign(); if (parcel.IsError()) { + LOGE("parcel align wrong, errcode: %d", -E_PARSE_FAIL); return -E_PARSE_FAIL; } return E_OK; 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 5b47602ea871474f8be9beef1c1a98a6f3f971ca..199adeda8a456cbb4d4668c04611f7ba61408d43 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 @@ -64,6 +64,8 @@ int RelationalSchemaObject::ParseFromSchemaString(const std::string &inSchemaStr schemaType_ = SchemaType::RELATIVE; schemaString_ = schemaObj.ToString(); isValid_ = true; + GenerateReachableRef(); + GenerateTableInfoReferenced(); return E_OK; } 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 ea406582c3c71d7b8cfd154f2bb9769c8b68c5ee..cbfb0cbbe6029a99030eac4de1c147dcc6a1b038 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 @@ -145,7 +145,7 @@ const std::string TrackerTable::GetTempTriggerName(TriggerMode::TriggerModeEnum return DBConstant::RELATIONAL_PREFIX + tableName_ + "_ON_" + TriggerMode::GetTriggerModeString(mode) + "_TEMP"; } -const std::string TrackerTable::GetTempInsertTriggerSql() const +const std::string TrackerTable::GetTempInsertTriggerSql(bool incFlag) const { // This trigger is built on the log table std::string sql = "CREATE TEMP TRIGGER IF NOT EXISTS " + DBConstant::RELATIONAL_PREFIX + tableName_; @@ -153,7 +153,11 @@ const std::string TrackerTable::GetTempInsertTriggerSql() const sql += " WHEN (SELECT 1 FROM " + DBConstant::RELATIONAL_PREFIX + "metadata" + " WHERE key = 'log_trigger_switch' AND value = 'false')\n"; sql += "BEGIN\n"; + if (incFlag) { + sql += CloudStorageUtils::GetCursorIncSqlWhenAllow(tableName_) + "\n"; + } else { sql += CloudStorageUtils::GetCursorIncSql(tableName_) + "\n"; + } sql += "UPDATE " + DBConstant::RELATIONAL_PREFIX + tableName_ + "_log" + " SET "; sql += "cursor=" + CloudStorageUtils::GetSelectIncCursorSql(tableName_) + " WHERE"; sql += " hash_key = NEW.hash_key;\n"; @@ -164,14 +168,18 @@ const std::string TrackerTable::GetTempInsertTriggerSql() const return sql; } -const std::string TrackerTable::GetTempUpdateTriggerSql() const +const std::string TrackerTable::GetTempUpdateTriggerSql(bool incFlag) const { std::string sql = "CREATE TEMP TRIGGER IF NOT EXISTS " + DBConstant::RELATIONAL_PREFIX + tableName_; sql += "_ON_UPDATE_TEMP AFTER UPDATE ON " + tableName_; sql += " WHEN (SELECT 1 FROM " + DBConstant::RELATIONAL_PREFIX + "metadata" + " WHERE key = 'log_trigger_switch' AND value = 'false')\n"; sql += "BEGIN\n"; - sql += CloudStorageUtils::GetCursorIncSql(tableName_) + "\n"; + if (incFlag) { + sql += CloudStorageUtils::GetCursorIncSqlWhenAllow(tableName_) + "\n"; + } else { + sql += CloudStorageUtils::GetCursorIncSql(tableName_) + "\n"; + } sql += "UPDATE " + DBConstant::RELATIONAL_PREFIX + tableName_ + "_log" + " SET "; if (!IsEmpty()) { sql += "extend_field=" + GetAssignValSql() + ","; @@ -185,20 +193,32 @@ const std::string TrackerTable::GetTempUpdateTriggerSql() const return sql; } -const std::string TrackerTable::GetTempDeleteTriggerSql() const +const std::string TrackerTable::GetTempDeleteTriggerSql(bool incFlag) const { std::string sql = "CREATE TEMP TRIGGER IF NOT EXISTS " + DBConstant::RELATIONAL_PREFIX + tableName_; sql += "_ON_DELETE_TEMP AFTER DELETE ON " + tableName_ + " WHEN (SELECT 1 FROM " + DBConstant::RELATIONAL_PREFIX + "metadata" + " WHERE key = 'log_trigger_switch' AND value = 'false')\n"; sql += "BEGIN\n"; - sql += CloudStorageUtils::GetCursorIncSql(tableName_) + "\n"; + if (IsEmpty() && incFlag) { + sql += "SELECT 1;\n"; + sql += "\nEND;"; + return sql; + } + if (!incFlag) { + sql += CloudStorageUtils::GetCursorIncSql(tableName_) + "\n"; + } sql += "UPDATE " + DBConstant::RELATIONAL_PREFIX + tableName_ + "_log" + " SET "; if (!IsEmpty()) { sql += "extend_field=" + GetAssignValSql(true) + ","; } - sql += "cursor=" + CloudStorageUtils::GetSelectIncCursorSql(tableName_) + " WHERE"; - sql += " data_key = OLD." + std::string(DBConstant::SQLITE_INNER_ROWID) + ";\n"; + if (!incFlag) { + sql += "cursor=" + CloudStorageUtils::GetSelectIncCursorSql(tableName_); + } + if (!IsEmpty() && incFlag) { + sql.pop_back(); + } + sql += " WHERE data_key = OLD." + std::string(DBConstant::SQLITE_INNER_ROWID) + ";\n"; if (!IsEmpty()) { sql += "SELECT server_observer('" + tableName_ + "', 1);"; } diff --git a/kv_store/frameworks/libs/distributeddb/common/src/runtime_context.cpp b/kv_store/frameworks/libs/distributeddb/common/src/runtime_context.cpp index 7c84bba70ebe22d9fa66f2e30d764964c44a52ad..29100e2422c04b89fb77f33990a7d8899b1eb7c2 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/runtime_context.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/runtime_context.cpp @@ -20,22 +20,16 @@ namespace DistributedDB { RuntimeContext *RuntimeContext::GetInstance() { - const int MEMORY_MAX_SIZE = 4096; - static_assert(sizeof(RuntimeContextImpl) < MEMORY_MAX_SIZE); - static char instMemory[MEMORY_MAX_SIZE]; static std::mutex instLock_; static std::atomic instPtr = nullptr; // For Double-Checked Locking, we need check insPtr twice if (instPtr == nullptr) { std::lock_guard lock(instLock_); if (instPtr == nullptr) { - // Use instMemory to make sure this singleton not free before other object. - // This operation needn't to malloc memory, we needn't to check nullptr. - instPtr = new (instMemory) RuntimeContextImpl; + instPtr = new RuntimeContextImpl(); LOGI("DistributedDB Version : %s", SOFTWARE_VERSION_STRING); } } return instPtr; } } // 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 0d693f48c95af050bbe6a9ff5d62ee42c79a3661..36d1831b3aa99cba7720d80ea47def84eab6f040 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 @@ -193,14 +193,14 @@ private: std::shared_ptr GetDBStatusAdapter(); std::shared_ptr GetSubscribeRecorder(); - int ScheduleTaskByThreadPool(const TaskAction &task) const __attribute__((no_sanitize("cfi"))); + int ScheduleTaskByThreadPool(const TaskAction &task) const; int SetTimerByThreadPool(int milliSeconds, const TimerAction &action, - const TimerFinalizer &finalizer, bool allocTimerId, TimerId &timerId) __attribute__((no_sanitize("cfi"))); + const TimerFinalizer &finalizer, bool allocTimerId, TimerId &timerId); int ModifyTimerByThreadPool(TimerId timerId, int milliSeconds); - void RemoveTimerByThreadPool(TimerId timerId, bool wait) __attribute__((no_sanitize("cfi"))); + void RemoveTimerByThreadPool(TimerId timerId, bool wait); void ThreadPoolTimerAction(int milliSeconds, const TimerAction &action, TimerId timerId); diff --git a/kv_store/frameworks/libs/distributeddb/communicator/src/communicator_aggregator.cpp b/kv_store/frameworks/libs/distributeddb/communicator/src/communicator_aggregator.cpp index ad7ca8c46e9f84278bb94b9458ca39dbb85f2d59..61af65e241e47c090a0944d42e929ec44ad87b6b 100644 --- a/kv_store/frameworks/libs/distributeddb/communicator/src/communicator_aggregator.cpp +++ b/kv_store/frameworks/libs/distributeddb/communicator/src/communicator_aggregator.cpp @@ -901,7 +901,7 @@ void CommunicatorAggregator::NotifyConnectChange(const std::string &srcTarget, // Ignore nonactivated communicator if (commMap_.count(entry.first) != 0 && commMap_.at(entry.first).second) { LOGI("[CommAggr][NotifyConnectChange] label=%s, srcTarget=%s{private}, isOnline=%d.", - VEC_TO_STR(entry.first), srcTarget.c_str(), entry.second); + VEC_TO_STR(entry.first), srcTarget.c_str(), entry.second); commMap_.at(entry.first).first->OnConnectChange(srcTarget, entry.second); } } diff --git a/kv_store/frameworks/libs/distributeddb/communicator/src/serial_buffer.cpp b/kv_store/frameworks/libs/distributeddb/communicator/src/serial_buffer.cpp index 4f562a292943673efcc6d40663cd77c675336026..1e60c6df9b93fd59e5e1618c5d451429c3577af2 100644 --- a/kv_store/frameworks/libs/distributeddb/communicator/src/serial_buffer.cpp +++ b/kv_store/frameworks/libs/distributeddb/communicator/src/serial_buffer.cpp @@ -129,6 +129,8 @@ SerialBuffer *SerialBuffer::Clone(int &outErrorNo) errno_t errCode = memcpy_s(twinBuffer->bytes_, totalLen_, bytes_, totalLen_); if (errCode != EOK) { outErrorNo = -E_SECUREC_ERROR; + delete twinBuffer->bytes_; + twinBuffer->bytes_ = nullptr; delete twinBuffer; twinBuffer = nullptr; return nullptr; diff --git a/kv_store/frameworks/libs/distributeddb/distributeddb.gni b/kv_store/frameworks/libs/distributeddb/distributeddb.gni index edad8b1888960ec1faf32dbe990507a45218f895..620289b4b697a85b4533d18e24467136c696f92e 100644 --- a/kv_store/frameworks/libs/distributeddb/distributeddb.gni +++ b/kv_store/frameworks/libs/distributeddb/distributeddb.gni @@ -194,6 +194,7 @@ distributeddb_src = [ "${distributeddb_path}/storage/src/sqlite/sqlite_storage_engine.cpp", "${distributeddb_path}/storage/src/sqlite/sqlite_storage_executor.cpp", "${distributeddb_path}/storage/src/sqlite/sqlite_utils.cpp", + "${distributeddb_path}/storage/src/sqlite/sqlite_utils_extend.cpp", "${distributeddb_path}/storage/src/storage_engine.cpp", "${distributeddb_path}/storage/src/storage_engine_manager.cpp", "${distributeddb_path}/storage/src/storage_executor.cpp", @@ -234,6 +235,7 @@ distributeddb_src = [ "${distributeddb_path}/syncer/src/device/singlever/single_ver_data_message_schedule.cpp", "${distributeddb_path}/syncer/src/device/singlever/single_ver_data_packet.cpp", "${distributeddb_path}/syncer/src/device/singlever/single_ver_data_sync.cpp", + "${distributeddb_path}/syncer/src/device/singlever/single_ver_data_sync_extend.cpp", "${distributeddb_path}/syncer/src/device/singlever/single_ver_data_sync_utils.cpp", "${distributeddb_path}/syncer/src/device/singlever/single_ver_kv_sync_task_context.cpp", "${distributeddb_path}/syncer/src/device/singlever/single_ver_kv_syncer.cpp", diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/include/json_common.h b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/include/json_common.h index e8046aed6305d9cf74a7cd5ff55b7b23eda452f8..b02231e7ea7941028e8850b54fd139cc4096eaa9 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/include/json_common.h +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/include/json_common.h @@ -37,6 +37,7 @@ public: static bool isValueEqual(const ValueObject &srcValue, const ValueObject &targetValue); static int Append(const JsonObject &src, const JsonObject &add, bool isReplace); static bool IsJsonNodeMatch(const JsonObject &src, const JsonObject &target, int &errCode); + static bool ConvertToInt(const std::string &str, int &value); private: static bool JsonEqualJudge(const JsonFieldPath &itemPath, const JsonObject &src, const JsonObject &item, 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 98473caed4443ec682afc5d0e459a666b4baeda8..abdf6779ad4422d5b9384556dedeab7637dfb463 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 @@ -14,6 +14,7 @@ */ #include "json_common.h" +#include #include #include "doc_errno.h" @@ -149,12 +150,8 @@ bool JsonCommon::CheckProjectionNode(JsonObject &node, bool isFirstLevel, int &e return false; } for (size_t i = 0; i < fieldName.size(); i++) { - if (!((isalpha(fieldName[i])) || (isdigit(fieldName[i])) || (fieldName[i] == '_') || - (isFirstLevel && fieldName[i] == '.'))) { - errCode = -E_INVALID_ARGS; - return false; - } - if (i == 0 && (isdigit(fieldName[i]))) { + if ((i == 0 && (isdigit(fieldName[i]))) || !((isalpha(fieldName[i])) || + (isdigit(fieldName[i])) || (fieldName[i] == '_') || (isFirstLevel && fieldName[i] == '.'))) { errCode = -E_INVALID_ARGS; return false; } @@ -169,6 +166,12 @@ bool JsonCommon::CheckProjectionNode(JsonObject &node, bool isFirstLevel, int &e return true; } +bool JsonCommon::ConvertToInt(const std::string &str, int &value) +{ + auto [ptr, errCode] = std::from_chars(str.data(), str.data() + str.size(), value); + return errCode == std::errc{} && ptr == str.data() + str.size(); +} + bool JsonCommon::CheckProjectionField(JsonObject &jsonObj, int &errCode) { bool isFirstLevel = true; @@ -464,8 +467,10 @@ bool JsonNodeReplace(const JsonObject &src, const JsonFieldPath &itemPath, const GLOGE("Find father item in source json object failed. %d", errCode); return false; } - if (fatherItem.GetType() == JsonObject::Type::JSON_ARRAY && IsNumber(itemPath.back())) { - fatherItem.ReplaceItemInArray(std::stoi(itemPath.back()), item, errCode); + int intItemPath = 0; + if (fatherItem.GetType() == JsonObject::Type::JSON_ARRAY && + JsonCommon::ConvertToInt(itemPath.back(), intItemPath)) { + fatherItem.ReplaceItemInArray(intItemPath, item, errCode); if (errCode != E_OK) { externErrCode = (externErrCode == E_OK ? errCode : externErrCode); GLOGE("Find father item in source json object failed. %d", errCode); @@ -473,11 +478,6 @@ bool JsonNodeReplace(const JsonObject &src, const JsonFieldPath &itemPath, const return false; } fatherItem.ReplaceItemInObject(itemPath.back().c_str(), item, errCode); - if (errCode != E_OK) { - externErrCode = (externErrCode == E_OK ? errCode : externErrCode); - GLOGE("Find father item in source json object failed. %d", errCode); - return false; - } } else { JsonObject fatherItem = src.FindItem(fatherPath, errCode); if (errCode != E_OK) { @@ -491,11 +491,11 @@ bool JsonNodeReplace(const JsonObject &src, const JsonFieldPath &itemPath, const return false; } fatherItem.ReplaceItemInObject(itemPath.back().c_str(), item, errCode); - if (errCode != E_OK) { - externErrCode = (externErrCode == E_OK ? errCode : externErrCode); - GLOGE("Find father item in source json object failed. %d", errCode); - return false; - } + } + if (errCode != E_OK) { + externErrCode = (externErrCode == E_OK ? errCode : externErrCode); + GLOGE("Find father item in source json object failed. %d", errCode); + return false; } return true; } diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/interface/include/result_set.h b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/interface/include/result_set.h index e200ed4e0499f38526ae5f8e5986c53b386c74a8..a8a7e14cf7f52083b4a9670c0d9f9845143d88a1 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/interface/include/result_set.h +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/interface/include/result_set.h @@ -45,6 +45,8 @@ private: int CheckCutNode(JsonObject *node, std::vector singleCutPath, std::vector> &allCutPath); int GetNextWithField(); + int CutJsonBranchInner(JsonObject &cjsonObj, bool viewType, bool isIdExistInValue, + bool &isInsertIdflag); DocumentStore *store_ = nullptr; bool isCutBranch_ = false; diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/interface/src/result_set.cpp b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/interface/src/result_set.cpp index e09a511d74ccfbdcc2b2fac722586bbb35ed898d..439a5485682b884dd68ef416cb4d2e2b9a548ba7 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/interface/src/result_set.cpp +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/interface/src/result_set.cpp @@ -236,21 +236,11 @@ int InsertId(JsonObject &cjsonObj, const std::string &jsonKey) return E_OK; } -int ResultSet::CutJsonBranch(std::string &jsonKey, std::string &jsonData) +int ResultSet::CutJsonBranchInner(JsonObject &cjsonObj, bool viewType, bool isIdExistInValue, + bool &isInsertIdflag) { - int errCode; - JsonObject cjsonObj = JsonObject::Parse(jsonData, errCode, true); - if (errCode != E_OK) { - GLOGE("jsonData Parsed failed"); - return errCode; - } - bool isIdExistInValue = true; // if id exsit in the value string that get from db. - bool isInsertIdflag = false; - isIdExistInValue = cjsonObj.GetObjectItem("_id", errCode).IsNull() ? false : true; - if (context_->ifShowId && !isIdExistInValue) { - isInsertIdflag = true; // ifShowId is true,and then the data taken out does not have IDs, insert id. - } - if (context_->viewType) { + int errCode = E_OK; + if (viewType) { std::vector singlePath; JsonObject cjsonObjChild = cjsonObj.GetChild(); std::vector> allCutPath; @@ -267,14 +257,7 @@ int ResultSet::CutJsonBranch(std::string &jsonKey, std::string &jsonData) isInsertIdflag = true; } } - } - if (isInsertIdflag) { - errCode = InsertId(cjsonObj, jsonKey); - if (errCode != E_OK) { - return errCode; - } - } - if (!context_->viewType) { + } else { for (const auto &singleCutPaht : context_->projectionPath) { cjsonObj.DeleteItemDeeplyOnTarget(singleCutPaht); } @@ -284,6 +267,32 @@ int ResultSet::CutJsonBranch(std::string &jsonKey, std::string &jsonData) cjsonObj.DeleteItemDeeplyOnTarget(idPath); } } + return errCode; +} +int ResultSet::CutJsonBranch(std::string &jsonKey, std::string &jsonData) +{ + int errCode; + JsonObject cjsonObj = JsonObject::Parse(jsonData, errCode, true); + if (errCode != E_OK) { + GLOGE("jsonData Parsed failed"); + return errCode; + } + bool isIdExistInValue = true; // if id exsit in the value string that get from db. + bool isInsertIdflag = false; + isIdExistInValue = cjsonObj.GetObjectItem("_id", errCode).IsNull() ? false : true; + if (context_->ifShowId && !isIdExistInValue) { + isInsertIdflag = true; // ifShowId is true,and then the data taken out does not have IDs, insert id. + } + errCode = CutJsonBranchInner(cjsonObj, context_->viewType, isIdExistInValue, isInsertIdflag); + if (errCode != E_OK) { + return errCode; + } + if (isInsertIdflag) { + errCode = InsertId(cjsonObj, jsonKey); + if (errCode != E_OK) { + return errCode; + } + } jsonData = cjsonObj.Print(); return E_OK; } diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/oh_adapter/src/rd_json_object.cpp b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/oh_adapter/src/rd_json_object.cpp index 09d8847252aba0137812d2829065ec2dfe7f3db1..1b469f2c410f16a5d33424e90e15945b8de6742c 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/oh_adapter/src/rd_json_object.cpp +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/oh_adapter/src/rd_json_object.cpp @@ -20,19 +20,11 @@ #include #include "doc_errno.h" +#include "json_common.h" #include "rd_log_print.h" namespace DocumentDB { #ifndef OMIT_cJSON -namespace { -bool IsNumber(const std::string &str) -{ - return std::all_of(str.begin(), str.end(), [](char c) { - return std::isdigit(c); - }); -} -} // namespace - ValueObject::ValueObject(bool val) { valueType = ValueType::VALUE_BOOL; @@ -351,7 +343,8 @@ int JsonObject::AddItemToObject(const std::string &fieldName, const JsonObject & child = child->next; n++; } - if (IsNumber(fieldName) && n <= std::stoi(fieldName)) { + int intFieldName = 0; + if (JsonCommon::ConvertToInt(fieldName, intFieldName) && n <= intFieldName) { GLOGE("Add item object to array over size."); return -E_NO_DATA; } @@ -374,7 +367,8 @@ int JsonObject::AddItemToObject(const std::string &fieldName) child = child->next; n++; } - if (IsNumber(fieldName) && n <= std::stoi(fieldName)) { + int intFieldName = 0; + if (JsonCommon::ConvertToInt(fieldName, intFieldName) && n <= intFieldName) { GLOGE("Add item object to array over size."); return -E_NO_DATA; } @@ -496,11 +490,12 @@ cJSON *GetChild(cJSON *cjson, const std::string &field, bool caseSens) return cJSON_GetObjectItem(cjson, field.c_str()); } } else if (cjson->type == cJSON_Array) { - if (!IsNumber(field)) { + int intField = 0; + if (!JsonCommon::ConvertToInt(field, intField)) { GLOGW("Invalid json field path, expect array index."); return nullptr; } - return cJSON_GetArrayItem(cjson, std::stoi(field)); + return cJSON_GetArrayItem(cjson, intField); } GLOGW("Invalid json field type, expect object or array."); @@ -521,7 +516,8 @@ cJSON *GetChildPowerMode(cJSON *cjson, const std::string &field, bool caseSens) } // type is cJSON_Array - if (!IsNumber(field)) { + int intField = 0; + if (!JsonCommon::ConvertToInt(field, intField)) { cjson = cjson->child; while (cjson != nullptr) { cJSON *resultItem = GetChild(cjson, field, caseSens); @@ -532,7 +528,7 @@ cJSON *GetChildPowerMode(cJSON *cjson, const std::string &field, bool caseSens) } return nullptr; } - return cJSON_GetArrayItem(cjson, std::stoi(field)); + return cJSON_GetArrayItem(cjson, intField); } cJSON *MoveToPath(cJSON *cjson, const JsonFieldPath &jsonPath, bool caseSens) @@ -654,11 +650,12 @@ int JsonObject::DeleteItemDeeplyOnTarget(const JsonFieldPath &path) } } } else if (nodeFather->type == cJSON_Array) { - if (!IsNumber(fieldName)) { + int intFieldName = 0; + if (!JsonCommon::ConvertToInt(fieldName, intFieldName)) { GLOGW("Invalid json field path, expect array index."); return -E_JSON_PATH_NOT_EXISTS; } - cJSON_DeleteItemFromArray(nodeFather, std::stoi(fieldName)); + cJSON_DeleteItemFromArray(nodeFather, intFieldName); if (nodeFather->child == nullptr && path.size() > 1) { JsonFieldPath fatherPath(path.begin(), path.end() - 1); DeleteItemDeeplyOnTarget(fatherPath); diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/test/unittest/api/documentdb_api_test.cpp b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/test/unittest/api/documentdb_api_test.cpp index 8a7d3409b9bd3f230ecf225b0534f8730c8e6a2e..7232eab6d8b25bc81f5e1d03eb13f75d1da58316 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/test/unittest/api/documentdb_api_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/test/unittest/api/documentdb_api_test.cpp @@ -136,7 +136,7 @@ HWTEST_F(DocumentDBApiTest, OpenDBTest004, TestSize.Level0) FILE *fp; fp = fopen("./test.txt", "w"); fwrite("hello", 5, 5, fp); - fclose(fp); + (void)fclose(fp); GRD_DB *db = nullptr; int status = GRD_DBOpen(path.c_str(), nullptr, GRD_DB_OPEN_ONLY, &db); EXPECT_EQ(status, GRD_INVALID_FILE_FORMAT); @@ -177,6 +177,21 @@ HWTEST_F(DocumentDBApiTest, OpenDBPathTest002, TestSize.Level0) EXPECT_EQ(status, GRD_FAILED_FILE_OPERATION); } +/** + * @tc.name: OpenDBPathTest004 + * @tc.desc: call GRD_DBOpen, input dbFile as existed menu + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentDBApiTest, OpenDBPathTest004, TestSize.Level0) +{ + GRD_DB *db = nullptr; + std::string pathNoPerm = "../test"; + int status = GRD_DBOpen(pathNoPerm.c_str(), nullptr, GRD_DB_OPEN_CREATE, &db); + EXPECT_EQ(status, GRD_INVALID_ARGS); +} + /** * @tc.name: OpenDBConfigTest001 * @tc.desc: Test open document db with invalid config option @@ -276,9 +291,9 @@ HWTEST_F(DocumentDBApiTest, OpenDBConfigTest005, TestSize.Level0) * @tc.steps:step2. connection2 call GRD_DBOpen to open the db with the different configStr. * @tc.expected:step2. return GRD_CONFIG_OPTION_MISMATCH. */ - const char *configStr_2 = R"({"pageSize":4})"; + const char *configStr2 = R"({"pageSize":4})"; GRD_DB *db2 = nullptr; - result = GRD_DBOpen(path.c_str(), configStr_2, GRD_DB_OPEN_ONLY, &db2); + result = GRD_DBOpen(path.c_str(), configStr2, GRD_DB_OPEN_ONLY, &db2); ASSERT_EQ(result, GRD_INVALID_ARGS); ASSERT_EQ(GRD_DBClose(db1, GRD_DB_CLOSE), GRD_OK); @@ -379,12 +394,13 @@ HWTEST_F(DocumentDBApiTest, OpenDBConfigMaxConnNumTest004, TestSize.Level1) std::string config = "{\"maxConnNum\":" + std::to_string(maxCnt) + "}"; std::vector dbList; - while (maxCnt--) { + while (maxCnt > 0) { GRD_DB *db = nullptr; int status = GRD_DBOpen(path.c_str(), config.c_str(), GRD_DB_OPEN_CREATE, &db); EXPECT_EQ(status, GRD_OK); EXPECT_NE(db, nullptr); dbList.push_back(db); + maxCnt--; } GRD_DB *db = nullptr; diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/test/unittest/api/documentdb_find_test.cpp b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/test/unittest/api/documentdb_find_test.cpp index c799a1f1f3227a4acf5e220d024f986c95bea538..44515ca6b43275908b51a46dbc5c38bbb0a41699 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/test/unittest/api/documentdb_find_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/test/unittest/api/documentdb_find_test.cpp @@ -35,7 +35,7 @@ namespace { std::string g_path = "./document.db"; GRD_DB *g_db = nullptr; constexpr const char *COLLECTION_NAME = "student"; -constexpr const char *colName = "data_"; +constexpr const char *COLLECTION_NAME_2 = "data_"; const int MAX_COLLECTION_NAME = 511; const int MAX_ID_LENS = 899; @@ -1472,7 +1472,7 @@ HWTEST_F(DocumentDBFindTest, DocumentDBFindTest063, TestSize.Level1) std::string path = "./dataShare.db"; int status = GRD_DBOpen(path.c_str(), nullptr, GRD_DB_OPEN_CREATE, &test_db); EXPECT_EQ(status, GRD_OK); - EXPECT_EQ(GRD_CreateCollection(test_db, colName, "", 0), GRD_OK); + EXPECT_EQ(GRD_CreateCollection(test_db, COLLECTION_NAME_2, "", 0), GRD_OK); string document1 = "{\"_id\":\"key2_11_com.acts.ohos.data.datasharetestclient_100\",\ \"bundleName\":\"com.acts.ohos.data.datasharetestclient\",\"key\":\"key2\",\ \"subscriberId\":11,\"timestamp\":1509100700,""\"userId\":100,\"value\":{\"type\":0,"; @@ -1485,14 +1485,14 @@ HWTEST_F(DocumentDBFindTest, DocumentDBFindTest063, TestSize.Level1) document4.push_back('5'); string document5 = "]}}"; string document0635 = document1 + document2 + document4 + document5; - EXPECT_EQ(GRD_InsertDoc(test_db, colName, document0635.c_str(), 0), GRD_OK); + EXPECT_EQ(GRD_InsertDoc(test_db, COLLECTION_NAME_2, document0635.c_str(), 0), GRD_OK); EXPECT_EQ(status, GRD_OK); const char *filter = "{}"; GRD_ResultSet *resultSet = nullptr; const char *projection = "{\"id_\":true, \"timestamp\":true, \"key\":true, \"bundleName\": true, " "\"subscriberId\": true}"; Query query = { filter, projection }; - EXPECT_EQ(GRD_FindDoc(test_db, colName, query, 1, &resultSet), GRD_OK); + EXPECT_EQ(GRD_FindDoc(test_db, COLLECTION_NAME_2, query, 1, &resultSet), GRD_OK); char *value; while (GRD_Next(resultSet) == GRD_OK) { EXPECT_EQ(GRD_GetValue(resultSet, &value), GRD_OK); diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/test/unittest/api/documentdb_insert_test.cpp b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/test/unittest/api/documentdb_insert_test.cpp index 8e862bb6f03454940e39a9bdc2d711020c5d8c2b..c34d5f7a6f10109a471cce64faf0606a6f604073 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/test/unittest/api/documentdb_insert_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/test/unittest/api/documentdb_insert_test.cpp @@ -564,7 +564,7 @@ HWTEST_F(DocumentDBInsertTest, DocumentDBInsertTest025, TestSize.Level1) * @tc.expected:step1.GRD_OK. */ const char *document1 = "{\"_id\" : \"25_0\", \"level1\" : {\"level2\" : {\"level3\" :\ - {\"level4\" : \"level4Val\"}}} , \"level1_2\" : \"level1_2Val\" }"; + {\"level4\" : \"level4Val\"}}}, \"level1_2\" : \"level1_2Val\" }"; EXPECT_EQ(GRD_InsertDoc(g_db, RIGHT_COLLECTION_NAME, document1, 0), GRD_OK); /** * @tc.steps:step2.documents JSON depth is exactly 4. diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/include/cloud/cloud_store_types.h b/kv_store/frameworks/libs/distributeddb/interfaces/include/cloud/cloud_store_types.h index 91e57739e4b4438984414be1b1ec2980db4b4ee5..5e481e6c8375ad4ad60cbca3b18ba6aaa3e3ccc7 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/include/cloud/cloud_store_types.h +++ b/kv_store/frameworks/libs/distributeddb/interfaces/include/cloud/cloud_store_types.h @@ -156,6 +156,7 @@ struct CloudSyncOption { bool merge = false; // default, upload insert need lock LockAction lockAction = LockAction::INSERT; + std::string prepareTraceId; }; enum class QueryNodeType : uint32_t { diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/include/cloud/icloud_db.h b/kv_store/frameworks/libs/distributeddb/interfaces/include/cloud/icloud_db.h index 30d0f4a46bddd25391489be238bab34e249cde50..79e24a0c66efd6bd49c372932e7a8d7ee6906713 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/include/cloud/icloud_db.h +++ b/kv_store/frameworks/libs/distributeddb/interfaces/include/cloud/icloud_db.h @@ -44,6 +44,16 @@ public: virtual DBStatus UnLock() = 0; virtual DBStatus HeartBeat() = 0; virtual DBStatus Close() = 0; + virtual void SetPrepareTraceId(const std::string &traceId) + { + this->prepareTraceId = traceId; + } + virtual std::string GetPrepareTraceId() + { + return this->prepareTraceId; + } +private: + std::string prepareTraceId; }; } // namespace DistributedDB 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 90926d77842888e22f477b62523c6f4c985e14ae..616d78fc14f614f06f4e84d1c45886f146ca00fc 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,9 @@ public: std::string storageEngineType = SQLITE; // use gaussdb_rd as storage engine Rdconfig rdconfig; }; + struct DatabaseStatus { + bool isRebuild = false; + }; DB_API virtual ~KvStoreNbDelegate() {} @@ -200,10 +203,16 @@ 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) = 0; + DB_API virtual DBStatus Sync(const DeviceSyncOption &option, const DeviceSyncProcessCallback &onProcess) + { + return OK; + }; // Cancel sync by syncId - DB_API virtual DBStatus CancelSync(uint32_t syncId) = 0; + DB_API virtual DBStatus CancelSync(uint32_t syncId) + { + return OK; + }; // Check the integrity of this kvStore. DB_API virtual DBStatus CheckIntegrity() const = 0; @@ -280,6 +289,11 @@ public: // Get Entries by the device(uuid) in sync_data. // 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 {}; + } }; } // 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 53080b4a7c1798fa182d37c96b5f9bf088cb9b6c..726171df30f00ad673c9ec718e23179da6e015ab 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/include/store_types.h +++ b/kv_store/frameworks/libs/distributeddb/interfaces/include/store_types.h @@ -26,8 +26,8 @@ namespace DistributedDB { enum DBStatus { - DB_ERROR = -1, // DBStatus in [27328512, 27394048] OK = 0, + DB_ERROR = 27328512, // DBStatus in [27328512, 27394048) BUSY, NOT_FOUND, INVALID_ARGS, @@ -90,7 +90,7 @@ enum DBStatus { CLOUD_RECORD_ALREADY_EXISTED, // this error happen in BatchInsert SQLITE_CANT_OPEN, // the sqlite cannot open LOCAL_ASSET_NOT_FOUND, // file manager miss local assets - BUTT_STATUS // end of status + BUTT_STATUS = 27394048 // end of status }; struct KvStoreConfig { @@ -238,6 +238,7 @@ struct TrackerSchema { std::string tableName; std::string extendColName; std::set trackerColNames; + bool isForceUpgrade = false; }; struct TableReferenceProperty { 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 aef7e2c5c1b2643a4b3b0e86582079c283362c54..b4d78bde6d27b937d0d7303c5748b499c00279a5 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 @@ -88,14 +88,14 @@ namespace { DBStatus TransferDBErrno(int err, bool isPass) { - if (isPass && err > 0) { - return static_cast(err); - } for (const auto &item : ERRNO_MAP) { if (item.errCode == err) { return item.status; } } + if (isPass) { + return static_cast(err); + } return DB_ERROR; } }; 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 3558ab16cf0483833129ba9b5fefd0c7b9a43c90..f3f7c9f532709b6d1a84eaf4f069ba340b208660 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 @@ -1326,4 +1326,16 @@ DBStatus KvStoreNbDelegateImpl::GetDeviceEntries(const std::string &device, std: LOGE("[KvStoreNbDelegate] Get the entries failed:%d", errCode); return TransferDBErrno(errCode); } + +KvStoreNbDelegate::DatabaseStatus KvStoreNbDelegateImpl::GetDatabaseStatus() const +{ + KvStoreNbDelegate::DatabaseStatus status; + if (conn_ == nullptr) { + LOGE("%s", INVALID_CONNECTION); + return status; + } + status.isRebuild = conn_->IsRebuild(); + LOGI("[KvStoreNbDelegate] rebuild %d", static_cast(status.isRebuild)); + return status; +} } // namespace DistributedDB 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 6bf1c508efd59964a24d16ea4af24698f3bf665d..f166d7b37d864094621065db179fd2d358bad37e 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 @@ -188,6 +188,8 @@ public: DBStatus SetCloudSyncConfig(const CloudSyncConfig &config) override; DBStatus GetDeviceEntries(const std::string &device, std::vector &entries) const override; + + DatabaseStatus GetDatabaseStatus() const override; private: DBStatus GetInner(const IOption &option, const Key &key, Value &value) const; DBStatus PutInner(const IOption &option, const Key &key, const Value &value); 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 dd965239ad9ee0bc0f375806858d939007623fe3..c12cbd7ea6948de1940302457bcfdc24f5d9255f 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 @@ -884,7 +884,8 @@ int GetTriggerSqls(sqlite3 *db, const std::map &tableInfos, s return E_OK; } -int AuthorizerCallback(void *data, int operation, const char *tableNameChar, const char *, const char *, const char *) +int AuthorizerCallback([[gnu::unused]] void *data, int operation, const char *tableNameChar, const char *, const char *, + const char *) { if (operation != SQLITE_CREATE_TABLE || tableNameChar == nullptr) { return SQLITE_OK; @@ -1276,6 +1277,8 @@ void HandleDropCloudSyncTable(sqlite3 *db, const std::string &tableName) int HandleDropLogicDeleteData(sqlite3 *db, const std::string &tableName, uint64_t cursor) { + LOGI("DropLogicDeleteData on table:%s length:%d cursor:%" PRIu64, + DBCommon::StringMiddleMasking(tableName).c_str(), tableName.size(), cursor); std::string logTblName = DBCommon::GetLogTableName(tableName); std::string sql = "INSERT OR REPLACE INTO " + DBConstant::RELATIONAL_PREFIX + "metadata" + " VALUES ('log_trigger_switch', 'false')"; @@ -1291,21 +1294,11 @@ int HandleDropLogicDeleteData(sqlite3 *db, const std::string &tableName, uint64_ LOGE("delete logic deletedData failed. %d", errCode); return errCode; } - std::string logTableVersion; - errCode = SQLiteUtils::GetLogTableVersion(db, logTableVersion); - if (errCode != E_OK && errCode != -E_NOT_FOUND) { - LOGE("get log table version failed. %d", errCode); - return errCode; - } - sql = "UPDATE " + logTblName + " SET data_key = -1, flag = (flag & ~0x08) | 0x01"; - // sharing_resource is added after VERSION_5_3, this one is for compatibility - if (logTableVersion >= DBConstant::LOG_TABLE_VERSION_5_3) { - sql += ", sharing_resource = ''"; - } - sql += " WHERE flag&0x08=0x08" + (cursor == 0 ? ";" : " AND cursor <= '" + std::to_string(cursor) + "';"); + sql = "DELETE FROM " + logTblName + " WHERE (flag&0x08=0x08" + + (cursor == 0 ? ");" : " AND cursor <= '" + std::to_string(cursor) + "');"); errCode = sqlite3_exec(db, sql.c_str(), nullptr, nullptr, nullptr); if (errCode != SQLITE_OK) { - LOGE("update logic deletedData failed. %d", errCode); + LOGE("delete logic delete log failed. %d", errCode); return errCode; } sql = "INSERT OR REPLACE INTO " + DBConstant::RELATIONAL_PREFIX + "metadata" + @@ -1710,7 +1703,7 @@ DB_API DistributedDB::DBStatus UnregisterStoreObserver(sqlite3 *db) { std::string fileName; if (!GetDbFileName(db, fileName)) { - LOGE("[UnregisterAllStoreObserver] StoreObserver is invalid."); + LOGD("[UnregisterAllStoreObserver] StoreObserver is invalid."); 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 5f95ec4bf431f9d065eb2090ff0587bf37b80cc7..7d30d941fd525a68380f2d8510dd66cff84b0c94 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 @@ -177,6 +177,7 @@ public: int FillCloudAssetForDownload(const std::string &tableName, VBucket &asset, bool isDownloadSuccess) override; int SetLogTriggerStatus(bool status) override; + int SetCursorIncFlag(bool flag) override; int FillCloudLogAndAsset(OpType opType, const CloudSyncData &data, bool fillAsset, bool ignoreEmptyGid) override; @@ -199,8 +200,6 @@ public: void SetLogicDelete(bool logicDelete); - void SetCloudTaskConfig(const CloudTaskConfig &config) override; - std::pair GetAssetsByGidOrHashKey(const TableSchema &tableSchema, const std::string &gid, const Bytes &hashKey, VBucket &assets) override; @@ -210,7 +209,9 @@ public: int UpdateRecordFlag(const std::string &tableName, bool recordConflict, const LogInfo &logInfo) override; - int GetCompensatedSyncQuery(std::vector &syncQuery) override; + int GetCompensatedSyncQuery(std::vector &syncQuery, std::vector &users) override; + + int ClearUnLockingNoNeedCompensated() override; int MarkFlagAsConsistent(const std::string &tableName, const DownloadData &downloadData, const std::set &gidFilters) override; @@ -224,8 +225,6 @@ public: bool IsTableExistReferenceOrReferenceBy(const std::string &table) override; void ReleaseUploadRecord(const std::string &tableName, const CloudWaterType &type, Timestamp localMark) override; - - bool IsSameCloudLocalDeviceAndNotLocal(const LogInfo &localInfo, const LogInfo &cloudInfo) override; protected: int FillReferenceData(CloudSyncData &syncData); @@ -247,6 +246,9 @@ protected: static int FillReferenceDataIntoExtend(const std::vector &rowid, const std::map &referenceGid, std::vector &extend); + int ReviseLocalModTime(const std::string &tableName, + const std::vector &revisedData) override; + private: SQLiteSingleVerRelationalStorageExecutor *GetHandle(bool isWrite, int &errCode, OperatePerm perm = OperatePerm::NORMAL_PERM) const; @@ -285,7 +287,8 @@ private: int GetCompensatedSyncQueryInner(SQLiteSingleVerRelationalStorageExecutor *handle, const std::vector &tables, std::vector &syncQuery); - int CreateTempSyncTriggerInner(SQLiteSingleVerRelationalStorageExecutor *handle, const std::string &tableName); + int CreateTempSyncTriggerInner(SQLiteSingleVerRelationalStorageExecutor *handle, const std::string &tableName, + bool flag = false); bool CheckTableSupportCompensatedSync(const TableSchema &table); @@ -318,7 +321,6 @@ private: std::shared_ptr syncAbleEngine_ = nullptr; std::atomic logicDelete_ = false; - std::atomic allowLogicDelete_ = false; std::function syncFinishFunc_; std::function uploadStartFunc_; 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 c84a8b9b481e9905b34edfd96cdfe65122d01dc9..d42fe193c50c0ab09055a66a9e389fc8b0718c2a 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 @@ -104,6 +104,7 @@ public: std::vector &updateColName); static std::string GetSelectIncCursorSql(const std::string &tableName); static std::string GetCursorIncSql(const std::string &tableName); + static std::string GetCursorIncSqlWhenAllow(const std::string &tableName); static std::string GetCursorUpgradeSql(const std::string &tableName); static std::string GetUpdateUploadFinishedSql(const std::string &tableName); @@ -116,6 +117,8 @@ public: bool allowEmpty); static std::string GetUpdateRecordFlagSql(const std::string &tableName, bool recordConflict, const LogInfo &logInfo, const VBucket &uploadExtend = {}, const CloudWaterType &type = CloudWaterType::BUTT); + static std::string GetUpdateRecordFlagSqlUpload(const std::string &tableName, bool recordConflict, + const LogInfo &logInfo, const VBucket &uploadExtend = {}, const CloudWaterType &type = CloudWaterType::BUTT); static int BindStepConsistentFlagStmt(sqlite3_stmt *stmt, const VBucket &data, const std::set &gidFilters); static bool IsCloudGidMismatch(const std::string &downloadGid, const std::string &curGid); diff --git a/kv_store/frameworks/libs/distributeddb/storage/include/cloud/schema_mgr.h b/kv_store/frameworks/libs/distributeddb/storage/include/cloud/schema_mgr.h index b21e0b861ce45c0280a00fb70c33c8387b73fe74..71ffce60311140163e7e9833d0f12cc4c5144031 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/include/cloud/schema_mgr.h +++ b/kv_store/frameworks/libs/distributeddb/storage/include/cloud/schema_mgr.h @@ -29,6 +29,7 @@ public: explicit SchemaMgr(); ~SchemaMgr() =default; void SetCloudDbSchema(const DataBaseSchema &schema); + void SetCloudDbSchema(const DataBaseSchema &schema, RelationalSchemaObject &localSchema); std::shared_ptr GetCloudDbSchema(); int GetCloudTableSchema(const TableName &tableName, TableSchema &retSchema); int ChkSchema(const TableName &tableName, RelationalSchemaObject &localSchema); 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 72624574cabd59b259379fe19995d2dfd4294cae..a0036ea993ffac4a445295e9772f9d9256fa8179 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 @@ -143,6 +143,10 @@ public: virtual int SetLogTriggerStatus(bool status) = 0; + virtual int SetCursorIncFlag(bool flag) + { + return E_OK; + }; virtual int FillCloudLogAndAsset(OpType opType, const CloudSyncData &data, bool fillAsset, bool ignoreEmptyGid) = 0; virtual std::string GetIdentify() const = 0; @@ -166,10 +170,6 @@ public: virtual bool IsSharedTable(const std::string &tableName) = 0; - virtual void SetCloudTaskConfig([[gnu::unused]] const CloudTaskConfig &config) - { - } - virtual std::pair GetAssetsByGidOrHashKey(const TableSchema &tableSchema, const std::string &gid, const Bytes &hashKey, VBucket &assets) { @@ -187,7 +187,13 @@ public: return E_OK; } - virtual int GetCompensatedSyncQuery([[gnu::unused]] std::vector &syncQuery) + virtual int GetCompensatedSyncQuery([[gnu::unused]] std::vector &syncQuery, + std::vector &users) + { + return E_OK; + } + + virtual int ClearUnLockingNoNeedCompensated() { return E_OK; } @@ -224,10 +230,17 @@ public: { } - virtual bool IsSameCloudLocalDeviceAndNotLocal(const LogInfo &localInfo, const LogInfo &cloudInfo) + virtual bool IsTagCloudUpdateLocal(const LogInfo &localInfo, const LogInfo &cloudInfo, + SingleVerConflictResolvePolicy policy) { return false; } + + virtual int ReviseLocalModTime(const std::string &tableName, + const std::vector &revisedData) + { + return E_OK; + } }; } diff --git a/kv_store/frameworks/libs/distributeddb/storage/include/ikvdb.h b/kv_store/frameworks/libs/distributeddb/storage/include/ikvdb.h index 9ec875dc8e4dfdc5906d5ae416112dfed2e3dcad..b35821527e93ba572e53f3c81691b84eca768b7c 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/include/ikvdb.h +++ b/kv_store/frameworks/libs/distributeddb/storage/include/ikvdb.h @@ -57,6 +57,8 @@ public: virtual std::string GetStorePath() const = 0; virtual void Dump(int fd) = 0; + + virtual void MarkRebuild() = 0; }; } // namespace DistributedDB 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 fde488cb176af22d52b97468470bb631f9addcae..dd55180a6d4242092bbb8100b8bd8bb41ce1ba8a 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/include/ikvdb_connection.h +++ b/kv_store/frameworks/libs/distributeddb/storage/include/ikvdb_connection.h @@ -165,6 +165,10 @@ public: virtual int SetCloudSyncConfig(const CloudSyncConfig &config) = 0; virtual int GetEntries(const std::string &device, std::vector &entries) const = 0; + + virtual void MarkRebuild() = 0; + + virtual bool IsRebuild() const = 0; }; } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/storage/include/storage_engine_manager.h b/kv_store/frameworks/libs/distributeddb/storage/include/storage_engine_manager.h index 8acab7bb972b0d162055d694e9aba0c4e717555e..e91471048a9799f20fe211d461f85b39bbe95b94 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/include/storage_engine_manager.h +++ b/kv_store/frameworks/libs/distributeddb/storage/include/storage_engine_manager.h @@ -66,7 +66,7 @@ private: static std::mutex instanceLock_; static std::atomic instance_; - static bool isRegLockStatusListener_; + static volatile bool isRegLockStatusListener_; static std::mutex storageEnginesLock_; std::map storageEngines_; 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 4238cbe160bb058bf96b75c09e6278a8e9fd5dbe..add570272f8df21f7ff99b0a4488e7a080bc845c 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/include/storage_proxy.h +++ b/kv_store/frameworks/libs/distributeddb/storage/include/storage_proxy.h @@ -97,9 +97,10 @@ public: int ReleaseContinueToken(ContinueToken &continueStmtToken); int FillCloudAssetForDownload(const std::string &tableName, VBucket &asset, bool isDownloadSuccess); - int SetLogTriggerStatus(bool status); + int SetCursorIncFlag(bool flag); + int FillCloudLogAndAsset(OpType opType, const CloudSyncData &data); std::string GetIdentify() const; @@ -116,8 +117,6 @@ public: void FillCloudGidIfSuccess(const OpType opType, const CloudSyncData &data); - void SetCloudTaskConfig(const CloudTaskConfig &config); - std::pair GetAssetsByGidOrHashKey(const std::string &tableName, const std::string &gid, const Bytes &hashKey, VBucket &assets); @@ -125,7 +124,9 @@ public: int UpdateRecordFlag(const std::string &tableName, bool recordConflict, const LogInfo &logInfo); - int GetCompensatedSyncQuery(std::vector &syncQuery); + int GetCompensatedSyncQuery(std::vector &syncQuery, std::vector &users); + + int ClearUnLockingNoNeedCompensated(); int MarkFlagAsConsistent(const std::string &tableName, const DownloadData &downloadData, const std::set &gidFilters); @@ -152,7 +153,10 @@ public: void ReleaseUploadRecord(const std::string &table, const CloudWaterType &type, Timestamp localWaterMark); - bool IsSameCloudLocalDeviceAndNotLocal(const LogInfo &localInfo, const LogInfo &cloudInfo); + bool IsTagCloudUpdateLocal(const LogInfo &localInfo, const LogInfo &cloudInfo, + SingleVerConflictResolvePolicy policy); + + int ReviseLocalModTime(const std::string &tableName, const std::vector &revisedData); 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 fa0e7cd6b1ac9795cb49b9fc6f4a55eb541cce86..e78ea7c2daeb5dcca3fcfc55d7d98167fdf38f8a 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 @@ -1124,7 +1124,7 @@ std::string CloudStorageUtils::GetUpdateRecordFlagSql(const std::string &tableNa const LogInfo &logInfo, const VBucket &uploadExtend, const CloudWaterType &type) { std::string compensatedBit = std::to_string(static_cast(LogInfoFlag::FLAG_WAIT_COMPENSATED_SYNC)); - std::string consistentBit = std::to_string(static_cast(LogInfoFlag::FLAG_DEVICE_CLOUD_CONSISTENCY)); + std::string inconsistencyBit = std::to_string(static_cast(LogInfoFlag::FLAG_DEVICE_CLOUD_INCONSISTENCY)); bool gidEmpty = logInfo.cloudGid.empty(); bool isDeleted = logInfo.dataKey == DBConstant::DEFAULT_ROW_ID; std::string sql = "UPDATE " + DBCommon::GetLogTableName(tableName) + " SET flag = (CASE WHEN timestamp = ? THEN "; @@ -1132,7 +1132,45 @@ std::string CloudStorageUtils::GetUpdateRecordFlagSql(const std::string &tableNa if (isNeedCompensated && !(isDeleted && gidEmpty)) { sql += "flag | " + compensatedBit + " ELSE flag | " + compensatedBit; } else { - sql += "flag & ~" + compensatedBit + " & ~" + consistentBit + " ELSE flag & ~" + compensatedBit; + sql += "flag & ~" + compensatedBit + " & ~" + inconsistencyBit + " ELSE flag & ~" + compensatedBit; + } + sql += " END), status = (CASE WHEN status == 2 THEN 3 WHEN (status == 1 AND timestamp = ?) THEN 0 ELSE status END)"; + if (DBCommon::IsCloudRecordNotFound(uploadExtend) && + (type == CloudWaterType::UPDATE || type == CloudWaterType::DELETE)) { + sql += ", cloud_gid = '', version = '' "; + } + sql += " WHERE "; + if (!gidEmpty) { + sql += " cloud_gid = '" + logInfo.cloudGid + "'"; + } + if (!isDeleted) { + if (!gidEmpty) { + sql += " OR "; + } + sql += " data_key = '" + std::to_string(logInfo.dataKey) + "'"; + } + if (gidEmpty && isDeleted) { + sql += " hash_key = ?"; + } + sql += ";"; + return sql; +} + +std::string CloudStorageUtils::GetUpdateRecordFlagSqlUpload(const std::string &tableName, bool recordConflict, + const LogInfo &logInfo, const VBucket &uploadExtend, const CloudWaterType &type) +{ + std::string compensatedBit = std::to_string(static_cast(LogInfoFlag::FLAG_WAIT_COMPENSATED_SYNC)); + std::string inconsistencyBit = std::to_string(static_cast(LogInfoFlag::FLAG_DEVICE_CLOUD_INCONSISTENCY)); + bool gidEmpty = logInfo.cloudGid.empty(); + bool isDeleted = logInfo.dataKey == DBConstant::DEFAULT_ROW_ID; + std::string sql; + bool isNeedCompensated = recordConflict || DBCommon::IsNeedCompensatedForUpload(uploadExtend, type); + if (isNeedCompensated && !(isDeleted && gidEmpty)) { + sql += "UPDATE " + DBCommon::GetLogTableName(tableName) + " SET flag = (CASE WHEN timestamp = ? OR " + + "flag & 0x01 = 0 THEN flag | " + compensatedBit + " ELSE flag"; + } else { + sql += "UPDATE " + DBCommon::GetLogTableName(tableName) + " SET flag = (CASE WHEN timestamp = ? THEN " + + "flag & ~" + compensatedBit + " & ~" + inconsistencyBit + " ELSE flag & ~" + compensatedBit; } sql += " END), status = (CASE WHEN status == 2 THEN 3 WHEN (status == 1 AND timestamp = ?) THEN 0 ELSE status END)"; if (DBCommon::IsCloudRecordNotFound(uploadExtend) && @@ -1440,6 +1478,13 @@ std::string CloudStorageUtils::GetCursorUpgradeSql(const std::string &tableName) " 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 " + + DBConstant::RELATIONAL_PREFIX + "metadata" + " where key='cursor_inc_flag' AND value = 'true') then value + 1" + + " else value end WHERE key=x'" + DBCommon::TransferStringToHex(DBCommon::GetCursorKey(tableName)) + "';"; +} + int CloudStorageUtils::GetSyncQueryByPk(const std::string &tableName, const std::vector &data, bool isKv, QuerySyncObject &querySyncObject) { @@ -1448,7 +1493,8 @@ int CloudStorageUtils::GetSyncQueryByPk(const std::string &tableName, const std: int ignoreCount = 0; for (const auto &oneRow : data) { if (oneRow.size() >= 2u) { // mean this data has more than 2 pk - LOGW("Not support compensated sync with composite primary key now"); + LOGW("compensated sync does not support composite PK, oneRow size: %zu, tableName: %s", + oneRow.size(), DBCommon::StringMiddleMasking(tableName).c_str()); return -E_NOT_SUPPORT; } for (const auto &[col, value] : oneRow) { 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 ae8b452e0cdf843c79d6aabced331adddec4335c..039c02eaa7e1c7972227ca6286803adf197b1ccf 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 @@ -35,19 +35,19 @@ int SchemaMgr::ChkSchema(const TableName &tableName, RelationalSchemaObject &loc } TableInfo tableInfo = localSchema.GetTable(tableName); if (tableInfo.Empty()) { - LOGE("Local schema does not contain certain table [ %s size = %d ]", + LOGE("Local schema does not contain certain table [%s size = %d]", DBCommon::StringMiddleMasking(tableName).c_str(), tableName.size()); return -E_SCHEMA_MISMATCH; } if (tableInfo.GetTableSyncType() != TableSyncType::CLOUD_COOPERATION) { - LOGE("Sync type of local table [ %s size = %d ] is not CLOUD_COOPERATION", + LOGE("Sync type of local table [%s size = %d] is not CLOUD_COOPERATION", DBCommon::StringMiddleMasking(tableName).c_str(), tableName.size()); return -E_NOT_SUPPORT; } TableSchema cloudTableSchema; int ret = GetCloudTableSchema(tableName, cloudTableSchema); if (ret != E_OK) { - LOGE("Cloud schema does not contain certain table [ %s size = %d ]:%d", + LOGE("Cloud schema does not contain certain table [%s size = %d]:%d", DBCommon::StringMiddleMasking(tableName).c_str(), tableName.size(), ret); return -E_SCHEMA_MISMATCH; } @@ -147,6 +147,37 @@ bool SchemaMgr::ComparePrimaryField(std::map &localPrimaryKeys, return isLocalFieldPrimary == cloudField.primary; } +void SchemaMgr::SetCloudDbSchema(const DataBaseSchema &schema, RelationalSchemaObject &localSchema) +{ + uint32_t missingTables = 0u; + std::string msg; + DataBaseSchema cloudSchema = schema; + for (TableSchema &table : cloudSchema.tables) { + std::string tableName = table.name; + TableInfo tableInfo = localSchema.GetTable(tableName); + if (tableInfo.Empty()) { + msg += ("[" + DBCommon::StringMiddleMasking(tableName) + ", " + std::to_string(tableName.size()) + "]"); + missingTables++; + continue; + } + FieldInfoMap localFields = tableInfo.GetFields(); + + // remove the fields that are not found in local schema from cloud schema + for (auto it = table.fields.begin(); it != table.fields.end();) { + if (localFields.find((*it).colName) == localFields.end()) { + it = table.fields.erase(it); + LOGI("Column name mismatch between local and cloud schema, colName: %s", (*it).colName.c_str()); + } else { + ++it; + } + } + } + if (missingTables > 0u) { + LOGD("Local schema does not contain following %" PRIu32 " tables: %s", missingTables, msg.c_str()); + } + SetCloudDbSchema(cloudSchema); +} + void SchemaMgr::SetCloudDbSchema(const DataBaseSchema &schema) { DataBaseSchema cloudSchema = schema; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/data_transformer.h b/kv_store/frameworks/libs/distributeddb/storage/src/data_transformer.h index 042786c023382e28d68a6b4162e1eb7166fa7082..9e338e520f69477d49eaa5887d7e2efb2468d502 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/data_transformer.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/data_transformer.h @@ -50,7 +50,7 @@ enum class LogInfoFlag : uint32_t { FLAG_FORCE_PUSH_IGNORE = 0x4, // use in RDB FLAG_LOGIC_DELETE = 0x8, // use in RDB FLAG_WAIT_COMPENSATED_SYNC = 0x10, - FLAG_DEVICE_CLOUD_CONSISTENCY = 0x20, + FLAG_DEVICE_CLOUD_INCONSISTENCY = 0x20, FLAG_KV_FORCE_PUSH_IGNORE = 0x40, FLAG_KV_LOGIC_DELETE = 0x80, FLAG_CLOUD_WRITE = 0x100, 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 3645b6996e6f6ef388e7af42671bfb59cee44a39..8bb6705873244627e48457042087e7d3b8050659 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 @@ -427,12 +427,27 @@ KvDBProperties &RdSingleVerNaturalStore::GetDbPropertyForUpdate() return MyProp(); } +static void SetStorageEngineAttr(StorageEngineAttr &poolSize, uint32_t minWriteNum, uint32_t maxWriteNum, + uint32_t minReadNum, uint32_t maxReadNum) +{ + poolSize.minWriteNum = minWriteNum; + poolSize.maxWriteNum = maxWriteNum; + poolSize.minReadNum = minReadNum; + poolSize.maxReadNum = maxReadNum; +} + int RdSingleVerNaturalStore::InitDatabaseContext(const KvDBProperties &kvDBProp) { OpenDbProperties option; InitDataBaseOption(kvDBProp, option); - StorageEngineAttr poolSize = {1, 1, 1, 16}; // at most 1 write 16 read. + StorageEngineAttr poolSize = { 0 }; + bool isReadOnly = kvDBProp.GetBoolProp(KvDBProperties::READ_ONLY_MODE, false); + if (isReadOnly) { + SetStorageEngineAttr(poolSize, 0, 1, 1, 16); // max 16 readNum + } else { + SetStorageEngineAttr(poolSize, 1, 1, 0, 16); // max 16 readNum + } storageEngine_->SetNotifiedCallback( [&](int eventType, KvDBCommitNotifyFilterAbleData *committedData) { @@ -551,8 +566,8 @@ void RdSingleVerNaturalStore::InitDataBaseOption(const KvDBProperties &kvDBProp, option.isNeedRmCorruptedDb = kvDBProp.GetBoolProp(KvDBProperties::RM_CORRUPTED_DB, false); bool isSharedMode = kvDBProp.GetBoolProp(KvDBProperties::SHARED_MODE, false); option.isHashTable = (IndexType)kvDBProp.GetIntProp(KvDBProperties::INDEX_TYPE, BTREE) == HASH; - int pageSize = kvDBProp.GetIntProp(KvDBProperties::PAGE_SIZE1, 32); - int cacheSize = kvDBProp.GetIntProp(KvDBProperties::CACHE_SIZE, 2048); + uint32_t pageSize = kvDBProp.GetUIntProp(KvDBProperties::PAGE_SIZE1, 32u); // one page has 32KB + uint32_t cacheSize = kvDBProp.GetUIntProp(KvDBProperties::CACHE_SIZE, 2048u); // max cache 2048KB std::string config = "{"; config += InitRdConfig() + R"(, )"; @@ -560,7 +575,7 @@ void RdSingleVerNaturalStore::InitDataBaseOption(const KvDBProperties &kvDBProp, R"("bufferPoolPolicy": "BUF_PRIORITY_NORMAL")" : R"("bufferPoolPolicy": "BUF_PRIORITY_INDEX")"; config += R"(, "pageSize":)" + std::to_string(pageSize) + R"(, )"; config += R"("bufferPoolSize":)" + std::to_string(cacheSize) + R"(, )"; - config += R"("redoPubBufSize":)" + std::to_string(cacheSize) + R"(, )"; + config += R"("redoPubBufSize":)" + std::to_string(pageSize * REDO_BUF_ATOMIC_SIZE) + R"(, )"; config += isSharedMode ? R"("sharedModeEnable": 1)" : R"("sharedModeEnable": 0)"; config += "}"; option.rdConfig = config; 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 5dbc25baf6da472961d66ed1cb4b339c3a1f013c..15a14e4b8e6da5efcca88df70d7931caf62a9fb6 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 @@ -144,7 +144,6 @@ public: void CommitNotify(int notifyEvent, KvDBCommitNotifyFilterAbleData *data) override; void SetReceiveDataInterceptor(const DataInterceptor &interceptor) override; - private: int PreCheckRdImport(std::string &storePath); @@ -158,6 +157,8 @@ private: mutable std::shared_mutex engineMutex_; RdSingleVerStorageEngine *storageEngine_; bool notificationEventsRegistered_; + + static constexpr uint32_t REDO_BUF_ATOMIC_SIZE = 64u; }; } // namespace DistributedDB #endif // RD_SINGLE_VER_NATURAL_STORE_H 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 b0229b50ae60c162ac03d235046dedeccfbfa81b..6784b71ff871d83ba1353dbea5db589bd68db64e 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 @@ -25,8 +25,8 @@ #include "kvdb_observer_handle.h" #include "kvdb_pragma.h" #include "log_print.h" -#include "store_types.h" #include "sqlite_single_ver_storage_engine.h" +#include "store_types.h" namespace DistributedDB { @@ -129,26 +129,6 @@ int RdSingleVerNaturalStoreConnection::GetResultSet(const IOption &option, const return E_OK; } -static void PrintResultsetKeys(const QueryExpression &queryExpression) -{ - std::vector beginKeyVec = queryExpression.GetBeginKey(); - std::vector endKeyVec = queryExpression.GetEndKey(); - std::string beginKey; - std::string endKey; - if (beginKeyVec.size() == 0) { - beginKey = "NULL"; - } else { - beginKey.assign(beginKeyVec.begin(), beginKeyVec.end()); - } - if (endKeyVec.size() == 0) { - endKey = "NULL"; - } else { - endKey.assign(endKeyVec.begin(), endKeyVec.end()); - } - - LOGD("begin key: %s, end key: %s", beginKey.c_str(), endKey.c_str()); -} - int RdSingleVerNaturalStoreConnection::GetResultSet(const IOption &option, const Query &query, IKvDBResultSet *&resultSet) const { @@ -345,9 +325,6 @@ int RdSingleVerNaturalStoreConnection::GetEntriesInner(const IOption &option, co queryExpression.GetEndKey()), entries); ReleaseExecutor(handle); DBDfxAdapter::FinishTracing(); - if (errCode != -E_NOT_FOUND) { - PrintResultsetKeys(queryExpression); - } return errCode; } int RdSingleVerNaturalStoreConnection::GetEntries(const IOption &option, const Query &query, @@ -551,27 +528,32 @@ int RdSingleVerNaturalStoreConnection::CheckSyncEntriesValid(const std::vector &entries) { - LOGD("PutBatchInner"); + return SetBatchInner(option, entries, false); +} + +int RdSingleVerNaturalStoreConnection::SetBatchInner(const IOption &option, const std::vector &entries, + bool isDelete) +{ std::lock_guard lock(transactionMutex_); - bool isAuto = false; - int errCode = E_OK; if (option.dataType != IOption::SYNC_DATA) { LOGE("LOCAL_DATA TYPE NOT SUPPORT in RD executor"); return -E_NOT_SUPPORT; } + bool isAuto = false; + int errCode = E_OK; + bool isCommitNotify = !IsObserverEmpty(); if (writeHandle_ == nullptr) { isAuto = true; - errCode = StartTransactionInner(TransactType::IMMEDIATE); + errCode = StartTransactionInner(isCommitNotify, TransactType::IMMEDIATE); if (errCode != E_OK) { return errCode; } } - - errCode = SaveSyncEntries(entries, false); + errCode = SaveSyncEntries(entries, isDelete); if (isAuto) { if (errCode == E_OK) { - errCode = CommitInner(); + errCode = CommitInner(isCommitNotify); } else { int innerCode = RollbackInner(); errCode = (innerCode != E_OK) ? innerCode : errCode; @@ -611,14 +593,13 @@ int RdSingleVerNaturalStoreConnection::SaveEntryNormally(const Entry &entry, boo { int errCode = writeHandle_->SaveSyncDataItem(entry, committedData_, isDelete); if (errCode != E_OK) { - LOGE("Save entry failed, err:%d", errCode); + LOGE("Save sync entry failed, err:%d", errCode); } return errCode; } RdSingleVerStorageExecutor *RdSingleVerNaturalStoreConnection::GetExecutor(bool isWrite, int &errCode) const { - LOGD("[RdSingleVerNaturalStoreConnection] Getting Executor "); RdSingleVerNaturalStore *naturalStore = GetDB(); if (naturalStore == nullptr) { errCode = -E_NOT_INIT; @@ -645,35 +626,35 @@ void RdSingleVerNaturalStoreConnection::ReleaseCommitData(SingleVerNaturalStoreC } } -int RdSingleVerNaturalStoreConnection::StartTransactionInner(TransactType transType) +int RdSingleVerNaturalStoreConnection::StartTransactionInner(bool isCommitNotify, TransactType transType) { if (IsExtendedCacheDBMode()) { return -E_NOT_SUPPORT; } else { - return StartTransactionNormally(transType); + return StartTransactionNormally(isCommitNotify, transType); } } -int RdSingleVerNaturalStoreConnection::StartTransactionNormally(TransactType transType) +int RdSingleVerNaturalStoreConnection::StartTransactionNormally(bool isCommitNotify, TransactType transType) { int errCode = E_OK; RdSingleVerStorageExecutor *handle = GetExecutor(true, errCode); if (handle == nullptr) { return errCode; } - errCode = kvDB_->TryToDisableConnection(OperatePerm::NORMAL_WRITE); if (errCode != E_OK) { ReleaseExecutor(handle); LOGE("Start transaction failed, %d", errCode); return errCode; } - - if (committedData_ == nullptr) { - committedData_ = new (std::nothrow) SingleVerNaturalStoreCommitNotifyData; + if (isCommitNotify) { if (committedData_ == nullptr) { - ReleaseExecutor(handle); - return -E_OUT_OF_MEMORY; + committedData_ = new (std::nothrow) SingleVerNaturalStoreCommitNotifyData; + if (committedData_ == nullptr) { + ReleaseExecutor(handle); + return -E_OUT_OF_MEMORY; + } } } @@ -688,14 +669,15 @@ int RdSingleVerNaturalStoreConnection::StartTransactionNormally(TransactType tra return E_OK; } -int RdSingleVerNaturalStoreConnection::CommitInner() +int RdSingleVerNaturalStoreConnection::CommitInner(bool isCommitNotify) { int errCode = writeHandle_->Commit(); ReleaseExecutor(writeHandle_); writeHandle_ = nullptr; - - CommitAndReleaseNotifyData(committedData_, true, - static_cast(SQLiteGeneralNSNotificationEventType::SQLITE_GENERAL_NS_PUT_EVENT)); + if (isCommitNotify) { + CommitAndReleaseNotifyData(committedData_, true, + static_cast(SQLiteGeneralNSNotificationEventType::SQLITE_GENERAL_NS_PUT_EVENT)); + } return errCode; } @@ -739,40 +721,6 @@ int RdSingleVerNaturalStoreConnection::CheckSyncKeysValid(const std::vector } int RdSingleVerNaturalStoreConnection::DeleteBatchInner(const IOption &option, const std::vector &keys) -{ - DBDfxAdapter::StartTracing(); - bool isAuto = false; - int errCode = E_OK; - if (option.dataType != IOption::SYNC_DATA) { - LOGE("LOCAL_DATA TYPE NOT SUPPORT in RD executor"); - DBDfxAdapter::FinishTracing(); - return -E_NOT_SUPPORT; - } - std::lock_guard lock(transactionMutex_); - if (writeHandle_ == nullptr) { - isAuto = true; - errCode = StartTransactionInner(TransactType::IMMEDIATE); - if (errCode != E_OK) { - DBDfxAdapter::FinishTracing(); - return errCode; - } - } - - errCode = DeleteSyncEntries(keys); - - if (isAuto) { - if (errCode == E_OK) { - errCode = CommitInner(); - } else { - int innerCode = RollbackInner(); - errCode = (innerCode != E_OK) ? innerCode : errCode; - } - } - DBDfxAdapter::FinishTracing(); - return errCode; -} - -int RdSingleVerNaturalStoreConnection::DeleteSyncEntries(const std::vector &keys) { std::vector entries; for (const auto &key : keys) { @@ -780,12 +728,7 @@ int RdSingleVerNaturalStoreConnection::DeleteSyncEntries(const std::vector entry.key = std::move(key); entries.emplace_back(std::move(entry)); } - - int errCode = SaveSyncEntries(entries, true); - if ((errCode != E_OK) && (errCode != -E_NOT_FOUND)) { - LOGE("[DeleteSyncEntries] Delete data err:%d", errCode); - } - return (errCode == -E_NOT_FOUND) ? E_OK : errCode; + return SetBatchInner(option, entries, true); } int RdSingleVerNaturalStoreConnection::GetSyncDataSize(const std::string &device, size_t &size) const @@ -793,6 +736,11 @@ int RdSingleVerNaturalStoreConnection::GetSyncDataSize(const std::string &device return -E_NOT_SUPPORT; } +int RdSingleVerNaturalStoreConnection::GetWatermarkInfo(const std::string &device, WatermarkInfo &info) +{ + return -E_NOT_SUPPORT; +} + int RdSingleVerNaturalStoreConnection::Sync(const CloudSyncOption &option, const SyncProcessCallback &onProcess) { return -E_NOT_SUPPORT; 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 33a0f48a9fb0e6d555777b409c1e89da2efb4293..5b71d1ebec0c84bcb17ba20c854101fb209ed8b8 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 @@ -100,6 +100,8 @@ public: int GetSyncDataSize(const std::string &device, size_t &size) const override; + int GetWatermarkInfo(const std::string &device, WatermarkInfo &info) override; + int Sync(const CloudSyncOption &option, const SyncProcessCallback &onProcess) override; int SetCloudDB(const std::map> &cloudDBs) override; @@ -142,11 +144,11 @@ private: void ReleaseCommitData(SingleVerNaturalStoreCommitNotifyData *&committedData); - int StartTransactionInner(TransactType transType = TransactType::DEFERRED); + int StartTransactionInner(bool isCommitNotify, TransactType transType = TransactType::DEFERRED); - int StartTransactionNormally(TransactType transType = TransactType::DEFERRED); + int StartTransactionNormally(bool isCommitNotify, TransactType transType = TransactType::DEFERRED); - int CommitInner(); + int CommitInner(bool isCommitNotify); int RollbackInner(); @@ -159,7 +161,7 @@ private: int DeleteBatchInner(const IOption &option, const std::vector &keys) override; - int DeleteSyncEntries(const std::vector &keys); + int SetBatchInner(const IOption &option, const std::vector &entries, bool isDelete); bool IsSinglePutOrDelete(const std::vector &entries) { 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 ce2e802dcad87a276265c45c64b2708f75291b24..7ae02aeb0851fe030511e5d7185296c3dd680f8d 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 @@ -157,34 +157,30 @@ int RdSingleVerResultSet::Move(int offset) const if (offset == 0) { return errCode; } - offset = offset > INT_MAX ? INT_MAX : offset; - offset = offset < INT_MIN ? INT_MIN : offset; while (offset > 0) { errCode = MoveToNext(); - if (errCode != E_OK && errCode != -E_NOT_FOUND) { + if (errCode != E_OK) { + if (errCode == -E_NOT_FOUND) { + LOGE("[RdSingleVerStorageExecutor] move offset: %d, out of bounds, position: %d", offset, position_); + return -E_INVALID_ARGS; + } LOGE("[RdSinResSet] move by offset failed, errCode=%d, offset=%d", errCode, offset); return errCode; } --offset; - if (errCode == -E_NOT_FOUND && offset >= 0) { - LOGE("[RdSingleVerStorageExecutor] move offset: %d, out of bounds or result set empty, position: %d", - offset, position_); - return -E_INVALID_ARGS; - } } while (offset < 0) { errCode = MoveToPrev(); - if (errCode != E_OK && errCode != -E_NOT_FOUND) { + if (errCode != E_OK) { + if (errCode == -E_NOT_FOUND && offset <= 0) { + LOGE("[RdSingleVerStorageExecutor] move offset: %d, out of bounds, position: %d", offset, position_); + return -E_INVALID_ARGS; + } LOGE("[RdSinResSet] move by offset failed, errCode=%d, offset=%d", errCode, offset); return errCode; } ++offset; - if (errCode == -E_NOT_FOUND && offset <= 0) { - LOGE("[RdSingleVerStorageExecutor] move offset: %d, out of bounds or result set empty, position: %d", - offset, position_); - return -E_INVALID_ARGS; - } } return errCode; } @@ -242,20 +238,22 @@ int RdSingleVerResultSet::MoveToPrev() const } errCode = handle_->MoveToPrev(resultSet_); - if (errCode != E_OK && errCode != -E_NOT_FOUND) { + if (errCode != E_OK) { + if (errCode == -E_NOT_FOUND) { + LOGD("[RdSinResSet] move prev reach left end, errCode=%d.", errCode); + position_ = INIT_POSITION; + return errCode; + } LOGE("[RdSinResSet] move prev failed, errCode=%d.", errCode); return errCode; } - if (errCode == -E_NOT_FOUND) { - position_ = INIT_POSITION; + if (position_ <= 0) { + position_ = 0; } else { - if (position_ <= 0) { - position_ = 0; - } else { - --position_; - } + --position_; } + return errCode; } @@ -319,11 +317,10 @@ int RdSingleVerResultSet::MoveToLast() bool RdSingleVerResultSet::IsFirst() const { - int position = GetPosition(); if (GetCount() == 0) { return false; } - if (position == 0) { + if (GetPosition() == 0) { return true; } return false; @@ -331,12 +328,11 @@ bool RdSingleVerResultSet::IsFirst() const bool RdSingleVerResultSet::IsLast() const { - int position = GetPosition(); int count = GetCount(); if (count == 0) { return false; } - if (position == (count - 1)) { + if (GetPosition() == (count - 1)) { return true; } return false; @@ -344,12 +340,10 @@ bool RdSingleVerResultSet::IsLast() const bool RdSingleVerResultSet::IsBeforeFirst() const { - int position = GetPosition(); - if (GetCount() == 0) { return true; } - if (position <= INIT_POSITION) { + if (GetPosition() <= INIT_POSITION) { return true; } return false; @@ -357,12 +351,11 @@ bool RdSingleVerResultSet::IsBeforeFirst() const bool RdSingleVerResultSet::IsAfterLast() const { - int position = GetPosition(); int count = GetCount(); if (count == 0) { return true; } - if (position >= count) { + if (GetPosition() >= count) { return true; } return false; 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 598471086b5788c0153cbcb721b1b10baaaaabb6..737bad2b05546001a25a3a8baee2ed26f232539c 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 @@ -23,6 +23,7 @@ #include "sqlite_single_ver_storage_executor_sql.h" namespace DistributedDB { + RdSingleVerStorageEngine::RdSingleVerStorageEngine() { LOGD("[RdSingleVerStorageEngine] RdSingleVerStorageEngine Created"); @@ -52,24 +53,29 @@ int RdSingleVerStorageEngine::CreateNewExecutor(bool isWrite, StorageExecutor *& } if (!option_.readOnly) { std::string tableMode = GetTableMode(option_.isHashTable); - ret = TransferGrdErrno(GRD_CreateCollection(db, SYNC_COLLECTION_NAME, tableMode.c_str(), 0)); + ret = RdCreateCollection(db, SYNC_COLLECTION_NAME, tableMode.c_str(), 0); if (ret != E_OK) { LOGE("[RdSingleVerStorageEngine] GRD_CreateCollection SYNC_COLLECTION_NAME FAILED %d", ret); + (void)RdDBClose(db, GRD_DB_CLOSE_IGNORE_ERROR); return ret; } } - ret = TransferGrdErrno(IndexPreLoad(db, SYNC_COLLECTION_NAME)); + ret = IndexPreLoad(db, SYNC_COLLECTION_NAME); if (ret != E_OK) { LOGE("[RdSingleVerStorageEngine] GRD_IndexPreload FAILED %d", ret); + (void)RdDBClose(db, GRD_DB_CLOSE_IGNORE_ERROR); return ret; } handle = new (std::nothrow) RdSingleVerStorageExecutor(db, isWrite); if (handle == nullptr) { + (void)RdDBClose(db, GRD_DB_CLOSE_IGNORE_ERROR); return -E_OUT_OF_MEMORY; } if (OS::CheckPathExistence(option_.subdir + DBConstant::PATH_POSTFIX_DB_INCOMPLETE) && OS::RemoveFile(option_.subdir + DBConstant::PATH_POSTFIX_DB_INCOMPLETE) != E_OK) { LOGE("Finish to create the complete database, but delete token fail! errCode = [E_SYSTEM_API_FAIL]"); + delete handle; + handle = nullptr; return -E_SYSTEM_API_FAIL; } return E_OK; @@ -86,7 +92,7 @@ int RdSingleVerStorageEngine::InitRdStorageEngine(const StorageEngineAttr &poolS option_ = option; identifier_ = identifier; hashIdentifier_ = DBCommon::TransferStringToHex(identifier_); - int errCode = Init(); + int errCode = Init(true); if (errCode != E_OK) { LOGI("Storage engine init fail! errCode = [%d]", errCode); } @@ -135,7 +141,7 @@ int RdSingleVerStorageEngine::TryToOpenMainDatabase(bool isWrite, GRD_DB *&db) } int errCode = OpenGrdDb(optionTemp, db); if (errCode != E_OK) { - LOGE("Failed to open the main database [%d], uri: %s", errCode, (option_.uri).c_str()); + LOGE("Failed to open the main database [%d]", errCode); return errCode; } @@ -203,6 +209,14 @@ int RdSingleVerStorageEngine::OpenGrdDb(const OpenDbProperties &option, GRD_DB * int RdSingleVerStorageEngine::IndexPreLoad(GRD_DB *&db, const char *collectionName) { - return RdIndexPreload(db, collectionName); + if (isFirstTimeOpenDb_) { + int ret = RdIndexPreload(db, collectionName); + if (ret != E_OK) { + LOGE("Unable to RdIndexPreload %d", ret); + return ret; + } + isFirstTimeOpenDb_ = false; + } + return E_OK; } } // namespace DistributedDB \ No newline at end of file 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 5e935721aef75c50c7110ebf4eeeefc0ef9091fa..10335c95a5183e5e5b1b0a3a6fef45e6cc8f0672 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 @@ -55,6 +55,7 @@ private: int IndexPreLoad(GRD_DB *&db, const char *collectionName); std::atomic crcCheck_ = false; + std::atomic isFirstTimeOpenDb_ = true; }; } // namespace DistributedDB #endif // RD_SINGLE_VER_STORAGE_ENGINE_H \ No newline at end of file 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 610e7e6b2edeec8b710d22cc4dac60bd805117d6..93f0b8481b7dc7a700e2b2fcb9e320d0a0ed5264 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 @@ -79,7 +79,7 @@ int RdSingleVerStorageExecutor::OpenResultSet(const Key &beginKey, const Key &en { int errCode = RdKVRangeScan(db_, SYNC_COLLECTION_NAME, beginKey, endKey, resultSet); if (errCode != E_OK) { - LOGE("[RdSingleVerStorageExecutor][OpenResultSet] Can not open rd result set."); + LOGE("Can not open rd result set."); } return errCode; } @@ -311,7 +311,7 @@ int RdSingleVerStorageExecutor::GetEntriesPrepare(GRD_DB *db, const GRD_KvScanMo return -E_INVALID_ARGS; } if (ret != E_OK) { - LOGE("[RdSingleVerStorageExecutor][GetEntriesPrepare]ERROR %d", ret); + LOGE("[RdSingleVerStorageExecutor][GetEntries]ERROR %d", ret); return ret; } entries.clear(); @@ -407,7 +407,9 @@ int RdSingleVerStorageExecutor::BatchSaveEntries(const std::vector &entri } } std::vector notifys; - ret = PrepareNotifyForEntries(entries, committedData, notifys, isDelete); + if (committedData != nullptr) { + ret = PrepareNotifyForEntries(entries, committedData, notifys, isDelete); + } if (ret != E_OK) { (void)RdKVBatchDestroy(batch); return ret; @@ -421,7 +423,7 @@ int RdSingleVerStorageExecutor::BatchSaveEntries(const std::vector &entri (void)RdKVBatchDestroy(batch); LOGE("[RdSingleVerStorageExecutor][BatchSaveEntries] Can not put or delete batchly with mode %d", isDelete); return ret; - } else { + } else if (committedData != nullptr) { for (size_t i = 0; i < entries.size(); i++) { PutIntoCommittedData(entries[i].key, entries[i].value, notifys[i]); } @@ -459,19 +461,23 @@ int RdSingleVerStorageExecutor::GetAllSyncedEntries(const std::string &hashDev, int RdSingleVerStorageExecutor::SaveSyncDataItem(const Entry &entry, SingleVerNaturalStoreCommitNotifyData *committedData, bool isDelete) { - NotifyConflictAndObserverData notify = { - .committedData = committedData - }; + int errCode = E_OK; + NotifyConflictAndObserverData notify; + if (committedData != nullptr) { + notify = { + .committedData = committedData + }; - int errCode = PrepareForNotifyConflictAndObserver(entry, notify, isDelete); - if (errCode != E_OK) { - return errCode; + errCode = PrepareForNotifyConflictAndObserver(entry, notify, isDelete); + if (errCode != E_OK) { + return errCode; + } } - errCode = SaveSyncDataToDatabase(entry, isDelete); - if (errCode == E_OK) { + if (committedData != nullptr && errCode == E_OK) { PutIntoCommittedData(entry.key, entry.value, notify); - } else { + } + if (errCode != E_OK) { LOGE("Save sync data to db failed:%d", errCode); } return errCode; 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 5285f9ac4c766625058361134cffc5183843b7a6..c085079129645a31fea5662e39e501a071cbd18b 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 @@ -97,7 +97,7 @@ int TransferGrdErrno(int err) return -E_INTERNAL_ERROR; } -std::vector KvItemToBlob(GRD_KVItemT &item) +static inline std::vector KvItemToBlob(GRD_KVItemT &item) { return std::vector((uint8_t *)item.data, (uint8_t *)item.data + item.dataLen); } @@ -303,14 +303,14 @@ bool CheckParaOption(const KvStoreNbDelegate::Option &option, if ((option.rdconfig.pageSize < SQLITE_PAGE_SIZE_MIN) || (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 703ae25c5d085e82061320d15e42236fc141f364..d1b660bea2e88c02f47a4041355bf1ee14b46881 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 @@ -37,8 +37,6 @@ std::string InitRdConfig(); int TransferGrdErrno(int err); -std::vector KvItemToBlob(GRD_KVItemT &item); - int GetCollNameFromType(SingleVerDataType type, std::string &collName); int RdKVPut(GRD_DB *db, const char *collectionName, const Key &key, const Value &value); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/kv/generic_kvdb.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/kv/generic_kvdb.cpp index 6ae5ae388e79c85498708d5582a711a57f3e21f2..8003b0deeb7e602db27797a1b04c2e00109d30da 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/kv/generic_kvdb.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/kv/generic_kvdb.cpp @@ -32,7 +32,8 @@ GenericKvDB::GenericKvDB() eventNotifyCounter_(0), connectionCount_(0), notificationChain_(nullptr), - operatePerm_(OperatePerm::NORMAL_PERM) + operatePerm_(OperatePerm::NORMAL_PERM), + isRebuild_(false) {} GenericKvDB::~GenericKvDB() @@ -68,6 +69,9 @@ IKvDBConnection *GenericKvDB::GetDBConnection(int &errCode) if (connection != nullptr) { IncObjRef(this); IncreaseConnectionCounter(); + if (isRebuild_) { + connection->MarkRebuild(); + } } return connection; } @@ -406,4 +410,9 @@ void GenericKvDB::Dump(int fd) void GenericKvDB::ResetSyncStatus() { } + +void GenericKvDB::MarkRebuild() +{ + isRebuild_ = true; +} } // 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 a3d026a8064a8f1c751706b2d2d45df73cbdcdc1..7c32c3be4a8397b390485ab2fb6feefefb4dba4b 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 @@ -130,6 +130,7 @@ public: virtual void ResetSyncStatus(); + void MarkRebuild() override; protected: // Create a connection object, no DB ref increased. virtual GenericKvDBConnection *NewConnection(int &errCode) = 0; @@ -192,6 +193,7 @@ private: OperatePerm operatePerm_; mutable std::mutex regFuncCountMutex_; std::vector registerFunctionCount_; + std::atomic isRebuild_; }; } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/kv/generic_kvdb_connection.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/kv/generic_kvdb_connection.cpp index 29bdee3a457c27e5cfbc27735be06280dcbe92c3..b260e7933e335d8304b8b6a66e1a5241db44ab52 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/kv/generic_kvdb_connection.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/kv/generic_kvdb_connection.cpp @@ -28,7 +28,8 @@ namespace DistributedDB { GenericKvDBConnection::GenericKvDBConnection(GenericKvDB *kvDB) : kvDB_(kvDB), isExclusive_(false), - isSafeDeleted_(false) + isSafeDeleted_(false), + isRebuild_(false) { } @@ -445,4 +446,14 @@ int GenericKvDBConnection::GetEntries(const std::string &device, std::vector &entries) const override; + + void MarkRebuild() override; + + bool IsRebuild() const override; protected: // Get the stashed 'KvDB_ pointer' without ref. template @@ -141,6 +145,8 @@ private: bool isSafeDeleted_; std::mutex observerListLock_; std::list observerList_; + + std::atomic isRebuild_; }; } diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/kv/generic_single_ver_kv_entry.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/kv/generic_single_ver_kv_entry.cpp index efd52eb36ee63283391dfc5961395c514c8430c8..d5464af3098ad6138e6fc93f8c5f59546cbde2cb 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/kv/generic_single_ver_kv_entry.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/kv/generic_single_ver_kv_entry.cpp @@ -439,6 +439,10 @@ int GenericSingleVerKvEntry::DeSerializeCompressedDatas(std::vector DBConstant::MAX_SYNC_BLOCK_SIZE) { + LOGE("[GenericSingleVerKvEntry] Invalid compress data len %" PRIu32, destLen); + return -E_INVALID_ARGS; + } // Get compressed data. std::vector srcData; 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 e4c4c6f922baffc44bef13eb5ce9b3e540b3e739..595c84b11fb83afb6f049c2771964f2bcb5e2a7e 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 @@ -403,9 +403,13 @@ IKvDB *KvDBManager::CreateDataBase(const KvDBProperties &property, int &errCode) LOGI("Remove the corrupted database while open"); ExecuteRemoveDatabase(property); kvDB = OpenNewDatabase(property, errCode); + if (kvDB != nullptr) { + kvDB->MarkRebuild(); + } } return kvDB; } + bool rebuild = false; if (property.GetBoolProp(KvDBProperties::CHECK_INTEGRITY, false) && databaseType != KvDBProperties::SINGLE_VER_TYPE_RD_KERNAL) { int integrityStatus = kvDB->CheckIntegrity(); @@ -418,9 +422,13 @@ IKvDB *KvDBManager::CreateDataBase(const KvDBProperties &property, int &errCode) LOGI("Remove the corrupted database for the integrity check"); ExecuteRemoveDatabase(property); kvDB = OpenNewDatabase(property, errCode); + rebuild = true; } } } + if (kvDB != nullptr && rebuild) { + kvDB->MarkRebuild(); + } return kvDB; } 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 ac90c3392eee2aae7b844e3644fc77a36700957e..3b7166e88f28dc9d1e3317d2b1189e8fa9a2a18a 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_) { @@ -303,11 +303,21 @@ void SyncAbleKvDB::ChangeUserListener() } } +uint64_t SyncAbleKvDB::GetTimestampFromDB() +{ + return 0; //default is 0 +} + // Get The current virtual timestamp -uint64_t SyncAbleKvDB::GetTimestamp() +uint64_t SyncAbleKvDB::GetTimestamp(bool needStartSync) { if (NeedStartSyncer()) { - StartSyncer(); + if (needStartSync) { + StartSyncer(); + } else { + // if syncer not start, get offset time from database + return GetTimestampFromDB(); + } } return syncer_.GetTimestamp(); } @@ -524,8 +534,8 @@ void SyncAbleKvDB::StartCloudSyncer() if (cloudSyncer_ != nullptr) { return; } - cloudSyncer_ = new(std::nothrow) CloudSyncer(StorageProxy::GetCloudDb(cloudStorage), - static_cast(conflictType)); + cloudSyncer_ = new (std::nothrow) CloudSyncer( + StorageProxy::GetCloudDb(cloudStorage), true, static_cast(conflictType)); if (cloudSyncer_ == nullptr) { LOGW("[SyncAbleKvDB][StartCloudSyncer] start cloud syncer and cloud syncer was not initialized"); } @@ -543,7 +553,7 @@ TimeOffset SyncAbleKvDB::GetLocalTimeOffset() void SyncAbleKvDB::FillSyncInfo(const CloudSyncOption &option, const SyncProcessCallback &onProcess, CloudSyncer::CloudTaskInfo &info) { - QuerySyncObject query(option.query); + QuerySyncObject query(Query::Select()); query.SetTableName(CloudDbConstant::CLOUD_KV_TABLE_NAME); info.queryList.push_back(query); info.table.push_back(CloudDbConstant::CLOUD_KV_TABLE_NAME); @@ -555,6 +565,7 @@ void SyncAbleKvDB::FillSyncInfo(const CloudSyncOption &option, const SyncProcess info.lockAction = option.lockAction; info.storeId = MyProp().GetStringProp(DBProperties::STORE_ID, ""); info.merge = option.merge; + info.prepareTraceId = option.prepareTraceId; } int SyncAbleKvDB::CheckSyncOption(const CloudSyncOption &option, const CloudSyncer &syncer) diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/kv/sync_able_kvdb.h b/kv_store/frameworks/libs/distributeddb/storage/src/kv/sync_able_kvdb.h index 99340ace44f6bf181689314112370f162c43a5cb..d14fecc900dcc1a51cc6984d475a3a1bd02667cb 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/kv/sync_able_kvdb.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/kv/sync_able_kvdb.h @@ -54,8 +54,11 @@ public: // Stop a sync action in progress. void StopSync(uint64_t connectionId); + // Get The current virtual timestamp from db + virtual uint64_t GetTimestampFromDB(); + // Get The current virtual timestamp - uint64_t GetTimestamp(); + uint64_t GetTimestamp(bool needStartSync = true); void WakeUpSyncer() override; 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 37d7c2d4be4e09fa18ebee46d37b3bd800d5d1af..d58a7b064c6cdc3be4bcdb748c09b1ec8472b424 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,13 +154,15 @@ 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); }; } @@ -185,7 +187,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.h b/kv_store/frameworks/libs/distributeddb/storage/src/multiver/multi_ver_natural_store.h index 58658faf632b5475dda430968a44d468f95133a6..8d1adb24061dea70b6ceb03f1fbc57164a68fc5c 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 @@ -159,7 +159,6 @@ public: void SetSendDataInterceptor(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/relational/relational_store_instance.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/relational/relational_store_instance.cpp index 9cd05382f234cd5211fa5e1de49fb6feed70b793..5359c192ab2882b18637346c7d69c907c740a89d 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/relational/relational_store_instance.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/relational/relational_store_instance.cpp @@ -132,6 +132,7 @@ IRelationalStore *RelationalStoreInstance::GetDataBase(const RelationalDBPropert bool isNeedIfOpened) { auto *db = GetFromCache(properties, errCode); + if (db != nullptr && !isNeedIfOpened) { RefObject::DecObjRef(db); errCode = -E_ALREADY_OPENED; 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 04c846a96e106ffd28ab43199c122d90fd0dcfb2..f7d99629bc3fb7d3e0653f2c67b7b695d7fbd303 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 @@ -556,6 +556,15 @@ int RelationalSyncAbleStorage::SaveSyncDataItems(const QueryObject &object, std: return errCode; } + // To prevent certain abnormal scenarios from deleting the table, + // check if the table exists before each synchronization. + // If the table does not exist, create it. + // Because it is a fallback scenario, if the table creation fails, no failure will be returned + errCode = handle->CreateDistributedDeviceTable(deviceName, + storageEngine_->GetSchema().GetTable(query.GetTableName()), info); + if (errCode != E_OK) { + LOGW("[RelationalSyncAbleStorage::SaveSyncDataItems] Create distributed device table fail %d", errCode); + } DBDfxAdapter::StartTracing(); errCode = handle->SaveSyncItems(inserter); @@ -1223,8 +1232,8 @@ int RelationalSyncAbleStorage::ChkSchema(const TableName &tableName) RelationalSchemaObject newSchema; errCode = GetSchemaFromDB(newSchema); if (errCode != E_OK) { - LOGE("Get schema from db when check schema."); - return errCode; + LOGE("Get schema from db when check schema. err: %d", errCode); + return -E_SCHEMA_MISMATCH; } errCode = schemaMgr_.ChkSchema(tableName, newSchema); } @@ -1234,7 +1243,8 @@ int RelationalSyncAbleStorage::ChkSchema(const TableName &tableName) int RelationalSyncAbleStorage::SetCloudDbSchema(const DataBaseSchema &schema) { std::unique_lock writeLock(schemaMgrMutex_); - schemaMgr_.SetCloudDbSchema(schema); + RelationalSchemaObject localSchema = GetSchemaInfo(); + schemaMgr_.SetCloudDbSchema(schema, localSchema); return E_OK; } @@ -1316,7 +1326,12 @@ int RelationalSyncAbleStorage::CleanCloudData(ClearMode mode, const std::vector< changedData.type = ChangedDataType::DATA; changedData.tableName = notifyTableName; std::vector dataVec; - DistributedDB::Type type = std::string(CloudDbConstant::FLAG_AND_DATA_MODE_NOTIFY); + DistributedDB::Type type; + if (mode == FLAG_ONLY) { + type = std::string(CloudDbConstant::FLAG_ONLY_MODE_NOTIFY); + } else { + type = std::string(CloudDbConstant::FLAG_AND_DATA_MODE_NOTIFY); + } dataVec.push_back(type); changedData.primaryData[ChangeType::OP_DELETE].push_back(dataVec); TriggerObserverAction("CLOUD", std::move(changedData), true); @@ -1369,6 +1384,20 @@ int RelationalSyncAbleStorage::SetLogTriggerStatus(bool status) return errCode; } +int RelationalSyncAbleStorage::SetCursorIncFlag(bool flag) +{ + int errCode = E_OK; + auto *handle = GetHandleExpectTransaction(false, errCode); + if (handle == nullptr) { + return errCode; + } + errCode = handle->SetCursorIncFlag(flag); + if (transactionHandle_ == nullptr) { + ReleaseHandle(handle); + } + return errCode; +} + int RelationalSyncAbleStorage::FillCloudLogAndAsset(const OpType opType, const CloudSyncData &data, bool fillAsset, bool ignoreEmptyGid) { @@ -1467,7 +1496,7 @@ int RelationalSyncAbleStorage::CreateTempSyncTrigger(const std::string &tableNam if (handle == nullptr) { return errCode; } - errCode = CreateTempSyncTriggerInner(handle, tableName); + errCode = CreateTempSyncTriggerInner(handle, tableName, true); ReleaseHandle(handle); if (errCode != E_OK) { LOGE("[RelationalSyncAbleStorage] Create temp sync trigger failed %d", errCode); @@ -1693,15 +1722,9 @@ void RelationalSyncAbleStorage::SetLogicDelete(bool logicDelete) LOGI("[RelationalSyncAbleStorage] set logic delete %d", static_cast(logicDelete)); } -void RelationalSyncAbleStorage::SetCloudTaskConfig(const CloudTaskConfig &config) -{ - allowLogicDelete_ = config.allowLogicDelete; - LOGD("[RelationalSyncAbleStorage] allow logic delete %d", static_cast(config.allowLogicDelete)); -} - bool RelationalSyncAbleStorage::IsCurrentLogicDelete() const { - return allowLogicDelete_ && logicDelete_; + return logicDelete_; } std::pair RelationalSyncAbleStorage::GetAssetsByGidOrHashKey(const TableSchema &tableSchema, @@ -1894,7 +1917,7 @@ int RelationalSyncAbleStorage::UpdateRecordFlagAfterUpload(SQLiteSingleVerRelati logInfo.timestamp = updateData.timestamp[i]; logInfo.dataKey = rowId; logInfo.hashKey = updateData.hashKey[i]; - std::string sql = CloudStorageUtils::GetUpdateRecordFlagSql(tableName, DBCommon::IsRecordIgnored(record), + std::string sql = CloudStorageUtils::GetUpdateRecordFlagSqlUpload(tableName, DBCommon::IsRecordIgnored(record), logInfo, record, type); int errCode = handle->UpdateRecordFlag(tableName, sql, logInfo); if (errCode != E_OK) { @@ -1907,7 +1930,8 @@ int RelationalSyncAbleStorage::UpdateRecordFlagAfterUpload(SQLiteSingleVerRelati return E_OK; } -int RelationalSyncAbleStorage::GetCompensatedSyncQuery(std::vector &syncQuery) +int RelationalSyncAbleStorage::GetCompensatedSyncQuery(std::vector &syncQuery, + std::vector &users) { std::vector tables; int errCode = GetCloudTableWithoutShared(tables); @@ -1927,6 +1951,40 @@ int RelationalSyncAbleStorage::GetCompensatedSyncQuery(std::vector tables; + int errCode = GetCloudTableWithoutShared(tables); + if (errCode != E_OK) { + return errCode; + } + if (tables.empty()) { + LOGI("[RDBStorage] Table is empty, no need to clear unlocking status"); + return E_OK; + } + auto *handle = GetHandle(true, errCode); + if (errCode != E_OK || handle == nullptr) { + return errCode; + } + errCode = handle->StartTransaction(TransactType::IMMEDIATE); + if (errCode != E_OK) { + ReleaseHandle(handle); + return errCode; + } + for (const auto &table : tables) { + errCode = handle->ClearUnLockingStatus(table.name); + if (errCode != E_OK) { + LOGW("[ClearUnLockingNoNeedCompensated] clear unlocking status failed, continue! errCode=%d", errCode); + } + } + errCode = handle->Commit(); + if (errCode != E_OK) { + LOGE("[ClearUnLockingNoNeedCompensated] commit failed %d when clear unlocking status", errCode); + } + ReleaseHandle(handle); + return errCode; +} + int RelationalSyncAbleStorage::GetCloudTableWithoutShared(std::vector &tables) { const auto tableInfos = GetSchemaInfo().GetTables(); @@ -1996,13 +2054,13 @@ int RelationalSyncAbleStorage::GetCompensatedSyncQueryInner(SQLiteSingleVerRelat } int RelationalSyncAbleStorage::CreateTempSyncTriggerInner(SQLiteSingleVerRelationalStorageExecutor *handle, - const std::string &tableName) + const std::string &tableName, bool flag) { TrackerTable trackerTable = storageEngine_->GetTrackerSchema().GetTrackerTable(tableName); if (trackerTable.IsEmpty()) { trackerTable.SetTableName(tableName); } - return handle->CreateTempSyncTrigger(trackerTable); + return handle->CreateTempSyncTrigger(trackerTable, flag); } bool RelationalSyncAbleStorage::CheckTableSupportCompensatedSync(const TableSchema &table) @@ -2098,9 +2156,36 @@ void RelationalSyncAbleStorage::ReleaseUploadRecord(const std::string &tableName uploadRecorder_.ReleaseUploadRecord(tableName, type, localMark); } -bool RelationalSyncAbleStorage::IsSameCloudLocalDeviceAndNotLocal(const LogInfo &localInfo, const LogInfo &cloudInfo) +int RelationalSyncAbleStorage::ReviseLocalModTime(const std::string &tableName, + const std::vector &revisedData) { - return false; + if (storageEngine_ == nullptr) { + LOGE("[ReviseLocalModTime] Storage is null"); + return -E_INVALID_DB; + } + int errCode = E_OK; + auto writeHandle = static_cast( + storageEngine_->FindExecutor(true, OperatePerm::NORMAL_PERM, errCode)); + if (writeHandle == nullptr) { + LOGE("[ReviseLocalModTime] Get write handle fail: %d", errCode); + return errCode; + } + errCode = writeHandle->StartTransaction(TransactType::IMMEDIATE); + if (errCode != E_OK) { + LOGE("[ReviseLocalModTime] Start Transaction fail: %d", errCode); + ReleaseHandle(writeHandle); + return errCode; + } + errCode = writeHandle->ReviseLocalModTime(tableName, revisedData); + if (errCode != E_OK) { + LOGE("[ReviseLocalModTime] Revise local modify time fail: %d", errCode); + writeHandle->Rollback(); + ReleaseHandle(writeHandle); + return errCode; + } + errCode = writeHandle->Commit(); + ReleaseHandle(writeHandle); + return errCode; } } -#endif \ No newline at end of file +#endif diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/single_ver_utils.h b/kv_store/frameworks/libs/distributeddb/storage/src/single_ver_utils.h index 6243d39b8902fcbd7f8200d6001d147b2a1f00eb..23c2a5b454c7644f48861966f59f0b50dc62d4d0 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/single_ver_utils.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/single_ver_utils.h @@ -65,7 +65,7 @@ int CreateNewDirsAndSetSecOption(const OpenDbProperties &option); int GetExistedSecOpt(const OpenDbProperties &option, SecurityOption &secOption); -int CheckStoreStatus(const OpenDbProperties &option); +int CheckStoreStatus(const OpenDbProperties &opt); void InitCommitNotifyDataKeyStatus(SingleVerNaturalStoreCommitNotifyData *committedData, const Key &hashKey, const DataOperStatus &dataStatus); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/kv_storage_handle.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/kv_storage_handle.h index 55fde2caa8f30e163676e53a8bf7ddb11e96966d..d7aa519d2c6e756b299222c6274f758e14f77bc2 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/kv_storage_handle.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/kv_storage_handle.h @@ -33,7 +33,7 @@ public: virtual TimeOffset GetLocalTimeOffsetForCloud() = 0; - virtual Timestamp GetCurrentTimestamp() = 0; + virtual Timestamp GetCurrentTimestamp(bool needStartSync = true) = 0; }; } #endif // I_STORAGE_HANDLE_H diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/query_sync_object.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/query_sync_object.cpp index ed5379071abbef8658b4edc6f56b07d683b8a672..f08f648ad163ba770f16fadd94d573c44fb21321 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/query_sync_object.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/query_sync_object.cpp @@ -245,19 +245,28 @@ int QuerySyncObject::SerializeData(Parcel &parcel, uint32_t softWareVersion) void QuerySyncObject::SetCloudGid(const std::vector &cloudGid) { - QueryObjNode objNode; - objNode.operFlag = QueryObjType::OR; - objNode.type = QueryValueType::VALUE_TYPE_NULL; - queryObjNodes_.push_back(objNode); - objNode.operFlag = QueryObjType::IN; - objNode.fieldName = CloudDbConstant::GID_FIELD; - objNode.type = QueryValueType::VALUE_TYPE_STRING; - for (const auto &gid : cloudGid) { - FieldValue fieldValue; - fieldValue.stringValue = gid; - objNode.fieldValue.emplace_back(fieldValue); - } - queryObjNodes_.emplace_back(objNode); + for (size_t i = 0; i < cloudGid.size(); i+= MAX_VALUE_SIZE) { + size_t end = std::min(i + MAX_VALUE_SIZE, cloudGid.size()); + QueryObjNode operateNode; + operateNode.operFlag = QueryObjType::OR; + operateNode.type = QueryValueType::VALUE_TYPE_NULL; + queryObjNodes_.emplace_back(operateNode); + + QueryObjNode objNode; + objNode.operFlag = QueryObjType::IN; + objNode.fieldName = CloudDbConstant::GID_FIELD; + objNode.type = QueryValueType::VALUE_TYPE_STRING; + std::vector subCloudGid(cloudGid.begin() + i, cloudGid.begin() + end); + for (const auto &gid : subCloudGid) { + if (gid.empty()) { + continue; + } + FieldValue fieldValue; + fieldValue.stringValue = gid; + objNode.fieldValue.emplace_back(fieldValue); + } + queryObjNodes_.emplace_back(objNode); + } } namespace { diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/cloud_sync_log_table_manager.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/cloud_sync_log_table_manager.cpp index b6302aff78e816f30f6b3ee2c540485e473f264e..79e893047e463feb16b8a460d64e878ad5eb5964 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/cloud_sync_log_table_manager.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/cloud_sync_log_table_manager.cpp @@ -155,7 +155,6 @@ std::string CloudSyncLogTableManager::GetUpdateTrigger(const TableInfo &table, c std::string CloudSyncLogTableManager::GetDeleteTrigger(const TableInfo &table, const std::string &identity) { (void)identity; - std::string logTblName = GetLogTableName(table); std::string tableName = table.GetTableName(); std::string deleteTrigger = "CREATE TRIGGER IF NOT EXISTS "; deleteTrigger += "naturalbase_rdb_" + tableName + "_ON_DELETE BEFORE DELETE \n"; @@ -169,7 +168,8 @@ std::string CloudSyncLogTableManager::GetDeleteTrigger(const TableInfo &table, c uint32_t localDeleteFlag = static_cast(LogInfoFlag::FLAG_DELETE) | static_cast(LogInfoFlag::FLAG_LOCAL); deleteTrigger += "flag=(CASE WHEN cloud_gid='' THEN " + std::to_string(localDeleteFlag) + " ELSE " + - std::to_string(localDeleteFlag | static_cast(LogInfoFlag::FLAG_DEVICE_CLOUD_CONSISTENCY)) + " END),"; + std::to_string(localDeleteFlag | static_cast(LogInfoFlag::FLAG_DEVICE_CLOUD_INCONSISTENCY)) + + " END),"; deleteTrigger += "timestamp=get_raw_sys_time()"; if (!table.GetTrackerTable().GetTrackerColNames().empty()) { deleteTrigger += table.GetTrackerTable().GetExtendAssignValSql(true); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/collaboration_log_table_manager.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/collaboration_log_table_manager.h index b7e2091af6975a37d8e9f5cc5f60cc758e67cde5..4893e359b721f6822676c3166d01b9af90f788a2 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/collaboration_log_table_manager.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/collaboration_log_table_manager.h @@ -15,6 +15,7 @@ #ifndef COLLABORATION_LOG_TABLE_MANAGER_H #define COLLABORATION_LOG_TABLE_MANAGER_H + #include "sqlite_log_table_manager.h" namespace DistributedDB { diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/split_device_log_table_manager.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/split_device_log_table_manager.h index 6499a0ae158fd67669d890497b20eb3036e5a3ab..eef03c17f02ba988f65ca93052ca62d33ddfbbe2 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/split_device_log_table_manager.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/split_device_log_table_manager.h @@ -15,6 +15,7 @@ #ifndef SPLICT_DEVICE_LOG_TABLE_MANAGER_H #define SPLICT_DEVICE_LOG_TABLE_MANAGER_H + #include "sqlite_log_table_manager.h" namespace DistributedDB { 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 83d151178c60d8724e3fd25d8ed9e5342d0ae81f..d063d53e586d762be99c01ca965a1c96ce2a1d9f 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. error %d size %zu", errCode, schemaVal.size()); + LOGW("No relational schema info was found."); return -E_NOT_FOUND; } @@ -200,19 +200,6 @@ int SQLiteRelationalStore::CheckProperties(RelationalDBProperties properties) return E_OK; } -int SQLiteRelationalStore::SaveSchemaToMeta() -{ - Key schemaKey; - DBCommon::StringToVector(DBConstant::RELATIONAL_SCHEMA_KEY, schemaKey); - Value schemaVal; - DBCommon::StringToVector(sqliteStorageEngine_->GetSchema().ToSchemaString(), schemaVal); - int errCode = storageEngine_->PutMetaData(schemaKey, schemaVal); - if (errCode != E_OK) { - LOGE("Save relational schema to meta table failed. %d", errCode); - } - return errCode; -} - int SQLiteRelationalStore::SaveTableModeToMeta(DistributedTableMode mode) { const Key modeKey(DISTRIBUTED_TABLE_MODE, DISTRIBUTED_TABLE_MODE + strlen(DISTRIBUTED_TABLE_MODE)); @@ -288,7 +275,7 @@ int SQLiteRelationalStore::Open(const RelationalDBProperties &properties) // to guarantee the life cycle of sync module and syncAbleEngine_ are the same, then the sync module will not // be destructed when close store storageEngine_->SetSyncAbleEngine(syncAbleEngine_); - cloudSyncer_ = new (std::nothrow) CloudSyncer(StorageProxy::GetCloudDb(storageEngine_)); + cloudSyncer_ = new (std::nothrow) CloudSyncer(StorageProxy::GetCloudDb(storageEngine_), false); errCode = CheckDBMode(); if (errCode != E_OK) { @@ -1247,6 +1234,7 @@ void SQLiteRelationalStore::FillSyncInfo(const CloudSyncOption &option, const Sy info.lockAction = option.lockAction; info.merge = option.merge; info.storeId = sqliteStorageEngine_->GetProperties().GetStringProp(DBProperties::STORE_ID, ""); + info.prepareTraceId = option.prepareTraceId; } int SQLiteRelationalStore::SetTrackerTable(const TrackerSchema &trackerSchema) diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.h index 786691aa6ca3a8f387d129ee488bfb25a3e65293..26aea5c5e43dd7e1dd0bf32ba8c7771c5687a653 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.h @@ -115,7 +115,6 @@ private: void DecreaseConnectionCounter(uint64_t connectionId); int CheckDBMode(); int GetSchemaFromMeta(RelationalSchemaObject &schema); - int SaveSchemaToMeta(); int CheckTableModeFromMeta(DistributedTableMode mode, bool isUnSet); int SaveTableModeToMeta(DistributedTableMode mode); int CheckProperties(RelationalDBProperties properties); 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 5dd72f49421e0779169eabb6843493b78522b0a6..cdc6eaa479886ce046c30a3e40464c70da92f425 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 @@ -31,14 +31,12 @@ int SQLiteRelationalUtils::GetDataValueByType(sqlite3_stmt *statement, int cid, int errCode = E_OK; int storageType = sqlite3_column_type(statement, cid); switch (storageType) { - case SQLITE_INTEGER: { + case SQLITE_INTEGER: value = static_cast(sqlite3_column_int64(statement, cid)); break; - } - case SQLITE_FLOAT: { + case SQLITE_FLOAT: value = sqlite3_column_double(statement, cid); break; - } case SQLITE_BLOB: { std::vector blobValue; errCode = SQLiteUtils::GetColumnBlobValue(statement, cid, blobValue); @@ -51,11 +49,14 @@ int SQLiteRelationalUtils::GetDataValueByType(sqlite3_stmt *statement, int cid, } blob->WriteBlob(blobValue.data(), static_cast(blobValue.size())); errCode = value.Set(blob); + if (errCode != E_OK) { + delete blob; + blob = nullptr; + } break; } - case SQLITE_NULL: { + case SQLITE_NULL: break; - } case SQLITE3_TEXT: { std::string str; (void)SQLiteUtils::GetColumnTextValue(statement, cid, str); @@ -65,9 +66,8 @@ int SQLiteRelationalUtils::GetDataValueByType(sqlite3_stmt *statement, int cid, } break; } - default: { + default: break; - } } return errCode; } 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 f4c49cbe40a2b7a97840ce32f1e239bf957e903e..7104e98ae8d594685a3423c606b8bfa9e8d0aa28 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 @@ -452,7 +452,7 @@ int SQLiteSingleRelationalStorageEngine::SetTrackerTable(const TrackerSchema &sc return errCode; } RelationalSchemaObject tracker = trackerSchema_; - if (!tracker.GetTrackerTable(schema.tableName).IsChanging(schema)) { + if (!tracker.GetTrackerTable(schema.tableName).IsChanging(schema) && !schema.isForceUpgrade) { (void)handle->Rollback(); ReleaseExecutor(handle); LOGW("tracker schema is no change."); @@ -501,7 +501,7 @@ int SQLiteSingleRelationalStorageEngine::CheckAndCacheTrackerSchema(const Tracke return errCode; } RelationalSchemaObject tracker = trackerSchema_; - if (!tracker.GetTrackerTable(schema.tableName).IsChanging(schema)) { // LCOV_EXCL_BR_LINE + if (!tracker.GetTrackerTable(schema.tableName).IsChanging(schema) && !schema.isForceUpgrade) { // LCOV_EXCL_BR_LINE ReleaseExecutor(handle); LOGW("tracker schema is no change for distributed table."); return -E_IGNORE_DATA; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_continue_token.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_continue_token.cpp index 8777844b7edd9d07d47f125f7703870f643d3a6a..3b355030ca5c29f8de5550d6b4d3135a837a5e18 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_continue_token.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_continue_token.cpp @@ -188,7 +188,7 @@ int SQLiteSingleVerRelationalContinueToken::GetCloudStatement(sqlite3 *db, Cloud } std::string sql = helper.GetRelationalCloudQuerySql(tableSchema_.fields, cloudDataResult.isCloudForcePushStrategy, cloudDataResult.isCompensatedTask, cloudDataResult.mode); - errCode = helper.GetCloudQueryStatement(true, db, timeRange_.beginTime, sql, queryStmt_); + errCode = helper.GetCloudQueryStatement(true, db, sql, queryStmt_); if (errCode == E_OK) { queryStmt = queryStmt_; } 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 dad010cdc57b6c8ac7a70a3323634da72f6455a9..ca52c0084276878af62dda2e3f608d4222e409c0 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 @@ -44,8 +44,8 @@ static constexpr const char *FLAG_IS_CLOUD_CONSISTENCY = "FLAG & 0x20 = 0"; // s 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)"; 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 and exist passport -static constexpr const char *SET_FLAG_LOGIC_DELETE = "(FLAG | 0x08 | 0x800 | 0x01) & (~0x02)"; +// set data logic delete, exist passport, delete, not compensated and cloud +static constexpr const char *SET_FLAG_WHEN_LOGOUT = "(FLAG | 0x08 | 0x800 | 0x01) & (~0x12)"; static constexpr const char *DATA_IS_DELETE = "data_key = -1 AND FLAG & 0X08 = 0"; // see if data is delete static constexpr const char *UPDATE_CURSOR_SQL = "cursor=update_cursor()"; static constexpr const int SET_FLAG_ZERO_MASK = ~0x04; // clear 2th bit of flag @@ -65,6 +65,12 @@ int PermitSelect(void *a, int b, const char *c, const char *d, const char *e, co if (b != SQLITE_SELECT && b != SQLITE_READ && b != SQLITE_FUNCTION) { return SQLITE_DENY; } + if (b == SQLITE_FUNCTION) { + if (d != nullptr && (strcmp(d, "fts3_tokenizer") == 0)) { + LOGE("Deny fts3_tokenizer in remote query"); + return SQLITE_DENY; + } + } return SQLITE_OK; } } @@ -171,7 +177,7 @@ int SQLiteSingleVerRelationalStorageExecutor::GeneLogInfoForExistedData(sqlite3 std::string logTable = DBConstant::RELATIONAL_PREFIX + tableName + "_log"; std::string rowid = std::string(DBConstant::SQLITE_INNER_ROWID); std::string flag = std::to_string(static_cast(LogInfoFlag::FLAG_LOCAL) | - static_cast(LogInfoFlag::FLAG_DEVICE_CLOUD_CONSISTENCY)); + static_cast(LogInfoFlag::FLAG_DEVICE_CLOUD_INCONSISTENCY)); if (tableInfo.GetTableSyncType() == TableSyncType::DEVICE_COOPERATION) { std::string sql = "INSERT OR REPLACE INTO " + logTable + " SELECT " + rowid + ", '', '', " + timeOffsetStr + " + " + rowid + ", " + timeOffsetStr + " + " + rowid + ", " + flag + ", " + calPrimaryKeyHash + ", '', " + @@ -558,13 +564,16 @@ static int GetLogData(sqlite3_stmt *logStatement, LogInfo &logInfo) } namespace { -void GetCloudLog(sqlite3_stmt *logStatement, VBucket &logInfo, uint32_t &totalSize) +void GetCloudLog(sqlite3_stmt *logStatement, VBucket &logInfo, uint32_t &totalSize, + int64_t &revisedTime, int64_t &invalidTime) { int64_t modifyTime = static_cast(sqlite3_column_int64(logStatement, TIMESTAMP_INDEX)); uint64_t curTime = 0; if (TimeHelper::GetSysCurrentRawTime(curTime) == E_OK) { if (modifyTime > static_cast(curTime)) { + invalidTime = modifyTime; modifyTime = static_cast(curTime); + revisedTime = modifyTime; } } else { LOGW("[Relational] get raw sys time failed."); @@ -581,6 +590,14 @@ void GetCloudLog(sqlite3_stmt *logStatement, VBucket &logInfo, uint32_t &totalSi totalSize += cloudGid.size(); } } + if (revisedTime != 0) { + std::string cloudGid; + if (logInfo.count(CloudDbConstant::GID_FIELD) != 0) { + cloudGid = std::get(logInfo[CloudDbConstant::GID_FIELD]); + } + LOGW("[Relational] Found invalid mod time: %lld, curTime: %lld, gid: %s", invalidTime, revisedTime, + DBCommon::StringMiddleMasking(cloudGid).c_str()); + } std::string version; SQLiteUtils::GetColumnTextValue(logStatement, VERSION_INDEX, version); logInfo.insert_or_assign(CloudDbConstant::VERSION_FIELD, version); @@ -1570,115 +1587,6 @@ int SQLiteSingleVerRelationalStorageExecutor::GetExistsDeviceList(std::set(sqlite3_column_int64(stmt, 0)); - errCode = E_OK; - } else { - LOGE("Failed to get the count to be uploaded. %d", errCode); - } - SQLiteUtils::ResetStatement(stmt, true, errCode); - return errCode; -} - -int SQLiteSingleVerRelationalStorageExecutor::GetUploadCount(const Timestamp ×tamp, bool isCloudForcePush, - bool isCompensatedTask, QuerySyncObject &query, int64_t &count) -{ - int errCode; - SqliteQueryHelper helper = query.GetQueryHelper(errCode); - if (errCode != E_OK) { - return errCode; - } - std::string sql = helper.GetCountRelationalCloudQuerySql(isCloudForcePush, isCompensatedTask, - CloudWaterType::DELETE); - return GetUploadCountInner(timestamp, helper, sql, count); -} - -int SQLiteSingleVerRelationalStorageExecutor::GetAllUploadCount(const std::vector ×tampVec, - bool isCloudForcePush, bool isCompensatedTask, QuerySyncObject &query, int64_t &count) -{ - std::vector typeVec = DBCommon::GetWaterTypeVec(); - if (timestampVec.size() != typeVec.size()) { - return -E_INVALID_ARGS; - } - int errCode; - SqliteQueryHelper helper = query.GetQueryHelper(errCode); - if (errCode != E_OK) { - return errCode; - } - count = 0; - for (size_t i = 0; i < typeVec.size(); i++) { - std::string sql = helper.GetCountRelationalCloudQuerySql(isCloudForcePush, isCompensatedTask, typeVec[i]); - int64_t tempCount = 0; - helper.AppendCloudQueryToGetDiffData(sql, typeVec[i]); - errCode = GetUploadCountInner(timestampVec[i], helper, sql, tempCount); - if (errCode != E_OK) { - return errCode; - } - count += tempCount; - } - return E_OK; -} - -int SQLiteSingleVerRelationalStorageExecutor::UpdateCloudLogGid(const CloudSyncData &cloudDataResult, - bool ignoreEmptyGid) -{ - if (cloudDataResult.insData.extend.empty() || cloudDataResult.insData.rowid.empty() || - cloudDataResult.insData.extend.size() != cloudDataResult.insData.rowid.size()) { - return -E_INVALID_ARGS; - } - std::string sql = "UPDATE '" + DBCommon::GetLogTableName(cloudDataResult.tableName) - + "' SET cloud_gid = ? WHERE data_key = ? "; - sqlite3_stmt *stmt = nullptr; - int errCode = SQLiteUtils::GetStatement(dbHandle_, sql, stmt); - if (errCode != E_OK) { - return errCode; - } - errCode = BindStmtWithCloudGid(cloudDataResult, ignoreEmptyGid, stmt); - int resetCode = E_OK; - SQLiteUtils::ResetStatement(stmt, true, resetCode); - return errCode == E_OK ? resetCode : errCode; -} - -int SQLiteSingleVerRelationalStorageExecutor::GetSyncCloudData(const CloudUploadRecorder &uploadRecorder, - CloudSyncData &cloudDataResult, SQLiteSingleVerRelationalContinueToken &token) -{ - token.GetCloudTableSchema(tableSchema_); - sqlite3_stmt *queryStmt = nullptr; - bool isStepNext = false; - int errCode = token.GetCloudStatement(dbHandle_, cloudDataResult, queryStmt, isStepNext); - if (errCode != E_OK) { - (void)token.ReleaseCloudStatement(); - return errCode; - } - uint32_t totalSize = 0; - uint32_t stepNum = -1; - do { - if (isStepNext) { - errCode = SQLiteUtils::StepNext(queryStmt, isMemDb_); - if (errCode != E_OK) { - errCode = (errCode == -E_FINISHED ? E_OK : errCode); - break; - } - } - isStepNext = true; - errCode = GetCloudDataForSync(uploadRecorder, queryStmt, cloudDataResult, ++stepNum, totalSize); - } while (errCode == E_OK); - if (errCode != -E_UNFINISHED) { - (void)token.ReleaseCloudStatement(); - } - return errCode; -} - int SQLiteSingleVerRelationalStorageExecutor::GetSyncCloudGid(QuerySyncObject &query, const SyncTimeRange &syncTimeRange, bool isCloudForcePushStrategy, bool isCompensatedTask, std::vector &cloudGid) @@ -1691,7 +1599,7 @@ int SQLiteSingleVerRelationalStorageExecutor::GetSyncCloudGid(QuerySyncObject &q } std::string sql = helper.GetGidRelationalCloudQuerySql(tableSchema_.fields, isCloudForcePushStrategy, isCompensatedTask); - errCode = helper.GetCloudQueryStatement(false, dbHandle_, syncTimeRange.beginTime, sql, queryStmt); + errCode = helper.GetCloudQueryStatement(false, dbHandle_, sql, queryStmt); if (errCode != E_OK) { return errCode; } @@ -1715,8 +1623,14 @@ int SQLiteSingleVerRelationalStorageExecutor::GetCloudDataForSync(const CloudUpl VBucket log; VBucket extraLog; uint32_t preSize = totalSize; - GetCloudLog(statement, log, totalSize); + int64_t revisedTime = 0; + int64_t invalidTime = 0; + GetCloudLog(statement, log, totalSize, revisedTime, invalidTime); GetCloudExtraLog(statement, extraLog); + if (revisedTime != 0) { + Bytes hashKey = std::get(extraLog[CloudDbConstant::HASH_KEY]); + cloudDataResult.revisedData.push_back({hashKey, revisedTime, invalidTime}); + } VBucket data; int64_t flag = 0; @@ -1753,43 +1667,12 @@ int SQLiteSingleVerRelationalStorageExecutor::GetCloudDataForSync(const CloudUpl return errCode; } -int SQLiteSingleVerRelationalStorageExecutor::PutVBucketByType(VBucket &vBucket, const Field &field, Type &cloudValue) -{ - if (field.type == TYPE_INDEX && cloudValue.index() == TYPE_INDEX) { - Asset asset; - int errCode = RuntimeContext::GetInstance()->BlobToAsset(std::get(cloudValue), asset); - if (errCode != E_OK) { - return errCode; - } - if (!CloudStorageUtils::CheckAssetStatus({asset})) { - return -E_CLOUD_INVALID_ASSET; - } - vBucket.insert_or_assign(field.colName, asset); - } else if (field.type == TYPE_INDEX && cloudValue.index() == TYPE_INDEX) { - Assets assets; - int errCode = RuntimeContext::GetInstance()->BlobToAssets(std::get(cloudValue), assets); - if (errCode != E_OK) { - return errCode; - } - if (CloudStorageUtils::IsAssetsContainDuplicateAsset(assets)) { - return -E_CLOUD_ERROR; - } - if (!CloudStorageUtils::CheckAssetStatus(assets)) { - return -E_CLOUD_INVALID_ASSET; - } - vBucket.insert_or_assign(field.colName, assets); - } else { - vBucket.insert_or_assign(field.colName, cloudValue); - } - return E_OK; -} - void SQLiteSingleVerRelationalStorageExecutor::SetLocalSchema(const RelationalSchemaObject &localSchema) { localSchema_ = localSchema; } -int SQLiteSingleVerRelationalStorageExecutor::CleanCloudDataOnLogTable(const std::string &logTableName) +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 + " = '', " + @@ -1808,7 +1691,12 @@ int SQLiteSingleVerRelationalStorageExecutor::CleanCloudDataOnLogTable(const std return errCode; } // set all flag logout and data upload is not finished. - cleanLogSql = "UPDATE " + logTableName + " SET " + CloudDbConstant::FLAG + " = flag | 0x800 & ~0x400;"; + cleanLogSql = "UPDATE " + logTableName + " SET " + CloudDbConstant::FLAG; + if (mode == FLAG_ONLY) { + cleanLogSql += " = flag | 0x800 & ~0x400;"; + } else { + cleanLogSql += " = flag & ~0x400;"; + } return SQLiteUtils::ExecuteRawSQL(dbHandle_, cleanLogSql); } @@ -1844,7 +1732,7 @@ int SQLiteSingleVerRelationalStorageExecutor::CleanCloudDataAndLogOnUserTable(co LOGE("[Storage Executor] failed to clean asset id when clean cloud data, %d", errCode); return errCode; } - errCode = CleanCloudDataOnLogTable(logTableName); + errCode = CleanCloudDataOnLogTable(logTableName, FLAG_AND_DATA); if (errCode != E_OK) { LOGE("Failed to clean gid on log table, %d.", errCode); } @@ -1863,44 +1751,82 @@ int SQLiteSingleVerRelationalStorageExecutor::ChangeCloudDataFlagOnLogTable(cons return errCode; } -int SQLiteSingleVerRelationalStorageExecutor::SetDataOnUserTablWithLogicDelete(const std::string &tableName, +int SQLiteSingleVerRelationalStorageExecutor::SetDataOnUserTableWithLogicDelete(const std::string &tableName, const std::string &logTableName) { UpdateCursorContext context; context.cursor = GetCursor(tableName); - LOGI("removeData start and cursor is, %d.", context.cursor); + LOGI("removeData on userTable:%s length:%d start and cursor is, %d.", + DBCommon::StringMiddleMasking(tableName).c_str(), tableName.size(), context.cursor); int errCode = CreateFuncUpdateCursor(context, &UpdateCursor); - std::string sql = "UPDATE '" + logTableName + "' SET " + CloudDbConstant::FLAG + " = " + SET_FLAG_LOGIC_DELETE + + if (errCode != E_OK) { + LOGE("Failed to create updateCursor func on userTable errCode=%d.", errCode); + return errCode; + } + std::string sql = "UPDATE '" + logTableName + "' SET " + CloudDbConstant::FLAG + " = " + SET_FLAG_WHEN_LOGOUT + ", " + VERSION + " = '', " + DEVICE_FIELD + " = '', " + CLOUD_GID_FIELD + " = '', " + SHARING_RESOURCE + " = '', " + UPDATE_CURSOR_SQL + - " WHERE (CLOUD_GID IS NOT NULL AND CLOUD_GID != '' AND " + FLAG_IS_CLOUD_CONSISTENCY + ");"; + " WHERE (CLOUD_GID IS NOT NULL AND CLOUD_GID != '' AND " + FLAG_IS_CLOUD_CONSISTENCY + + " AND NOT (" + DATA_IS_DELETE + ") " + " AND NOT (" + FLAG_IS_LOGIC_DELETE + "));"; errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, sql); + // here just clear updateCursor func, fail will not influence other function + (void)CreateFuncUpdateCursor(context, nullptr); if (errCode != E_OK) { LOGE("Failed to change cloud data flag on usertable, %d.", errCode); - CreateFuncUpdateCursor(context, nullptr); return errCode; } - // deal when data is logicDelete + // clear some column when data is logicDelete or physical delete sql = "UPDATE '" + logTableName + "' SET " + VERSION + " = '', " + DEVICE_FIELD + " = '', " + CLOUD_GID_FIELD + - " = '', " + SHARING_RESOURCE + " = '' WHERE " + FLAG_IS_LOGIC_DELETE + ";"; + " = '', " + SHARING_RESOURCE + " = '' WHERE (" + FLAG_IS_LOGIC_DELETE + ") OR (" + DATA_IS_DELETE + ");"; errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, sql); if (errCode != E_OK) { LOGE("Failed to deal logic delete data flag on usertable, %d.", errCode); - CreateFuncUpdateCursor(context, nullptr); return errCode; } - LOGI("removeData finish and cursor is %d.", context.cursor); + LOGI("removeData on userTable:%s length:%d finish and cursor is, %d.", + DBCommon::StringMiddleMasking(tableName).c_str(), tableName.size(), context.cursor); errCode = SetCursor(tableName, context.cursor); if (errCode != E_OK) { - CreateFuncUpdateCursor(context, nullptr); LOGE("set new cursor after removeData error %d.", errCode); return errCode; } - errCode = CreateFuncUpdateCursor(context, nullptr); + return ChangeCloudDataFlagOnLogTable(logTableName); +} + +int SQLiteSingleVerRelationalStorageExecutor::SetDataOnShareTableWithLogicDelete(const std::string &tableName, + const std::string &logTableName) +{ + UpdateCursorContext context; + context.cursor = GetCursor(tableName); + LOGI("removeData on shareTable:%s length:%d start and cursor is, %d.", + DBCommon::StringMiddleMasking(tableName).c_str(), tableName.size(), context.cursor); + int errCode = CreateFuncUpdateCursor(context, &UpdateCursor); + if (errCode != E_OK) { + LOGE("Failed to create updateCursor func on shareTable errCode=%d.", errCode); + return errCode; + } + std::string sql = "UPDATE '" + logTableName + "' SET " + CloudDbConstant::FLAG + " = " + SET_FLAG_WHEN_LOGOUT + + ", " + VERSION + " = '', " + DEVICE_FIELD + " = '', " + CLOUD_GID_FIELD + " = '', " + + SHARING_RESOURCE + " = '', " + UPDATE_CURSOR_SQL + " WHERE (NOT (" + DATA_IS_DELETE + ") " + + " 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); if (errCode != E_OK) { - LOGE("Clear FuncUpdateCursor error %d.", errCode); + LOGE("Failed to change cloud data flag on shareTable, %d.", errCode); + return errCode; } - return ChangeCloudDataFlagOnLogTable(logTableName); + // clear some column when data is logicDelete or physical delete + sql = "UPDATE '" + logTableName + "' SET " + VERSION + " = '', " + DEVICE_FIELD + " = '', " + CLOUD_GID_FIELD + + " = '', " + SHARING_RESOURCE + " = '' WHERE (" + FLAG_IS_LOGIC_DELETE + ") OR (" + DATA_IS_DELETE + ");"; + errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, sql); + if (errCode != E_OK) { + 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.", + DBCommon::StringMiddleMasking(tableName).c_str(), tableName.size(), context.cursor); + return SetCursor(tableName, context.cursor); } int SQLiteSingleVerRelationalStorageExecutor::GetCleanCloudDataKeys(const std::string &logTableName, @@ -1959,11 +1885,13 @@ int SQLiteSingleVerRelationalStorageExecutor::GetUpdateLogRecordStatement(const } else if (opType == OpType::LOCKED_NOT_HANDLE) { updateLogSql += std::string(CloudDbConstant::TO_LOCAL_CHANGE) + ", cloud_gid = ?"; updateColName.push_back(CloudDbConstant::GID_FIELD); + updateLogSql += ", version = ?"; + updateColName.push_back(CloudDbConstant::VERSION_FIELD); } else { updateLogSql += " device = 'cloud', timestamp = ?,"; updateColName.push_back(CloudDbConstant::MODIFY_FIELD); if (opType == OpType::DELETE) { - updateLogSql += GetCloudDeleteSql(DBCommon::GetLogTableName(tableSchema.name)); + updateLogSql += GetCloudDeleteSql(tableSchema.name); } 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 d41ea10ac1974a8c99c299d631a3c8a3f7bbacb1..2af07ab80a8d9a6e25cd5e2061bee58b25ab8abf 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 @@ -143,6 +143,7 @@ public: int FillCloudVersionForUpload(const OpType opType, const CloudSyncData &data); int SetLogTriggerStatus(bool status); + int SetCursorIncFlag(bool flag); int AnalysisTrackerTable(const TrackerTable &trackerTable, TableInfo &tableInfo); int CreateTrackerTable(const TrackerTable &trackerTable, bool isUpgrade); @@ -151,7 +152,7 @@ public: int GetClearWaterMarkTables(const std::vector &tableReferenceProperty, const RelationalSchemaObject &schema, std::set &clearWaterMarkTables); - int CreateTempSyncTrigger(const TrackerTable &trackerTable); + int CreateTempSyncTrigger(const TrackerTable &trackerTable, bool flag); int GetAndResetServerObserverData(const std::string &tableName, ChangeProperties &changeProperties); int ClearAllTempSyncTrigger(); int CleanTrackerData(const std::string &tableName, int64_t cursor); @@ -194,6 +195,8 @@ public: int GetWaitCompensatedSyncDataPk(const TableSchema &table, std::vector &data); + int ClearUnLockingStatus(const std::string &tableName); + int MarkFlagAsConsistent(const std::string &tableName, const DownloadData &downloadData, const std::set &gidFilters); @@ -206,20 +209,22 @@ public: int InitCursorToMeta(const std::string &tableName); void SetTableSchema(const TableSchema &tableSchema); + + int ReviseLocalModTime(const std::string &tableName, const std::vector &revisedData); private: int DoCleanLogs(const std::vector &tableNameList, const RelationalSchemaObject &localSchema); int DoCleanLogAndData(const std::vector &tableNameList, const RelationalSchemaObject &localSchema, std::vector &assets); - int CleanCloudDataOnLogTable(const std::string &logTableName); + int CleanCloudDataOnLogTable(const std::string &logTableName, ClearMode mode); int CleanCloudDataAndLogOnUserTable(const std::string &tableName, const std::string &logTableName, const RelationalSchemaObject &localSchema); int ChangeCloudDataFlagOnLogTable(const std::string &logTableName); - int SetDataOnUserTablWithLogicDelete(const std::string &tableName, const std::string &logTableName); + int SetDataOnUserTableWithLogicDelete(const std::string &tableName, const std::string &logTableName); static void UpdateCursor(sqlite3_context *ctx, int argc, sqlite3_value **argv); @@ -362,6 +367,8 @@ private: int BindUpdateVersionStatement(const VBucket &vBucket, const Bytes &hashKey, sqlite3_stmt *&stmt); int DoCleanShareTableDataAndLog(const std::vector &tableNameList); + int SetDataOnShareTableWithLogicDelete(const std::string &tableName, const std::string &logTableName); + int CleanShareTable(const std::string &tableName); int GetReferenceGidInner(const std::string &sourceTable, const std::string &targetTable, const CloudSyncBatch &syncBatch, const std::vector &targetTableReference, @@ -378,7 +385,7 @@ private: int BindStmtWithCloudGid(const CloudSyncData &cloudDataResult, bool ignoreEmptyGid, sqlite3_stmt *&stmt); - std::string GetCloudDeleteSql(const std::string &logTable); + std::string GetCloudDeleteSql(const std::string &table); int RemoveDataAndLog(const std::string &tableName, int64_t dataKey); @@ -420,21 +427,11 @@ private: void UpdateLocalAssetsId(const VBucket &vBucket, const std::string &fieldName, Assets &assets); - void UpdateLocalAssetsIdInner(const Assets &cloudAssets, Assets &assets); - int BindAssetToBlobStatement(const Asset &asset, int index, sqlite3_stmt *&stmt); int BindAssetsToBlobStatement(const Assets &assets, int index, sqlite3_stmt *&stmt); - int GetAssetOnTableInner(sqlite3_stmt *&stmt, Asset &asset); - - int GetAssetOnTable(const std::string &tableName, const std::string &fieldName, const int64_t dataKey, - Asset &asset); - - int GetAssetsOnTableInner(sqlite3_stmt *&stmt, Assets &assets); - - int GetAssetsOnTable(const std::string &tableName, const std::string &fieldName, const int64_t dataKey, - Assets &assets); + int GetAssetInfoOnTable(sqlite3_stmt *&stmt, const std::vector &assetFields, VBucket &assetInfo); int BindAssetFiledToBlobStatement(const TableSchema &tableSchema, const std::vector &assetOfOneRecord, const std::vector &assetsOfOneRecord, sqlite3_stmt *&stmt); @@ -442,6 +439,11 @@ private: int UpdateAssetsIdForOneRecord(const TableSchema &tableSchema, const std::string &sql, const std::vector &assetOfOneRecord, const std::vector &assetsOfOneRecord); + bool IsNeedUpdateAssetId(const TableSchema &tableSchema, int64_t dataKey, const VBucket &vBucket); + + bool IsNeedUpdateAssetIdInner(sqlite3_stmt *selectStmt, const VBucket &vBucket, const Field &field, + VBucket &assetInfo); + int UpdateAssetId(const TableSchema &tableSchema, int64_t dataKey, const VBucket &vBucket); int64_t GetDataFlag(); 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 88830d0ce3ece6a88e57c8371d3f82584e1d78ae..e837116d4c08a8d8b78e63fc9c745707a3a0e251 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 @@ -306,6 +306,7 @@ int SQLiteSingleVerRelationalStorageExecutor::DoCleanInner(ClearMode mode, LOGE("[Storage Executor] Failed to do clean logs when clean cloud data."); return errCode; } + notifyTableList = tableNameList; } else if (mode == FLAG_AND_DATA) { errCode = DoCleanLogAndData(tableNameList, localSchema, assets); if (errCode != E_OK) { @@ -319,6 +320,7 @@ int SQLiteSingleVerRelationalStorageExecutor::DoCleanInner(ClearMode mode, LOGE("[Storage Executor] Failed to do clean log and data when clean cloud data."); return errCode; } + notifyTableList = tableNameList; } errCode = SetLogTriggerStatus(true); if (errCode != E_OK) { @@ -341,7 +343,7 @@ int SQLiteSingleVerRelationalStorageExecutor::DoCleanLogs(const std::vectorBlobToAsset(blobValue, asset); if (errCode != E_OK) { // LCOV_EXCL_BR_LINE @@ -585,6 +591,23 @@ int SQLiteSingleVerRelationalStorageExecutor::GetCloudAssets(const std::string & return errCode; } +int SQLiteSingleVerRelationalStorageExecutor::SetCursorIncFlag(bool flag) +{ + std::string sql = "INSERT OR REPLACE INTO " + DBConstant::RELATIONAL_PREFIX + "metadata" + + " VALUES ('cursor_inc_flag', "; + if (flag) { + sql += "'true'"; + } else { + sql += "'false'"; + } + sql += ");"; + int errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, sql); + if (errCode != E_OK) { + LOGE("set cursor inc flag fail, errCode = %d", errCode); + } + return errCode; +} + int SQLiteSingleVerRelationalStorageExecutor::PutCloudSyncData(const std::string &tableName, const TableSchema &tableSchema, const TrackerTable &trackerTable, DownloadData &downloadData) { @@ -1199,5 +1222,381 @@ void SQLiteSingleVerRelationalStorageExecutor::SetTableSchema(const TableSchema { tableSchema_ = tableSchema; } + +int SQLiteSingleVerRelationalStorageExecutor::ReviseLocalModTime(const std::string &tableName, + const std::vector &revisedData) +{ + sqlite3_stmt *stmt = nullptr; + std::string sql = "UPDATE " + DBCommon::GetLogTableName(tableName) + + " SET timestamp=? where hash_key=? AND timestamp=?"; + int errCode = SQLiteUtils::GetStatement(dbHandle_, sql, stmt); + if (errCode != E_OK) { + LOGE("[RDBExecutor][ReviseLocalModTime] Get stmt failed: %d", errCode); + return errCode; + } + ResFinalizer finalizer([stmt]() { + sqlite3_stmt *statement = stmt; + int ret = E_OK; + SQLiteUtils::ResetStatement(statement, true, ret); + if (ret != E_OK) { + LOGW("[RDBExecutor][ReviseLocalModTime] Reset stmt failed %d", ret); + } + }); + for (auto &data : revisedData) { + int resetCode = E_OK; + errCode = SQLiteUtils::BindInt64ToStatement(stmt, 1, data.curTime); // 1st bind modify time + if (errCode != E_OK) { + LOGE("[RDBExecutor][ReviseLocalModTime] Bind revised modify time failed: %d", errCode); + return errCode; + } + errCode = SQLiteUtils::BindBlobToStatement(stmt, 2, data.hashKey); // 2nd bind hash key + if (errCode != E_OK) { + LOGE("[RDBExecutor][ReviseLocalModTime] Bind hash key failed: %d", errCode); + return errCode; + } + errCode = SQLiteUtils::BindInt64ToStatement(stmt, 3, data.invalidTime); // 3rd bind modify time + if (errCode != E_OK) { + LOGE("[RDBExecutor][ReviseLocalModTime] Bind modify time failed: %d", errCode); + return errCode; + } + errCode = SQLiteUtils::StepWithRetry(stmt); + if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + LOGE("[RDBExecutor][ReviseLocalModTime] Revise failed: %d", errCode); + return errCode; + } + LOGI("[RDBExecutor][ReviseLocalModTime] Local data mod time revised from %lld to %lld", + data.invalidTime, data.curTime); + SQLiteUtils::ResetStatement(stmt, false, resetCode); + if (resetCode != E_OK) { + LOGW("[RDBExecutor][ReviseLocalModTime] Reset stmt failed: %d", resetCode); + return resetCode; + } + } + return E_OK; +} + +bool SQLiteSingleVerRelationalStorageExecutor::IsNeedUpdateAssetIdInner(sqlite3_stmt *selectStmt, + const VBucket &vBucket, const Field &field, VBucket &assetInfo) +{ + if (field.type == TYPE_INDEX) { + Asset asset; + UpdateLocalAssetId(vBucket, field.colName, asset); + Asset *assetDBPtr = std::get_if(&assetInfo[field.colName]); + if (assetDBPtr == nullptr) { + return true; + } + Asset &assetDB = *assetDBPtr; + if (assetDB.assetId != asset.assetId) { + return true; + } + } + if (field.type == TYPE_INDEX) { + Assets assets; + UpdateLocalAssetsId(vBucket, field.colName, assets); + Assets *assetsDBPtr = std::get_if(&assetInfo[field.colName]); + if (assetsDBPtr == nullptr) { + return true; + } + Assets &assetsDB = *assetsDBPtr; + if (assets.size() != assetsDB.size()) { + return true; + } + for (uint32_t i = 0; i< assets.size(); ++i) { + if (assets[i].assetId != assetsDB[i].assetId) { + return true; + } + } + } + return false; +} + +bool SQLiteSingleVerRelationalStorageExecutor::IsNeedUpdateAssetId(const TableSchema &tableSchema, int64_t dataKey, + const VBucket &vBucket) +{ + std::vector assetFields; + for (const auto &field : tableSchema.fields) { + if (field.type == TYPE_INDEX) { + assetFields.push_back(field); + } + if (field.type == TYPE_INDEX) { + assetFields.push_back(field); + } + } + if (assetFields.empty()) { + return false; + } + sqlite3_stmt *selectStmt = nullptr; + std::string queryAssetsSql = "SELECT "; + for (const auto &field : assetFields) { + queryAssetsSql += field.colName + ","; + } + queryAssetsSql.pop_back(); + 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 + LOGE("Get select assets statement failed, %d.", errCode); + return errCode; + } + ResFinalizer finalizer([selectStmt] { + sqlite3_stmt *statementInner = selectStmt; + int ret = E_OK; + SQLiteUtils::ResetStatement(statementInner, true, ret); + if (ret != E_OK) { + LOGW("Reset stmt failed %d when get asset", ret); + } + }); + VBucket assetInfo; + errCode = GetAssetInfoOnTable(selectStmt, assetFields, assetInfo); + if (errCode != E_OK) { + return true; + } + for (const auto &field : tableSchema.fields) { + if (IsNeedUpdateAssetIdInner(selectStmt, vBucket, field, assetInfo)) { + return true; + } + } + return false; +} + +int SQLiteSingleVerRelationalStorageExecutor::MarkFlagAsConsistent(const std::string &tableName, + const DownloadData &downloadData, const std::set &gidFilters) +{ + if (downloadData.data.size() != downloadData.opType.size()) { + LOGE("The num of data:%zu an opType:%zu is not equal.", downloadData.data.size(), downloadData.opType.size()); + return -E_CLOUD_ERROR; + } + std::string sql = "UPDATE " + DBCommon::GetLogTableName(tableName) + + " 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) { + LOGE("Get mark flag as consistent stmt failed, %d.", errCode); + return errCode; + } + int ret = E_OK; + int index = 0; + for (const auto &data: downloadData.data) { + SQLiteUtils::ResetStatement(stmt, false, ret); + OpType opType = downloadData.opType[index++]; + if (opType == OpType::NOT_HANDLE || opType == OpType::LOCKED_NOT_HANDLE) { + continue; + } + errCode = CloudStorageUtils::BindStepConsistentFlagStmt(stmt, data, gidFilters); + if (errCode != E_OK) { + break; + } + } + SQLiteUtils::ResetStatement(stmt, true, ret); + return errCode == E_OK ? ret : errCode; +} + +int SQLiteSingleVerRelationalStorageExecutor::FillCloudVersionForUpload(const std::string &tableName, + const CloudSyncBatch &batchData) +{ + if (batchData.extend.empty()) { + return E_OK; + } + if (batchData.hashKey.empty() || batchData.extend.size() != batchData.hashKey.size()) { + LOGE("invalid sync data for filling version."); + return -E_INVALID_ARGS; + } + std::string sql = "UPDATE '" + DBCommon::GetLogTableName(tableName) + + "' SET version = ? WHERE hash_key = ? "; + sqlite3_stmt *stmt = nullptr; + int errCode = SQLiteUtils::GetStatement(dbHandle_, sql, stmt); + if (errCode != E_OK || stmt == nullptr) { + return errCode; + } + int ret = E_OK; + for (size_t i = 0; i < batchData.extend.size(); ++i) { + errCode = BindUpdateVersionStatement(batchData.extend[i], batchData.hashKey[i], stmt); + if (errCode != E_OK) { + LOGE("bind update version stmt failed."); + SQLiteUtils::ResetStatement(stmt, true, ret); + return errCode; + } + } + SQLiteUtils::ResetStatement(stmt, true, ret); + return ret; +} + +int SQLiteSingleVerRelationalStorageExecutor::QueryCount(const std::string &tableName, int64_t &count) +{ + return SQLiteRelationalUtils::QueryCount(dbHandle_, tableName, count); +} + +int SQLiteSingleVerRelationalStorageExecutor::CheckInventoryData(const std::string &tableName) +{ + int64_t dataCount = 0; + int errCode = SQLiteRelationalUtils::QueryCount(dbHandle_, tableName, dataCount); + if (errCode != E_OK) { + LOGE("Query count failed.", errCode); + return errCode; + } + return dataCount > 0 ? -E_WITH_INVENTORY_DATA : E_OK; +} + +int SQLiteSingleVerRelationalStorageExecutor::GetUploadCountInner(const Timestamp ×tamp, + SqliteQueryHelper &helper, std::string &sql, int64_t &count) +{ + sqlite3_stmt *stmt = nullptr; + int errCode = helper.GetCloudQueryStatement(false, dbHandle_, sql, stmt); + if (errCode != E_OK || stmt == nullptr) { + LOGE("failed to get count statement %d", errCode); + return errCode; + } + errCode = SQLiteUtils::StepWithRetry(stmt, isMemDb_); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + count = static_cast(sqlite3_column_int64(stmt, 0)); + errCode = E_OK; + } else { + LOGE("Failed to get the count to be uploaded. %d", errCode); + } + SQLiteUtils::ResetStatement(stmt, true, errCode); + return errCode; +} + +int SQLiteSingleVerRelationalStorageExecutor::GetUploadCount(const Timestamp ×tamp, bool isCloudForcePush, + bool isCompensatedTask, QuerySyncObject &query, int64_t &count) +{ + int errCode; + SqliteQueryHelper helper = query.GetQueryHelper(errCode); + if (errCode != E_OK) { + return errCode; + } + std::string sql = helper.GetCountRelationalCloudQuerySql(isCloudForcePush, isCompensatedTask, + CloudWaterType::DELETE); + return GetUploadCountInner(timestamp, helper, sql, count); +} + +int SQLiteSingleVerRelationalStorageExecutor::GetAllUploadCount(const std::vector ×tampVec, + bool isCloudForcePush, bool isCompensatedTask, QuerySyncObject &query, int64_t &count) +{ + std::vector typeVec = DBCommon::GetWaterTypeVec(); + if (timestampVec.size() != typeVec.size()) { + return -E_INVALID_ARGS; + } + int errCode; + SqliteQueryHelper helper = query.GetQueryHelper(errCode); + if (errCode != E_OK) { + return errCode; + } + count = 0; + for (size_t i = 0; i < typeVec.size(); i++) { + std::string sql = helper.GetCountRelationalCloudQuerySql(isCloudForcePush, isCompensatedTask, typeVec[i]); + int64_t tempCount = 0; + helper.AppendCloudQueryToGetDiffData(sql, typeVec[i]); + errCode = GetUploadCountInner(timestampVec[i], helper, sql, tempCount); + if (errCode != E_OK) { + return errCode; + } + count += tempCount; + } + return E_OK; +} + +int SQLiteSingleVerRelationalStorageExecutor::UpdateCloudLogGid(const CloudSyncData &cloudDataResult, + bool ignoreEmptyGid) +{ + if (cloudDataResult.insData.extend.empty() || cloudDataResult.insData.rowid.empty() || + cloudDataResult.insData.extend.size() != cloudDataResult.insData.rowid.size()) { + return -E_INVALID_ARGS; + } + std::string sql = "UPDATE '" + DBCommon::GetLogTableName(cloudDataResult.tableName) + + "' SET cloud_gid = ? WHERE data_key = ? "; + sqlite3_stmt *stmt = nullptr; + int errCode = SQLiteUtils::GetStatement(dbHandle_, sql, stmt); + if (errCode != E_OK || stmt == nullptr) { + return errCode; + } + errCode = BindStmtWithCloudGid(cloudDataResult, ignoreEmptyGid, stmt); + int resetCode = E_OK; + SQLiteUtils::ResetStatement(stmt, true, resetCode); + return errCode == E_OK ? resetCode : errCode; +} + +int SQLiteSingleVerRelationalStorageExecutor::GetSyncCloudData(const CloudUploadRecorder &uploadRecorder, + CloudSyncData &cloudDataResult, SQLiteSingleVerRelationalContinueToken &token) +{ + token.GetCloudTableSchema(tableSchema_); + sqlite3_stmt *queryStmt = nullptr; + bool isStepNext = false; + int errCode = token.GetCloudStatement(dbHandle_, cloudDataResult, queryStmt, isStepNext); + if (errCode != E_OK || queryStmt == nullptr) { + (void)token.ReleaseCloudStatement(); + return errCode; + } + uint32_t totalSize = 0; + uint32_t stepNum = -1; + do { + if (isStepNext) { + errCode = SQLiteUtils::StepNext(queryStmt, isMemDb_); + if (errCode != E_OK) { + errCode = (errCode == -E_FINISHED ? E_OK : errCode); + break; + } + } + isStepNext = true; + errCode = GetCloudDataForSync(uploadRecorder, queryStmt, cloudDataResult, ++stepNum, totalSize); + } while (errCode == E_OK); + if (errCode != -E_UNFINISHED) { + (void)token.ReleaseCloudStatement(); + } + return errCode; +} + +int SQLiteSingleVerRelationalStorageExecutor::PutVBucketByType(VBucket &vBucket, const Field &field, Type &cloudValue) +{ + if (field.type == TYPE_INDEX && cloudValue.index() == TYPE_INDEX) { + Asset asset; + int errCode = RuntimeContext::GetInstance()->BlobToAsset(std::get(cloudValue), asset); + if (errCode != E_OK) { + return errCode; + } + if (!CloudStorageUtils::CheckAssetStatus({asset})) { + return -E_CLOUD_ERROR; + } + vBucket.insert_or_assign(field.colName, asset); + } else if (field.type == TYPE_INDEX && cloudValue.index() == TYPE_INDEX) { + Assets assets; + int errCode = RuntimeContext::GetInstance()->BlobToAssets(std::get(cloudValue), assets); + if (errCode != E_OK) { + return errCode; + } + if (CloudStorageUtils::IsAssetsContainDuplicateAsset(assets) || !CloudStorageUtils::CheckAssetStatus(assets)) { + return -E_CLOUD_ERROR; + } + vBucket.insert_or_assign(field.colName, assets); + } else { + vBucket.insert_or_assign(field.colName, cloudValue); + } + return E_OK; +} + +int SQLiteSingleVerRelationalStorageExecutor::GetAssetInfoOnTable(sqlite3_stmt *&stmt, + const std::vector &assetFields, VBucket &assetInfo) +{ + int errCode = SQLiteUtils::StepWithRetry(stmt); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { // LCOV_EXCL_BR_LINE + int index = 0; + for (const auto &field : assetFields) { + Type cloudValue; + errCode = SQLiteRelationalUtils::GetCloudValueByType(stmt, field.type, index++, cloudValue); + if (errCode != E_OK) { + break; + } + errCode = PutVBucketByType(assetInfo, field, cloudValue); + if (errCode != E_OK) { + break; + } + } + } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + errCode = E_OK; + } else { + LOGE("[RDBExecutor] Step failed when get assets from table, errCode = %d.", errCode); + } + return errCode; +} } // namespace DistributedDB #endif 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 2581170702cad4060f995c53210fa2827e0439de..f3183f1da0b0d723c2c139f0efabca247265e774 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 @@ -156,7 +156,7 @@ int SQLiteSingleVerRelationalStorageExecutor::IncreaseCursorOnAssetData(const st 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); @@ -166,13 +166,11 @@ int SQLiteSingleVerRelationalStorageExecutor::IncreaseCursorOnAssetData(const st }); int index = 1; errCode = SQLiteUtils::BindInt64ToStatement(statement, index++, cursor); - int ret = E_OK; if (errCode != E_OK) { LOGE("bind cursor data stmt failed %d.", errCode); return errCode; } errCode = SQLiteUtils::BindTextToStatement(statement, index, gid); - ret = E_OK; if (errCode != E_OK) { LOGE("bind cursor gid data stmt failed %d.", errCode); return errCode; @@ -305,7 +303,7 @@ int SQLiteSingleVerRelationalStorageExecutor::InitFillUploadAssetStatement(OpTyp CloudStorageUtils::FillAssetFromVBucketFinish(assetOpType, vBucket, dbAssets, CloudStorageUtils::FillAssetBeforeUpload, CloudStorageUtils::FillAssetsBeforeUpload); } else { - if (DBCommon::IsRecordError(data.extend.at(index))) { + if (DBCommon::IsRecordError(data.extend.at(index)) || DBCommon::IsRecordAssetsMissing(data.extend.at(index))) { CloudStorageUtils::FillAssetFromVBucketFinish(assetOpType, vBucket, dbAssets, CloudStorageUtils::FillAssetForUploadFailed, CloudStorageUtils::FillAssetsForUploadFailed); } else { @@ -511,7 +509,7 @@ int SQLiteSingleVerRelationalStorageExecutor::UpgradedLogForExistedData(TableInf return SetLogTriggerStatus(true); } -int SQLiteSingleVerRelationalStorageExecutor::CreateTempSyncTrigger(const TrackerTable &trackerTable) +int SQLiteSingleVerRelationalStorageExecutor::CreateTempSyncTrigger(const TrackerTable &trackerTable, bool flag) { int errCode = E_OK; std::vector dropSql = trackerTable.GetDropTempTriggerSql(); @@ -522,17 +520,17 @@ int SQLiteSingleVerRelationalStorageExecutor::CreateTempSyncTrigger(const Tracke return errCode; } } - errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, trackerTable.GetTempInsertTriggerSql()); + errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, trackerTable.GetTempInsertTriggerSql(flag)); if (errCode != E_OK) { LOGE("[RDBExecutor] create temp insert trigger failed %d.", errCode); return errCode; } - errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, trackerTable.GetTempUpdateTriggerSql()); + errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, trackerTable.GetTempUpdateTriggerSql(flag)); if (errCode != E_OK) { LOGE("[RDBExecutor] create temp update trigger failed %d.", errCode); return errCode; } - errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, trackerTable.GetTempDeleteTriggerSql()); + errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, trackerTable.GetTempDeleteTriggerSql(flag)); if (errCode != E_OK) { LOGE("[RDBExecutor] create temp delete trigger failed %d.", errCode); } @@ -733,41 +731,59 @@ int SQLiteSingleVerRelationalStorageExecutor::AppendUpdateLogRecordWhereSqlCondi int SQLiteSingleVerRelationalStorageExecutor::DoCleanShareTableDataAndLog(const std::vector &tableNameList) { - int ret = E_OK; int errCode = E_OK; for (const auto &tableName: tableNameList) { - std::string delDataSql = "DELETE FROM '" + tableName + "';"; - sqlite3_stmt *statement = nullptr; - errCode = SQLiteUtils::GetStatement(dbHandle_, delDataSql, statement); - if (errCode != E_OK) { - LOGE("get clean shared data stmt failed %d.", errCode); - return errCode; - } - errCode = SQLiteUtils::StepWithRetry(statement); - SQLiteUtils::ResetStatement(statement, true, ret); - if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { - errCode = E_OK; + if (isLogicDelete_) { + std::string logTableName = DBCommon::GetLogTableName(tableName); + errCode = SetDataOnShareTableWithLogicDelete(tableName, logTableName); } else { - LOGE("clean shared data failed: %d.", errCode); - break; + errCode = CleanShareTable(tableName); } - statement = nullptr; - std::string delLogSql = "DELETE FROM '" + DBConstant::RELATIONAL_PREFIX + tableName + "_log';"; - errCode = SQLiteUtils::GetStatement(dbHandle_, delLogSql, statement); if (errCode != E_OK) { - LOGE("get clean shared log stmt failed %d.", errCode); + LOGE("clean shared table failed at table:%s, length:%d, deleteType:%d, errCode:%d", + DBCommon::StringMiddleMasking(tableName).c_str(), tableName.size(), isLogicDelete_ ? 1 : 0, errCode); return errCode; } - errCode = SQLiteUtils::StepWithRetry(statement); - SQLiteUtils::ResetStatement(statement, true, ret); - if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { - errCode = E_OK; - } else { - LOGE("clean shared log failed: %d.", errCode); - break; - } } - return errCode == E_OK ? ret : errCode; + return errCode; +} + +int SQLiteSingleVerRelationalStorageExecutor::CleanShareTable(const std::string &tableName) +{ + int ret = E_OK; + int errCode = E_OK; + std::string delDataSql = "DELETE FROM '" + tableName + "';"; + sqlite3_stmt *statement = nullptr; + errCode = SQLiteUtils::GetStatement(dbHandle_, delDataSql, statement); + if (errCode != E_OK || statement == nullptr) { + LOGE("get clean shared data stmt failed %d.", errCode); + return errCode; + } + errCode = SQLiteUtils::StepWithRetry(statement); + SQLiteUtils::ResetStatement(statement, true, ret); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + errCode = E_OK; + } else { + LOGE("clean shared data failed: %d.", errCode); + return errCode; + } + statement = nullptr; + std::string delLogSql = "DELETE FROM '" + DBConstant::RELATIONAL_PREFIX + tableName + "_log';"; + errCode = SQLiteUtils::GetStatement(dbHandle_, delLogSql, statement); + if (errCode != E_OK || statement == nullptr) { + LOGE("get clean shared log stmt failed %d.", errCode); + return errCode; + } + errCode = SQLiteUtils::StepWithRetry(statement); + SQLiteUtils::ResetStatement(statement, true, ret); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + errCode = E_OK; + } else { + LOGE("clean shared log failed: %d.", errCode); + return errCode; + } + // here errCode must be E_OK, just return ret + return ret; } int SQLiteSingleVerRelationalStorageExecutor::GetReferenceGid(const std::string &tableName, @@ -945,7 +961,7 @@ int SQLiteSingleVerRelationalStorageExecutor::BindStmtWithCloudGid(const CloudSy std::string val; if (CloudStorageUtils::GetValueFromVBucket(CloudDbConstant::GID_FIELD, cloudDataResult.insData.extend[i], val) != E_OK) { - errCode = -E_INVALID_DATA; + errCode = -E_CLOUD_ERROR; LOGE("[RDBExecutor] Can't get string gid from extend."); break; } @@ -967,7 +983,7 @@ int SQLiteSingleVerRelationalStorageExecutor::BindStmtWithCloudGid(const CloudSy int SQLiteSingleVerRelationalStorageExecutor::CleanExtendAndCursorForDeleteData(const std::string &tableName) { std::string logTable = DBConstant::RELATIONAL_PREFIX + tableName + "_log"; - std::string sql = "UPDATE " + logTable + " SET extend_field = NULL, cursor = NULL where flag&0x01=0x01;"; + std::string sql = "DELETE FROM " + logTable + " where flag&0x01=0x01;"; int errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, sql); if (errCode != E_OK) { // LCOV_EXCL_BR_LINE LOGE("update extend field and cursor failed %d.", errCode); @@ -999,19 +1015,27 @@ int SQLiteSingleVerRelationalStorageExecutor::CheckIfExistUserTable(const std::s return E_OK; } -std::string SQLiteSingleVerRelationalStorageExecutor::GetCloudDeleteSql(const std::string &logTable) +std::string SQLiteSingleVerRelationalStorageExecutor::GetCloudDeleteSql(const std::string &table) { + std::string logTable = DBCommon::GetLogTableName(table); + int cursor = GetCursor(table); std::string sql; sql += " cloud_gid = '', version = '', "; if (isLogicDelete_) { + // cursor already increased by DeleteCloudData, can be assigned directly here // 1001 which is logicDelete|cloudForcePush|local|delete sql += "flag = flag&" + std::string(CONSISTENT_FLAG) + "|" + std::to_string(static_cast(LogInfoFlag::FLAG_DELETE) | - static_cast(LogInfoFlag::FLAG_LOGIC_DELETE)) + ", cursor = (SELECT CASE WHEN (MAX(cursor) is " - "null) THEN 1 ELSE MAX(cursor) + 1 END FROM " + logTable + ")"; + static_cast(LogInfoFlag::FLAG_LOGIC_DELETE)) + ", cursor = " + std::to_string(cursor) + " "; } 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); + if (errCode == E_OK) { + sql += ", cursor = " + std::to_string(cursor + 1) + " "; + } else { + LOGW("[RDBExecutor] Increase cursor failed when delete log: %d", errCode); + } } return sql; } @@ -1476,6 +1500,9 @@ int SQLiteSingleVerRelationalStorageExecutor::OnlyUpdateAssetId(const std::strin // this is shared table, not need to update asset id. return E_OK; } + if (!IsNeedUpdateAssetId(tableSchema, dataKey, vBucket)) { + return E_OK; + } int errCode = UpdateAssetId(tableSchema, dataKey, vBucket); if (errCode != E_OK) { LOGE("[Storage Executor] failed to update assetId on table, %d.", errCode); @@ -1503,17 +1530,6 @@ void SQLiteSingleVerRelationalStorageExecutor::UpdateLocalAssetsId(const VBucket } } -void SQLiteSingleVerRelationalStorageExecutor::UpdateLocalAssetsIdInner(const Assets &cloudAssets, Assets &assets) -{ - for (const auto &cloudAsset : cloudAssets) { - for (auto &asset : assets) { - if (asset.name == cloudAsset.name) { - asset.assetId = cloudAsset.assetId; - } - } - } -} - int SQLiteSingleVerRelationalStorageExecutor::BindAssetToBlobStatement(const Asset &asset, int index, sqlite3_stmt *&stmt) { @@ -1546,84 +1562,6 @@ int SQLiteSingleVerRelationalStorageExecutor::BindAssetsToBlobStatement(const As return errCode; } -int SQLiteSingleVerRelationalStorageExecutor::GetAssetOnTableInner(sqlite3_stmt *&stmt, Asset &asset) -{ - int errCode = SQLiteUtils::StepWithRetry(stmt); - if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { // LCOV_EXCL_BR_LINE - std::vector blobValue; - errCode = SQLiteUtils::GetColumnBlobValue(stmt, 0, blobValue); - if (errCode != E_OK) { // LCOV_EXCL_BR_LINE - LOGE("[RDBExecutor][GetAssetOnTableInner] Get column blob value failed, %d.", errCode); - return errCode; - } - errCode = RuntimeContext::GetInstance()->BlobToAsset(blobValue, asset); - if (errCode != E_OK) { // LCOV_EXCL_BR_LINE - LOGE("[RDBExecutor] Transfer blob to asset failed, %d.", errCode); - } - } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { - errCode = E_OK; - } else { - LOGE("[RDBExecutor] Step failed when get asset from table, errCode = %d.", errCode); - } - return errCode; -} - -int SQLiteSingleVerRelationalStorageExecutor::GetAssetOnTable(const std::string &tableName, - const std::string &fieldName, const int64_t dataKey, Asset &asset) -{ - sqlite3_stmt *selectStmt = nullptr; - std::string queryAssetSql = "SELECT " + fieldName + " FROM '" + tableName + - "' WHERE " + std::string(DBConstant::SQLITE_INNER_ROWID) + " = " + std::to_string(dataKey) + ";"; - int errCode = SQLiteUtils::GetStatement(dbHandle_, queryAssetSql, selectStmt); - if (errCode != E_OK) { // LCOV_EXCL_BR_LINE - LOGE("Get select asset statement failed, %d.", errCode); - return errCode; - } - errCode = GetAssetOnTableInner(selectStmt, asset); - int ret = E_OK; - SQLiteUtils::ResetStatement(selectStmt, true, ret); - return errCode != E_OK ? errCode : ret; -} - -int SQLiteSingleVerRelationalStorageExecutor::GetAssetsOnTableInner(sqlite3_stmt *&stmt, Assets &assets) -{ - int errCode = SQLiteUtils::StepWithRetry(stmt); - if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { // LCOV_EXCL_BR_LINE - std::vector blobValue; - errCode = SQLiteUtils::GetColumnBlobValue(stmt, 0, blobValue); - if (errCode != E_OK) { // LCOV_EXCL_BR_LINE - LOGE("[RDBExecutor][GetAssetsOnTableInner] Get column blob value failed, %d.", errCode); - return errCode; - } - errCode = RuntimeContext::GetInstance()->BlobToAssets(blobValue, assets); - if (errCode != E_OK) { // LCOV_EXCL_BR_LINE - LOGE("[RDBExecutor] Transfer blob to assets failed, %d.", errCode); - } - } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { - errCode = E_OK; - } else { - LOGE("[RDBExecutor] Step failed when get assets from table, errCode = %d.", errCode); - } - return errCode; -} - -int SQLiteSingleVerRelationalStorageExecutor::GetAssetsOnTable(const std::string &tableName, - const std::string &fieldName, const int64_t dataKey, Assets &assets) -{ - sqlite3_stmt *selectStmt = nullptr; - std::string queryAssetsSql = "SELECT " + fieldName + " FROM '" + tableName + - "' WHERE " + std::string(DBConstant::SQLITE_INNER_ROWID) + " = " + std::to_string(dataKey) + ";"; - int errCode = SQLiteUtils::GetStatement(dbHandle_, queryAssetsSql, selectStmt); - if (errCode != E_OK) { // LCOV_EXCL_BR_LINE - LOGE("Get select assets statement failed, %d.", errCode); - return errCode; - } - errCode = GetAssetsOnTableInner(selectStmt, assets); - int ret = E_OK; - SQLiteUtils::ResetStatement(selectStmt, true, ret); - return errCode != E_OK ? errCode : ret; -} - int SQLiteSingleVerRelationalStorageExecutor::BindAssetFiledToBlobStatement(const TableSchema &tableSchema, const std::vector &assetOfOneRecord, const std::vector &assetsOfOneRecord, sqlite3_stmt *&stmt) { @@ -1733,13 +1671,13 @@ int64_t SQLiteSingleVerRelationalStorageExecutor::GetDataFlag() { if (putDataMode_ != PutDataMode::USER) { return static_cast(LogInfoFlag::FLAG_CLOUD) | - static_cast(LogInfoFlag::FLAG_DEVICE_CLOUD_CONSISTENCY); + static_cast(LogInfoFlag::FLAG_DEVICE_CLOUD_INCONSISTENCY); } uint32_t flag = static_cast(LogInfoFlag::FLAG_LOCAL); if (markFlagOption_ == MarkFlagOption::SET_WAIT_COMPENSATED_SYNC) { flag |= static_cast(LogInfoFlag::FLAG_WAIT_COMPENSATED_SYNC); } - flag |= static_cast(LogInfoFlag::FLAG_DEVICE_CLOUD_CONSISTENCY); + flag |= static_cast(LogInfoFlag::FLAG_DEVICE_CLOUD_INCONSISTENCY); return static_cast(flag); } @@ -1909,6 +1847,28 @@ int SQLiteSingleVerRelationalStorageExecutor::GetWaitCompensatedSyncDataPk(const return errCode == E_OK ? ret : errCode; } +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);"; + sqlite3_stmt *stmt = nullptr; + int errCode = SQLiteUtils::GetStatement(dbHandle_, sql, stmt); + if (errCode != E_OK || stmt == nullptr) { + LOGE("[RDBExecutor] Get stmt failed when clear unlocking status errCode = %d.", errCode); + return errCode; + } + int ret = E_OK; + errCode = SQLiteUtils::StepWithRetry(stmt); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + errCode = E_OK; + } else { + LOGE("[Storage Execute] Step update record status stmt failed, %d.", errCode); + } + SQLiteUtils::ResetStatement(stmt, true, ret); + return errCode == E_OK ? ret : errCode; +} + int SQLiteSingleVerRelationalStorageExecutor::GetRecordFromStmt(sqlite3_stmt *stmt, const std::vector &fields, int startIndex, VBucket &record) { @@ -1963,82 +1923,5 @@ int SQLiteSingleVerRelationalStorageExecutor::BindShareValueToInsertLogStatement return errCode; } -int SQLiteSingleVerRelationalStorageExecutor::MarkFlagAsConsistent(const std::string &tableName, - const DownloadData &downloadData, const std::set &gidFilters) -{ - if (downloadData.data.size() != downloadData.opType.size()) { - LOGE("The num of data:%zu an opType:%zu is not equal.", downloadData.data.size(), downloadData.opType.size()); - return -E_CLOUD_ERROR; - } - std::string sql = "UPDATE " + DBCommon::GetLogTableName(tableName) + - " 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) { - LOGE("Get mark flag as consistent stmt failed, %d.", errCode); - return errCode; - } - int ret = E_OK; - int index = 0; - for (const auto &data: downloadData.data) { - SQLiteUtils::ResetStatement(stmt, false, ret); - OpType opType = downloadData.opType[index++]; - if (opType == OpType::NOT_HANDLE || opType == OpType::LOCKED_NOT_HANDLE) { - continue; - } - errCode = CloudStorageUtils::BindStepConsistentFlagStmt(stmt, data, gidFilters); - if (errCode != E_OK) { - break; - } - } - SQLiteUtils::ResetStatement(stmt, true, ret); - return errCode == E_OK ? ret : errCode; -} - -int SQLiteSingleVerRelationalStorageExecutor::FillCloudVersionForUpload(const std::string &tableName, - const CloudSyncBatch &batchData) -{ - if (batchData.extend.empty()) { - return E_OK; - } - if (batchData.hashKey.empty() || batchData.extend.size() != batchData.hashKey.size()) { - LOGE("invalid sync data for filling version."); - return -E_INVALID_ARGS; - } - std::string sql = "UPDATE '" + DBCommon::GetLogTableName(tableName) + - "' SET version = ? WHERE hash_key = ? "; - sqlite3_stmt *stmt = nullptr; - int errCode = SQLiteUtils::GetStatement(dbHandle_, sql, stmt); - if (errCode != E_OK) { - return errCode; - } - int ret = E_OK; - for (size_t i = 0; i < batchData.extend.size(); ++i) { - errCode = BindUpdateVersionStatement(batchData.extend[i], batchData.hashKey[i], stmt); - if (errCode != E_OK) { - LOGE("bind update version stmt failed."); - SQLiteUtils::ResetStatement(stmt, true, ret); - return errCode; - } - } - SQLiteUtils::ResetStatement(stmt, true, ret); - return ret; -} - -int SQLiteSingleVerRelationalStorageExecutor::QueryCount(const std::string &tableName, int64_t &count) -{ - return SQLiteRelationalUtils::QueryCount(dbHandle_, tableName, count); -} - -int SQLiteSingleVerRelationalStorageExecutor::CheckInventoryData(const std::string &tableName) -{ - int64_t dataCount = 0; - int errCode = SQLiteRelationalUtils::QueryCount(dbHandle_, tableName, dataCount); - if (errCode != E_OK) { - LOGE("Query count failed.", errCode); - return errCode; - } - return dataCount > 0 ? -E_WITH_INVENTORY_DATA : E_OK; -} } // namespace DistributedDB #endif \ No newline at end of file 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 cf8564d4015ca0fb2e578720380ee0becea60fa5..37249195748e469b758f3f60793e03cca2edaaaa 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 @@ -58,7 +58,7 @@ int SqliteCloudKvExecutorUtils::GetCloudData(const CloudSyncConfig &config, cons return errCode; } -Timestamp SqliteCloudKvExecutorUtils::GetMaxTimeStamp(std::vector &dataExtend) +Timestamp SqliteCloudKvExecutorUtils::GetMaxTimeStamp(const std::vector &dataExtend) { Timestamp maxTimeStamp = 0; VBucket lastRecord = dataExtend.back(); @@ -69,7 +69,8 @@ Timestamp SqliteCloudKvExecutorUtils::GetMaxTimeStamp(std::vector &data return maxTimeStamp; } -bool SqliteCloudKvExecutorUtils::UpdateBeginTimeForMemoryDB(SQLiteSingleVerContinueToken &token, CloudSyncData &data) +bool SqliteCloudKvExecutorUtils::UpdateBeginTimeForMemoryDB(SQLiteSingleVerContinueToken &token, + const CloudSyncData &data) { Timestamp maxTimeStamp = 0; switch (data.mode) { @@ -101,8 +102,14 @@ int SqliteCloudKvExecutorUtils::GetCloudDataForSync(const CloudSyncConfig &confi VBucket log; VBucket extraLog; uint32_t preSize = totalSize; - GetCloudLog(statement, log, totalSize); + int64_t revisedTime = 0; + int64_t invalidTime = 0; + GetCloudLog(statement, log, totalSize, revisedTime, invalidTime); GetCloudExtraLog(statement, extraLog); + if (revisedTime != 0) { + Bytes hashKey = std::get(extraLog[CloudDbConstant::HASH_KEY]); + cloudDataResult.revisedData.push_back({hashKey, revisedTime, invalidTime}); + } VBucket data; int64_t flag = 0; @@ -132,13 +139,15 @@ int SqliteCloudKvExecutorUtils::GetCloudDataForSync(const CloudSyncConfig &confi } void SqliteCloudKvExecutorUtils::GetCloudLog(sqlite3_stmt *stmt, VBucket &logInfo, - uint32_t &totalSize) + uint32_t &totalSize, int64_t &revisedTime, int64_t &invalidTime) { int64_t modifyTime = static_cast(sqlite3_column_int64(stmt, CLOUD_QUERY_MODIFY_TIME_INDEX)); uint64_t curTime = 0; if (TimeHelper::GetSysCurrentRawTime(curTime) == E_OK) { if (modifyTime > static_cast(curTime)) { + invalidTime = modifyTime; modifyTime = static_cast(curTime); + revisedTime = modifyTime; } } else { LOGW("[SqliteCloudKvExecutorUtils] get raw sys time failed."); @@ -155,6 +164,14 @@ void SqliteCloudKvExecutorUtils::GetCloudLog(sqlite3_stmt *stmt, VBucket &logInf totalSize += cloudGid.size(); } } + if (revisedTime != 0) { + std::string cloudGid; + if (logInfo.count(CloudDbConstant::GID_FIELD) != 0) { + cloudGid = std::get(logInfo[CloudDbConstant::GID_FIELD]); + } + LOGW("[SqliteCloudKvExecutorUtils] Found invalid mod time: %lld, curTime: %lld, gid: %s", + invalidTime, revisedTime, DBCommon::StringMiddleMasking(cloudGid).c_str()); + } std::string version; SQLiteUtils::GetColumnTextValue(stmt, CLOUD_QUERY_VERSION_INDEX, version); logInfo.insert_or_assign(CloudDbConstant::VERSION_FIELD, version); @@ -228,7 +245,7 @@ int SqliteCloudKvExecutorUtils::GetCloudKvBlobData(const std::string &keyStr, in } std::pair SqliteCloudKvExecutorUtils::GetLogInfo(sqlite3 *db, bool isMemory, - const VBucket &cloudData) + const VBucket &cloudData, const std::string &userId) { std::pair res; int &errCode = res.first; @@ -246,7 +263,7 @@ std::pair SqliteCloudKvExecutorUtils::GetLogInfo(sqlite3 * Bytes hashKey; DBCommon::CalcValueHash(key, hashKey); sqlite3_stmt *stmt = nullptr; - std::tie(errCode, stmt) = GetLogInfoStmt(db, cloudData, !hashKey.empty()); + std::tie(errCode, stmt) = GetLogInfoStmt(db, cloudData, !hashKey.empty(), userId.empty()); if (errCode != E_OK) { LOGE("[SqliteCloudKvExecutorUtils] Get stmt failed %d", errCode); return res; @@ -257,19 +274,23 @@ std::pair SqliteCloudKvExecutorUtils::GetLogInfo(sqlite3 * LOGE("[SqliteCloudKvExecutorUtils] Get gid failed %d", errCode); return res; } - return GetLogInfoInner(stmt, isMemory, gid, hashKey); + return GetLogInfoInner(stmt, isMemory, gid, hashKey, userId); } std::pair SqliteCloudKvExecutorUtils::GetLogInfoStmt(sqlite3 *db, const VBucket &cloudData, - bool existKey) + bool existKey, bool emptyUserId) { std::pair res; auto &[errCode, stmt] = res; - std::string sql = QUERY_CLOUD_SYNC_DATA_LOG; + std::string querySql = QUERY_CLOUD_SYNC_DATA_LOG; + if (!emptyUserId) { + querySql = QUERY_CLOUD_SYNC_DATA_LOG_WITH_USERID; + } + std::string sql = querySql; sql += " WHERE cloud_gid = ?"; if (existKey) { sql += " UNION "; - sql += QUERY_CLOUD_SYNC_DATA_LOG; + sql += querySql; sql += " WHERE sync_data.hash_key = ?"; } errCode = SQLiteUtils::GetStatement(db, sql, stmt); @@ -277,7 +298,7 @@ std::pair SqliteCloudKvExecutorUtils::GetLogInfoStmt(sqlite3 } std::pair SqliteCloudKvExecutorUtils::GetLogInfoInner(sqlite3_stmt *stmt, bool isMemory, - const std::string &gid, const Bytes &key) + const std::string &gid, const Bytes &key, const std::string &userId) { ResFinalizer finalizer([stmt]() { sqlite3_stmt *statement = stmt; @@ -290,13 +311,27 @@ std::pair SqliteCloudKvExecutorUtils::GetLogInfoInner(sqli std::pair res; auto &[errCode, logInfo] = res; int index = 1; + if (!userId.empty()) { + errCode = SQLiteUtils::BindTextToStatement(stmt, index++, userId); + if (errCode != E_OK) { + LOGE("[SqliteCloudKvExecutorUtils] Bind 1st userId failed %d", errCode); + return res; + } + } errCode = SQLiteUtils::BindTextToStatement(stmt, index++, gid); if (errCode != E_OK) { LOGE("[SqliteCloudKvExecutorUtils] Bind gid failed %d", errCode); return res; } if (!key.empty()) { - errCode = SQLiteUtils::BindBlobToStatement(stmt, index, key); + if (!userId.empty()) { + errCode = SQLiteUtils::BindTextToStatement(stmt, index++, userId); + if (errCode != E_OK) { + LOGE("[SqliteCloudKvExecutorUtils] Bind 2nd userId failed %d", errCode); + return res; + } + } + errCode = SQLiteUtils::BindBlobToStatement(stmt, index++, key); if (errCode != E_OK) { LOGE("[SqliteCloudKvExecutorUtils] Bind key failed %d", errCode); return res; @@ -850,6 +885,7 @@ int SqliteCloudKvExecutorUtils::FillCloudGid(const FillGidParam ¶m, const Cl } CloudStorageUtils::GetValueFromVBucket(CloudDbConstant::VERSION_FIELD, data.extend[i], dataItem.version); dataItem.hashKey = data.hashKey[i]; + dataItem.dataDelete = CheckDataDelete(param, data, i); errCode = BindFillGidLogStmt(logStmt, user, dataItem, data.extend[i], type); if (errCode != E_OK) { return errCode; @@ -980,7 +1016,7 @@ std::pair SqliteCloudKvExecutorUtils::GetDataItem(int index, Down } std::pair SqliteCloudKvExecutorUtils::CountCloudDataInner(sqlite3 *db, bool isMemory, - const Timestamp ×tamp, const std::string &user, std::string &sql) + const Timestamp ×tamp, const std::string &user, const std::string &sql) { std::pair res; auto &[errCode, count] = res; @@ -1190,8 +1226,7 @@ void SqliteCloudKvExecutorUtils::InitDefaultCloudVersionRecord(const std::string syncData.insData.hashKey.push_back(bytesHashKey); } -int SqliteCloudKvExecutorUtils::BindVersionStmt(const std::string &device, const std::string &user, - sqlite3_stmt *dataStmt) +int SqliteCloudKvExecutorUtils::BindVersionStmt(const std::string &device, sqlite3_stmt *dataStmt) { std::string hashDevice; int errCode = RuntimeContext::GetInstance()->GetLocalIdentity(hashDevice); @@ -1212,8 +1247,8 @@ int SqliteCloudKvExecutorUtils::BindVersionStmt(const std::string &device, const return errCode; } -int SqliteCloudKvExecutorUtils::GetCloudVersionFromCloud(sqlite3 *db, bool isMemory, const std::string &user, - const std::string &device, std::vector &dataVector) +int SqliteCloudKvExecutorUtils::GetCloudVersionFromCloud(sqlite3 *db, bool isMemory, const std::string &device, + std::vector &dataVector) { sqlite3_stmt *dataStmt = nullptr; bool isDeviceEmpty = device.empty(); @@ -1232,7 +1267,7 @@ int SqliteCloudKvExecutorUtils::GetCloudVersionFromCloud(sqlite3 *db, bool isMem } }); if (!isDeviceEmpty) { - errCode = BindVersionStmt(device, user, dataStmt); + errCode = BindVersionStmt(device, dataStmt); if (errCode != E_OK) { return errCode; } @@ -1303,8 +1338,61 @@ int SqliteCloudKvExecutorUtils::GetWaitCompensatedSyncDataPk(sqlite3 *db, bool i return errCode; } +int SqliteCloudKvExecutorUtils::GetWaitCompensatedSyncDataUserId(sqlite3 *db, bool isMemory, + std::vector &users) +{ + 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); + return errCode; + } + ResFinalizer finalizerData([stmt]() { + int ret = E_OK; + sqlite3_stmt *statement = stmt; + SQLiteUtils::ResetStatement(statement, true, ret); + if (ret != E_OK) { + LOGW("[SqliteCloudKvExecutorUtils] Reset compensate key stmt failed %d", ret); + } + }); + uint32_t totalSize = 0; + do { + errCode = SQLiteUtils::StepWithRetry(stmt, isMemory); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + errCode = E_OK; + break; + } else if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + LOGE("[SqliteCloudKvExecutorUtils] Get key from compensate key stmt failed. %d", errCode); + break; + } + VBucket key; + errCode = GetCloudKvBlobData(CloudDbConstant::CLOUD_KV_FIELD_USERID, CLOUD_QUERY_KEY_INDEX, + stmt, key, totalSize); + if (errCode != E_OK) { + return errCode; + } + users.push_back(key); + } while (errCode == E_OK); + return errCode; +} + +int SqliteCloudKvExecutorUtils::GetWaitCompensatedSyncData(sqlite3 *db, bool isMemory, std::vector &data, + std::vector &users) +{ + int errCode = SqliteCloudKvExecutorUtils::GetWaitCompensatedSyncDataPk(db, isMemory, data); + if (errCode != E_OK) { + LOGE("[GetWaitCompensatedSyncData] Get wait compensate 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); + } + return errCode; +} + int SqliteCloudKvExecutorUtils::QueryCloudGid(sqlite3 *db, bool isMemory, const std::string &user, - QuerySyncObject &querySyncObject, std::vector &cloudGid) + const QuerySyncObject &querySyncObject, std::vector &cloudGid) { int errCode = E_OK; QuerySyncObject query = querySyncObject; @@ -1339,7 +1427,7 @@ int SqliteCloudKvExecutorUtils::BindFillGidLogStmt(sqlite3_stmt *logStmt, const const DataItem &dataItem, const VBucket &uploadExtend, const CloudWaterType &type) { DataItem wItem = dataItem; - if (DBCommon::IsNeedCompensatedForUpload(uploadExtend, type)) { + if (DBCommon::IsNeedCompensatedForUpload(uploadExtend, type) && !wItem.dataDelete) { wItem.cloud_flag |= static_cast(LogInfoFlag::FLAG_WAIT_COMPENSATED_SYNC); } if (DBCommon::IsCloudRecordNotFound(uploadExtend) && @@ -1383,6 +1471,10 @@ bool SqliteCloudKvExecutorUtils::CheckDataChanged(const FillGidParam ¶m, { sqlite3_stmt *checkStmt = nullptr; int errCode = SQLiteUtils::GetStatement(param.first, CHECK_DATA_CHANGED, checkStmt); + if (errCode != E_OK) { + LOGW("[SqliteCloudKvExecutorUtils] check data change get stmt failed %d", errCode); + return true; + } ResFinalizer finalizerData([checkStmt]() { sqlite3_stmt *statement = checkStmt; int ret = E_OK; @@ -1392,22 +1484,66 @@ bool SqliteCloudKvExecutorUtils::CheckDataChanged(const FillGidParam ¶m, } }); int index = 1; - errCode = SQLiteUtils::BindInt64ToStatement(checkStmt, index++, data.timestamp[dataIndex]); + if (data.timestamp.size() > 0) { + errCode = SQLiteUtils::BindInt64ToStatement(checkStmt, index++, data.timestamp[dataIndex]); + if (errCode != E_OK) { + LOGW("[SqliteCloudKvExecutorUtils] bind modify time failed %d when check data changed", errCode); + return true; + } + } + if (data.hashKey.size() > 0) { + errCode = SQLiteUtils::BindBlobToStatement(checkStmt, index++, data.hashKey[dataIndex]); + if (errCode != E_OK) { + LOGW("[SqliteCloudKvExecutorUtils] bind hashKey failed %d when check data changed", errCode); + return true; + } + } + errCode = SQLiteUtils::StepNext(checkStmt); if (errCode != E_OK) { - LOGW("[SqliteCloudKvExecutorUtils] bind modify time failed %d when check data changed", errCode); + LOGW("[SqliteCloudKvExecutorUtils] step failed %d when check data changed", errCode); return true; } - errCode = SQLiteUtils::BindBlobToStatement(checkStmt, index++, data.hashKey[dataIndex]); + return sqlite3_column_int64(checkStmt, 0) == 0; // get index start at 0, get 0 is data changed +} + +bool SqliteCloudKvExecutorUtils::CheckDataDelete(const FillGidParam ¶m, + const CloudSyncBatch &data, size_t dataIndex) +{ + sqlite3_stmt *checkStmt = nullptr; + int errCode = SQLiteUtils::GetStatement(param.first, CHECK_DATA_DELETE, checkStmt); if (errCode != E_OK) { - LOGW("[SqliteCloudKvExecutorUtils] bind hashKey failed %d when check data changed", errCode); + LOGW("[SqliteCloudKvExecutorUtils] check data delete get stmt failed %d", errCode); return true; } + ResFinalizer finalizerData([checkStmt]() { + sqlite3_stmt *statement = checkStmt; + int ret = E_OK; + SQLiteUtils::ResetStatement(statement, true, ret); + if (ret != E_OK) { + LOGW("[SqliteCloudKvExecutorUtils] reset log stmt failed %d when check data delete", ret); + } + }); + int index = 1; + if (data.timestamp.size() > 0) { + errCode = SQLiteUtils::BindInt64ToStatement(checkStmt, index++, data.timestamp[dataIndex]); + if (errCode != E_OK) { + LOGW("[SqliteCloudKvExecutorUtils] bind modify time failed %d when check data delete", errCode); + return true; + } + } + if (data.hashKey.size() > 0) { + errCode = SQLiteUtils::BindBlobToStatement(checkStmt, index++, data.hashKey[dataIndex]); + if (errCode != E_OK) { + LOGW("[SqliteCloudKvExecutorUtils] bind hashKey failed %d when check data delete", errCode); + return true; + } + } errCode = SQLiteUtils::StepNext(checkStmt); if (errCode != E_OK) { - LOGW("[SqliteCloudKvExecutorUtils] step failed %d when check data changed", errCode); + LOGW("[SqliteCloudKvExecutorUtils] step failed %d when check data delete", errCode); return true; } - return sqlite3_column_int64(checkStmt, 0) == 0; // get index start at 0, get 0 is data changed + return sqlite3_column_int64(checkStmt, 0) != 0; // get index start at !0, get 0 means data delete } void SqliteCloudKvExecutorUtils::MarkUploadSuccessInner(const FillGidParam ¶m, @@ -1415,6 +1551,10 @@ void SqliteCloudKvExecutorUtils::MarkUploadSuccessInner(const FillGidParam ¶ { sqlite3_stmt *logStmt = nullptr; int errCode = SQLiteUtils::GetStatement(param.first, MARK_UPLOAD_SUCCESS, logStmt); + if (errCode != E_OK) { + LOGW("[SqliteCloudKvExecutorUtils] mark upload success inner get stmt failed %d", errCode); + return; + } ResFinalizer finalizerData([logStmt]() { sqlite3_stmt *statement = logStmt; int ret = E_OK; @@ -1440,4 +1580,4 @@ void SqliteCloudKvExecutorUtils::MarkUploadSuccessInner(const FillGidParam ¶ return; } } -} \ No newline at end of file +} diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_executor_utils.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_executor_utils.h index 00e7bc7269fe546944425870b04301b3edb2049f..85d1d20a16383949ce13f6482842c1d59b57f799 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_executor_utils.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_cloud_kv_executor_utils.h @@ -33,7 +33,8 @@ public: static int GetCloudData(const CloudSyncConfig &config, const DBParam ¶m, const CloudUploadRecorder &recorder, SQLiteSingleVerContinueToken &token, CloudSyncData &data); - static std::pair GetLogInfo(sqlite3 *db, bool isMemory, const VBucket &cloudData); + static std::pair GetLogInfo(sqlite3 *db, bool isMemory, const VBucket &cloudData, + const std::string &userId); static int PutCloudData(sqlite3 *db, bool isMemory, DownloadData &downloadData); @@ -48,19 +49,25 @@ public: static std::pair GetLocalCloudVersion(sqlite3 *db, bool isMemory, const std::string &user); - static int GetCloudVersionFromCloud(sqlite3 *db, bool isMemory, const std::string &user, - const std::string &device, std::vector &dataVector); + static int GetCloudVersionFromCloud(sqlite3 *db, bool isMemory, const std::string &device, + std::vector &dataVector); static int GetWaitCompensatedSyncDataPk(sqlite3 *db, bool isMemory, std::vector &data); - static int QueryCloudGid(sqlite3 *db, bool isMemory, const std::string &user, QuerySyncObject &querySyncObject, - std::vector &cloudGid); + static int GetWaitCompensatedSyncDataUserId(sqlite3 *db, bool isMemory, std::vector &users); + + static int GetWaitCompensatedSyncData(sqlite3 *db, bool isMemory, std::vector &data, + std::vector &users); + + static int QueryCloudGid(sqlite3 *db, bool isMemory, const std::string &user, + const QuerySyncObject &querySyncObject, std::vector &cloudGid); private: using UploadDetail = std::pair; static int GetCloudDataForSync(const CloudSyncConfig &config, const CloudUploadRecorder &recorder, sqlite3_stmt *statement, CloudSyncData &cloudDataResult, UploadDetail &detail); - static void GetCloudLog(sqlite3_stmt *stmt, VBucket &logInfo, uint32_t &totalSize); + static void GetCloudLog(sqlite3_stmt *stmt, VBucket &logInfo, uint32_t &totalSize, + int64_t &revisedTime, int64_t &invalidTime); static void GetCloudExtraLog(sqlite3_stmt *stmt, VBucket &flags); @@ -69,10 +76,11 @@ private: static int GetCloudKvBlobData(const std::string &keyStr, int index, sqlite3_stmt *stmt, VBucket &data, uint32_t &totalSize); - static std::pair GetLogInfoStmt(sqlite3 *db, const VBucket &cloudData, bool existKey); + static std::pair GetLogInfoStmt(sqlite3 *db, const VBucket &cloudData, bool existKey, + bool emptyUserId); static std::pair GetLogInfoInner(sqlite3_stmt *stmt, bool isMemory, const std::string &gid, - const Bytes &key); + const Bytes &key, const std::string &userId); static DataInfoWithLog FillLogInfoWithStmt(sqlite3_stmt *stmt); @@ -129,7 +137,7 @@ private: static std::pair GetDataItem(int index, DownloadData &downloadData); static std::pair CountCloudDataInner(sqlite3 *db, bool isMemory, const Timestamp ×tamp, - const std::string &user, std::string &sql); + const std::string &user, const std::string &sql); static int FillCloudVersionRecord(sqlite3 *db, OpType opType, const CloudSyncData &data); @@ -140,22 +148,24 @@ private: static void InitDefaultCloudVersionRecord(const std::string &key, const std::string &dev, CloudSyncData &syncData); - static int BindVersionStmt(const std::string &device, const std::string &user, sqlite3_stmt *dataStmt); + static int BindVersionStmt(const std::string &device, sqlite3_stmt *dataStmt); static int GetCloudVersionRecordData(sqlite3_stmt *stmt, VBucket &data, uint32_t &totalSize); - static Timestamp GetMaxTimeStamp(std::vector &dataExtend); + static Timestamp GetMaxTimeStamp(const std::vector &dataExtend); - static bool UpdateBeginTimeForMemoryDB(SQLiteSingleVerContinueToken &token, CloudSyncData &data); + static bool UpdateBeginTimeForMemoryDB(SQLiteSingleVerContinueToken &token, const CloudSyncData &data); static int BindFillGidLogStmt(sqlite3_stmt *logStmt, const std::string &user, const DataItem &dataItem, const VBucket &uploadExtend, const CloudWaterType &type); private: - static void MarkUploadSuccess(const FillGidParam ¶m, const CloudSyncBatch &data, const std::string &user, - size_t dataIndex); + static void MarkUploadSuccess(const FillGidParam ¶m, const CloudSyncBatch &data, + const std::string &user, size_t dataIndex); static bool CheckDataChanged(const FillGidParam ¶m, const CloudSyncBatch &data, size_t dataIndex); + static bool CheckDataDelete(const FillGidParam ¶m, const CloudSyncBatch &data, size_t dataIndex); + static void MarkUploadSuccessInner(const FillGidParam ¶m, const CloudSyncBatch &data, const std::string &user, size_t dataIndex); }; 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 71d27673f78582d3367b49e00525fe9a8a2b0e48..0dae56bd2d8839469339c601f9fea2db83309eb5 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 @@ -19,6 +19,7 @@ #include "db_base64_utils.h" #include "db_common.h" #include "query_utils.h" +#include "res_finalizer.h" #include "runtime_context.h" #include "sqlite_cloud_kv_executor_utils.h" #include "sqlite_single_ver_continue_token.h" @@ -180,8 +181,7 @@ int SqliteCloudKvStore::GetCloudData(const TableSchema &tableSchema, const Query const Timestamp &beginTime, ContinueToken &continueStmtToken, CloudSyncData &cloudDataResult) { SyncTimeRange timeRange; - // memory db use watermark - timeRange.beginTime = GetTransactionDbHandleAndMemoryStatus().second ? beginTime : 0; + timeRange.beginTime = 0; auto token = new (std::nothrow) SQLiteSingleVerContinueToken(timeRange, object); if (token == nullptr) { LOGE("[SqliteCloudKvStore] create token failed"); @@ -245,7 +245,7 @@ int SqliteCloudKvStore::GetInfoByPrimaryKeyOrGid([[gnu::unused]] const std::stri return -E_INTERNAL_ERROR; } int errCode = E_OK; - std::tie(errCode, dataInfoWithLog) = SqliteCloudKvExecutorUtils::GetLogInfo(db, isMemory, vBucket); + std::tie(errCode, dataInfoWithLog) = SqliteCloudKvExecutorUtils::GetLogInfo(db, isMemory, vBucket, user_); return errCode; } @@ -374,6 +374,11 @@ int SqliteCloudKvStore::SetLogTriggerStatus(bool status) return E_OK; } +int SqliteCloudKvStore::SetCursorIncFlag(bool status) +{ + return E_OK; +} + int SqliteCloudKvStore::CheckQueryValid(const QuerySyncObject &query) { return E_OK; @@ -422,7 +427,7 @@ int SqliteCloudKvStore::GetCloudVersion(const std::string &device, std::mapGetDbHandle(db); std::vector dataVector = {}; - errCode = SqliteCloudKvExecutorUtils::GetCloudVersionFromCloud(db, handle->IsMemory(), user_, device, dataVector); + errCode = SqliteCloudKvExecutorUtils::GetCloudVersionFromCloud(db, handle->IsMemory(), device, dataVector); storageHandle_->RecycleStorageExecutor(handle); if (errCode != E_OK) { LOGE("[SqliteCloudKvStore] get cloud version record failed %d", errCode); @@ -540,8 +545,18 @@ void SqliteCloudKvStore::ReleaseUploadRecord(const std::string &tableName, const recorder_.ReleaseUploadRecord(tableName, type, localMark); } -bool SqliteCloudKvStore::IsSameCloudLocalDeviceAndNotLocal(const LogInfo &localInfo, const LogInfo &cloudInfo) +bool SqliteCloudKvStore::IsTagCloudUpdateLocal(const LogInfo &localInfo, const LogInfo &cloudInfo, + SingleVerConflictResolvePolicy policy) { + std::string cloudInfoDev; + auto decodeCloudInfoDev = DBBase64Utils::Decode(cloudInfo.device); + if (!decodeCloudInfoDev.empty()) { + cloudInfoDev = std::string(decodeCloudInfoDev.begin(), decodeCloudInfoDev.end()); + } + if (policy == SingleVerConflictResolvePolicy::DENY_OTHER_DEV_AMEND_CUR_DEV_DATA && + !localInfo.originDev.empty() && localInfo.originDev == cloudInfoDev) { + return true; + } std::string device; if (RuntimeContext::GetInstance()->GetLocalIdentity(device) != E_OK) { LOGE("[SqliteCloudKvStore] GetLocalIdentity device failed."); @@ -549,24 +564,19 @@ bool SqliteCloudKvStore::IsSameCloudLocalDeviceAndNotLocal(const LogInfo &localI } device = DBCommon::TransferHashString(device); std::string localInfoDev = localInfo.device; - std::string cloudInfoDev; - auto decodeCloudInfoDev = DBBase64Utils::Decode(cloudInfo.device); - if (!decodeCloudInfoDev.empty()) { - cloudInfoDev = std::string(decodeCloudInfoDev.begin(), decodeCloudInfoDev.end()); + if (localInfoDev.empty()) { + return false; } bool isLocal = (localInfo.flag & static_cast(LogInfoFlag::FLAG_LOCAL)) == static_cast(LogInfoFlag::FLAG_LOCAL); - bool isLocalDelete = (localInfo.flag & static_cast(LogInfoFlag::FLAG_DELETE)) == - static_cast(LogInfoFlag::FLAG_DELETE); if (cloudInfoDev.empty()) { return !isLocal; - } else if (isLocalDelete) { - return cloudInfoDev != device; } return localInfoDev == cloudInfoDev && localInfoDev != device; } -int SqliteCloudKvStore::GetCompensatedSyncQuery(std::vector &syncQuery) +int SqliteCloudKvStore::GetCompensatedSyncQuery(std::vector &syncQuery, + std::vector &users) { std::shared_ptr cloudSchema; (void)GetCloudDbSchema(cloudSchema); @@ -584,8 +594,9 @@ int SqliteCloudKvStore::GetCompensatedSyncQuery(std::vector &sy (void)transactionHandle_->GetDbHandle(db); for (const auto &table: cloudSchema->tables) { std::vector syncDataPk; - int errCode = SqliteCloudKvExecutorUtils::GetWaitCompensatedSyncDataPk(db, transactionHandle_->IsMemory(), - syncDataPk); + std::vector syncDataUserId; + int errCode = SqliteCloudKvExecutorUtils::GetWaitCompensatedSyncData(db, transactionHandle_->IsMemory(), + syncDataPk, syncDataUserId); if (errCode != E_OK) { LOGW("[SqliteCloudKvStore] Get wait compensated sync date failed, continue! errCode=%d", errCode); continue; @@ -600,7 +611,86 @@ int SqliteCloudKvStore::GetCompensatedSyncQuery(std::vector &sy continue; } syncQuery.push_back(syncObject); + for (auto &oneRow : syncDataUserId) { + std::string user; + errCode = CloudStorageUtils::GetStringFromCloudData(CloudDbConstant::CLOUD_KV_FIELD_USERID, oneRow, user); + if (errCode != E_OK) { + LOGW("[SqliteCloudKvStore] Get compensated sync query happen error, ignore it! errCode = %d", errCode); + continue; + } + users.push_back(user); + } } return Commit(); } + +int SqliteCloudKvStore::ReviseOneLocalModTime(sqlite3_stmt *stmt, const ReviseModTimeInfo &data, bool isMemory) +{ + int errCode = SQLiteUtils::BindInt64ToStatement(stmt, 1, data.curTime); // 1st bind modify time + if (errCode != E_OK) { + LOGE("[SqliteCloudKvStore][ReviseOneLocalModTime] Bind revise modify time failed: %d", errCode); + return errCode; + } + errCode = SQLiteUtils::BindBlobToStatement(stmt, 2, data.hashKey); // 2nd bind hash key + if (errCode != E_OK) { + LOGE("[SqliteCloudKvStore][ReviseOneLocalModTime] Bind hash key failed: %d", errCode); + return errCode; + } + errCode = SQLiteUtils::BindInt64ToStatement(stmt, 3, data.invalidTime); // 3rd bind modify time + if (errCode != E_OK) { + LOGE("[SqliteCloudKvStore][ReviseOneLocalModTime] Bind modify time failed: %d", errCode); + return errCode; + } + errCode = SQLiteUtils::StepWithRetry(stmt, isMemory); + if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + LOGE("[SqliteCloudKvStore][ReviseOneLocalModTime] Revise failed: %d", errCode); + return errCode; + } + return E_OK; +} + +int SqliteCloudKvStore::ReviseLocalModTime(const std::string &tableName, + const std::vector &revisedData) +{ + auto [errCode, handle] = storageHandle_->GetStorageExecutor(true); + if (errCode != E_OK) { + LOGE("[SqliteCloudKvStore][ReviseLocalModTime] Get handle failed: %d", errCode); + return errCode; + } + sqlite3 *db = nullptr; + (void)handle->GetDbHandle(db); + sqlite3_stmt *stmt = nullptr; + std::string sql = "UPDATE " + tableName + " SET modify_time=? WHERE hash_key=? AND modify_time=?"; + errCode = SQLiteUtils::GetStatement(db, sql, stmt); + if (errCode != E_OK) { + LOGE("[SqliteCloudKvStore][ReviseLocalModTime] Get stmt failed: %d", errCode); + storageHandle_->RecycleStorageExecutor(handle); + return errCode; + } + ResFinalizer finalizer([stmt]() { + sqlite3_stmt *statement = stmt; + int ret = E_OK; + SQLiteUtils::ResetStatement(statement, true, ret); + if (ret != E_OK) { + LOGW("[SqliteCloudKvStore][ReviseLocalModTime] Reset stmt failed %d", ret); + } + }); + for (auto &data : revisedData) { + errCode = ReviseOneLocalModTime(stmt, data, handle->IsMemory()); + if (errCode != E_OK) { + LOGE("[SqliteCloudKvStore][ReviseLocalModTime] Revise one record failed %d", errCode); + break; + } + LOGI("[SqliteCloudKvStore][ReviseLocalModTime] Local data mod time revised from %lld to %lld", + data.invalidTime, data.curTime); + int resetCode = E_OK; + SQLiteUtils::ResetStatement(stmt, false, resetCode); + if (resetCode != E_OK) { + LOGE("[SqliteCloudKvStore][ReviseLocalModTime] Reset stmt failed: %d", resetCode); + break; + } + } + storageHandle_->RecycleStorageExecutor(handle); + return errCode; +} } \ No newline at end of file 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 b0b2284974e0801aacae6569324fdda5b5a147b6..9fcbe0e5ecf496cca08e320367baf566b93a2e5c 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 @@ -69,6 +69,7 @@ public: int FillCloudAssetForDownload(const std::string &tableName, VBucket &asset, bool isDownloadSuccess) override; int SetLogTriggerStatus(bool status) override; + int SetCursorIncFlag(bool status) override; int FillCloudLogAndAsset(OpType opType, const CloudSyncData &data, bool fillAsset, bool ignoreEmptyGid) override; @@ -98,10 +99,13 @@ public: void ReleaseUploadRecord(const std::string &tableName, const CloudWaterType &type, Timestamp localMark) override; - bool IsSameCloudLocalDeviceAndNotLocal(const LogInfo &localInfo, const LogInfo &cloudInfo) override; + bool IsTagCloudUpdateLocal(const LogInfo &localInfo, const LogInfo &cloudInfo, + SingleVerConflictResolvePolicy policy) override; - int GetCompensatedSyncQuery(std::vector &syncQuery) override; + int GetCompensatedSyncQuery(std::vector &syncQuery, std::vector &users) override; + int ReviseLocalModTime(const std::string &tableName, + const std::vector &revisedData) override; private: std::pair GetTransactionDbHandleAndMemoryStatus(); @@ -111,6 +115,8 @@ private: bool CheckSchema(std::map schema); + int ReviseOneLocalModTime(sqlite3_stmt *stmt, const ReviseModTimeInfo &data, bool isMemory); + KvStorageHandle *storageHandle_; std::mutex schemaMutex_; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_query_helper.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_query_helper.cpp index 901d28859f6e832ccf503e739a1144fce91ed59b..fbcd9902dba849fcb4cccc5d48a25661981eed60 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_query_helper.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_query_helper.cpp @@ -527,7 +527,7 @@ int SqliteQueryHelper::GetSyncDataQuerySql(std::string &sql, bool hasSubQuery, b isNeedOrderbyKey_ = false; // Need order by timestamp. } - sql = AssembleSqlForSuggestIndex(((isCount == true && hasSubQuery == false) ? + sql = AssembleSqlForSuggestIndex(((isCount && !hasSubQuery) ? PRE_QUERY_COUNT_ITEM_SQL : PRE_QUERY_ITEM_SQL) + tableName_ + " ", FILTER_REMOTE_QUERY); sql = !hasPrefixKey_ ? sql : (sql + " AND (key>=? AND key<=?) "); sql = keys_.empty() ? sql : (sql + " AND " + MapKeysInToSql(keys_.size())); @@ -888,8 +888,7 @@ int SqliteQueryHelper::GetSubscribeCondition(const std::string &accessStr, std:: return errCode; } -int SqliteQueryHelper::GetSubscribeSql(const std::string &subscribeId, TriggerModeEnum mode, - std::string &subscribeCondition) +int SqliteQueryHelper::GetSubscribeSql(TriggerModeEnum mode, std::string &subscribeCondition) { if (!isValid_) { return -E_INVALID_QUERY_FORMAT; @@ -1191,8 +1190,11 @@ void SqliteQueryHelper::AppendCloudQuery(bool isCloudForcePush, bool isCompensat if (isCloudForcePush) { sql += " (b.flag & 0x04 != 0x04)"; } else { - // local data and flag is not upload finished. - sql += "(b.flag & 0x02 = 0x02) AND (b.flag & 0x400 != 0x400)"; + sql += "(b.flag & 0x02 = 0x02)"; + if (!isCompensatedTask) { + // local data and flag is not upload finished. + sql += " AND (b.flag & 0x400 != 0x400)"; + } } sql += " AND (b.flag & 0x08 != 0x08) AND (b.cloud_gid != '' or"; // actually, b.cloud_gid will not be null. sql += " (b.cloud_gid == '' and (b.flag & 0x01 = 0))) "; @@ -1230,8 +1232,8 @@ void SqliteQueryHelper::AppendCloudGidQuery(bool isCloudForcePush, bool isCompen sql += isCloudForcePush ? " (b.flag & 0x04 != 0x04) AND (b.cloud_gid != '') " : " (b.cloud_gid != '') "; } -int SqliteQueryHelper::GetCloudQueryStatement(bool useTimestampAlias, sqlite3 *dbHandle, uint64_t beginTime, - std::string &sql, sqlite3_stmt *&statement) +int SqliteQueryHelper::GetCloudQueryStatement(bool useTimestampAlias, sqlite3 *dbHandle, std::string &sql, + sqlite3_stmt *&statement) { querySql_.clear(); // clear local query sql format int errCode = ToQuerySyncSql(false, useTimestampAlias); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_query_helper.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_query_helper.h index f4100cc917ee5424f8c490270620e59d005ffe8f..3ce89eb6a4349a609e9430064c639d178c64a320 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_query_helper.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_query_helper.h @@ -81,8 +81,7 @@ public: int GetSyncDataCheckSql(std::string &sql); int BindSyncDataCheckStmt(sqlite3_stmt *statement, const Key &hashKey) const; - int GetSubscribeSql(const std::string &subscribeId, TriggerMode::TriggerModeEnum mode, - std::string &subscribeCondition); + int GetSubscribeSql(TriggerMode::TriggerModeEnum mode, std::string &subscribeCondition); static SymbolType GetSymbolType(const QueryObjType &queryObjType); @@ -110,8 +109,7 @@ public: std::string GetGidRelationalCloudQuerySql(const std::vector &fields, bool isCloudForcePush, bool isCompensatedTask); - int GetCloudQueryStatement(bool useTimestampAlias, sqlite3 *dbHandle, uint64_t beginTime, std::string &sql, - sqlite3_stmt *&statement); + int GetCloudQueryStatement(bool useTimestampAlias, sqlite3 *dbHandle, std::string &sql, sqlite3_stmt *&statement); int GetAndBindGidKvCloudQueryStatement(const std::string &user, sqlite3 *dbHandle, sqlite3_stmt *&stmt); 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 2e5f65dde364cc3b40cd0376da8176db95a2ef3b..f34178ee1a207969272893d8ee0aa1a17948d90e 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 @@ -72,6 +72,10 @@ namespace { const constexpr char *DROP_META_TABLE_SQL = "DROP TABLE IF EXISTS main.meta_data;"; const constexpr char *COPY_META_TABLE_SQL = "INSERT OR REPLACE INTO meta.meta_data SELECT * FROM meta_data " "where (SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name='main.meta_data') > 0;"; + + const constexpr char *DROP_META_DB_TABLE_SQL = "DROP TABLE IF EXISTS meta.meta_data;"; + const constexpr char *COPY_META_DB_TABLE_SQL = "INSERT OR REPLACE INTO meta_data SELECT * FROM meta.meta_data " + "where (SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name='meta.meta_data') > 0;"; } SQLiteSingleVerDatabaseUpgrader::SQLiteSingleVerDatabaseUpgrader(sqlite3 *db, @@ -79,7 +83,8 @@ SQLiteSingleVerDatabaseUpgrader::SQLiteSingleVerDatabaseUpgrader(sqlite3 *db, : db_(db), secOpt_(secopt), isMemDB_(isMemDb), - isMetaUpgrade_(false) + isMetaUpgrade_(false), + isMigrateMetaDb_(false) { } @@ -157,27 +162,7 @@ void SQLiteSingleVerDatabaseUpgrader::SetUpgradeSqls(int version, std::vectorSetSecurityOption(dbItemFilePath, secOption); - if (errCode != E_OK) { - LOGE("[SetPathSecOptWithCheck] SetSecurityOption failed."); - return errCode; - } + int errCode = RuntimeContext::GetInstance()->SetSecurityOption(dbItemFilePath, secOption); + if (errCode != E_OK) { + LOGE("[SetPathSecOptWithCheck] SetSecurityOption failed."); + return errCode; } } return E_OK; @@ -441,4 +436,50 @@ void SQLiteSingleVerDatabaseUpgrader::UpgradeTime(TimeOffset offset) LOGE("[SQLiteSinVerUp] Upgrade time failed %d", errCode); } } + +void SQLiteSingleVerDatabaseUpgrader::MigrateMetaFromMetaDB() +{ + bool isCreate = false; + int errCode = SQLiteUtils::CheckTableExists(db_, "meta_data", isCreate, true); + if (errCode != E_OK || !isCreate) { + LOGW("[SQLiteSinVerUp] Check table in meta db errCode %d isCreate %d", errCode, static_cast(isCreate)); + return; + } + errCode = SQLiteUtils::ExecuteRawSQL(db_, COPY_META_DB_TABLE_SQL); + if (errCode != E_OK) { + LOGW("[SQLiteSinVerUp] Copy meta from meta db failed %d", errCode); + return; + } + errCode = SQLiteUtils::ExecuteRawSQL(db_, DROP_META_DB_TABLE_SQL); + if (errCode != E_OK) { + LOGW("[SQLiteSinVerUp] Drop meta in meta db failed %d", errCode); + } else { + LOGI("[SQLiteSinVerUp] Migrate meta from meta db success"); + } +} + +void SQLiteSingleVerDatabaseUpgrader::SetCreateSql(std::vector &sql) const +{ + if ((!isMemDB_) && ParamCheckUtils::IsS3SECEOpt(secOpt_)) { + sql = { + CREATE_LOCAL_TABLE_SQL, + CREATE_SINGLE_META_TABLE_SQL, + CREATE_SYNC_TABLE_SQL, + CREATE_SYNC_TABLE_INDEX_SQL_KEY_INDEX, + CREATE_SYNC_TABLE_INDEX_SQL_TIME_INDEX, + CREATE_SYNC_TABLE_INDEX_SQL_DEV_INDEX, + CREATE_SYNC_TABLE_INDEX_SQL_LOCAL_HASHKEY_INDEX + }; + } else { + sql = { + CREATE_LOCAL_TABLE_SQL, + CREATE_META_TABLE_SQL, + CREATE_SYNC_TABLE_SQL, + CREATE_SYNC_TABLE_INDEX_SQL_KEY_INDEX, + CREATE_SYNC_TABLE_INDEX_SQL_TIME_INDEX, + CREATE_SYNC_TABLE_INDEX_SQL_DEV_INDEX, + CREATE_SYNC_TABLE_INDEX_SQL_LOCAL_HASHKEY_INDEX + }; + } +} } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_database_upgrader.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_database_upgrader.h index 0aac7c9e4de6e51ff08650c8556780acfce71d35..e929839a0622646a36c857a3e11bc8b4bf2eec58 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_database_upgrader.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_database_upgrader.h @@ -47,6 +47,8 @@ protected: void InitTimeForUpgrade(int version); std::pair GetLocalTimeOffset(); void UpgradeTime(TimeOffset offset); + void MigrateMetaFromMetaDB(); + void SetCreateSql(std::vector &sql) const; static int MoveDatabaseToNewDir(const std::string &parentDir, const std::string &upgradeLockFile); static int GetDbVersion(const std::string &dbPath, const OpenDbProperties &option, int &version); @@ -55,6 +57,7 @@ protected: bool isMemDB_; bool isMetaUpgrade_; std::string subDir_; + bool isMigrateMetaDb_; // need recreate meta table and migrate data from meta.meta }; } // namespace DistributedDB #endif // SQLITE_SINGLE_VER_DATABASE_UPGRADER_H 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 45af660e5f82d029bef4bde271fc0e41669114c0..e0b9f1093c253dc68e05ee98cf194587cfd6cfbe 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 @@ -35,6 +35,7 @@ #include "single_ver_utils.h" #include "storage_engine_manager.h" #include "sqlite_single_ver_natural_store_connection.h" +#include "time_helper.h" #include "value_hash_calc.h" namespace DistributedDB { @@ -1366,9 +1367,36 @@ int SQLiteSingleVerNaturalStore::SaveSyncDataToCacheDB(const QueryObject &query, return errCode; } -Timestamp SQLiteSingleVerNaturalStore::GetCurrentTimestamp() +uint64_t SQLiteSingleVerNaturalStore::GetTimestampFromDB() { - return GetTimestamp(); + std::vector key; + std::vector timeOffset; + int64_t localTimeOffset = TimeHelper::BASE_OFFSET; + DBCommon::StringToVector(std::string(DBConstant::LOCALTIME_OFFSET_KEY), key); + int errCode = GetMetaData(key, timeOffset); + if (errCode == E_OK) { + std::string timeOffsetString(timeOffset.begin(), timeOffset.end()); + int64_t result = std::strtoll(timeOffsetString.c_str(), nullptr, DBConstant::STR_TO_LL_BY_DEVALUE); + if (errno != ERANGE && result != LLONG_MIN && result != LLONG_MAX) { + localTimeOffset = result; + } + } else { + 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))) { + return currentSysTime - static_cast(std::abs(localTimeOffset)); + } else if (localTimeOffset >= 0 && (UINT64_MAX - currentSysTime >= static_cast(localTimeOffset))) { + return currentSysTime + static_cast(localTimeOffset); + } else { + LOGW("[GetTimestampFromDB] localTimeOffset plus currentSysTime overflow"); + return currentSysTime; + } +} + +Timestamp SQLiteSingleVerNaturalStore::GetCurrentTimestamp(bool needStartSync) +{ + return GetTimestamp(needStartSync); } int SQLiteSingleVerNaturalStore::InitStorageEngine(const KvDBProperties &kvDBProp, bool isNeedUpdateSecOpt) 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 bfe2f5c40adc39b3caecc8f17621561083de163b..637a735ff712a22ac69ca97c5691521d9fd21186 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 @@ -132,7 +132,7 @@ public: bool CheckCompatible(const std::string &schema, uint8_t type) const override; - Timestamp GetCurrentTimestamp() override; + Timestamp GetCurrentTimestamp(bool needStartSync = true) override; SchemaObject GetSchemaObject() const; @@ -224,6 +224,8 @@ public: int SetCloudSyncConfig(const CloudSyncConfig &config); + uint64_t GetTimestampFromDB() override; + // for test mock const SqliteCloudKvStore* GetCloudKvStore() { 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 6bb4cbc2b018222eeeab31ebbd357a61046a62e7..f4fea96ce796b39c49a9442d5f921ce4ac02112c 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 @@ -803,6 +803,12 @@ int SQLiteSingleVerNaturalStoreConnection::GetDeviceIdentifier(PragmaEntryDevice int SQLiteSingleVerNaturalStoreConnection::PutBatchInner(const IOption &option, const std::vector &entries) { DBDfxAdapter::StartTracing(); + SQLiteSingleVerNaturalStore *naturalStore = GetDB(); + if (naturalStore == nullptr) { + return -E_INVALID_DB; + } + // check whether sync started to get SystemTime + naturalStore->WakeUpSyncer(); std::lock_guard lock(transactionMutex_); bool isAuto = false; int errCode = E_OK; @@ -844,6 +850,12 @@ int SQLiteSingleVerNaturalStoreConnection::PutBatchInner(const IOption &option, int SQLiteSingleVerNaturalStoreConnection::DeleteBatchInner(const IOption &option, const std::vector &keys) { DBDfxAdapter::StartTracing(); + SQLiteSingleVerNaturalStore *naturalStore = GetDB(); + if (naturalStore == nullptr) { + return -E_INVALID_DB; + } + // check whether sync started to get SystemTime + naturalStore->WakeUpSyncer(); std::lock_guard lock(transactionMutex_); bool isAuto = false; int errCode = E_OK; @@ -1395,6 +1407,12 @@ int SQLiteSingleVerNaturalStoreConnection::PublishLocal(const Key &key, bool del SingleVerRecord localRecord; localRecord.key = key; SingleVerRecord syncRecord; + SQLiteSingleVerNaturalStore *naturalStore = GetDB(); + if (naturalStore == nullptr) { + return -E_INVALID_DB; + } + // check whether sync started to get SystemTime + naturalStore->WakeUpSyncer(); { if (IsTransactionStarted()) { return -E_NOT_SUPPORT; @@ -1513,6 +1531,11 @@ int SQLiteSingleVerNaturalStoreConnection::UnpublishToLocal(const Key &key, bool if (IsTransactionStarted()) { return -E_NOT_SUPPORT; } + // check whether sync started to get SystemTime + SQLiteSingleVerNaturalStore *naturalStore = GetDB(); + if (naturalStore == nullptr) { + naturalStore->WakeUpSyncer(); + } std::lock_guard lock(transactionMutex_); @@ -1524,25 +1547,15 @@ int SQLiteSingleVerNaturalStoreConnection::UnpublishToLocal(const Key &key, bool Key hashKey; int innerErrCode = E_OK; SingleVerRecord syncRecord; + std::pair keyPair = { key, hashKey }; SingleVerNaturalStoreCommitNotifyData *localCommittedData = nullptr; - errCode = DBCommon::CalcValueHash(key, hashKey); - if (errCode != E_OK) { - goto END; - } - - errCode = writeHandle_->GetKvDataByHashKey(hashKey, syncRecord); - if (errCode != E_OK) { - goto END; - } - - syncRecord.key = key; - errCode = UnpublishInner(localCommittedData, syncRecord, updateTimestamp, innerErrCode); + errCode = UnpublishInner(keyPair, localCommittedData, syncRecord, updateTimestamp, innerErrCode); if (errCode != E_OK) { goto END; } if (deletePublic && (syncRecord.flag & DataItem::DELETE_FLAG) != DataItem::DELETE_FLAG) { - errCode = SaveEntry({hashKey, {}}, true); + errCode = SaveEntry({keyPair.second, {}}, true); } END: @@ -1562,10 +1575,21 @@ END: return (errCode == E_OK) ? innerErrCode : errCode; } -int SQLiteSingleVerNaturalStoreConnection::UnpublishInner(SingleVerNaturalStoreCommitNotifyData *&committedData, - const SingleVerRecord &syncRecord, bool updateTimestamp, int &innerErrCode) +int SQLiteSingleVerNaturalStoreConnection::UnpublishInner(std::pair &keyPair, + SingleVerNaturalStoreCommitNotifyData *&committedData, SingleVerRecord &syncRecord, bool updateTimestamp, + int &innerErrCode) { int errCode = E_OK; + auto &[key, hashKey] = keyPair; + errCode = DBCommon::CalcValueHash(key, hashKey); + if (errCode != E_OK) { + return errCode; + } + errCode = writeHandle_->GetKvDataByHashKey(hashKey, syncRecord); + if (errCode != E_OK) { + return errCode; + } + syncRecord.key = key; int localOperation = static_cast(LocalOperType::LOCAL_OPR_NONE); SingleVerRecord localRecord; @@ -1948,7 +1972,7 @@ int SQLiteSingleVerNaturalStoreConnection::SetCloudSyncConfig(const CloudSyncCon void SQLiteSingleVerNaturalStoreConnection::RecordTimeIntoDataItem(Timestamp existCreateTime, DataItem &dataItem, SQLiteSingleVerNaturalStore &naturalStore) { - dataItem.timestamp = naturalStore.GetCurrentTimestamp(); + dataItem.timestamp = naturalStore.GetCurrentTimestamp(false); if (currentMaxTimestamp_ > dataItem.timestamp) { dataItem.timestamp = currentMaxTimestamp_; } 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 b67eb9d40a1b191e3a9ff0b033502fd664bce926..1bf4b8286e9a5a46980d9eede025ca032fc9e468 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 @@ -168,8 +168,8 @@ private: int UnpublishToLocal(const Key &key, bool deletePublic, bool updateTimestamp); - int UnpublishInner(SingleVerNaturalStoreCommitNotifyData *&committedData, const SingleVerRecord &syncRecord, - bool updateTimestamp, int &innerErrCode); + int UnpublishInner(std::pair &keyPair, SingleVerNaturalStoreCommitNotifyData *&committedData, + SingleVerRecord &syncRecord, bool updateTimestamp, int &innerErrCode); int UnpublishOper(SingleVerNaturalStoreCommitNotifyData *&committedData, const SingleVerRecord &syncRecord, bool updateTimestamp, int operType); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_engine.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_engine.cpp index f1b65dd5f84e8fddf58ec4d9f27b7ddb52d484a5..d1f7ede43bcab0eb8f0c284c790c8b3a8c76e5e2 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_engine.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_engine.cpp @@ -556,6 +556,13 @@ StorageExecutor *SQLiteSingleVerStorageEngine::NewSQLiteStorageExecutor(sqlite3 return executor; } executor->SetConflictResolvePolicy(option_.conflictReslovePolicy); + + int errCode = executor->CreateCloudLogTable(); + if (errCode != E_OK) { + LOGE("[SQLiteSingleVerStorageEngine] create cloud log table failed, errCode = [%d]", errCode); + delete executor; + executor = nullptr; + } return executor; } @@ -689,17 +696,15 @@ int SQLiteSingleVerStorageEngine::GetCacheDbHandle(sqlite3 *&db) return errCode; } -int SQLiteSingleVerStorageEngine::CheckDatabaseSecOpt(const SecurityOption &secOption) const +void SQLiteSingleVerStorageEngine::CheckDatabaseSecOpt(const SecurityOption &secOption) const { if (!(secOption == option_.securityOpt) && (secOption.securityLabel > option_.securityOpt.securityLabel) && secOption.securityLabel != SecurityLabel::NOT_SET && option_.securityOpt.securityLabel != SecurityLabel::NOT_SET) { - LOGE("[SQLiteSingleVerStorageEngine] SecurityOption mismatch, existed:[%d-%d] vs input:[%d-%d]", + LOGW("[SQLiteSingleVerStorageEngine] SecurityOption mismatch, existed:[%d-%d] vs input:[%d-%d]", secOption.securityLabel, secOption.securityFlag, option_.securityOpt.securityLabel, option_.securityOpt.securityFlag); - return -E_SECURITY_OPTION_CHECK_ERROR; } - return E_OK; } int SQLiteSingleVerStorageEngine::CreateNewDirsAndSetSecOpt() const @@ -719,7 +724,7 @@ void SQLiteSingleVerStorageEngine::ClearCorruptedFlag() isCorrupted_ = false; } -int SQLiteSingleVerStorageEngine::PreCreateExecutor(bool isWrite) +int SQLiteSingleVerStorageEngine::PreCreateExecutor(bool isWrite, SecurityOption &existedSecOpt) { // Assume that create the write executor firstly and the write one we will not be released. // If the write one would be released in the future, should take care the pass through. @@ -738,16 +743,12 @@ int SQLiteSingleVerStorageEngine::PreCreateExecutor(bool isWrite) } // Get the existed database secure option. - SecurityOption existedSecOpt; errCode = GetExistedSecOption(existedSecOpt); if (errCode != E_OK) { return errCode; } - errCode = CheckDatabaseSecOpt(existedSecOpt); - if (errCode != E_OK) { - return errCode; - } + CheckDatabaseSecOpt(existedSecOpt); // Judge whether need update the security option of the engine. // Should update the security in the import or rekey scene(inner) or exist is not set. @@ -773,7 +774,7 @@ int SQLiteSingleVerStorageEngine::PreCreateExecutor(bool isWrite) return E_OK; } -int SQLiteSingleVerStorageEngine::EndCreateExecutor(bool isWrite) +int SQLiteSingleVerStorageEngine::EndCreateExecutor(sqlite3 *db, bool isWrite, bool isDetachMeta) { if (option_.isMemDb || !isWrite) { return E_OK; @@ -797,27 +798,40 @@ int SQLiteSingleVerStorageEngine::EndCreateExecutor(bool isWrite) LOGE("Finish to create the complete database, but delete token fail! errCode = [E_SYSTEM_API_FAIL]"); return -E_SYSTEM_API_FAIL; } + if (isDetachMeta) { + errCode = SQLiteUtils::ExecuteRawSQL(db, "DETACH 'meta'"); + if (errCode != E_OK) { + LOGE("Detach meta db failed %d", errCode); + } else { + LOGI("Detach meta db success"); + } + } return errCode; } -int SQLiteSingleVerStorageEngine::TryAttachMetaDb(sqlite3 *&dbHandle, bool &isAttachMeta) +int SQLiteSingleVerStorageEngine::TryAttachMetaDb(const SecurityOption &existedSecOpt, sqlite3 *&dbHandle, + bool &isAttachMeta, bool &isNeedDetachMeta) { + bool isCurrentSESECE = ParamCheckUtils::IsS3SECEOpt(existedSecOpt); + bool isOpenSESECE = ParamCheckUtils::IsS3SECEOpt(option_.securityOpt); // attach or not depend on its true secOpt, but it's not permit while option_.secOpt different from true secOpt - if ((!option_.isMemDb) && (ParamCheckUtils::IsS3SECEOpt(option_.securityOpt))) { + if ((!option_.isMemDb) && (isOpenSESECE || (isNeedUpdateSecOpt_ && isCurrentSESECE))) { int errCode = AttachMetaDatabase(dbHandle, option_); if (errCode != E_OK) { (void)sqlite3_close_v2(dbHandle); dbHandle = nullptr; return errCode; } - isAttachMeta = true; + isAttachMeta = isOpenSESECE; // only open with S3 SECE need in attach mode + isNeedDetachMeta = !isOpenSESECE && isCurrentSESECE; // NOT S3 SECE no need meta.db } return E_OK; } int SQLiteSingleVerStorageEngine::CreateNewExecutor(bool isWrite, StorageExecutor *&handle) { - int errCode = PreCreateExecutor(isWrite); + SecurityOption existedSecOpt; + int errCode = PreCreateExecutor(isWrite, existedSecOpt); if (errCode != E_OK) { return errCode; } @@ -829,7 +843,8 @@ int SQLiteSingleVerStorageEngine::CreateNewExecutor(bool isWrite, StorageExecuto } bool isAttachMeta = false; - errCode = TryAttachMetaDb(dbHandle, isAttachMeta); + bool isDetachMeta = false; + errCode = TryAttachMetaDb(existedSecOpt, dbHandle, isAttachMeta, isDetachMeta); if (errCode != E_OK) { return errCode; } @@ -842,7 +857,7 @@ int SQLiteSingleVerStorageEngine::CreateNewExecutor(bool isWrite, StorageExecuto return errCode; } - errCode = EndCreateExecutor(isWrite); + errCode = EndCreateExecutor(dbHandle, isWrite, isDetachMeta); if (errCode != E_OK) { LOGE("After create executor, set security option incomplete!"); (void)sqlite3_close_v2(dbHandle); @@ -867,8 +882,6 @@ int SQLiteSingleVerStorageEngine::CreateNewExecutor(bool isWrite, StorageExecuto int SQLiteSingleVerStorageEngine::Upgrade(sqlite3 *db) { if (isUpdated_ || GetEngineState() == EngineState::CACHEDB) { - LOGI("Storage engine [%.6s] is in cache status or has been upgraded[%d]!", - DBCommon::TransferStringToHex(identifier_).c_str(), isUpdated_); return E_OK; } @@ -1069,8 +1082,8 @@ void SQLiteSingleVerStorageEngine::CommitNotifyForMigrateCache(NotifyMigrateSync return; } } - if (entry.key.size() > DBConstant::MAX_KEY_SIZE || entry.value.size() > - DBConstant::MAX_VALUE_SIZE) { // LCOV_EXCL_BR_LINE + if (entry.key.size() > DBConstant::MAX_KEY_SIZE || + entry.value.size() > DBConstant::MAX_VALUE_SIZE) { // LCOV_EXCL_BR_LINE iter++; continue; } @@ -1103,11 +1116,7 @@ bool SQLiteSingleVerStorageEngine::IsUseExistedSecOption(const SecurityOption &e if (isNeedUpdateSecOpt_) { return false; } - if (existedSecOpt.securityLabel != openSecOpt.securityLabel && - existedSecOpt.securityLabel == SecurityLabel::NOT_SET) { - return false; - } - if (existedSecOpt.securityLabel < openSecOpt.securityLabel) { + if (existedSecOpt.securityLabel != openSecOpt.securityLabel) { return false; } return true; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_engine.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_engine.h index fa9ce3341f95d671185749537dff1f96cf598f6e..ef7d66ef07edc7641c9c2cb73f09dace35d34556 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_engine.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_engine.h @@ -73,8 +73,8 @@ protected: private: // For executor. - int PreCreateExecutor(bool isWrite); - int EndCreateExecutor(bool isWrite); + int PreCreateExecutor(bool isWrite, SecurityOption &existedSecOpt); + int EndCreateExecutor(sqlite3 *db, bool isWrite, bool isDetachMeta); int ReInit() override; int ReleaseExecutor(SQLiteSingleVerStorageExecutor *&handle); int ReleaseHandleTransiently(SQLiteSingleVerStorageExecutor *&handle, uint64_t idleTime, @@ -103,11 +103,12 @@ private: int AttachMainDbAndCacheDb(SQLiteSingleVerStorageExecutor *handle, EngineState stateBeforeMigrate); int AttachMainDbAndCacheDb(sqlite3 *dbHandle, EngineState stateBeforeMigrate) const; void RegisterFunctionIfNeed(sqlite3 *dbHandle) const; - int TryAttachMetaDb(sqlite3 *&dbHandle, bool &isAttachMeta); + int TryAttachMetaDb(const SecurityOption &existedSecOpt, sqlite3 *&dbHandle, bool &isAttachMeta, + bool &isNeedDetachMeta); // For secOpt. int CreateNewDirsAndSetSecOpt() const; - int CheckDatabaseSecOpt(const SecurityOption &secOption) const; + void CheckDatabaseSecOpt(const SecurityOption &secOption) const; int GetExistedSecOption(SecurityOption &secOption) const; void ClearCorruptedFlag() 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 1e567ce327b4597471f839136046bb7557ec800a..09d4c05e4675bde4a476c5f213b355cdfa92983d 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 @@ -1241,7 +1241,7 @@ DataOperStatus SQLiteSingleVerStorageExecutor::JudgeSyncSaveType(DataItem &dataI std::string deviceName = DBCommon::TransferHashString(devName); if (itemGet.writeTimestamp >= dataItem.writeTimestamp) { // for multi user mode, no permit to forcewrite - if ((!deviceName.empty()) && (itemGet.dev == deviceName) && isPermitForceWrite) { + if ((!deviceName.empty()) && IsFromDataOwner(itemGet, deviceName) && isPermitForceWrite) { LOGI("Force overwrite the data:%" PRIu64 " vs %" PRIu64, itemGet.writeTimestamp, dataItem.writeTimestamp); status.isDefeated = false; @@ -2220,6 +2220,29 @@ void SQLiteSingleVerStorageExecutor::CalHashKey(sqlite3_context *ctx, int argc, sqlite3_result_blob(ctx, hashKey.data(), static_cast(hashKey.size()), SQLITE_TRANSIENT); } +bool SQLiteSingleVerStorageExecutor::IsPrintTimestamp() +{ + // Print only maxLogTimesPerSecond times a second. + Timestamp curTime = TimeHelper::GetSysCurrentTime(); + if (curTime - startTime_ > printIntervalSeconds) { + logCount_ = 0; + startTime_ = curTime; + if (droppedCount_ > 0) { + LOGI("Dropped number of timestamp log:%" PRIu64, droppedCount_); + } + droppedCount_ = 0; + } else { + logCount_++; + } + + if (logCount_ < maxLogTimesPerSecond) { + return true; + } else { + droppedCount_++; + return false; + } +} + int SQLiteSingleVerStorageExecutor::BindSyncDataTime(sqlite3_stmt *statement, const DataItem &dataItem, bool isUpdate) { int errCode = SQLiteUtils::BindInt64ToStatement(statement, BIND_SYNC_STAMP_INDEX, dataItem.timestamp); @@ -2249,8 +2272,11 @@ int SQLiteSingleVerStorageExecutor::BindSyncDataTime(sqlite3_stmt *statement, co return errCode; } - LOGI("Write timestamp:%" PRIu64 " timestamp:%" PRIu64 ", flag:%" PRIu64 " modifyTime:%" PRIu64 " createTime:%" - PRIu64, dataItem.writeTimestamp, dataItem.timestamp, dataItem.flag, dataItem.modifyTime, dataItem.createTime); + if (IsPrintTimestamp()) { + LOGI("Write timestamp:%" PRIu64 " timestamp:%" PRIu64 ", flag:%" PRIu64 " modifyTime:%" PRIu64 " createTime:%" + PRIu64, dataItem.writeTimestamp, dataItem.timestamp, dataItem.flag, dataItem.modifyTime, + dataItem.createTime); + } return errCode; } 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 139b4a558821e09995885c57e7f3e4a46c605228..bec89c958efa6daba2d4bf57864478fa12398e70 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 @@ -22,6 +22,7 @@ #include "sqlite_utils.h" #include "sqlite_storage_executor.h" #include "single_ver_natural_store_commit_notify_data.h" +#include "time_helper.h" namespace DistributedDB { class SQLiteSingleVerStorageExecutor : public SQLiteStorageExecutor { @@ -226,7 +227,7 @@ private: void PutIntoCommittedData(const DataItem &itemPut, const DataItem &itemGet, const DataOperStatus &status, SingleVerNaturalStoreCommitNotifyData *committedData); - static int BindSavedSyncData(sqlite3_stmt *statement, const DataItem &dataItem, const Key &hashKey, + int BindSavedSyncData(sqlite3_stmt *statement, const DataItem &dataItem, const Key &hashKey, const SyncDataDevices &devices, bool isUpdate); static int BindDevForSavedSyncData(sqlite3_stmt *statement, const DataItem &dataItem, const std::string &origDev, @@ -235,7 +236,7 @@ private: static void PutConflictData(const DataItem &itemPut, const DataItem &itemGet, const DeviceInfo &deviceInfo, const DataOperStatus &dataStatus, SingleVerNaturalStoreCommitNotifyData *commitData); - static DataOperStatus JudgeSyncSaveType(DataItem &dataItem, const DataItem &itemGet, + DataOperStatus JudgeSyncSaveType(DataItem &dataItem, const DataItem &itemGet, const std::string &devName, bool isHashKeyExisted, bool isPermitForceWrite = true); static std::string GetOriginDevName(const DataItem &dataItem, const std::string &origDevGet); @@ -360,7 +361,9 @@ private: static void CalHashKey(sqlite3_context *ctx, int argc, sqlite3_value **argv); - static int BindSyncDataTime(sqlite3_stmt *statement, const DataItem &dataItem, bool isUpdate); + bool IsPrintTimestamp(); + + int BindSyncDataTime(sqlite3_stmt *statement, const DataItem &dataItem, bool isUpdate); int CloudExcuteRemoveOrUpdate(const std::string &sql, const std::string &deviceName, const std::string &user, bool isUserBlobType = false); @@ -377,6 +380,8 @@ private: int RemoveDeviceDataWithUserInner(const std::string &deviceName, const std::string &user, ClearMode mode); int RemoveCloudUploadFlag(const std::vector &hashKey); + + bool IsFromDataOwner(const DataItem &itemGet, const std::string &syncDev); sqlite3_stmt *getSyncStatement_; sqlite3_stmt *getResultRowIdStatement_; sqlite3_stmt *getResultEntryStatement_; @@ -399,6 +404,13 @@ private: // maxTimestampInMainDB_ and migrateTimeOffset_ is meaningful. bool isSyncMigrating_; int conflictResolvePolicy_; + + // Record log print count. + static constexpr uint64_t maxLogTimesPerSecond = 100; + static constexpr Timestamp printIntervalSeconds = (1000*TimeHelper::MS_TO_100_NS); + Timestamp startTime_ = 0; + uint64_t logCount_ = 0; + uint64_t droppedCount_ = 0; }; } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor_extend.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor_extend.cpp index ffab813098d9491b9cab974ee245055133105af5..ead11db61a34d62e68840410e8ff612f5b3f6376 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor_extend.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor_extend.cpp @@ -147,6 +147,11 @@ int SQLiteSingleVerStorageExecutor::RemoveDeviceDataInner(ClearMode mode) } if (mode == FLAG_AND_DATA) { return CloudExcuteRemoveOrUpdate(REMOVE_CLOUD_ALL_DEV_DATA_SQL, "", ""); + } else if (mode == FLAG_ONLY) { + errCode = CloudExcuteRemoveOrUpdate(REMOVE_CLOUD_ALL_DEV_DATA_VERSION_SQL, "", ""); + if (errCode != E_OK) { + return errCode; + } } return CloudExcuteRemoveOrUpdate(UPDATE_CLOUD_ALL_DEV_DATA_SQL, "", ""); } @@ -247,7 +252,7 @@ int SQLiteSingleVerStorageExecutor::RemoveDeviceData(const std::string &deviceNa { if (mode == ClearMode::DEFAULT) { return CheckCorruptedStatus(deviceName.empty() ? - RemoveDeviceDataInner(deviceName, mode) : RemoveDeviceDataInner(mode)); + RemoveDeviceDataInner(mode) : RemoveDeviceDataInner(deviceName, mode)); } int errCode = E_OK; bool isDataExist = false; @@ -393,8 +398,7 @@ int SQLiteSingleVerStorageExecutor::RemoveCloudUploadFlag(const std::vector(LogInfoFlag::FLAG_UPLOAD_FINISHED)) + ") WHERE hash_key=?"; + std::string removeSql = "UPDATE " + tableName + " SET cloud_flag=0 WHERE hash_key=?"; sqlite3_stmt *stmt = nullptr; errCode = SQLiteUtils::GetStatement(dbHandle_, removeSql, stmt); if (errCode != E_OK) { @@ -417,4 +421,10 @@ int SQLiteSingleVerStorageExecutor::RemoveCloudUploadFlag(const std::vector(mode), errCode); 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 de8da22e611583d61946b4a4a6d8c37567cb2cae..1de98517de541a98777baa1f3fd099c3ee5c29e8 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 @@ -40,7 +40,6 @@ namespace DistributedDB { std::mutex SQLiteUtils::logMutex_; std::string SQLiteUtils::lastErrorMsg_; namespace { - const int BUSY_TIMEOUT_MS = 3000; // 3000ms for sqlite busy timeout. const int BUSY_SLEEP_TIME = 50; // sleep for 50us const int NO_SIZE_LIMIT = -1; const int MAX_STEP_TIMES = 8000; @@ -63,23 +62,18 @@ namespace { const std::string ROLLBACK_SQL = "ROLLBACK TRANSACTION"; const std::string DEFAULT_ATTACH_CIPHER = "PRAGMA cipher_default_attach_cipher="; const std::string DEFAULT_ATTACH_KDF_ITER = "PRAGMA cipher_default_attach_kdf_iter=5000"; - const std::string SHA1_ALGO_SQL = "PRAGMA codec_hmac_algo=SHA1;"; const std::string SHA256_ALGO_SQL = "PRAGMA codec_hmac_algo=SHA256;"; const std::string SHA256_ALGO_REKEY_SQL = "PRAGMA codec_rekey_hmac_algo=SHA256;"; const std::string SHA1_ALGO_ATTACH_SQL = "PRAGMA cipher_default_attach_hmac_algo=SHA1;"; const std::string SHA256_ALGO_ATTACH_SQL = "PRAGMA cipher_default_attach_hmac_algo=SHA256;"; const std::string EXPORT_BACKUP_SQL = "SELECT export_database('backup');"; - const std::string CIPHER_CONFIG_SQL = "PRAGMA codec_cipher="; - const std::string KDF_ITER_CONFIG_SQL = "PRAGMA codec_kdf_iter="; const std::string BACK_CIPHER_CONFIG_SQL = "PRAGMA backup.codec_cipher="; const std::string BACK_KDF_ITER_CONFIG_SQL = "PRAGMA backup.codec_kdf_iter=5000;"; const std::string META_CIPHER_CONFIG_SQL = "PRAGMA meta.codec_cipher="; const std::string META_KDF_ITER_CONFIG_SQL = "PRAGMA meta.codec_kdf_iter=5000;"; - const std::string DETACH_BACKUP_SQL = "DETACH 'backup'"; - const std::string UPDATE_META_SQL = "INSERT OR REPLACE INTO meta_data VALUES (?, ?);"; - const std::string CHECK_TABLE_CREATED = "SELECT EXISTS(SELECT 1 FROM sqlite_master WHERE " \ - "type='table' AND (tbl_name=? COLLATE NOCASE));"; + const constexpr char *DETACH_BACKUP_SQL = "DETACH 'backup'"; + const constexpr char *UPDATE_META_SQL = "INSERT OR REPLACE INTO meta_data VALUES (?, ?);"; bool g_configLog = false; std::mutex g_serverChangedDataMutex; @@ -114,12 +108,20 @@ std::string SQLiteUtils::Anonymous(const std::string &name) return (name.substr(0, HEAD_SIZE) + REPLACE_CHAIN + name.substr(name.length() - END_SIZE, END_SIZE)); } +bool IsNeedSkipLog(const unsigned int errType, const char *msg) +{ + return errType == SQLITE_ERROR && strstr(msg, "\"?\": syntax error in \"PRAGMA user_ve") != nullptr; +} + void SQLiteUtils::SqliteLogCallback(void *data, int err, const char *msg) { bool verboseLog = (data != nullptr); auto errType = static_cast(err); std::string logMsg = msg == nullptr ? "NULL" : msg; errType &= 0xFF; + if (IsNeedSkipLog(errType, logMsg.c_str())) { + return; + } if (errType == 0 || errType == SQLITE_CONSTRAINT || errType == SQLITE_SCHEMA || errType == SQLITE_NOTICE || err == SQLITE_WARNING_AUTOINDEX) { if (verboseLog) { @@ -187,6 +189,7 @@ int SQLiteUtils::OpenDatabase(const OpenDbProperties &properties, sqlite3 *&db, std::lock_guard lock(logMutex_); if (!g_configLog) { sqlite3_config(SQLITE_CONFIG_LOG, &SqliteLogCallback, &properties.createIfNecessary); + sqlite3_config(SQLITE_CONFIG_LOOKASIDE, 0, 0); g_configLog = true; } } @@ -1792,647 +1795,4 @@ int SQLiteUtils::RegisterMetaDataUpdateFunction(sqlite3 *db) } return SQLiteUtils::MapSQLiteErrno(errCode); } - -struct ValueParseCache { - ValueObject valueParsed; - std::vector valueOriginal; -}; - -namespace { -inline bool IsDeleteRecord(const uint8_t *valueBlob, int valueBlobLen) -{ - return (valueBlob == nullptr) || (valueBlobLen <= 0); // In fact, sqlite guarantee valueBlobLen not negative -} - -// Use the same cache id as sqlite use for json_extract which is substituted by our json_extract_by_path -// A negative cache-id enables sharing of cache between different operation during the same statement -constexpr int VALUE_CACHE_ID = -429938; - -void ValueParseCacheFree(ValueParseCache *inCache) -{ - delete inCache; - inCache = nullptr; -} - -// We don't use cache array since we only cache value column of sqlite table, see sqlite implementation for compare. -const ValueObject *ParseValueThenCacheOrGetFromCache(sqlite3_context *ctx, const uint8_t *valueBlob, - uint32_t valueBlobLen, uint32_t offset) -{ - // Note: All parameter had already been check inside JsonExtractByPath, only called by JsonExtractByPath - auto cached = static_cast(sqlite3_get_auxdata(ctx, VALUE_CACHE_ID)); - if (cached != nullptr) { // A previous cache exist - if (cached->valueOriginal.size() == valueBlobLen) { - if (std::memcmp(cached->valueOriginal.data(), valueBlob, valueBlobLen) == 0) { - // Cache match - return &(cached->valueParsed); - } - } - } - // No cache or cache mismatch - auto newCache = new (std::nothrow) ValueParseCache; - if (newCache == nullptr) { - sqlite3_result_error(ctx, "[ParseValueCache] OOM.", USING_STR_LEN); - LOGE("[ParseValueCache] OOM."); - return nullptr; - } - int errCode = newCache->valueParsed.Parse(valueBlob, valueBlob + valueBlobLen, offset); - if (errCode != E_OK) { - sqlite3_result_error(ctx, "[ParseValueCache] Parse fail.", USING_STR_LEN); - LOGE("[ParseValueCache] Parse fail, errCode=%d.", errCode); - delete newCache; - newCache = nullptr; - return nullptr; - } - newCache->valueOriginal.assign(valueBlob, valueBlob + valueBlobLen); - sqlite3_set_auxdata(ctx, VALUE_CACHE_ID, newCache, reinterpret_cast(ValueParseCacheFree)); - // If sqlite3_set_auxdata fail, it will immediately call ValueParseCacheFree to delete newCache; - // Next time sqlite3_set_auxdata will call ValueParseCacheFree to delete newCache of this time; - // At the end, newCache will be eventually deleted when call sqlite3_reset or sqlite3_finalize; - // Since sqlite3_set_auxdata may fail, we have to call sqlite3_get_auxdata other than return newCache directly. - auto cacheInAuxdata = static_cast(sqlite3_get_auxdata(ctx, VALUE_CACHE_ID)); - if (cacheInAuxdata == nullptr) { - return nullptr; - } - return &(cacheInAuxdata->valueParsed); -} -} - -void SQLiteUtils::JsonExtractByPath(sqlite3_context *ctx, int argc, sqlite3_value **argv) -{ - if (ctx == nullptr || argc != 3 || argv == nullptr) { // 3 parameters, which are value, path and offset - LOGE("[JsonExtract] Invalid parameter, argc=%d.", argc); - return; - } - auto valueBlob = static_cast(sqlite3_value_blob(argv[0])); - int valueBlobLen = sqlite3_value_bytes(argv[0]); - if (IsDeleteRecord(valueBlob, valueBlobLen)) { - // Currently delete records are filtered out of query and create-index sql, so not allowed here. - sqlite3_result_error(ctx, "[JsonExtract] Delete record not allowed.", USING_STR_LEN); - LOGE("[JsonExtract] Delete record not allowed."); - return; - } - auto path = reinterpret_cast(sqlite3_value_text(argv[1])); - int offset = sqlite3_value_int(argv[2]); // index 2 is the third parameter - if ((path == nullptr) || (offset < 0)) { - sqlite3_result_error(ctx, "[JsonExtract] Path nullptr or offset invalid.", USING_STR_LEN); - LOGE("[JsonExtract] Path nullptr or offset=%d invalid.", offset); - return; - } - FieldPath outPath; - int errCode = SchemaUtils::ParseAndCheckFieldPath(path, outPath); - if (errCode != E_OK) { - sqlite3_result_error(ctx, "[JsonExtract] Path illegal.", USING_STR_LEN); - LOGE("[JsonExtract] Path illegal."); - return; - } - // Parameter Check Done Here - const ValueObject *valueObj = ParseValueThenCacheOrGetFromCache(ctx, valueBlob, static_cast(valueBlobLen), - static_cast(offset)); - if (valueObj == nullptr) { - return; // Necessary had been printed in ParseValueThenCacheOrGetFromCache - } - JsonExtractInnerFunc(ctx, *valueObj, outPath); -} - -namespace { -inline bool IsExtractableType(FieldType inType) -{ - return (inType != FieldType::LEAF_FIELD_NULL && inType != FieldType::LEAF_FIELD_ARRAY && - inType != FieldType::LEAF_FIELD_OBJECT && inType != FieldType::INTERNAL_FIELD_OBJECT); -} -} - -void SQLiteUtils::JsonExtractInnerFunc(sqlite3_context *ctx, const ValueObject &inValue, const FieldPath &inPath) -{ - FieldType outType = FieldType::LEAF_FIELD_NULL; // Default type null for invalid-path(path not exist) - int errCode = inValue.GetFieldTypeByFieldPath(inPath, outType); - if (errCode != E_OK && errCode != -E_INVALID_PATH) { - sqlite3_result_error(ctx, "[JsonExtract] GetFieldType fail.", USING_STR_LEN); - LOGE("[JsonExtract] GetFieldType fail, errCode=%d.", errCode); - return; - } - FieldValue outValue; - if (IsExtractableType(outType)) { - errCode = inValue.GetFieldValueByFieldPath(inPath, outValue); - if (errCode != E_OK) { - sqlite3_result_error(ctx, "[JsonExtract] GetFieldValue fail.", USING_STR_LEN); - LOGE("[JsonExtract] GetFieldValue fail, errCode=%d.", errCode); - return; - } - } - // FieldType null, array, object do not have value, all these FieldValue will be regarded as null in JsonReturn. - ExtractReturn(ctx, outType, outValue); -} - -// NOTE!!! This function is performance sensitive !!! Carefully not to allocate memory often!!! -void SQLiteUtils::FlatBufferExtractByPath(sqlite3_context *ctx, int argc, sqlite3_value **argv) -{ - if (ctx == nullptr || argc != 3 || argv == nullptr) { // 3 parameters, which are value, path and offset - LOGE("[FlatBufferExtract] Invalid parameter, argc=%d.", argc); - return; - } - auto schema = static_cast(sqlite3_user_data(ctx)); - if (schema == nullptr || !schema->IsSchemaValid() || - (schema->GetSchemaType() != SchemaType::FLATBUFFER)) { // LCOV_EXCL_BR_LINE - sqlite3_result_error(ctx, "[FlatBufferExtract] No SchemaObject or invalid.", USING_STR_LEN); - LOGE("[FlatBufferExtract] No SchemaObject or invalid."); - return; - } - // Get information from argv - auto valueBlob = static_cast(sqlite3_value_blob(argv[0])); - int valueBlobLen = sqlite3_value_bytes(argv[0]); - if (IsDeleteRecord(valueBlob, valueBlobLen)) { // LCOV_EXCL_BR_LINE - // Currently delete records are filtered out of query and create-index sql, so not allowed here. - sqlite3_result_error(ctx, "[FlatBufferExtract] Delete record not allowed.", USING_STR_LEN); - LOGE("[FlatBufferExtract] Delete record not allowed."); - return; - } - auto path = reinterpret_cast(sqlite3_value_text(argv[1])); - int offset = sqlite3_value_int(argv[2]); // index 2 is the third parameter - if ((path == nullptr) || (offset < 0) || - (static_cast(offset) != schema->GetSkipSize())) { // LCOV_EXCL_BR_LINE - sqlite3_result_error(ctx, "[FlatBufferExtract] Path null or offset invalid.", USING_STR_LEN); - LOGE("[FlatBufferExtract] Path null or offset=%d(skipsize=%u) invalid.", offset, schema->GetSkipSize()); - return; - } - FlatBufferExtractInnerFunc(ctx, *schema, RawValue { valueBlob, valueBlobLen }, path); -} - -namespace { -constexpr uint32_t FLATBUFFER_MAX_CACHE_SIZE = 102400; // 100 KBytes - -void FlatBufferCacheFree(std::vector *inCache) -{ - delete inCache; - inCache = nullptr; -} -} - -void SQLiteUtils::FlatBufferExtractInnerFunc(sqlite3_context *ctx, const SchemaObject &schema, const RawValue &inValue, - RawString inPath) -{ - // All parameter had already been check inside FlatBufferExtractByPath, only called by FlatBufferExtractByPath - if (schema.GetSkipSize() % SchemaConstant::SECURE_BYTE_ALIGN == 0) { // LCOV_EXCL_BR_LINE - TypeValue outExtract; - int errCode = schema.ExtractValue(ValueSource::FROM_DBFILE, inPath, inValue, outExtract, nullptr); - if (errCode != E_OK) { // LCOV_EXCL_BR_LINE - sqlite3_result_error(ctx, "[FlatBufferExtract] ExtractValue fail.", USING_STR_LEN); - LOGE("[FlatBufferExtract] ExtractValue fail, errCode=%d.", errCode); - return; - } - ExtractReturn(ctx, outExtract.first, outExtract.second); - return; - } - // Not byte-align secure, we have to make a cache for copy. Check whether cache had already exist. - auto cached = static_cast *>(sqlite3_get_auxdata(ctx, VALUE_CACHE_ID)); // Share the same id - if (cached == nullptr) { // LCOV_EXCL_BR_LINE - // Make the cache - auto newCache = new (std::nothrow) std::vector; - if (newCache == nullptr) { - sqlite3_result_error(ctx, "[FlatBufferExtract] OOM.", USING_STR_LEN); - LOGE("[FlatBufferExtract] OOM."); - return; - } - newCache->resize(FLATBUFFER_MAX_CACHE_SIZE); - sqlite3_set_auxdata(ctx, VALUE_CACHE_ID, newCache, reinterpret_cast(FlatBufferCacheFree)); - // If sqlite3_set_auxdata fail, it will immediately call FlatBufferCacheFree to delete newCache; - // Next time sqlite3_set_auxdata will call FlatBufferCacheFree to delete newCache of this time; - // At the end, newCache will be eventually deleted when call sqlite3_reset or sqlite3_finalize; - // Since sqlite3_set_auxdata may fail, we have to call sqlite3_get_auxdata other than return newCache directly. - // See sqlite.org for more information. - cached = static_cast *>(sqlite3_get_auxdata(ctx, VALUE_CACHE_ID)); - } - if (cached == nullptr) { // LCOV_EXCL_BR_LINE - LOGW("[FlatBufferExtract] Something wrong with Auxdata, but it is no matter without cache."); - } - TypeValue outExtract; - int errCode = schema.ExtractValue(ValueSource::FROM_DBFILE, inPath, inValue, outExtract, cached); - if (errCode != E_OK) { // LCOV_EXCL_BR_LINE - sqlite3_result_error(ctx, "[FlatBufferExtract] ExtractValue fail.", USING_STR_LEN); - LOGE("[FlatBufferExtract] ExtractValue fail, errCode=%d.", errCode); - return; - } - ExtractReturn(ctx, outExtract.first, outExtract.second); -} - -void SQLiteUtils::ExtractReturn(sqlite3_context *ctx, FieldType type, const FieldValue &value) -{ - if (ctx == nullptr) { - return; - } - switch (type) { - case FieldType::LEAF_FIELD_BOOL: - sqlite3_result_int(ctx, (value.boolValue ? 1 : 0)); - break; - case FieldType::LEAF_FIELD_INTEGER: - sqlite3_result_int(ctx, value.integerValue); - break; - case FieldType::LEAF_FIELD_LONG: - sqlite3_result_int64(ctx, value.longValue); - break; - case FieldType::LEAF_FIELD_DOUBLE: - sqlite3_result_double(ctx, value.doubleValue); - break; - case FieldType::LEAF_FIELD_STRING: - // The SQLITE_TRANSIENT value means that the content will likely change in the near future and - // that SQLite should make its own private copy of the content before returning. - sqlite3_result_text(ctx, value.stringValue.c_str(), -1, SQLITE_TRANSIENT); // -1 mean use the string length - break; - default: - // All other type regard as null - sqlite3_result_null(ctx); - } - return; -} - -static void CalcHashFunc(sqlite3_context *ctx, sqlite3_value **argv) -{ - auto keyBlob = static_cast(sqlite3_value_blob(argv[0])); - if (keyBlob == nullptr) { - sqlite3_result_error(ctx, "Parameters is invalid.", USING_STR_LEN); - LOGE("Parameters is invalid."); - return; - } - int blobLen = sqlite3_value_bytes(argv[0]); - std::vector value(keyBlob, keyBlob + blobLen); - std::vector hashValue; - int errCode = DBCommon::CalcValueHash(value, hashValue); - if (errCode != E_OK) { - sqlite3_result_error(ctx, "Get hash value error.", USING_STR_LEN); - LOGE("Get hash value error."); - return; - } - sqlite3_result_blob(ctx, hashValue.data(), hashValue.size(), SQLITE_TRANSIENT); -} - -void SQLiteUtils::CalcHashKey(sqlite3_context *ctx, int argc, sqlite3_value **argv) -{ - // 1 means that the function only needs one parameter, namely key - if (ctx == nullptr || argc != 1 || argv == nullptr) { - LOGE("Parameter does not meet restrictions."); - return; - } - CalcHashFunc(ctx, argv); -} - -void SQLiteUtils::CalcHash(sqlite3_context *ctx, int argc, sqlite3_value **argv) -{ - if (ctx == nullptr || argc != 2 || argv == nullptr) { // 2 is params count - LOGE("Parameter does not meet restrictions."); - return; - } - CalcHashFunc(ctx, argv); -} - - -int SQLiteUtils::GetDbSize(const std::string &dir, const std::string &dbName, uint64_t &size) -{ - std::string dataDir = dir + "/" + dbName + DBConstant::DB_EXTENSION; - uint64_t localDbSize = 0; - int errCode = OS::CalFileSize(dataDir, localDbSize); - if (errCode != E_OK) { - LOGD("Failed to get the db file size, errCode:%d", errCode); - return errCode; - } - - std::string shmFileName = dataDir + "-shm"; - uint64_t localshmFileSize = 0; - errCode = OS::CalFileSize(shmFileName, localshmFileSize); - if (errCode != E_OK) { - localshmFileSize = 0; - } - - std::string walFileName = dataDir + "-wal"; - uint64_t localWalFileSize = 0; - errCode = OS::CalFileSize(walFileName, localWalFileSize); - if (errCode != E_OK) { - localWalFileSize = 0; - } - - // 64-bit system is Suffice. Computer storage is less than uint64_t max - size += (localDbSize + localshmFileSize + localWalFileSize); - return E_OK; -} - -int SQLiteUtils::SetDataBaseProperty(sqlite3 *db, const OpenDbProperties &properties, bool setWal, - const std::vector &sqls) -{ - // Set the default busy handler to retry automatically before returning SQLITE_BUSY. - int errCode = SetBusyTimeout(db, BUSY_TIMEOUT_MS); - if (errCode != E_OK) { - return errCode; - } - if (!properties.isMemDb) { - errCode = SQLiteUtils::SetKey(db, properties.cipherType, properties.passwd, setWal, - properties.iterTimes); - if (errCode != E_OK) { - LOGD("SQLiteUtils::SetKey fail!!![%d]", errCode); - return errCode; - } - } - - for (const auto &sql : sqls) { - errCode = SQLiteUtils::ExecuteRawSQL(db, sql); - if (errCode != E_OK) { - LOGE("[SQLite] execute sql failed: %d", errCode); - return errCode; - } - } - // Create table if not exist according the sqls. - if (properties.createIfNecessary) { - for (const auto &sql : properties.sqls) { - errCode = SQLiteUtils::ExecuteRawSQL(db, sql); - if (errCode != E_OK) { - LOGE("[SQLite] execute preset sqls failed"); - return errCode; - } - } - } - return E_OK; -} - -#ifndef OMIT_ENCRYPT -int SQLiteUtils::SetCipherSettings(sqlite3 *db, CipherType type, uint32_t iterTimes) -{ - if (db == nullptr) { - return -E_INVALID_DB; - } - std::string cipherName = GetCipherName(type); - if (cipherName.empty()) { - return -E_INVALID_ARGS; - } - std::string cipherConfig = CIPHER_CONFIG_SQL + cipherName + ";"; - int errCode = SQLiteUtils::ExecuteRawSQL(db, cipherConfig); - if (errCode != E_OK) { - LOGE("[SQLiteUtils][SetCipherSettings] config cipher failed:%d", errCode); - return errCode; - } - errCode = SQLiteUtils::ExecuteRawSQL(db, KDF_ITER_CONFIG_SQL + std::to_string(iterTimes)); - if (errCode != E_OK) { - LOGE("[SQLiteUtils][SetCipherSettings] config iter failed:%d", errCode); - } - return errCode; -} - -std::string SQLiteUtils::GetCipherName(CipherType type) -{ - if (type == CipherType::AES_256_GCM || type == CipherType::DEFAULT) { - return "'aes-256-gcm'"; - } - return ""; -} -#endif - -int SQLiteUtils::DropTriggerByName(sqlite3 *db, const std::string &name) -{ - const std::string dropTriggerSql = "DROP TRIGGER " + name + ";"; - int errCode = SQLiteUtils::ExecuteRawSQL(db, dropTriggerSql); - if (errCode != E_OK) { - LOGE("Remove trigger failed. %d", errCode); - } - return errCode; -} - -int SQLiteUtils::ExpandedSql(sqlite3_stmt *stmt, std::string &basicString) -{ - if (stmt == nullptr) { - return -E_INVALID_ARGS; - } - char *eSql = sqlite3_expanded_sql(stmt); - if (eSql == nullptr) { - LOGE("expand statement to sql failed."); - return -E_INVALID_DATA; - } - basicString = std::string(eSql); - sqlite3_free(eSql); - return E_OK; -} - -void SQLiteUtils::ExecuteCheckPoint(sqlite3 *db) -{ - if (db == nullptr) { - return; - } - - int chkResult = sqlite3_wal_checkpoint_v2(db, nullptr, SQLITE_CHECKPOINT_TRUNCATE, nullptr, nullptr); - LOGI("SQLite checkpoint result:%d", chkResult); -} - -int SQLiteUtils::CheckTableEmpty(sqlite3 *db, const std::string &tableName, bool &isEmpty) -{ - if (db == nullptr) { - return -E_INVALID_ARGS; - } - - std::string cntSql = "SELECT min(rowid) FROM '" + tableName + "';"; - sqlite3_stmt *stmt = nullptr; - int errCode = SQLiteUtils::GetStatement(db, cntSql, stmt); - if (errCode != E_OK) { - return errCode; - } - - errCode = SQLiteUtils::StepWithRetry(stmt, false); - if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { - isEmpty = (sqlite3_column_type(stmt, 0) == SQLITE_NULL); - errCode = E_OK; - } - - SQLiteUtils::ResetStatement(stmt, true, errCode); - return SQLiteUtils::MapSQLiteErrno(errCode); -} - -int SQLiteUtils::SetPersistWalMode(sqlite3 *db) -{ - if (db == nullptr) { - return -E_INVALID_ARGS; - } - int opCode = 1; - int errCode = sqlite3_file_control(db, "main", SQLITE_FCNTL_PERSIST_WAL, &opCode); - if (errCode != SQLITE_OK) { - LOGE("Set persist wal mode failed. %d", errCode); - } - return SQLiteUtils::MapSQLiteErrno(errCode); -} - -int64_t SQLiteUtils::GetLastRowId(sqlite3 *db) -{ - if (db == nullptr) { - return -1; - } - return sqlite3_last_insert_rowid(db); -} - -std::string SQLiteUtils::GetLastErrorMsg() -{ - std::lock_guard autoLock(logMutex_); - return lastErrorMsg_; -} - -int SQLiteUtils::SetAuthorizer(sqlite3 *db, - int (*xAuth)(void*, int, const char*, const char*, const char*, const char*)) -{ - return SQLiteUtils::MapSQLiteErrno(sqlite3_set_authorizer(db, xAuth, nullptr)); -} - -void SQLiteUtils::GetSelectCols(sqlite3_stmt *stmt, std::vector &colNames) -{ - colNames.clear(); - for (int i = 0; i < sqlite3_column_count(stmt); ++i) { - const char *name = sqlite3_column_name(stmt, i); - colNames.emplace_back(name == nullptr ? std::string() : std::string(name)); - } -} - -int SQLiteUtils::SetKeyInner(sqlite3 *db, CipherType type, const CipherPassword &passwd, uint32_t iterTimes) -{ -#ifndef OMIT_ENCRYPT - int errCode = sqlite3_key(db, static_cast(passwd.GetData()), static_cast(passwd.GetSize())); - if (errCode != SQLITE_OK) { - LOGE("[SQLiteUtils][SetKeyInner] config key failed:(%d)", errCode); - return SQLiteUtils::MapSQLiteErrno(errCode); - } - - errCode = SQLiteUtils::SetCipherSettings(db, type, iterTimes); - if (errCode != E_OK) { - LOGE("[SQLiteUtils][SetKeyInner] set cipher settings failed:%d", errCode); - } - return errCode; -#else - return -E_NOT_SUPPORT; -#endif -} - -int SQLiteUtils::BindDataValueByType(sqlite3_stmt *statement, const std::optional &data, int cid) -{ - int errCode = E_OK; - StorageType type = data.value_or(DataValue()).GetType(); - switch (type) { - case StorageType::STORAGE_TYPE_INTEGER: { - int64_t intData = 0; - (void)data.value().GetInt64(intData); - errCode = SQLiteUtils::MapSQLiteErrno(sqlite3_bind_int64(statement, cid, intData)); - break; - } - - case StorageType::STORAGE_TYPE_REAL: { - double doubleData = 0; - (void)data.value().GetDouble(doubleData); - errCode = SQLiteUtils::MapSQLiteErrno(sqlite3_bind_double(statement, cid, doubleData)); - break; - } - - case StorageType::STORAGE_TYPE_TEXT: { - std::string strData; - (void)data.value().GetText(strData); - errCode = SQLiteUtils::BindTextToStatement(statement, cid, strData); - break; - } - - case StorageType::STORAGE_TYPE_BLOB: { - Blob blob; - (void)data.value().GetBlob(blob); - std::vector blobData(blob.GetData(), blob.GetData() + blob.GetSize()); - errCode = SQLiteUtils::BindBlobToStatement(statement, cid, blobData, true); - break; - } - - case StorageType::STORAGE_TYPE_NULL: { - errCode = SQLiteUtils::MapSQLiteErrno(sqlite3_bind_null(statement, cid)); - break; - } - - default: - break; - } - return errCode; -} - -int SQLiteUtils::UpdateCipherShaAlgo(sqlite3 *db, bool setWal, CipherType type, const CipherPassword &passwd, - uint32_t iterTimes) -{ - if (passwd.GetSize() != 0) { - int errCode = SetKeyInner(db, type, passwd, iterTimes); - if (errCode != E_OK) { - return errCode; - } - // set sha1 algo for old version - errCode = SQLiteUtils::ExecuteRawSQL(db, SHA1_ALGO_SQL); - if (errCode != E_OK) { - LOGE("[SQLiteUtils][UpdateCipherShaAlgo] set sha algo failed:%d", errCode); - return errCode; - } - // try to get user version - errCode = SQLiteUtils::ExecuteRawSQL(db, USER_VERSION_SQL); - if (errCode != E_OK) { - LOGE("[SQLiteUtils][UpdateCipherShaAlgo] verify version failed:%d", errCode); - if (errno == EKEYREVOKED) { - return -E_EKEYREVOKED; - } - if (errCode == -E_BUSY) { - return errCode; - } - return -E_INVALID_PASSWD_OR_CORRUPTED_DB; - } - // try to update rekey sha algo by rekey operation - errCode = SQLiteUtils::ExecuteRawSQL(db, SHA256_ALGO_REKEY_SQL); - if (errCode != E_OK) { - LOGE("[SQLiteUtils][UpdateCipherShaAlgo] set rekey sha algo failed:%d", errCode); - return errCode; - } - if (setWal) { - errCode = SQLiteUtils::ExecuteRawSQL(db, WAL_MODE_SQL); - if (errCode != E_OK) { - LOGE("[SQLite][UpdateCipherShaAlgo] execute wal sql failed: %d", errCode); - return errCode; - } - } - return Rekey(db, passwd); - } - return -E_INVALID_PASSWD_OR_CORRUPTED_DB; -} - -int SQLiteUtils::CheckTableExists(sqlite3 *db, const std::string &tableName, bool &isCreated) -{ - if (db == nullptr) { - return -1; - } - - sqlite3_stmt *stmt = nullptr; - int errCode = SQLiteUtils::GetStatement(db, CHECK_TABLE_CREATED, stmt); - if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_OK)) { - LOGE("Get check table statement failed. err=%d", errCode); - return errCode; - } - - errCode = SQLiteUtils::BindTextToStatement(stmt, 1, tableName); - if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_OK)) { - LOGE("Bind table name to statement failed. err=%d", errCode); - goto END; - } - - errCode = SQLiteUtils::StepWithRetry(stmt); - if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { - LOGE("Check table exists failed. err=%d", errCode); // should always return a row data - goto END; - } - errCode = E_OK; - isCreated = (sqlite3_column_int(stmt, 0) == 1); -END: - SQLiteUtils::ResetStatement(stmt, true, errCode); - return errCode; -} - -int SQLiteUtils::StepNext(sqlite3_stmt *stmt, bool isMemDb) -{ - if (stmt == nullptr) { - return -E_INVALID_ARGS; - } - int errCode = SQLiteUtils::StepWithRetry(stmt, isMemDb); - if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { - errCode = -E_FINISHED; - } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { - errCode = E_OK; - } - return errCode; -} } // namespace DistributedDB 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 12736fda798161f35d29c66b1ccae9151d47ccae..99629c6fb7c893f93cc84f6e31f36cfea7bd571e 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 @@ -197,7 +197,7 @@ public: static void GetAndResetServerObserverData(const std::string &dbName, const std::string &tableName, ChangeProperties &changeProperties); - static int CheckTableExists(sqlite3 *db, const std::string &tableName, bool &isCreated); + static int CheckTableExists(sqlite3 *db, const std::string &tableName, bool &isCreated, bool isCheckMeta = false); static int AnalysisSchemaFieldDefine(sqlite3 *db, const std::string &tableName, TableInfo &table); 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 new file mode 100644 index 0000000000000000000000000000000000000000..e28017e15d418bf309dbd524ae3c2fe448ebc250 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils_extend.cpp @@ -0,0 +1,698 @@ +/* + * Copyright (c) 2021 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 "sqlite_utils.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "sqlite_import.h" +#include "securec.h" +#include "db_constant.h" +#include "db_common.h" +#include "db_errno.h" +#include "log_print.h" +#include "value_object.h" +#include "schema_utils.h" +#include "schema_constant.h" +#include "time_helper.h" +#include "platform_specific.h" +#include "sqlite_relational_utils.h" + +namespace DistributedDB { +namespace { + const int BUSY_TIMEOUT_MS = 3000; // 3000ms for sqlite busy timeout. + const int USING_STR_LEN = -1; + const std::string CIPHER_CONFIG_SQL = "PRAGMA codec_cipher="; + const std::string KDF_ITER_CONFIG_SQL = "PRAGMA codec_kdf_iter="; + const std::string USER_VERSION_SQL = "PRAGMA user_version;"; + const std::string WAL_MODE_SQL = "PRAGMA journal_mode=WAL;"; + const std::string SHA1_ALGO_SQL = "PRAGMA codec_hmac_algo=SHA1;"; + const std::string SHA256_ALGO_REKEY_SQL = "PRAGMA codec_rekey_hmac_algo=SHA256;"; + + const constexpr char *CHECK_TABLE_CREATED = "SELECT EXISTS(SELECT 1 FROM sqlite_master WHERE " \ + "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; +}; + +namespace { +inline bool IsDeleteRecord(const uint8_t *valueBlob, int valueBlobLen) +{ + return (valueBlob == nullptr) || (valueBlobLen <= 0); // In fact, sqlite guarantee valueBlobLen not negative +} + +// Use the same cache id as sqlite use for json_extract which is substituted by our json_extract_by_path +// A negative cache-id enables sharing of cache between different operation during the same statement +constexpr int VALUE_CACHE_ID = -429938; + +void ValueParseCacheFree(ValueParseCache *inCache) +{ + delete inCache; + inCache = nullptr; +} + +// We don't use cache array since we only cache value column of sqlite table, see sqlite implementation for compare. +const ValueObject *ParseValueThenCacheOrGetFromCache(sqlite3_context *ctx, const uint8_t *valueBlob, + uint32_t valueBlobLen, uint32_t offset) +{ + // Note: All parameter had already been check inside JsonExtractByPath, only called by JsonExtractByPath + auto cached = static_cast(sqlite3_get_auxdata(ctx, VALUE_CACHE_ID)); + if (cached != nullptr) { // A previous cache exist + if (cached->valueOriginal.size() == valueBlobLen) { + if (std::memcmp(cached->valueOriginal.data(), valueBlob, valueBlobLen) == 0) { + // Cache match + return &(cached->valueParsed); + } + } + } + // No cache or cache mismatch + auto newCache = new (std::nothrow) ValueParseCache; + if (newCache == nullptr) { + sqlite3_result_error(ctx, "[ParseValueCache] OOM.", USING_STR_LEN); + LOGE("[ParseValueCache] OOM."); + return nullptr; + } + int errCode = newCache->valueParsed.Parse(valueBlob, valueBlob + valueBlobLen, offset); + if (errCode != E_OK) { + sqlite3_result_error(ctx, "[ParseValueCache] Parse fail.", USING_STR_LEN); + LOGE("[ParseValueCache] Parse fail, errCode=%d.", errCode); + delete newCache; + newCache = nullptr; + return nullptr; + } + newCache->valueOriginal.assign(valueBlob, valueBlob + valueBlobLen); + sqlite3_set_auxdata(ctx, VALUE_CACHE_ID, newCache, reinterpret_cast(ValueParseCacheFree)); + // If sqlite3_set_auxdata fail, it will immediately call ValueParseCacheFree to delete newCache; + // Next time sqlite3_set_auxdata will call ValueParseCacheFree to delete newCache of this time; + // At the end, newCache will be eventually deleted when call sqlite3_reset or sqlite3_finalize; + // Since sqlite3_set_auxdata may fail, we have to call sqlite3_get_auxdata other than return newCache directly. + auto cacheInAuxdata = static_cast(sqlite3_get_auxdata(ctx, VALUE_CACHE_ID)); + if (cacheInAuxdata == nullptr) { + return nullptr; + } + return &(cacheInAuxdata->valueParsed); +} +} + +void SQLiteUtils::JsonExtractByPath(sqlite3_context *ctx, int argc, sqlite3_value **argv) +{ + if (ctx == nullptr || argc != 3 || argv == nullptr) { // 3 parameters, which are value, path and offset + LOGE("[JsonExtract] Invalid parameter, argc=%d.", argc); + return; + } + auto valueBlob = static_cast(sqlite3_value_blob(argv[0])); + int valueBlobLen = sqlite3_value_bytes(argv[0]); + if (IsDeleteRecord(valueBlob, valueBlobLen)) { + // Currently delete records are filtered out of query and create-index sql, so not allowed here. + sqlite3_result_error(ctx, "[JsonExtract] Delete record not allowed.", USING_STR_LEN); + LOGE("[JsonExtract] Delete record not allowed."); + return; + } + auto path = reinterpret_cast(sqlite3_value_text(argv[1])); + int offset = sqlite3_value_int(argv[2]); // index 2 is the third parameter + if ((path == nullptr) || (offset < 0)) { + sqlite3_result_error(ctx, "[JsonExtract] Path nullptr or offset invalid.", USING_STR_LEN); + LOGE("[JsonExtract] Path nullptr or offset=%d invalid.", offset); + return; + } + FieldPath outPath; + int errCode = SchemaUtils::ParseAndCheckFieldPath(path, outPath); + if (errCode != E_OK) { + sqlite3_result_error(ctx, "[JsonExtract] Path illegal.", USING_STR_LEN); + LOGE("[JsonExtract] Path illegal."); + return; + } + // Parameter Check Done Here + const ValueObject *valueObj = ParseValueThenCacheOrGetFromCache(ctx, valueBlob, static_cast(valueBlobLen), + static_cast(offset)); + if (valueObj == nullptr) { + return; // Necessary had been printed in ParseValueThenCacheOrGetFromCache + } + JsonExtractInnerFunc(ctx, *valueObj, outPath); +} + +namespace { +inline bool IsExtractableType(FieldType inType) +{ + return (inType != FieldType::LEAF_FIELD_NULL && inType != FieldType::LEAF_FIELD_ARRAY && + inType != FieldType::LEAF_FIELD_OBJECT && inType != FieldType::INTERNAL_FIELD_OBJECT); +} +} + +void SQLiteUtils::JsonExtractInnerFunc(sqlite3_context *ctx, const ValueObject &inValue, const FieldPath &inPath) +{ + FieldType outType = FieldType::LEAF_FIELD_NULL; // Default type null for invalid-path(path not exist) + int errCode = inValue.GetFieldTypeByFieldPath(inPath, outType); + if (errCode != E_OK && errCode != -E_INVALID_PATH) { + sqlite3_result_error(ctx, "[JsonExtract] GetFieldType fail.", USING_STR_LEN); + LOGE("[JsonExtract] GetFieldType fail, errCode=%d.", errCode); + return; + } + FieldValue outValue; + if (IsExtractableType(outType)) { + errCode = inValue.GetFieldValueByFieldPath(inPath, outValue); + if (errCode != E_OK) { + sqlite3_result_error(ctx, "[JsonExtract] GetFieldValue fail.", USING_STR_LEN); + LOGE("[JsonExtract] GetFieldValue fail, errCode=%d.", errCode); + return; + } + } + // FieldType null, array, object do not have value, all these FieldValue will be regarded as null in JsonReturn. + ExtractReturn(ctx, outType, outValue); +} + +// NOTE!!! This function is performance sensitive !!! Carefully not to allocate memory often!!! +void SQLiteUtils::FlatBufferExtractByPath(sqlite3_context *ctx, int argc, sqlite3_value **argv) +{ + if (ctx == nullptr || argc != 3 || argv == nullptr) { // 3 parameters, which are value, path and offset + LOGE("[FlatBufferExtract] Invalid parameter, argc=%d.", argc); + return; + } + auto schema = static_cast(sqlite3_user_data(ctx)); + if (schema == nullptr || !schema->IsSchemaValid() || + (schema->GetSchemaType() != SchemaType::FLATBUFFER)) { // LCOV_EXCL_BR_LINE + sqlite3_result_error(ctx, "[FlatBufferExtract] No SchemaObject or invalid.", USING_STR_LEN); + LOGE("[FlatBufferExtract] No SchemaObject or invalid."); + return; + } + // Get information from argv + auto valueBlob = static_cast(sqlite3_value_blob(argv[0])); + int valueBlobLen = sqlite3_value_bytes(argv[0]); + if (IsDeleteRecord(valueBlob, valueBlobLen)) { // LCOV_EXCL_BR_LINE + // Currently delete records are filtered out of query and create-index sql, so not allowed here. + sqlite3_result_error(ctx, "[FlatBufferExtract] Delete record not allowed.", USING_STR_LEN); + LOGE("[FlatBufferExtract] Delete record not allowed."); + return; + } + auto path = reinterpret_cast(sqlite3_value_text(argv[1])); + int offset = sqlite3_value_int(argv[2]); // index 2 is the third parameter + if ((path == nullptr) || (offset < 0) || + (static_cast(offset) != schema->GetSkipSize())) { // LCOV_EXCL_BR_LINE + sqlite3_result_error(ctx, "[FlatBufferExtract] Path null or offset invalid.", USING_STR_LEN); + LOGE("[FlatBufferExtract] Path null or offset=%d(skipsize=%u) invalid.", offset, schema->GetSkipSize()); + return; + } + FlatBufferExtractInnerFunc(ctx, *schema, RawValue { valueBlob, valueBlobLen }, path); +} + +namespace { +constexpr uint32_t FLATBUFFER_MAX_CACHE_SIZE = 102400; // 100 KBytes + +void FlatBufferCacheFree(std::vector *inCache) +{ + delete inCache; + inCache = nullptr; +} +} + +void SQLiteUtils::FlatBufferExtractInnerFunc(sqlite3_context *ctx, const SchemaObject &schema, const RawValue &inValue, + RawString inPath) +{ + // All parameter had already been check inside FlatBufferExtractByPath, only called by FlatBufferExtractByPath + if (schema.GetSkipSize() % SchemaConstant::SECURE_BYTE_ALIGN == 0) { // LCOV_EXCL_BR_LINE + TypeValue outExtract; + int errCode = schema.ExtractValue(ValueSource::FROM_DBFILE, inPath, inValue, outExtract, nullptr); + if (errCode != E_OK) { // LCOV_EXCL_BR_LINE + sqlite3_result_error(ctx, "[FlatBufferExtract] ExtractValue fail.", USING_STR_LEN); + LOGE("[FlatBufferExtract] ExtractValue fail, errCode=%d.", errCode); + return; + } + ExtractReturn(ctx, outExtract.first, outExtract.second); + return; + } + // Not byte-align secure, we have to make a cache for copy. Check whether cache had already exist. + auto cached = static_cast *>(sqlite3_get_auxdata(ctx, VALUE_CACHE_ID)); // Share the same id + if (cached == nullptr) { // LCOV_EXCL_BR_LINE + // Make the cache + auto newCache = new (std::nothrow) std::vector; + if (newCache == nullptr) { + sqlite3_result_error(ctx, "[FlatBufferExtract] OOM.", USING_STR_LEN); + LOGE("[FlatBufferExtract] OOM."); + return; + } + newCache->resize(FLATBUFFER_MAX_CACHE_SIZE); + sqlite3_set_auxdata(ctx, VALUE_CACHE_ID, newCache, reinterpret_cast(FlatBufferCacheFree)); + // If sqlite3_set_auxdata fail, it will immediately call FlatBufferCacheFree to delete newCache; + // Next time sqlite3_set_auxdata will call FlatBufferCacheFree to delete newCache of this time; + // At the end, newCache will be eventually deleted when call sqlite3_reset or sqlite3_finalize; + // Since sqlite3_set_auxdata may fail, we have to call sqlite3_get_auxdata other than return newCache directly. + // See sqlite.org for more information. + cached = static_cast *>(sqlite3_get_auxdata(ctx, VALUE_CACHE_ID)); + } + if (cached == nullptr) { // LCOV_EXCL_BR_LINE + LOGW("[FlatBufferExtract] Something wrong with Auxdata, but it is no matter without cache."); + } + TypeValue outExtract; + int errCode = schema.ExtractValue(ValueSource::FROM_DBFILE, inPath, inValue, outExtract, cached); + if (errCode != E_OK) { // LCOV_EXCL_BR_LINE + sqlite3_result_error(ctx, "[FlatBufferExtract] ExtractValue fail.", USING_STR_LEN); + LOGE("[FlatBufferExtract] ExtractValue fail, errCode=%d.", errCode); + return; + } + ExtractReturn(ctx, outExtract.first, outExtract.second); +} + +void SQLiteUtils::ExtractReturn(sqlite3_context *ctx, FieldType type, const FieldValue &value) +{ + if (ctx == nullptr) { + return; + } + switch (type) { + case FieldType::LEAF_FIELD_BOOL: + sqlite3_result_int(ctx, (value.boolValue ? 1 : 0)); + break; + case FieldType::LEAF_FIELD_INTEGER: + sqlite3_result_int(ctx, value.integerValue); + break; + case FieldType::LEAF_FIELD_LONG: + sqlite3_result_int64(ctx, value.longValue); + break; + case FieldType::LEAF_FIELD_DOUBLE: + sqlite3_result_double(ctx, value.doubleValue); + break; + case FieldType::LEAF_FIELD_STRING: + // The SQLITE_TRANSIENT value means that the content will likely change in the near future and + // that SQLite should make its own private copy of the content before returning. + sqlite3_result_text(ctx, value.stringValue.c_str(), -1, SQLITE_TRANSIENT); // -1 mean use the string length + break; + default: + // All other type regard as null + sqlite3_result_null(ctx); + } + return; +} + +static void CalcHashFunc(sqlite3_context *ctx, sqlite3_value **argv) +{ + auto keyBlob = static_cast(sqlite3_value_blob(argv[0])); + if (keyBlob == nullptr) { + sqlite3_result_error(ctx, "Parameters is invalid.", USING_STR_LEN); + LOGE("Parameters is invalid."); + return; + } + int blobLen = sqlite3_value_bytes(argv[0]); + std::vector value(keyBlob, keyBlob + blobLen); + std::vector hashValue; + int errCode = DBCommon::CalcValueHash(value, hashValue); + if (errCode != E_OK) { + sqlite3_result_error(ctx, "Get hash value error.", USING_STR_LEN); + LOGE("Get hash value error."); + return; + } + sqlite3_result_blob(ctx, hashValue.data(), hashValue.size(), SQLITE_TRANSIENT); +} + +void SQLiteUtils::CalcHashKey(sqlite3_context *ctx, int argc, sqlite3_value **argv) +{ + // 1 means that the function only needs one parameter, namely key + if (ctx == nullptr || argc != 1 || argv == nullptr) { + LOGE("Parameter does not meet restrictions."); + return; + } + CalcHashFunc(ctx, argv); +} + +void SQLiteUtils::CalcHash(sqlite3_context *ctx, int argc, sqlite3_value **argv) +{ + if (ctx == nullptr || argc != 2 || argv == nullptr) { // 2 is params count + LOGE("Parameter does not meet restrictions."); + return; + } + CalcHashFunc(ctx, argv); +} + + +int SQLiteUtils::GetDbSize(const std::string &dir, const std::string &dbName, uint64_t &size) +{ + std::string dataDir = dir + "/" + dbName + DBConstant::DB_EXTENSION; + uint64_t localDbSize = 0; + int errCode = OS::CalFileSize(dataDir, localDbSize); + if (errCode != E_OK) { + LOGD("Failed to get the db file size, errCode:%d", errCode); + return errCode; + } + + std::string shmFileName = dataDir + "-shm"; + uint64_t localshmFileSize = 0; + errCode = OS::CalFileSize(shmFileName, localshmFileSize); + if (errCode != E_OK) { + localshmFileSize = 0; + } + + std::string walFileName = dataDir + "-wal"; + uint64_t localWalFileSize = 0; + errCode = OS::CalFileSize(walFileName, localWalFileSize); + if (errCode != E_OK) { + localWalFileSize = 0; + } + + // 64-bit system is Suffice. Computer storage is less than uint64_t max + size += (localDbSize + localshmFileSize + localWalFileSize); + return E_OK; +} + +int SQLiteUtils::SetDataBaseProperty(sqlite3 *db, const OpenDbProperties &properties, bool setWal, + const std::vector &sqls) +{ + // Set the default busy handler to retry automatically before returning SQLITE_BUSY. + int errCode = SetBusyTimeout(db, BUSY_TIMEOUT_MS); + if (errCode != E_OK) { + return errCode; + } + if (!properties.isMemDb) { + errCode = SQLiteUtils::SetKey(db, properties.cipherType, properties.passwd, setWal, + properties.iterTimes); + if (errCode != E_OK) { + LOGD("SQLiteUtils::SetKey fail!!![%d]", errCode); + return errCode; + } + } + + for (const auto &sql : sqls) { + errCode = SQLiteUtils::ExecuteRawSQL(db, sql); + if (errCode != E_OK) { + LOGE("[SQLite] execute sql failed: %d", errCode); + return errCode; + } + } + // Create table if not exist according the sqls. + if (properties.createIfNecessary) { + for (const auto &sql : properties.sqls) { + errCode = SQLiteUtils::ExecuteRawSQL(db, sql); + if (errCode != E_OK) { + LOGE("[SQLite] execute preset sqls failed"); + return errCode; + } + } + } + return E_OK; +} + +#ifndef OMIT_ENCRYPT +int SQLiteUtils::SetCipherSettings(sqlite3 *db, CipherType type, uint32_t iterTimes) +{ + if (db == nullptr) { + return -E_INVALID_DB; + } + std::string cipherName = GetCipherName(type); + if (cipherName.empty()) { + return -E_INVALID_ARGS; + } + std::string cipherConfig = CIPHER_CONFIG_SQL + cipherName + ";"; + int errCode = SQLiteUtils::ExecuteRawSQL(db, cipherConfig); + if (errCode != E_OK) { + LOGE("[SQLiteUtils][SetCipherSettings] config cipher failed:%d", errCode); + return errCode; + } + errCode = SQLiteUtils::ExecuteRawSQL(db, KDF_ITER_CONFIG_SQL + std::to_string(iterTimes)); + if (errCode != E_OK) { + LOGE("[SQLiteUtils][SetCipherSettings] config iter failed:%d", errCode); + } + return errCode; +} + +std::string SQLiteUtils::GetCipherName(CipherType type) +{ + if (type == CipherType::AES_256_GCM || type == CipherType::DEFAULT) { + return "'aes-256-gcm'"; + } + return ""; +} +#endif + +int SQLiteUtils::DropTriggerByName(sqlite3 *db, const std::string &name) +{ + const std::string dropTriggerSql = "DROP TRIGGER " + name + ";"; + int errCode = SQLiteUtils::ExecuteRawSQL(db, dropTriggerSql); + if (errCode != E_OK) { + LOGE("Remove trigger failed. %d", errCode); + } + return errCode; +} + +int SQLiteUtils::ExpandedSql(sqlite3_stmt *stmt, std::string &basicString) +{ + if (stmt == nullptr) { + return -E_INVALID_ARGS; + } + char *eSql = sqlite3_expanded_sql(stmt); + if (eSql == nullptr) { + LOGE("expand statement to sql failed."); + return -E_INVALID_DATA; + } + basicString = std::string(eSql); + sqlite3_free(eSql); + return E_OK; +} + +void SQLiteUtils::ExecuteCheckPoint(sqlite3 *db) +{ + if (db == nullptr) { + return; + } + + int chkResult = sqlite3_wal_checkpoint_v2(db, nullptr, SQLITE_CHECKPOINT_TRUNCATE, nullptr, nullptr); + LOGI("SQLite checkpoint result:%d", chkResult); +} + +int SQLiteUtils::CheckTableEmpty(sqlite3 *db, const std::string &tableName, bool &isEmpty) +{ + if (db == nullptr) { + return -E_INVALID_ARGS; + } + + std::string cntSql = "SELECT min(rowid) FROM '" + tableName + "';"; + sqlite3_stmt *stmt = nullptr; + int errCode = SQLiteUtils::GetStatement(db, cntSql, stmt); + if (errCode != E_OK) { + return errCode; + } + + errCode = SQLiteUtils::StepWithRetry(stmt, false); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + isEmpty = (sqlite3_column_type(stmt, 0) == SQLITE_NULL); + errCode = E_OK; + } + + SQLiteUtils::ResetStatement(stmt, true, errCode); + return SQLiteUtils::MapSQLiteErrno(errCode); +} + +int SQLiteUtils::SetPersistWalMode(sqlite3 *db) +{ + if (db == nullptr) { + return -E_INVALID_ARGS; + } + int opCode = 1; + int errCode = sqlite3_file_control(db, "main", SQLITE_FCNTL_PERSIST_WAL, &opCode); + if (errCode != SQLITE_OK) { + LOGE("Set persist wal mode failed. %d", errCode); + } + return SQLiteUtils::MapSQLiteErrno(errCode); +} + +int64_t SQLiteUtils::GetLastRowId(sqlite3 *db) +{ + if (db == nullptr) { + return -1; + } + return sqlite3_last_insert_rowid(db); +} + +std::string SQLiteUtils::GetLastErrorMsg() +{ + std::lock_guard autoLock(logMutex_); + return lastErrorMsg_; +} + +int SQLiteUtils::SetAuthorizer(sqlite3 *db, + int (*xAuth)(void*, int, const char*, const char*, const char*, const char*)) +{ + return SQLiteUtils::MapSQLiteErrno(sqlite3_set_authorizer(db, xAuth, nullptr)); +} + +void SQLiteUtils::GetSelectCols(sqlite3_stmt *stmt, std::vector &colNames) +{ + colNames.clear(); + for (int i = 0; i < sqlite3_column_count(stmt); ++i) { + const char *name = sqlite3_column_name(stmt, i); + colNames.emplace_back(name == nullptr ? std::string() : std::string(name)); + } +} + +int SQLiteUtils::SetKeyInner(sqlite3 *db, CipherType type, const CipherPassword &passwd, uint32_t iterTimes) +{ +#ifndef OMIT_ENCRYPT + int errCode = sqlite3_key(db, static_cast(passwd.GetData()), static_cast(passwd.GetSize())); + if (errCode != SQLITE_OK) { + LOGE("[SQLiteUtils][SetKeyInner] config key failed:(%d)", errCode); + return SQLiteUtils::MapSQLiteErrno(errCode); + } + + errCode = SQLiteUtils::SetCipherSettings(db, type, iterTimes); + if (errCode != E_OK) { + LOGE("[SQLiteUtils][SetKeyInner] set cipher settings failed:%d", errCode); + } + return errCode; +#else + return -E_NOT_SUPPORT; +#endif +} + +int SQLiteUtils::BindDataValueByType(sqlite3_stmt *statement, const std::optional &data, int cid) +{ + int errCode = E_OK; + StorageType type = data.value_or(DataValue()).GetType(); + switch (type) { + case StorageType::STORAGE_TYPE_INTEGER: { + int64_t intData = 0; + (void)data.value().GetInt64(intData); + errCode = SQLiteUtils::MapSQLiteErrno(sqlite3_bind_int64(statement, cid, intData)); + break; + } + + case StorageType::STORAGE_TYPE_REAL: { + double doubleData = 0; + (void)data.value().GetDouble(doubleData); + errCode = SQLiteUtils::MapSQLiteErrno(sqlite3_bind_double(statement, cid, doubleData)); + break; + } + + case StorageType::STORAGE_TYPE_TEXT: { + std::string strData; + (void)data.value().GetText(strData); + errCode = SQLiteUtils::BindTextToStatement(statement, cid, strData); + break; + } + + case StorageType::STORAGE_TYPE_BLOB: { + Blob blob; + (void)data.value().GetBlob(blob); + std::vector blobData(blob.GetData(), blob.GetData() + blob.GetSize()); + errCode = SQLiteUtils::BindBlobToStatement(statement, cid, blobData, true); + break; + } + + case StorageType::STORAGE_TYPE_NULL: { + errCode = SQLiteUtils::MapSQLiteErrno(sqlite3_bind_null(statement, cid)); + break; + } + + default: + break; + } + return errCode; +} + +int SQLiteUtils::UpdateCipherShaAlgo(sqlite3 *db, bool setWal, CipherType type, const CipherPassword &passwd, + uint32_t iterTimes) +{ + if (passwd.GetSize() != 0) { + int errCode = SetKeyInner(db, type, passwd, iterTimes); + if (errCode != E_OK) { + return errCode; + } + // set sha1 algo for old version + errCode = SQLiteUtils::ExecuteRawSQL(db, SHA1_ALGO_SQL); + if (errCode != E_OK) { + LOGE("[SQLiteUtils][UpdateCipherShaAlgo] set sha algo failed:%d", errCode); + return errCode; + } + // try to get user version + errCode = SQLiteUtils::ExecuteRawSQL(db, USER_VERSION_SQL); + if (errCode != E_OK) { + LOGE("[SQLiteUtils][UpdateCipherShaAlgo] verify version failed:%d", errCode); + if (errno == EKEYREVOKED) { + return -E_EKEYREVOKED; + } + if (errCode == -E_BUSY) { + return errCode; + } + return -E_INVALID_PASSWD_OR_CORRUPTED_DB; + } + // try to update rekey sha algo by rekey operation + errCode = SQLiteUtils::ExecuteRawSQL(db, SHA256_ALGO_REKEY_SQL); + if (errCode != E_OK) { + LOGE("[SQLiteUtils][UpdateCipherShaAlgo] set rekey sha algo failed:%d", errCode); + return errCode; + } + if (setWal) { + errCode = SQLiteUtils::ExecuteRawSQL(db, WAL_MODE_SQL); + if (errCode != E_OK) { + LOGE("[SQLite][UpdateCipherShaAlgo] execute wal sql failed: %d", errCode); + return errCode; + } + } + return Rekey(db, passwd); + } + return -E_INVALID_PASSWD_OR_CORRUPTED_DB; +} + +int SQLiteUtils::CheckTableExists(sqlite3 *db, const std::string &tableName, bool &isCreated, bool isCheckMeta) +{ + if (db == nullptr) { + return -1; + } + + sqlite3_stmt *stmt = nullptr; + int errCode = SQLiteUtils::GetStatement(db, isCheckMeta ? CHECK_META_DB_TABLE_CREATED : CHECK_TABLE_CREATED, stmt); + if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_OK)) { + LOGE("Get check table statement failed. err=%d", errCode); + return errCode; + } + + errCode = SQLiteUtils::BindTextToStatement(stmt, 1, tableName); + if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_OK)) { + LOGE("Bind table name to statement failed. err=%d", errCode); + goto END; + } + + errCode = SQLiteUtils::StepWithRetry(stmt); + if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + LOGE("Check table exists failed. err=%d", errCode); // should always return a row data + goto END; + } + errCode = E_OK; + isCreated = (sqlite3_column_int(stmt, 0) == 1); +END: + SQLiteUtils::ResetStatement(stmt, true, errCode); + return errCode; +} + +int SQLiteUtils::StepNext(sqlite3_stmt *stmt, bool isMemDb) +{ + if (stmt == nullptr) { + return -E_INVALID_ARGS; + } + int errCode = SQLiteUtils::StepWithRetry(stmt, isMemDb); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + errCode = -E_FINISHED; + } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + errCode = E_OK; + } + return errCode; +} +} // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/storage_engine.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/storage_engine.cpp index 698074a21a98630e3c57131c270d1de80f4d08a4..baee1606312a6c270198b58b40edb518f2a2bd1e 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/storage_engine.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/storage_engine.cpp @@ -32,6 +32,7 @@ StorageEngine::StorageEngine() commitNotifyFunc_(nullptr), schemaChangedFunc_(nullptr), isSchemaChanged_(false), + isEnhance_(false), isInitialized_(false), perm_(OperatePerm::NORMAL_PERM), operateAbort_(false), @@ -98,12 +99,13 @@ int StorageEngine::InitReadWriteExecutors() } -int StorageEngine::Init() +int StorageEngine::Init(bool isEnhance) { if (isInitialized_.load()) { LOGD("Storage engine has been initialized!"); return E_OK; } + isEnhance_ = isEnhance; int errCode = InitReadWriteExecutors(); if (errCode == E_OK) { @@ -234,7 +236,9 @@ void StorageEngine::Recycle(StorageExecutor *&handle) if (handle == nullptr) { return; } - LOGD("Recycle executor[%d] for id[%.6s]", handle->GetWritable(), hashIdentifier_.c_str()); + if (!isEnhance_) { + LOGD("Recycle executor[%d] for id[%.6s]", handle->GetWritable(), hashIdentifier_.c_str()); + } if (handle->GetWritable()) { std::unique_lock lock(writeMutex_); auto iter = std::find(writeUsingList_.begin(), writeUsingList_.end(), handle); @@ -362,7 +366,9 @@ EngineState StorageEngine::GetEngineState() const void StorageEngine::SetEngineState(EngineState state) { - LOGI("Storage engine state to [%d]!", state); + if (state != EngineState::MAINDB) { + LOGI("Storage engine state to [%d]!", state); + } engineState_ = state; } @@ -454,7 +460,9 @@ StorageExecutor *StorageEngine::FetchStorageExecutor(bool isWrite, std::list &idleList, std::list &usingList, int &errCode); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/storage_engine_manager.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/storage_engine_manager.cpp index 474b348bfa47add8301ad3f6f6b2a9fa91f73625..b4ba554a1854cee50ca6efa8037b3d9cb13287f1 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/storage_engine_manager.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/storage_engine_manager.cpp @@ -21,7 +21,7 @@ #include "sqlite_single_ver_storage_engine.h" namespace DistributedDB { -bool StorageEngineManager::isRegLockStatusListener_ = false; +volatile bool StorageEngineManager::isRegLockStatusListener_ = false; std::mutex StorageEngineManager::instanceLock_; std::atomic StorageEngineManager::instance_{nullptr}; std::mutex StorageEngineManager::storageEnginesLock_; @@ -150,10 +150,13 @@ StorageEngineManager *StorageEngineManager::GetInstance() } if (!isRegLockStatusListener_) { - int errCode = (instance_.load())->RegisterLockStatusListener(); - if (errCode == E_OK) { - isRegLockStatusListener_ = true; - LOGW("[StorageEngineManager] Register lock status listener."); + std::lock_guard mgrLock(storageEnginesLock_); + if (!isRegLockStatusListener_) { + int errCode = (instance_.load())->RegisterLockStatusListener(); + if (errCode == E_OK) { + isRegLockStatusListener_ = true; + LOGW("[StorageEngineManager] Register lock status listener."); + } } } return instance_; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/storage_executor.h b/kv_store/frameworks/libs/distributeddb/storage/src/storage_executor.h index 8a2c7d980dbd9f1e778dea9dc7982c6c323ce140..e7a8310b6b02b05b2819b59aa094d62979be2072 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/storage_executor.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/storage_executor.h @@ -16,6 +16,9 @@ #ifndef STORAGE_EXECUTOR_H #define STORAGE_EXECUTOR_H +#include +#include + #include "macro_utils.h" #include "single_ver_natural_store_commit_notify_data.h" #include "types_export.h" 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 e6455d83b9b66cfc06cc41a75df3147aac1b4621..0871dc38797883fdfcd8065a81af724d1fc8124a 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/storage_proxy.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/storage_proxy.cpp @@ -297,6 +297,15 @@ int StorageProxy::GetInfoByPrimaryKeyOrGid(const std::string &tableName, const V return errCode; } +int StorageProxy::SetCursorIncFlag(bool flag) +{ + std::shared_lock readLock(storeMutex_); + if (store_ == nullptr) { + return -E_INVALID_DB; + } + return store_->SetCursorIncFlag(flag); +} + int StorageProxy::PutCloudSyncData(const std::string &tableName, DownloadData &downloadData) { std::shared_lock readLock(storeMutex_); @@ -525,16 +534,6 @@ void StorageProxy::FillCloudGidIfSuccess(const OpType opType, const CloudSyncDat } } -void StorageProxy::SetCloudTaskConfig(const CloudTaskConfig &config) -{ - std::shared_lock readLock(storeMutex_); - if (store_ == nullptr) { - LOGW("[StorageProxy] fill gid failed with store invalid"); - return; - } - store_->SetCloudTaskConfig(config); -} - std::pair StorageProxy::GetAssetsByGidOrHashKey(const std::string &tableName, const std::string &gid, const Bytes &hashKey, VBucket &assets) { @@ -569,13 +568,22 @@ int StorageProxy::UpdateRecordFlag(const std::string &tableName, bool recordConf return store_->UpdateRecordFlag(tableName, recordConflict, logInfo); } -int StorageProxy::GetCompensatedSyncQuery(std::vector &syncQuery) +int StorageProxy::GetCompensatedSyncQuery(std::vector &syncQuery, std::vector &users) +{ + std::shared_lock readLock(storeMutex_); + if (store_ == nullptr) { + return -E_INVALID_DB; + } + return store_->GetCompensatedSyncQuery(syncQuery, users); +} + +int StorageProxy::ClearUnLockingNoNeedCompensated() { std::shared_lock readLock(storeMutex_); if (store_ == nullptr) { return -E_INVALID_DB; } - return store_->GetCompensatedSyncQuery(syncQuery); + return store_->ClearUnLockingNoNeedCompensated(); } int StorageProxy::MarkFlagAsConsistent(const std::string &tableName, const DownloadData &downloadData, @@ -673,11 +681,21 @@ void StorageProxy::ReleaseUploadRecord(const std::string &table, const CloudWate store_->ReleaseUploadRecord(table, type, localWaterMark); } -bool StorageProxy::IsSameCloudLocalDeviceAndNotLocal(const LogInfo &localInfo, const LogInfo &cloudInfo) +bool StorageProxy::IsTagCloudUpdateLocal(const LogInfo &localInfo, const LogInfo &cloudInfo, + SingleVerConflictResolvePolicy policy) { if (store_ == nullptr) { return false; } - return store_->IsSameCloudLocalDeviceAndNotLocal(localInfo, cloudInfo); + return store_->IsTagCloudUpdateLocal(localInfo, cloudInfo, policy); +} + +int StorageProxy::ReviseLocalModTime(const std::string &tableName, + const std::vector &revisedData) +{ + if (store_ == nullptr) { + return -E_INVALID_DB; + } + return store_->ReviseLocalModTime(tableName, revisedData); } } 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 3632ff4e56b60173a27f0a6d5f8e3143c4f508db..cffa5f6425dfecb55c607254c06828db7e128044 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 @@ -14,6 +14,7 @@ */ #include "cloud_db_proxy.h" #include "cloud/cloud_db_constant.h" +#include "cloud/cloud_storage_utils.h" #include "db_common.h" #include "db_errno.h" #include "log_print.h" @@ -35,11 +36,10 @@ void CloudDBProxy::SetCloudDB(const std::shared_ptr &cloudDB) int CloudDBProxy::SetCloudDB(const std::map> &cloudDBs) { std::unique_lock writeLock(cloudMutex_); - for (const auto &item : cloudDBs) { - if (item.second == nullptr) { - LOGE("[CloudDBProxy] User %s setCloudDB with nullptr", item.first.c_str()); - return -E_INVALID_ARGS; - } + auto it = std::find_if(cloudDBs.begin(), cloudDBs.end(), [](const auto &item) { return item.second == nullptr; }); + if (it != cloudDBs.end()) { + LOGE("[CloudDBProxy] User %s setCloudDB with nullptr", it->first.c_str()); + return -E_INVALID_ARGS; } cloudDbs_ = cloudDBs; return E_OK; @@ -66,6 +66,32 @@ void CloudDBProxy::SetIAssetLoader(const std::shared_ptr &loader) iAssetLoader_ = loader; } +static void RecordSyncDataTimeStampLog(std::vector &data, uint8_t action) +{ + if (data.empty()) { + LOGI("[CloudDBProxy] sync data is empty"); + return; + } + + int64_t first = 0; + int errCode = CloudStorageUtils::GetValueFromVBucket(CloudDbConstant::MODIFY_FIELD, data[0], first); + if (errCode != E_OK) { + LOGE("get first modify time for bucket failed, %d", errCode); + return; + } + + int64_t last = 0; + errCode = CloudStorageUtils::GetValueFromVBucket(CloudDbConstant::MODIFY_FIELD, data[data.size() - 1], + last); + if (errCode != E_OK) { + LOGE("get last modify time for bucket failed, %d", errCode); + return; + } + + LOGI("[CloudDBProxy] sync action is %d and size is %d, sync data: first timestamp %lld, last timestamp %lld", + action, data.size(), first, last); +} + int CloudDBProxy::BatchInsert(const std::string &tableName, std::vector &record, std::vector &extend, Info &uploadInfo) { @@ -138,6 +164,7 @@ int CloudDBProxy::Query(const std::string &tableName, VBucket &extend, std::vect DBCommon::RemoveDuplicateAssetsData(*assets); } } + RecordSyncDataTimeStampLog(data, QUERY); return errCode; } @@ -308,24 +335,26 @@ DBStatus CloudDBProxy::DMLActionTask(const std::shared_ptr & std::vector record; std::vector extend; context->MoveOutRecordAndExtend(record, extend); + RecordSyncDataTimeStampLog(extend, action); + uint32_t recordSize = record.size(); switch (action) { case INSERT: { status = cloudDb->BatchInsert(context->GetTableName(), std::move(record), extend); - context->MoveInRecordAndExtend(record, extend); - context->SetInfo(CloudWaterType::INSERT, status); + context->MoveInExtend(extend); + context->SetInfo(CloudWaterType::INSERT, status, recordSize); break; } case UPDATE: { status = cloudDb->BatchUpdate(context->GetTableName(), std::move(record), extend); - context->MoveInRecordAndExtend(record, extend); - context->SetInfo(CloudWaterType::UPDATE, status); + context->MoveInExtend(extend); + context->SetInfo(CloudWaterType::UPDATE, status, recordSize); break; } case DELETE: { status = cloudDb->BatchDelete(context->GetTableName(), extend); context->MoveInRecordAndExtend(record, extend); - context->SetInfo(CloudWaterType::DELETE, status); + context->SetInfo(CloudWaterType::DELETE, status, recordSize); break; } default: { @@ -570,13 +599,15 @@ bool CloudDBProxy::CloudActionContext::IsEmptyAssetId(const Assets &assets) bool CloudDBProxy::CloudActionContext::IsRecordActionFail(const VBucket &extend, bool isInsert, DBStatus status) { + if (DBCommon::IsRecordAssetsMissing(extend)) { + return false; + } if (extend.count(CloudDbConstant::GID_FIELD) == 0) { return true; } if (status != OK) { if (DBCommon::IsRecordError(extend) || - (!DBCommon::IsRecordSuccess(extend) && !DBCommon::IsRecordIgnored(extend) && - !DBCommon::IsRecordVersionConflict(extend))) { + (!DBCommon::IsRecordSuccess(extend) && !DBCommon::IsRecordVersionConflict(extend))) { return true; } } @@ -597,17 +628,17 @@ bool CloudDBProxy::CloudActionContext::IsRecordActionFail(const VBucket &extend, return false; } -void CloudDBProxy::CloudActionContext::SetInfo(const CloudWaterType &type, DBStatus status) +void CloudDBProxy::CloudActionContext::SetInfo(const CloudWaterType &type, DBStatus status, uint32_t size) { - totalCount_ = record_.size(); + totalCount_ = size; - // records_ size should be equal to extend_ or batch data failed. - if (record_.size() != extend_.size()) { - failedCount_ += record_.size(); + // totalCount_ should be equal to extend_ or batch data failed. + if (totalCount_ != extend_.size()) { + failedCount_ += totalCount_; return; } for (auto &extend : extend_) { - if (DBCommon::IsNeedCompensatedForUpload(extend, type)) { + if (DBCommon::IsRecordIgnoredForReliability(extend, type) || DBCommon::IsRecordIgnored(extend)) { continue; } if (IsRecordActionFail(extend, type == CloudWaterType::INSERT, status)) { @@ -658,4 +689,14 @@ std::pair CloudDBProxy::GetCloudVersion(const std::string &ori LOGI("[CloudDBProxy] End get cloud version"); return {E_OK, version}; } + +void CloudDBProxy::SetPrepareTraceId(const std::string &traceId) const +{ + std::shared_ptr iCloudDb = nullptr; + std::unique_lock writeLock(cloudMutex_); + if (iCloudDb_ != nullptr) { + iCloudDb = iCloudDb_; + iCloudDb->SetPrepareTraceId(traceId); + } +} } 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 c1a306e172ac0a132eb8519e6e1de0fc8c5ae8c8..c11a86962290fcfe3b4356f0d108051d10254a8b 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 @@ -20,7 +20,6 @@ #include #include #include "cloud/cloud_db_types.h" -#include "cloud/cloud_db_types.h" #include "cloud/icloud_db.h" #include "cloud/iAssetLoader.h" @@ -76,6 +75,8 @@ public: bool IsExistCloudVersionCallback() const; std::pair GetCloudVersion(const std::string &originVersion) const; + + void SetPrepareTraceId(const std::string &traceId) const; protected: class CloudActionContext { public: @@ -108,7 +109,7 @@ protected: Info GetInfo(); - void SetInfo(const CloudWaterType &type, DBStatus status); + void SetInfo(const CloudWaterType &type, DBStatus status, uint32_t size); void SetTableName(const std::string &tableName); diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_force_pull_strategy.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_force_pull_strategy.cpp index 1a5f0981cd1dd4e08c4a61954634a7662106843e..d5a790448b96a967bf10a38d1a3ca8070e60f0fa 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_force_pull_strategy.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_force_pull_strategy.cpp @@ -17,8 +17,8 @@ namespace DistributedDB { -OpType CloudForcePullStrategy::TagSyncDataStatus(bool existInLocal, bool isSameCurDevice, const LogInfo &localInfo, - const LogInfo &cloudInfo) +OpType CloudForcePullStrategy::TagSyncDataStatus(bool existInLocal, [[gnu::unused]] bool isCloudWin, + const LogInfo &localInfo, const LogInfo &cloudInfo) { if (CloudStorageUtils::IsDataLocked(localInfo.status)) { return OpType::LOCKED_NOT_HANDLE; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_force_pull_strategy.h b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_force_pull_strategy.h index 225befd47ddb5fdcf7bd7ed2fa8d1e119a4b010c..b090225825a5a42b6c4d265387c7b360c574d5a5 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_force_pull_strategy.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_force_pull_strategy.h @@ -19,7 +19,7 @@ namespace DistributedDB { class CloudForcePullStrategy : public CloudSyncStrategy { public: - OpType TagSyncDataStatus(bool existInLocal, bool isSameDeviceNotLocal, const LogInfo &localInfo, + OpType TagSyncDataStatus(bool existInLocal, bool isCloudWin, const LogInfo &localInfo, const LogInfo &cloudInfo) override; bool JudgeUpdateCursor() override; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_force_push_strategy.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_force_push_strategy.cpp index b5b503cf23e1e559d44ab2c0da193dac007734d0..9b108f67ffab3a4f1b9355396b789080cedb1cef 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_force_push_strategy.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_force_push_strategy.cpp @@ -17,8 +17,8 @@ namespace DistributedDB { const std::string cloud_device_name = "cloud"; -OpType CloudForcePushStrategy::TagSyncDataStatus(bool existInLocal, bool isSameCurDevice, const LogInfo &localInfo, - const LogInfo &cloudInfo) +OpType CloudForcePushStrategy::TagSyncDataStatus(bool existInLocal, [[gnu::unused]] bool isCloudWin, + const LogInfo &localInfo, const LogInfo &cloudInfo) { if (CloudStorageUtils::IsDataLocked(localInfo.status)) { return OpType::LOCKED_NOT_HANDLE; @@ -29,8 +29,9 @@ OpType CloudForcePushStrategy::TagSyncDataStatus(bool existInLocal, bool isSameC } if (localInfo.cloudGid.empty()) { - // when cloud data is deleted, we think it is different data - return isCloudDelete ? OpType::NOT_HANDLE : OpType::ONLY_UPDATE_GID; + // when cloud or local data is deleted, we think it is different data + bool isLocalDelete = IsDelete(localInfo); + return isCloudDelete || isLocalDelete ? OpType::NOT_HANDLE : OpType::ONLY_UPDATE_GID; } if (isCloudDelete) { diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_force_push_strategy.h b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_force_push_strategy.h index 8064b3c301d4c0f9bf7c888e44afc64f72751b65..184155e66307796cf989f0c0d1d7fa905c1737a0 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_force_push_strategy.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_force_push_strategy.h @@ -19,7 +19,7 @@ namespace DistributedDB { class CloudForcePushStrategy : public CloudSyncStrategy { public: - OpType TagSyncDataStatus(bool existInLocal, bool isSameCurDevice, const LogInfo &localInfo, + OpType TagSyncDataStatus(bool existInLocal, bool isCloudWin, const LogInfo &localInfo, const LogInfo &cloudInfo) override; bool JudgeUpdateCursor() override; 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 978a55ca87da52061c20e6fcb9df7b2c585f724e..eb62c0938f9e9d73047534fc8cc866185165667e 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 @@ -17,12 +17,12 @@ namespace DistributedDB { -OpType CloudMergeStrategy::TagSyncDataStatus(bool existInLocal, bool isSameCurDevice, const LogInfo &localInfo, +OpType CloudMergeStrategy::TagSyncDataStatus(bool existInLocal, bool isCloudWin, const LogInfo &localInfo, const LogInfo &cloudInfo) { bool isCloudDelete = IsDelete(cloudInfo); bool isLocalDelete = IsDelete(localInfo); - if (isSameCurDevice) { + if (isCloudWin) { return TagCloudUpdateLocal(localInfo, cloudInfo, isCloudDelete, isLocalDelete); } if (CloudStorageUtils::IsDataLocked(localInfo.status)) { @@ -70,7 +70,8 @@ OpType CloudMergeStrategy::TagLocallyNewer(const LogInfo &localInfo, const LogIn bool isCloudDelete, bool isLocalDelete) { if (localInfo.cloudGid.empty()) { - return isCloudDelete ? OpType::NOT_HANDLE : (isLocalDelete ? OpType::INSERT : OpType::ONLY_UPDATE_GID); + return isCloudDelete ? OpType::NOT_HANDLE + : ((isLocalDelete && !JudgeLocalDeleteUpload()) ? OpType::INSERT : OpType::ONLY_UPDATE_GID); } if (isCloudDelete) { return OpType::CLEAR_GID; @@ -96,9 +97,9 @@ OpType CloudMergeStrategy::TagCloudUpdateLocal(const LogInfo &localInfo, const L OpType CloudMergeStrategy::TagLocalNotExist(bool isCloudDelete) { // when cloud data is deleted, we think it is different data - if (isCloudDelete) { - return OpType::NOT_HANDLE; - } - return OpType::INSERT; + if (isCloudDelete) { + return OpType::NOT_HANDLE; + } + return OpType::INSERT; } } \ 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 dc0e6888a39d6cc5aabafb265d5f54dac95a4191..0af819a5ff9e3d1a530bf4d2f9b7b0cce5b3bfef 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 @@ -23,7 +23,7 @@ public: CloudMergeStrategy() = default; ~CloudMergeStrategy() override = default; - OpType TagSyncDataStatus(bool existInLocal, bool isSameCurDevice, const LogInfo &localInfo, + OpType TagSyncDataStatus(bool existInLocal, bool isCloudWin, const LogInfo &localInfo, const LogInfo &cloudInfo) override; bool JudgeUpdateCursor() override; 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 5048082931967af17712715312b332cf4a1e38c0..907242f04ceb0d4b742d0b0b05c7cc20d2b97334 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,12 +20,17 @@ CloudSyncStrategy::CloudSyncStrategy() : policy_(SingleVerConflictResolvePolicy: { } +void CloudSyncStrategy::SetIsLocalDeleteUpload(bool isLocalDeleteUpload) +{ + isLocalDeleteUpload_ = isLocalDeleteUpload; +} + void CloudSyncStrategy::SetConflictResolvePolicy(SingleVerConflictResolvePolicy policy) { policy_ = policy; } -OpType CloudSyncStrategy::TagSyncDataStatus([[gnu::unused]] bool existInLocal, [[gnu::unused]] bool isSameCurDevice, +OpType CloudSyncStrategy::TagSyncDataStatus([[gnu::unused]] bool existInLocal, [[gnu::unused]] bool isCloudWin, [[gnu::unused]] const LogInfo &localInfo, [[gnu::unused]] const LogInfo &cloudInfo) { return OpType::NOT_HANDLE; @@ -41,6 +46,11 @@ bool CloudSyncStrategy::JudgeUpload() return false; } +bool CloudSyncStrategy::JudgeLocalDeleteUpload() +{ + return isLocalDeleteUpload_; +} + bool CloudSyncStrategy::IsDelete(const LogInfo &info) { return (info.flag & static_cast(LogInfoFlag::FLAG_DELETE)) == 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 a4d55f6a97fdea7c6d2af4362cf8780dedde9c16..d719c6e2b9e80e4766bd2cda6b5a378b1fa7770f 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,15 +27,19 @@ public: CloudSyncStrategy(); virtual ~CloudSyncStrategy() = default; + void SetIsLocalDeleteUpload(bool isLocalDeleteUpload); + void SetConflictResolvePolicy(SingleVerConflictResolvePolicy policy); - virtual OpType TagSyncDataStatus(bool existInLocal, bool isSameCurDevice, const LogInfo &localInfo, + virtual OpType TagSyncDataStatus(bool existInLocal, bool isCloudWin, const LogInfo &localInfo, const LogInfo &cloudInfo); virtual bool JudgeUpdateCursor(); virtual bool JudgeUpload(); + bool JudgeLocalDeleteUpload(); + static bool IsDelete(const LogInfo &info); static bool IsLogNeedUpdate(const LogInfo &cloudInfo, const LogInfo &localInfo); @@ -46,9 +50,11 @@ protected: bool IsIgnoreUpdate(const LogInfo &localInfo) const; - bool IsSameRecord(const LogInfo &cloudInfo, const LogInfo &localInfo); + static bool IsSameRecord(const LogInfo &cloudInfo, const LogInfo &localInfo); SingleVerConflictResolvePolicy policy_; + + bool isLocalDeleteUpload_ = false; // Whether upload to the cloud after delete local data that does not have a gid }; } #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 bf23f2c9a1bc4b62c7d9765bc29d5e1d86bff53c..116391ad2b90fa0dbabada5601ef7906eb17c424 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 @@ -51,7 +51,7 @@ void TagSingleAssetForDownload(AssetOpType flag, Asset &asset, Assets &res, int res.push_back(asset); } -void TagSingleAssetForUpload(AssetOpType flag, Asset &asset, Assets &res, int &errCode) +void TagSingleAssetForUpload(AssetOpType flag, Asset &asset, Assets &res) { uint32_t lowBitStatus = AssetOperationUtils::EraseBitMask(asset.status); if (lowBitStatus == static_cast(AssetStatus::DELETE)) { @@ -87,7 +87,7 @@ void TagAssetWithNormalStatus(const bool isNormalStatus, AssetOpType flag, Asset &asset, Assets &res, int &errCode) { if (isNormalStatus) { - TagSingleAssetForUpload(flag, asset, res, errCode); + TagSingleAssetForUpload(flag, asset, res); return; } TagSingleAssetForDownload(flag, asset, res, errCode); @@ -124,10 +124,10 @@ bool IsDataContainField(const std::string &assetFieldName, const VBucket &data) return true; } -void TagAssetWithSameHash(const bool setNormalStatus, Asset &beCoveredAsset, Asset &coveredAsset, Assets &res, +void TagAssetWithSameHash(const bool isNormalStatus, Asset &beCoveredAsset, Asset &coveredAsset, Assets &res, int &errCode) { - TagAssetWithNormalStatus(setNormalStatus, ( + TagAssetWithNormalStatus(isNormalStatus, ( AssetOperationUtils::EraseBitMask(beCoveredAsset.status) == AssetStatus::DELETE || AssetOperationUtils::EraseBitMask(beCoveredAsset.status) == AssetStatus::ABNORMAL || beCoveredAsset.status == (AssetStatus::DOWNLOADING | DOWNLOAD_WITH_NULL)) ? @@ -184,7 +184,9 @@ Assets TagAssets(const std::string &assetFieldName, VBucket &coveredData, VBucke // fill asset id for upload data coveredAsset.assetId = beCoveredAsset.assetId; } - if (beCoveredAsset.hash != coveredAsset.hash) { + if (!setNormalStatus && !beCoveredAsset.hash.empty() && beCoveredAsset.hash != coveredAsset.hash) { + TagAssetWithNormalStatus(setNormalStatus, AssetOpType::UPDATE, coveredAsset, res, errCode); + } else if (setNormalStatus && beCoveredAsset.hash != coveredAsset.hash) { TagAssetWithNormalStatus(setNormalStatus, AssetOpType::UPDATE, coveredAsset, res, errCode); } else { TagAssetWithSameHash(setNormalStatus, beCoveredAsset, coveredAsset, res, errCode); @@ -207,6 +209,19 @@ Assets TagAssets(const std::string &assetFieldName, VBucket &coveredData, VBucke return res; } +static void TagCoveredAssetInner(Asset &covered, const Asset &beCovered, const bool setNormalStatus, Assets &res, + int &errCode) +{ + if (!setNormalStatus && beCovered.hash.empty()) { + TagAssetWithNormalStatus(setNormalStatus, AssetOpType::INSERT, covered, res, errCode); + } else if (covered.hash != beCovered.hash) { + TagAssetWithNormalStatus(setNormalStatus, AssetOpType::UPDATE, covered, res, errCode); + } else { + Assets tmpAssets = {}; + TagAssetWithNormalStatus(true, AssetOpType::NO_CHANGE, covered, tmpAssets, errCode); + } +} + // AssetOpType and AssetStatus will be tagged, assets to be changed will be returned Assets TagAsset(const std::string &assetFieldName, VBucket &coveredData, VBucket &beCoveredData, bool setNormalStatus, int &errCode) @@ -255,12 +270,7 @@ Assets TagAsset(const std::string &assetFieldName, VBucket &coveredData, VBucket // fill asset id for upload data covered.assetId = beCovered.assetId; } - if (covered.hash != beCovered.hash) { - TagAssetWithNormalStatus(setNormalStatus, AssetOpType::UPDATE, covered, res, errCode); - } else { - Assets tmpAssets = {}; - TagAssetWithNormalStatus(true, AssetOpType::NO_CHANGE, covered, tmpAssets, errCode); - } + TagCoveredAssetInner(covered, beCovered, setNormalStatus, res, errCode); return res; } diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_tag_assets.h b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_tag_assets.h index bde28d8128886b9dbc91b1fdb44bad3e2a589606..0db944fa7c883d3f215188fadf014fc0b0b15ac3 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_tag_assets.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_tag_assets.h @@ -16,6 +16,7 @@ #define CLOUD_SYNC_TAG_ASSETS_H #include +#include #include "cloud/cloud_db_constant.h" #include "cloud/cloud_storage_utils.h" 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 1d88bc6865c7be37217f11283749e9eb9d6d2526..cf3fea51746d1be847c40b3f2392d0017061c70d 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 @@ -397,6 +397,7 @@ int CloudSyncUtils::SaveChangedData(ICloudSyncer::SyncParam ¶m, size_t dataI } // INSERT: for no primary key or composite primary key situation if (!param.isSinglePrimaryKey && opType == OpType::INSERT) { + param.info.downLoadInfo.insertCount++; param.withoutRowIdData.insertData.push_back(dataIndex); return E_OK; } @@ -623,6 +624,7 @@ CloudSyncer::CloudTaskInfo CloudSyncUtils::InitCompensatedSyncTaskInfo(const Clo CloudSyncer::CloudTaskInfo taskInfo = InitCompensatedSyncTaskInfo(); taskInfo.callback = onProcess; taskInfo.devices = option.devices; + taskInfo.prepareTraceId = option.prepareTraceId; if (option.users.empty()) { taskInfo.users.push_back(""); } else { @@ -638,6 +640,7 @@ CloudSyncer::CloudTaskInfo CloudSyncUtils::InitCompensatedSyncTaskInfo(const Clo taskInfo.users = oriTaskInfo.users; taskInfo.devices = oriTaskInfo.devices; taskInfo.storeId = oriTaskInfo.storeId; + taskInfo.prepareTraceId = oriTaskInfo.prepareTraceId; return taskInfo; } -} +} \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_utils.h b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_utils.h index 1569891ef32d929da96be01639023d857ad8eed5..b175c74c5813362e00973729412852d4e5ed1187 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_utils.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_utils.h @@ -108,4 +108,4 @@ private: ChangedData &changedData); }; } -#endif // CLOUD_SYNC_UTILS_H +#endif // CLOUD_SYNC_UTILS_H \ No newline at end of file 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 c880084ccadcba251d8658d0db11c29505830423..26818e310deee785a7cfd7b6f913ffeb94139a77 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 @@ -34,12 +34,14 @@ #include "version.h" namespace DistributedDB { -CloudSyncer::CloudSyncer(std::shared_ptr storageProxy, SingleVerConflictResolvePolicy policy) +CloudSyncer::CloudSyncer( + std::shared_ptr storageProxy, bool isLocalDeleteUpload, SingleVerConflictResolvePolicy policy) : lastTaskId_(INVALID_TASK_ID), storageProxy_(std::move(storageProxy)), queuedManualSyncLimit_(DBConstant::QUEUED_SYNC_LIMIT_DEFAULT), closed_(false), timerId_(0u), + isLocalDeleteUpload_(isLocalDeleteUpload), policy_(policy) { if (storageProxy_ != nullptr) { @@ -227,6 +229,9 @@ int CloudSyncer::DoSync(TaskId taskId) { std::lock_guard autoLock(dataLock_); taskInfo = cloudTaskInfos_[taskId]; + cloudDB_.SetPrepareTraceId(taskInfo.prepareTraceId); // SetPrepareTraceId before task started + LOGD("[CloudSyncer] DoSync get taskInfo, taskId is: %llu, prepareTraceId is:%s.", + static_cast(taskInfo.taskId), taskInfo.prepareTraceId.c_str()); } bool needUpload = true; bool isNeedFirstDownload = false; @@ -317,8 +322,10 @@ int CloudSyncer::DoUploadInNeed(const CloudTaskInfo &taskInfo, const bool needUp continue; } errCode = PrepareAndUpload(taskInfo, i); - if (errCode == -E_TASK_PAUSED) { // should re download paused table - MarkDownloadFinishIfNeed(taskInfo.table[i], false); + if (errCode == -E_TASK_PAUSED) { // should re download [paused table, last table] + for (size_t j = i; j < taskInfo.table.size(); ++j) { + MarkDownloadFinishIfNeed(taskInfo.table[j], false); + } } if (errCode != E_OK) { break; @@ -424,11 +431,14 @@ CloudSyncEvent CloudSyncer::SyncMachineDoFinished() std::lock_guard autoLock(dataLock_); taskId = currentContext_.currentTaskId; errCode = cloudTaskInfos_[currentContext_.currentTaskId].errCode; - cloudTaskInfos_[currentContext_.currentTaskId].errCode = E_OK; currentUserIndex = currentContext_.currentUserIndex; userListSize = static_cast(cloudTaskInfos_[taskId].users.size()); } if (currentUserIndex >= userListSize) { + { + std::lock_guard autoLock(dataLock_); + cloudTaskInfos_[currentContext_.currentTaskId].errCode = E_OK; + } DoFinished(taskId, errCode); } else { CloudTaskInfo taskInfo; @@ -437,7 +447,11 @@ CloudSyncEvent CloudSyncer::SyncMachineDoFinished() taskInfo = cloudTaskInfos_[currentContext_.currentTaskId]; } taskInfo.status = ProcessStatus::FINISHED; - currentContext_.notifier->NotifyProcess(taskInfo, {}); + currentContext_.notifier->NotifyProcess(taskInfo, {}, true); + { + std::lock_guard autoLock(dataLock_); + cloudTaskInfos_[currentContext_.currentTaskId].errCode = E_OK; + } } return CloudSyncEvent::ALL_TASK_FINISHED_EVENT; } @@ -999,7 +1013,9 @@ int CloudSyncer::SaveDataInTransaction(CloudSyncer::TaskId taskId, SyncParam &pa param.changedData.field = param.pkColNames; param.changedData.type = ChangedDataType::DATA; } + (void)storageProxy_->SetCursorIncFlag(true); ret = SaveData(taskId, param); + (void)storageProxy_->SetCursorIncFlag(false); param.insertPk.clear(); if (ret != E_OK) { LOGE("[CloudSyncer] cannot save data: %d.", ret); @@ -1064,9 +1080,7 @@ int CloudSyncer::SaveDataNotifyProcess(CloudSyncer::TaskId taskId, SyncParam &pa param.downloadData.opType.resize(param.downloadData.data.size()); param.downloadData.existDataKey.resize(param.downloadData.data.size()); param.downloadData.existDataHashKey.resize(param.downloadData.data.size()); - (void)storageProxy_->CreateTempSyncTrigger(param.tableName); ret = SaveDataInTransaction(taskId, param); - (void)storageProxy_->ClearAllTempSyncTrigger(); if (ret != E_OK) { return ret; } @@ -1109,7 +1123,9 @@ int CloudSyncer::DoDownload(CloudSyncer::TaskId taskId, bool isFirstDownload) LOGE("[CloudSyncer] get sync param for download failed %d", errCode); return errCode; } + (void)storageProxy_->CreateTempSyncTrigger(param.tableName); errCode = DoDownloadInner(taskId, param, isFirstDownload); + (void)storageProxy_->ClearAllTempSyncTrigger(); if (errCode == -E_TASK_PAUSED) { // No need to handle ret. int ret = storageProxy_->GetCloudWaterMark(param.tableName, param.cloudWaterMark); @@ -1498,7 +1514,8 @@ int CloudSyncer::PrepareSync(TaskId taskId) currentContext_.locker = tempLocker; } else { currentContext_.notifier = std::make_shared(this); - currentContext_.strategy = StrategyFactory::BuildSyncStrategy(cloudTaskInfos_[taskId].mode, policy_); + currentContext_.strategy = + StrategyFactory::BuildSyncStrategy(cloudTaskInfos_[taskId].mode, isLocalDeleteUpload_, policy_); currentContext_.notifier->Init(cloudTaskInfos_[taskId].table, cloudTaskInfos_[taskId].devices, cloudTaskInfos_[taskId].users); currentContext_.processRecorder = std::make_shared(); @@ -1736,10 +1753,10 @@ int CloudSyncer::TagStatusByStrategy(bool isExist, SyncParam ¶m, DataInfo &d LOGE("[CloudSyncer] strategy has not been set when tag status, %d.", -E_INTERNAL_ERROR); return -E_INTERNAL_ERROR; } - bool isSameCurDevice = storageProxy_->IsSameCloudLocalDeviceAndNotLocal(dataInfo.localInfo.logInfo, - dataInfo.cloudLogInfo); - strategyOpResult = currentContext_.strategy->TagSyncDataStatus( - isExist, isSameCurDevice, dataInfo.localInfo.logInfo, dataInfo.cloudLogInfo); + bool isCloudWin = storageProxy_->IsTagCloudUpdateLocal(dataInfo.localInfo.logInfo, + dataInfo.cloudLogInfo, policy_); + strategyOpResult = currentContext_.strategy->TagSyncDataStatus(isExist, isCloudWin, + dataInfo.localInfo.logInfo, dataInfo.cloudLogInfo); } if (strategyOpResult == OpType::DELETE) { param.deletePrimaryKeySet.insert(dataInfo.localInfo.logInfo.hashKey); @@ -1892,6 +1909,11 @@ void CloudSyncer::ClearContextAndNotify(TaskId taskId, int errCode) cloudTaskInfos_.erase(taskId); resumeTaskInfos_.erase(taskId); } + int err = storageProxy_->ClearUnLockingNoNeedCompensated(); + if (err != E_OK) { + // if clear unlocking failed, no return to avoid affecting the entire process + LOGW("[CloudSyncer] clear unlocking status failed! errCode = %d", err); + } contextCv_.notify_one(); if (info.errCode == E_OK) { info.errCode = errCode; @@ -1986,16 +2008,21 @@ int CloudSyncer::DownloadOneAssetRecord(const std::set &dupHashKeySet, cons int CloudSyncer::GetSyncParamForDownload(TaskId taskId, SyncParam ¶m) { + int ret = E_OK; if (IsCurrentTableResume(taskId, false)) { std::lock_guard autoLock(dataLock_); if (resumeTaskInfos_[taskId].syncParam.tableName == currentContext_.tableName) { param = resumeTaskInfos_[taskId].syncParam; resumeTaskInfos_[taskId].syncParam = {}; + ret = storageProxy_->GetCloudWaterMark(param.tableName, param.cloudWaterMark); + if (ret != E_OK) { + LOGE("[CloudSyncer] Cannot get cloud water level from cloud meta data when table is resume: %d.", ret); + } LOGD("[CloudSyncer] Get sync param from cache"); return E_OK; } } - int ret = GetCurrentTableName(param.tableName); + ret = GetCurrentTableName(param.tableName); if (ret != E_OK) { LOGE("[CloudSyncer] Invalid table name for syncing: %d", ret); return ret; @@ -2019,7 +2046,6 @@ int CloudSyncer::GetSyncParamForDownload(TaskId taskId, SyncParam ¶m) LOGE("[CloudSyncer] Cannot get cloud water level from cloud meta data: %d.", ret); } } - ReloadCloudWaterMarkIfNeed(param.tableName, param.cloudWaterMark); currentContext_.notifier->GetDownloadInfoByTableName(param.info); return ret; } 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 e98fbb92e3e30268ce10f5a45388d1ba972e9877..ff7a6fc3818f4f83048e97c4295e6711565946d9 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, + explicit CloudSyncer(std::shared_ptr storageProxy, bool isLocalDeleteUpload = false, SingleVerConflictResolvePolicy policy = SingleVerConflictResolvePolicy::DEFAULT_LAST_WIN); void InitCloudSyncStateMachine(); ~CloudSyncer() override = default; @@ -295,6 +295,9 @@ 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); @@ -339,7 +342,7 @@ protected: void ReloadUploadInfoIfNeed(TaskId taskId, const UploadParam ¶m, InnerProcessInfo &info); - uint32_t GetLastUploadSuccessCount(const std::string &tableName); + void GetLastUploadInfo(const std::string &tableName, Info &lastUploadInfo); QuerySyncObject GetQuerySyncObject(const std::string &tableName); @@ -347,6 +350,8 @@ protected: void NotifyUploadFailed(int errCode, InnerProcessInfo &info); + void UpdateProcessWhenUploadFailed(InnerProcessInfo &info); + int BatchInsert(Info &insertInfo, CloudSyncData &uploadData, InnerProcessInfo &innerProcessInfo); int BatchUpdate(Info &updateInfo, CloudSyncData &uploadData, InnerProcessInfo &innerProcessInfo); @@ -405,7 +410,7 @@ protected: std::pair GetLocalWater(const std::string &tableName, UploadParam &uploadParam); int HandleBatchUpload(UploadParam &uploadParam, InnerProcessInfo &info, CloudSyncData &uploadData, - ContinueToken &continueStmtToken); + ContinueToken &continueStmtToken, std::vector &revisedData); bool IsNeedLock(const UploadParam ¶m); @@ -456,6 +461,7 @@ protected: std::map failedHeartbeatCount_; std::string id_; + bool isLocalDeleteUpload_; // Whether upload to the cloud after delete local data that does not have a gid. 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 8f7f5e839e165a2e04ad82466ce510b6e5625ff3..89235b5385f235388aa19d3c47718a35c98f18b3 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 @@ -50,25 +50,22 @@ void CloudSyncer::ReloadCloudWaterMarkIfNeed(const std::string &tableName, std:: void CloudSyncer::ReloadUploadInfoIfNeed(TaskId taskId, const UploadParam ¶m, InnerProcessInfo &info) { info.upLoadInfo.total = static_cast(param.count); - { - std::lock_guard autoLock(dataLock_); - if (!cloudTaskInfos_[taskId].resume) { - return; - } - } - uint32_t lastSuccessCount = GetLastUploadSuccessCount(info.tableName); - if (lastSuccessCount == 0) { - return; - } - info.upLoadInfo.total += lastSuccessCount; - info.upLoadInfo.successCount += lastSuccessCount; - LOGD("[CloudSyncer] resume upload, last success count %" PRIu32, lastSuccessCount); + Info lastUploadInfo; + GetLastUploadInfo(info.tableName, lastUploadInfo); + 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; + LOGD("[CloudSyncer] resume upload, last success count %" PRIu32 ", last fail count %" PRIu32, + lastUploadInfo.successCount, lastUploadInfo.failCount); } -uint32_t CloudSyncer::GetLastUploadSuccessCount(const std::string &tableName) +void CloudSyncer::GetLastUploadInfo(const std::string &tableName, Info &lastUploadInfo) { std::lock_guard autoLock(dataLock_); - return currentContext_.notifier->GetLastUploadSuccessCount(tableName); + return currentContext_.notifier->GetLastUploadInfo(tableName, lastUploadInfo); } int CloudSyncer::FillDownloadExtend(TaskId taskId, const std::string &tableName, const std::string &cloudWaterMark, @@ -129,20 +126,22 @@ QuerySyncObject CloudSyncer::GetQuerySyncObject(const std::string &tableName) return querySyncObject; } +void CloudSyncer::UpdateProcessWhenUploadFailed(InnerProcessInfo &info) +{ + info.tableStatus = ProcessStatus::FINISHED; + std::lock_guard autoLock(dataLock_); + currentContext_.notifier->UpdateProcess(info); +} + void CloudSyncer::NotifyUploadFailed(int errCode, InnerProcessInfo &info) { if (errCode == -E_CLOUD_VERSION_CONFLICT) { LOGI("[CloudSyncer] Stop upload due to version conflict, %d", errCode); - return; } else { LOGE("[CloudSyncer] Failed to do upload, %d", errCode); + info.upLoadInfo.failCount = info.upLoadInfo.total - info.upLoadInfo.successCount; } - info.upLoadInfo.failCount = info.upLoadInfo.total - info.upLoadInfo.successCount; - info.tableStatus = ProcessStatus::FINISHED; - { - std::lock_guard autoLock(dataLock_); - currentContext_.notifier->UpdateProcess(info); - } + UpdateProcessWhenUploadFailed(info); } int CloudSyncer::BatchInsert(Info &insertInfo, CloudSyncData &uploadData, InnerProcessInfo &innerProcessInfo) @@ -167,7 +166,7 @@ int CloudSyncer::BatchInsert(Info &insertInfo, CloudSyncData &uploadData, InnerP if (!isSharedTable) { ret = CloudSyncUtils::FillAssetIdToAssets(uploadData.insData, errCode, CloudWaterType::INSERT); if (ret != errCode) { - LOGE("[CloudSyncer][BatchInsert] FillAssetIdToAssets with error, ret is %d.", ret); + LOGW("[CloudSyncer][BatchInsert] FillAssetIdToAssets with error, ret is %d.", ret); } } if (errCode != E_OK) { @@ -212,12 +211,12 @@ int CloudSyncer::BatchUpdate(Info &updateInfo, CloudSyncData &uploadData, InnerP if (!isSharedTable) { ret = CloudSyncUtils::FillAssetIdToAssets(uploadData.updData, errCode, CloudWaterType::UPDATE); if (ret != E_OK) { - LOGE("[CloudSyncer][BatchUpdate] FillAssetIdToAssets with error, ret is %d.", ret); + LOGW("[CloudSyncer][BatchUpdate] FillAssetIdToAssets with error, ret is %d.", ret); } } if (errCode != E_OK) { storageProxy_->FillCloudGidIfSuccess(OpType::UPDATE, uploadData); - bool isSkip = CloudSyncUtils::IsSkipAssetsMissingRecord(uploadData.insData.extend); + bool isSkip = CloudSyncUtils::IsSkipAssetsMissingRecord(uploadData.updData.extend); if (isSkip) { LOGI("[CloudSyncer][BatchUpdate] Try to FillCloudLogAndAsset when assets missing. errCode: %d", errCode); return E_OK; @@ -403,6 +402,33 @@ int CloudSyncer::DownloadAssetsOneByOneInner(bool isSharedTable, const InnerProc return errCode; } +void CloudSyncer::SeparateNormalAndFailAssets(const std::map &assetsMap, VBucket &normalAssets, + VBucket &failedAssets) +{ + for (auto &[key, assets] : assetsMap) { + Assets tempFailedAssets; + Assets tempNormalAssets; + int32_t otherStatusCnt = 0; + for (auto &asset : assets) { + if (asset.status == AssetStatus::NORMAL) { + tempNormalAssets.push_back(asset); + } else if (asset.status == AssetStatus::ABNORMAL) { + tempFailedAssets.push_back(asset); + } else { + otherStatusCnt++; + } + } + LOGD("[CloudSyncer] download asset times, normalCount %d, abnormalCount %d, otherStatusCnt %d", + tempNormalAssets.size(), tempFailedAssets.size(), otherStatusCnt); + if (tempFailedAssets.size() > 0) { + failedAssets[key] = std::move(tempFailedAssets); + } + if (tempNormalAssets.size() > 0) { + normalAssets[key] = std::move(tempNormalAssets); + } + } +} + int CloudSyncer::CommitDownloadAssets(const DownloadItem &downloadItem, const std::string &tableName, DownloadCommitList &commitList, uint32_t &successCount) { @@ -419,9 +445,12 @@ int CloudSyncer::CommitDownloadAssets(const DownloadItem &downloadItem, const st VBucket failedAssets; normalAssets[CloudDbConstant::GID_FIELD] = gid; failedAssets[CloudDbConstant::GID_FIELD] = gid; - VBucket &assets = setAllNormal ? normalAssets : failedAssets; - for (auto &[key, asset] : assetsMap) { - assets[key] = std::move(asset); + if (setAllNormal) { + for (auto &[key, asset] : assetsMap) { + normalAssets[key] = std::move(asset); + } + } else { + SeparateNormalAndFailAssets(assetsMap, normalAssets, failedAssets); } if (!downloadItem.recordConflict) { errCode = FillCloudAssets(tableName, normalAssets, failedAssets); @@ -453,7 +482,8 @@ int CloudSyncer::CommitDownloadAssets(const DownloadItem &downloadItem, const st void CloudSyncer::GenerateCompensatedSync(CloudTaskInfo &taskInfo) { std::vector syncQuery; - int errCode = storageProxy_->GetCompensatedSyncQuery(syncQuery); + std::vector users; + int errCode = storageProxy_->GetCompensatedSyncQuery(syncQuery, users); if (errCode != E_OK) { LOGW("[CloudSyncer] Generate compensated sync failed by get query! errCode = %d", errCode); return; @@ -462,6 +492,14 @@ void CloudSyncer::GenerateCompensatedSync(CloudTaskInfo &taskInfo) LOGD("[CloudSyncer] Not need generate compensated sync"); return; } + taskInfo.users.clear(); + auto cloudDBs = cloudDB_.GetCloudDB(); + for (auto &[user, cloudDb] : cloudDBs) { + auto it = std::find(users.begin(), users.end(), user); + if (it != users.end()) { + taskInfo.users.push_back(user); + } + } for (const auto &query : syncQuery) { taskInfo.table.push_back(query.GetRelationTableName()); taskInfo.queryList.push_back(query); @@ -516,18 +554,16 @@ int CloudSyncer::SaveCursorIfNeed(const std::string &tableName) int CloudSyncer::PrepareAndDownload(const std::string &table, const CloudTaskInfo &taskInfo, bool isFirstDownload) { - int errCode = SaveCursorIfNeed(table); + std::string hashDev; + int errCode = RuntimeContext::GetInstance()->GetLocalIdentity(hashDev); if (errCode != E_OK) { + LOGE("[CloudSyncer] Failed to get local identity."); return errCode; } - bool isShared = false; - errCode = storageProxy_->IsSharedTable(table, isShared); + errCode = SaveCursorIfNeed(table); if (errCode != E_OK) { - LOGE("[CloudSyncer] check shared table failed %d", errCode); return errCode; } - // shared table not allow logic delete - storageProxy_->SetCloudTaskConfig({ !isShared }); errCode = CheckTaskIdValid(taskInfo.taskId); if (errCode != E_OK) { LOGW("[CloudSyncer] task is invalid, abort sync"); @@ -565,6 +601,7 @@ int CloudSyncer::BatchDelete(Info &deleteInfo, CloudSyncData &uploadData, InnerP uploadData.delData.extend, deleteInfo); innerProcessInfo.upLoadInfo.successCount += deleteInfo.successCount; innerProcessInfo.upLoadInfo.deleteCount += deleteInfo.successCount; + innerProcessInfo.upLoadInfo.total -= deleteInfo.total - deleteInfo.successCount - deleteInfo.failCount; if (errCode != E_OK) { LOGE("[CloudSyncer] Failed to batch delete, %d", errCode); storageProxy_->FillCloudGidIfSuccess(OpType::DELETE, uploadData); @@ -741,17 +778,18 @@ int CloudSyncer::TryToAddSyncTask(CloudTaskInfo &&taskInfo) if (errCode != E_OK) { return errCode; } - cloudTaskInfos_[lastTaskId_] = std::move(taskInfo); - if (cloudTaskInfos_[lastTaskId_].priorityTask) { - priorityTaskQueue_.push_back(lastTaskId_); + auto taskId = taskInfo.taskId; + cloudTaskInfos_[taskId] = std::move(taskInfo); + if (cloudTaskInfos_[taskId].priorityTask) { + priorityTaskQueue_.push_back(taskId); LOGI("[CloudSyncer] Add priority task ok, storeId %.3s, taskId %" PRIu64, - cloudTaskInfos_[lastTaskId_].storeId.c_str(), cloudTaskInfos_[lastTaskId_].taskId); + cloudTaskInfos_[taskId].storeId.c_str(), cloudTaskInfos_[taskId].taskId); return E_OK; } - if (!MergeTaskInfo(cloudSchema, lastTaskId_)) { - taskQueue_.push_back(lastTaskId_); - LOGI("[CloudSyncer] Add task ok, storeId %.3s, taskId %" PRIu64, - cloudTaskInfos_[lastTaskId_].storeId.c_str(), cloudTaskInfos_[lastTaskId_].taskId); + if (!MergeTaskInfo(cloudSchema, taskId)) { + taskQueue_.push_back(taskId); + LOGI("[CloudSyncer] Add task ok, storeId %.3s, taskId %" PRIu64, cloudTaskInfos_[taskId].storeId.c_str(), + cloudTaskInfos_[taskId].taskId); } return E_OK; } @@ -897,12 +935,13 @@ std::pair CloudSyncer::GetLocalWater(const std::string &tableNam } int CloudSyncer::HandleBatchUpload(UploadParam &uploadParam, InnerProcessInfo &info, - CloudSyncData &uploadData, ContinueToken &continueStmtToken) + CloudSyncData &uploadData, ContinueToken &continueStmtToken, std::vector &revisedData) { int ret = E_OK; uint32_t batchIndex = GetCurrentTableUploadBatchIndex(); bool isLocked = false; while (!CloudSyncUtils::CheckCloudSyncDataEmpty(uploadData)) { + revisedData.insert(revisedData.end(), uploadData.revisedData.begin(), uploadData.revisedData.end()); ret = PreProcessBatchUpload(uploadParam, info, uploadData); if (ret != E_OK) { break; @@ -932,7 +971,7 @@ int CloudSyncer::HandleBatchUpload(UploadParam &uploadParam, InnerProcessInfo &i } ChkIgnoredProcess(info, uploadData, uploadParam); } - if ((ret != E_OK) && (ret != -E_UNFINISHED)) { + if ((ret != E_OK) && (ret != -E_UNFINISHED) && (ret != -E_TASK_PAUSED)) { NotifyUploadFailed(ret, info); } if (isLocked && IsNeedLock(uploadParam)) { @@ -1104,7 +1143,8 @@ int CloudSyncer::DoUploadByMode(const std::string &tableName, UploadParam &uploa } uploadParam.count -= uploadData.ignoredCount; info.upLoadInfo.total -= static_cast(uploadData.ignoredCount); - ret = HandleBatchUpload(uploadParam, info, uploadData, continueStmtToken); + std::vector revisedData; + ret = HandleBatchUpload(uploadParam, info, uploadData, continueStmtToken, revisedData); if (ret != -E_TASK_PAUSED) { // reset watermark to zero when task no paused RecordWaterMark(uploadParam.taskId, 0u); @@ -1112,6 +1152,13 @@ int CloudSyncer::DoUploadByMode(const std::string &tableName, UploadParam &uploa if (continueStmtToken != nullptr) { storageProxy_->ReleaseContinueToken(continueStmtToken); } + if (!revisedData.empty()) { + int errCode = storageProxy_->ReviseLocalModTime(tableName, revisedData); + if (errCode != E_OK) { + LOGE("[CloudSyncer] Failed to revise local modify time: %d, table: %s", + errCode, DBCommon::StringMiddleMasking(tableName).c_str()); + } + } return ret; } @@ -1192,7 +1239,7 @@ int CloudSyncer::GenerateTaskIdIfNeed(CloudTaskInfo &taskInfo) taskInfo.storeId.c_str()); return -E_INVALID_ARGS; } - lastTaskId_ = taskInfo.taskId; + lastTaskId_ = std::max(lastTaskId_, taskInfo.taskId); LOGI("[CloudSyncer] Sync with taskId %" PRIu64 " storeId %.3s", taskInfo.taskId, taskInfo.storeId.c_str()); return E_OK; } @@ -1203,4 +1250,4 @@ int CloudSyncer::GenerateTaskIdIfNeed(CloudTaskInfo &taskInfo) taskInfo.taskId = lastTaskId_; return E_OK; } -} \ 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 5228b3a259cc996d34e9479ecd19055118bb9964..afa96547c4a88f0f5232baf7f4c3286444f8844e 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 @@ -44,6 +44,7 @@ public: LockAction lockAction = LockAction::INSERT; bool merge = false; std::string storeId; + std::string prepareTraceId; }; struct InnerProcessInfo { 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 0a0161272b9b2bfd7e47bbf7e9e051f5ffdc1cbc..f852a2a783557a283b193de8dbbc546e16ac9f6c 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 @@ -149,17 +149,20 @@ void ProcessNotifier::ResetUploadBatchIndex(const std::string &tableName) LOGW("[ProcessNotifier] The specified table was not found when reset UploadBatchIndex"); return; } - syncProcess.tableProcess[tableName].upLoadInfo.batchIndex = 0; + if (syncProcess.tableProcess[tableName].upLoadInfo.total == 0) { + syncProcess.tableProcess[tableName].upLoadInfo.batchIndex = 0; + } } -uint32_t ProcessNotifier::GetLastUploadSuccessCount(const std::string &tableName) const +void ProcessNotifier::GetLastUploadInfo(const std::string &tableName, Info &lastUploadInfo) const { + Info lastInfo; std::lock_guard autoLock(processMutex_); auto &syncProcess = IsMultiUser() ? multiSyncProcess_.at(user_) : syncProcess_; - if (syncProcess.tableProcess.find(tableName) == syncProcess_.tableProcess.end()) { - return 0u; + if (syncProcess.tableProcess.find(tableName) != syncProcess_.tableProcess.end()) { + lastInfo = syncProcess.tableProcess.at(tableName).upLoadInfo; } - return syncProcess.tableProcess.at(tableName).upLoadInfo.successCount; + lastUploadInfo = lastInfo; } void ProcessNotifier::GetDownloadInfoByTableName(ICloudSyncer::InnerProcessInfo &process) 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 f688cd5c6db20aed7cedd12577292d29d29025dc..87e2cdfc1b60dceb5f84f003063be83dc1177438 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,7 @@ public: void ResetUploadBatchIndex(const std::string &tableName); - uint32_t GetLastUploadSuccessCount(const std::string &tableName) const; + void GetLastUploadInfo(const std::string &tableName, Info &lastUploadInfo) const; void GetDownloadInfoByTableName(ICloudSyncer::InnerProcessInfo &process); diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/process_recorder.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/process_recorder.cpp index 4c3301ebab3165cdaf2211165ca86d8ed73037d7..1454ccb68b013da23f024855b6b447fd1e3e5433 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/process_recorder.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/process_recorder.cpp @@ -57,7 +57,7 @@ bool ProcessRecorder::IsRecordFinish(int userIndex, const std::string &table, } void ProcessRecorder::RecordFinish(int userIndex, const std::string &table, bool finish, - std::map> &record) + std::map> &record) const { std::lock_guard autoLock(recordMutex_); record[userIndex][table] = finish; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/process_recorder.h b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/process_recorder.h index 5c301d02814294d0ee8a5e5e9ac1b76d588ba683..78f3dc2916a0f6a5ab9e55836189c270c1478702 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/process_recorder.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/process_recorder.h @@ -36,7 +36,7 @@ private: bool IsRecordFinish(int userIndex, const std::string &table, const std::map> &record) const; void RecordFinish(int userIndex, const std::string &table, bool finish, - std::map> &record); + std::map> &record) const; mutable std::mutex recordMutex_; std::map> downloadRecord_; // record table download finish 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 290714e354e3d1545b5480243d5d3b5cf5367bcc..f95ba94b5cb29d71fa12a5ebe88d0d086976d00c 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 @@ -19,8 +19,8 @@ #include "strategy_factory.h" namespace DistributedDB { -std::shared_ptr StrategyFactory::BuildSyncStrategy(SyncMode mode, - SingleVerConflictResolvePolicy policy) +std::shared_ptr StrategyFactory::BuildSyncStrategy( + SyncMode mode, bool isLocalDeleteUpload, SingleVerConflictResolvePolicy policy) { std::shared_ptr strategy; switch (mode) { @@ -38,6 +38,7 @@ std::shared_ptr StrategyFactory::BuildSyncStrategy(SyncMode m strategy = std::make_shared(); } strategy->SetConflictResolvePolicy(policy); + strategy->SetIsLocalDeleteUpload(isLocalDeleteUpload); 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 2a1ee2fa268e9c92df8d4744ba87eeca66ec9bec..d2a66d01a9f2a2fff3ccd57f80ced0932a24609e 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, + static std::shared_ptr BuildSyncStrategy(SyncMode mode, bool isLocalDeleteUpload = 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 3e75eefdc6cd32aa7d09f2fcb2edc65bad6cb53f..9a65b4bd455617a9fbfb8ee5333d480de15db544 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 - LOGI("[AbilitySync] Init remote version with default"); + LOGD("[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/commit_history_sync.h b/kv_store/frameworks/libs/distributeddb/syncer/src/device/commit_history_sync.h index 644d68732a7c48c44f659352e9693aa27ac202c8..3804bafe7474cb812caa723016bf000002638d9f 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/commit_history_sync.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/commit_history_sync.h @@ -17,6 +17,8 @@ #define COMMIT_HISTORY_SYNC_H #ifndef OMIT_MULTI_VER +#include +#include #include #include 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 0605b0985dc59a0f7086d4ebc0047c9bfc017c89..f991cfcf65322d0bffc1b7595eabe32df4140a02 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 @@ -211,7 +211,7 @@ int GenericSyncer::CancelSync(uint32_t syncId) if (iter == syncOperationMap_.end()) { LOGE("[Syncer] Non-existent syncId %" PRIu32 "", syncId); RefObject::DecObjRef(engine); - return -E_NOT_SUPPORT; + return -E_NOT_FOUND; } else if (iter->second->CanCancel() == false) { RefObject::DecObjRef(engine); LOGE("[Syncer] Can't cancel syncId %" PRIu32 " %" PRIu32 "", syncId, iter->second->CanCancel()); diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/isync_packet.h b/kv_store/frameworks/libs/distributeddb/syncer/src/device/isync_packet.h index a283187201463760ecf6ae4873dd2d3d692c0800..6d6d25adfb3d6114eccf6d68da8bcf071f2f8cac 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/isync_packet.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/isync_packet.h @@ -16,6 +16,7 @@ #ifndef ISYNC_PACKET_H #define ISYNC_PACKET_H +#include #include "sync_types.h" namespace DistributedDB { diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/isync_target.h b/kv_store/frameworks/libs/distributeddb/syncer/src/device/isync_target.h index e8fd05cf24eb47d490a88420c5722dfd54817ace..76caee6f993d526e9a8f2d5456acbde0f3e17748 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/isync_target.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/isync_target.h @@ -16,6 +16,7 @@ #ifndef I_SYNC_TARGET_H #define I_SYNC_TARGET_H +#include #include "sync_operation.h" namespace DistributedDB { diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/isync_task_context.h b/kv_store/frameworks/libs/distributeddb/syncer/src/device/isync_task_context.h index 5969004830891d9ce6afd1ab47cadbd9a6d80f12..d66ba8e89cbb35093a4caa2c6c57c51065ac0ce4 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/isync_task_context.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/isync_task_context.h @@ -66,9 +66,9 @@ public: virtual int GetMode() const = 0; // Move to next target to sync - virtual void MoveToNextTarget() = 0; + virtual void MoveToNextTarget(uint32_t timeout) = 0; - virtual int GetNextTarget() = 0; + virtual int GetNextTarget(uint32_t timeout) = 0; // Get the current task syncId virtual uint32_t GetSyncId() const = 0; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/meta_data.h b/kv_store/frameworks/libs/distributeddb/syncer/src/device/meta_data.h index 8c344e790ad538fdabe74694454549f686b7833f..8efc31348f5c034aebaa02dca2014a229a798a1b 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/meta_data.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/meta_data.h @@ -224,9 +224,9 @@ private: SET_TIME_CHANGE_MARK = 0x20, }; - int ClearAllMetaDataValue(uint32_t innerAction); + int ClearAllMetaDataValue(uint32_t innerClearAction); - static void ClearMetaDataValue(uint32_t innerAction, MetaDataValue &metaDataValue); + static void ClearMetaDataValue(uint32_t innerClearAction, MetaDataValue &metaDataValue); static std::pair SerializeLocalMetaData(const LocalMetaData &localMetaData); diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/remote_executor_packet.h b/kv_store/frameworks/libs/distributeddb/syncer/src/device/remote_executor_packet.h index 94ee8b02aa0b5fe4318287821597b4e991e928be..41b0fa6f97584fe5837ece2554d76254a8bfe090 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/remote_executor_packet.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/remote_executor_packet.h @@ -16,6 +16,8 @@ #ifndef REMOTE_EXECUTOR_PACKET_H #define REMOTE_EXECUTOR_PACKET_H +#include +#include #include "isync_packet.h" #include "message.h" #include "prepared_stmt.h" 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 98c60e9c66cad4d0d3134eaab35f929d808106dc..aaf525ec8b4df318c70a3ad4e9729c5459c53f8a 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 @@ -367,7 +367,7 @@ uint32_t DataRequestPacket::GetTotalDataCount() const return totalDataCount_; } -void DataAckPacket::SetData(uint64_t data) +void DataAckPacket::SetData(const uint64_t data) { data_ = data; } diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_packet.h b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_packet.h index 63b57372f5d4dda2f9144a1886c2d828fc04ca45..0f0d54333c27612ceaaffa26047882670316b766 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_packet.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_packet.h @@ -16,6 +16,8 @@ #ifndef SINGLE_VER_DATA_PACKET_NEW_H #define SINGLE_VER_DATA_PACKET_NEW_H +#include +#include #include "icommunicator.h" #include "parcel.h" #include "query_sync_object.h" @@ -160,7 +162,7 @@ public: DataAckPacket() {}; virtual ~DataAckPacket() {}; - void SetData(uint64_t data); + void SetData(const uint64_t data); uint64_t GetData() const; 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 75f8680d46d8c97e593d90bfa686edd0bab7e6ad..4c8a2524473198830c70e4e7cbde43351da12576 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 @@ -1015,7 +1015,7 @@ int SingleVerDataSync::DataRequestRecv(SingleVerSyncTaskContext *context, const (void)SendDataAck(context, message, errCode, dataTime.endTime); return errCode; } - SingleVerDataSyncUtils::UpdateSyncProcess(context, packet, data.size()); + SingleVerDataSyncUtils::UpdateSyncProcess(context, packet); if (pullEndWatermark > 0 && !storage_->IsReadable()) { // pull mode pullEndWatermark = 0; @@ -1096,7 +1096,6 @@ 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) { @@ -1406,8 +1405,13 @@ int32_t SingleVerDataSync::ReSend(SingleVerSyncTaskContext *context, DataSyncReS if (context == nullptr) { return -E_INVALID_ARGS; } + int errCode = RemoveDeviceDataIfNeed(context); + if (errCode != E_OK) { + context->SetTaskErrCode(errCode); + return errCode; + } SyncEntry syncData; - int errCode = GetReSendData(syncData, context, reSendInfo); + errCode = GetReSendData(syncData, context, reSendInfo); if (!SingleVerDataSyncUtils::IsGetDataSuccessfully(errCode)) { return errCode; } @@ -1763,7 +1767,7 @@ void SingleVerDataSync::FillRequestReSendPacket(SingleVerSyncTaskContext *contex FillRequestReSendPacketV2(context, packet); } -void SingleVerDataSync::FillRequestReSendPacketV2(SingleVerSyncTaskContext *context, DataRequestPacket *packet) +void SingleVerDataSync::FillRequestReSendPacketV2(const SingleVerSyncTaskContext *context, DataRequestPacket *packet) { if (context->GetMode() == SyncModeType::RESPONSE_PULL && SingleVerDataSyncUtils::IsSupportRequestTotal(packet->GetVersion())) { @@ -1850,312 +1854,4 @@ int SingleVerDataSync::ControlCmdRequestRecv(SingleVerSyncTaskContext *context, } return errCode; } - -int SingleVerDataSync::ControlCmdAckRecv(SingleVerSyncTaskContext *context, const Message *message) -{ - std::shared_ptr subManager = context->GetSubscribeManager(); - if (subManager == nullptr) { - return -E_INVALID_ARGS; - } - int errCode = SingleVerDataSyncUtils::AckMsgErrnoCheck(context, message); - if (errCode != E_OK) { - SingleVerDataSyncUtils::ControlAckErrorHandle(context, subManager); - return errCode; - } - const ControlAckPacket *packet = message->GetObject(); - if (packet == nullptr) { - return -E_INVALID_ARGS; - } - int32_t recvCode = packet->GetRecvCode(); - uint32_t cmdType = packet->GetcontrolCmdType(); - if (recvCode != E_OK) { - LOGE("[DataSync][AckRecv] control sync abort,recvCode=%d,label=%s,dev=%s,type=%u", recvCode, label_.c_str(), - STR_MASK(GetDeviceId()), cmdType); - // for unsubscribe no need to do something - SingleVerDataSyncUtils::ControlAckErrorHandle(context, subManager); - return recvCode; - } - if (cmdType == ControlCmdType::SUBSCRIBE_QUERY_CMD) { - errCode = subManager->ActiveLocalSubscribeQuery(context->GetDeviceId(), context->GetQuery()); - } else if (cmdType == ControlCmdType::UNSUBSCRIBE_QUERY_CMD) { - subManager->RemoveLocalSubscribeQuery(context->GetDeviceId(), context->GetQuery()); - } - if (errCode != E_OK) { - LOGE("[DataSync] ack handle failed,label =%s,dev=%s,type=%u", label_.c_str(), STR_MASK(GetDeviceId()), cmdType); - return errCode; - } - return -E_NO_DATA_SEND; // means control msg send finished -} - -int SingleVerDataSync::ControlCmdStartCheck(SingleVerSyncTaskContext *context) -{ - if ((context->GetMode() != SyncModeType::SUBSCRIBE_QUERY) && - (context->GetMode() != SyncModeType::UNSUBSCRIBE_QUERY)) { - LOGE("[ControlCmdStartCheck] not support controlCmd"); - return -E_INVALID_ARGS; - } - if (context->GetMode() == SyncModeType::SUBSCRIBE_QUERY && - context->GetQuery().HasInKeys() && - context->IsNotSupportAbility(SyncConfig::INKEYS_QUERY)) { - return -E_NOT_SUPPORT; - } - if ((context->GetMode() != SyncModeType::SUBSCRIBE_QUERY) || context->GetReceivcPermitCheck()) { - return E_OK; - } - bool permitReceive = SingleVerDataSyncUtils::CheckPermitReceiveData(context, communicateHandle_, storage_); - if (permitReceive) { - context->SetReceivcPermitCheck(true); - } else { - return -E_SECURITY_OPTION_CHECK_ERROR; - } - return E_OK; -} - -int SingleVerDataSync::SendControlPacket(ControlRequestPacket *packet, SingleVerSyncTaskContext *context) -{ - Message *message = new (std::nothrow) Message(CONTROL_SYNC_MESSAGE); - if (message == nullptr) { - LOGE("[DataSync][SendControlPacket] new message error"); - delete packet; - packet = nullptr; - return -E_OUT_OF_MEMORY; - } - uint32_t packetLen = packet->CalculateLen(); - int errCode = message->SetExternalObject(packet); - if (errCode != E_OK) { - delete packet; - packet = nullptr; - delete message; - message = nullptr; - LOGE("[DataSync][SendControlPacket] set external object failed errCode=%d", errCode); - return errCode; - } - SingleVerDataSyncUtils::SetMessageHeadInfo(*message, TYPE_REQUEST, context->GetDeviceId(), - context->GetSequenceId(), context->GetRequestSessionId()); - CommErrHandler handler = [this, context, sessionId = message->GetSessionId()](int ret) { - SyncTaskContext::CommErrHandlerFunc(ret, context, sessionId); - }; - errCode = Send(context, message, handler, packetLen); - if (errCode != E_OK) { - delete message; - message = nullptr; - } - return errCode; -} - -int SingleVerDataSync::SendControlAck(SingleVerSyncTaskContext *context, const Message *message, int32_t recvCode, - uint32_t controlCmdType, const CommErrHandler &handler) -{ - Message *ackMessage = new (std::nothrow) Message(message->GetMessageId()); - if (ackMessage == nullptr) { - LOGE("[DataSync][SendControlAck] new message error"); - return -E_OUT_OF_MEMORY; - } - uint32_t version = std::min(context->GetRemoteSoftwareVersion(), SOFTWARE_VERSION_CURRENT); - ControlAckPacket ack; - ack.SetPacketHead(recvCode, version, static_cast(controlCmdType), 0); - int errCode = ackMessage->SetCopiedObject(ack); - if (errCode != E_OK) { - delete ackMessage; - ackMessage = nullptr; - LOGE("[DataSync][SendControlAck] set copied object failed, errcode=%d", errCode); - return errCode; - } - SingleVerDataSyncUtils::SetMessageHeadInfo(*ackMessage, TYPE_RESPONSE, context->GetDeviceId(), - message->GetSequenceId(), message->GetSessionId()); - errCode = Send(context, ackMessage, handler, 0); - if (errCode != E_OK) { - delete ackMessage; - ackMessage = nullptr; - } - return errCode; -} - -int SingleVerDataSync::ControlCmdRequestRecvPre(SingleVerSyncTaskContext *context, const Message *message) -{ - if (context == nullptr || message == nullptr) { - return -E_INVALID_ARGS; - } - const ControlRequestPacket *packet = message->GetObject(); - if (packet == nullptr) { - return -E_INVALID_ARGS; - } - uint32_t controlCmdType = packet->GetcontrolCmdType(); - if (context->GetRemoteSoftwareVersion() <= SOFTWARE_VERSION_BASE) { - return DoAbilitySyncIfNeed(context, message, true); - } - if (controlCmdType >= ControlCmdType::INVALID_CONTROL_CMD) { - SendControlAck(context, message, -E_NOT_SUPPORT, controlCmdType); - return -E_WAIT_NEXT_MESSAGE; - } - return E_OK; -} - -int SingleVerDataSync::SubscribeRequestRecvPre(SingleVerSyncTaskContext *context, const SubscribeRequest *packet, - const Message *message) -{ - uint32_t controlCmdType = packet->GetcontrolCmdType(); - if (controlCmdType != ControlCmdType::SUBSCRIBE_QUERY_CMD) { - return E_OK; - } - QuerySyncObject syncQuery = packet->GetQuery(); - int errCode; - if (!packet->IsAutoSubscribe()) { - errCode = storage_->CheckAndInitQueryCondition(syncQuery); - if (errCode != E_OK) { - LOGE("[SingleVerDataSync] check sync query failed,errCode=%d", errCode); - SendControlAck(context, message, errCode, controlCmdType); - return -E_WAIT_NEXT_MESSAGE; - } - } - int mode = SingleVerDataSyncUtils::GetModeByControlCmdType( - static_cast(packet->GetcontrolCmdType())); - if (mode >= SyncModeType::INVALID_MODE) { - LOGE("[SingleVerDataSync] invalid mode"); - SendControlAck(context, message, -E_INVALID_ARGS, controlCmdType); - return -E_WAIT_NEXT_MESSAGE; - } - errCode = CheckPermitSendData(mode, context); - if (errCode != E_OK) { - LOGE("[SingleVerDataSync] check sync query failed,errCode=%d", errCode); - SendControlAck(context, message, errCode, controlCmdType); - } - return errCode; -} - -int SingleVerDataSync::SubscribeRequestRecv(SingleVerSyncTaskContext *context, const Message *message) -{ - const SubscribeRequest *packet = message->GetObject(); - if (packet == nullptr) { - return -E_INVALID_ARGS; - } - int errCode = SubscribeRequestRecvPre(context, packet, message); - if (errCode != E_OK) { - return errCode; - } - uint32_t controlCmdType = packet->GetcontrolCmdType(); - std::shared_ptr subscribeManager = context->GetSubscribeManager(); - if (subscribeManager == nullptr) { - LOGE("[SingleVerDataSync] subscribeManager check failed"); - SendControlAck(context, message, -E_NOT_REGISTER, controlCmdType); - return -E_INVALID_ARGS; - } - errCode = storage_->AddSubscribe(packet->GetQuery().GetIdentify(), packet->GetQuery(), packet->IsAutoSubscribe()); - if (errCode != E_OK) { - LOGE("[SingleVerDataSync] add trigger failed,err=%d,label=%s,dev=%s", errCode, label_.c_str(), - STR_MASK(GetDeviceId())); - SendControlAck(context, message, errCode, controlCmdType); - return errCode; - } - errCode = subscribeManager->ReserveRemoteSubscribeQuery(context->GetDeviceId(), packet->GetQuery()); - if (errCode != E_OK) { - LOGE("[SingleVerDataSync] add remote subscribe query failed,err=%d,label=%s,dev=%s", errCode, label_.c_str(), - STR_MASK(GetDeviceId())); - RemoveSubscribeIfNeed(packet->GetQuery().GetIdentify(), subscribeManager); - SendControlAck(context, message, errCode, controlCmdType); - return errCode; - } - errCode = SendControlAck(context, message, E_OK, controlCmdType); - if (errCode != E_OK) { - subscribeManager->DeleteRemoteSubscribeQuery(context->GetDeviceId(), packet->GetQuery()); - RemoveSubscribeIfNeed(packet->GetQuery().GetIdentify(), subscribeManager); - LOGE("[SingleVerDataSync] send control msg failed,err=%d,label=%s,dev=%s", errCode, label_.c_str(), - STR_MASK(GetDeviceId())); - return errCode; - } - subscribeManager->ActiveRemoteSubscribeQuery(context->GetDeviceId(), packet->GetQuery()); - DBInfo dbInfo; - storage_->GetDBInfo(dbInfo); - RuntimeContext::GetInstance()->RecordRemoteSubscribe(dbInfo, context->GetDeviceId(), packet->GetQuery()); - return errCode; -} - -int SingleVerDataSync::UnsubscribeRequestRecv(SingleVerSyncTaskContext *context, const Message *message) -{ - const SubscribeRequest *packet = message->GetObject(); - if (packet == nullptr) { - return -E_INVALID_ARGS; - } - uint32_t controlCmdType = packet->GetcontrolCmdType(); - std::shared_ptr subscribeManager = context->GetSubscribeManager(); - if (subscribeManager == nullptr) { - LOGE("[SingleVerDataSync] subscribeManager check failed"); - SendControlAck(context, message, -E_NOT_REGISTER, controlCmdType); - return -E_INVALID_ARGS; - } - int errCode; - std::lock_guard autoLock(unsubscribeLock_); - if (subscribeManager->IsLastRemoteContainSubscribe(context->GetDeviceId(), packet->GetQuery().GetIdentify())) { - errCode = storage_->RemoveSubscribe(packet->GetQuery().GetIdentify()); - if (errCode != E_OK) { - LOGE("[SingleVerDataSync] remove trigger failed,err=%d,label=%s,dev=%s", errCode, label_.c_str(), - STR_MASK(GetDeviceId())); - SendControlAck(context, message, errCode, controlCmdType); - return errCode; - } - } - errCode = SendControlAck(context, message, E_OK, controlCmdType); - if (errCode != E_OK) { - LOGE("[SingleVerDataSync] send control msg failed,err=%d,label=%s,dev=%s", errCode, label_.c_str(), - STR_MASK(GetDeviceId())); - return errCode; - } - subscribeManager->RemoveRemoteSubscribeQuery(context->GetDeviceId(), packet->GetQuery()); - DBInfo dbInfo; - storage_->GetDBInfo(dbInfo); - RuntimeContext::GetInstance()->RemoveRemoteSubscribe(dbInfo, context->GetDeviceId(), packet->GetQuery()); - metadata_->RemoveQueryFromRecordSet(context->GetDeviceId(), packet->GetQuery().GetIdentify()); - return errCode; -} - -void SingleVerDataSync::PutDataMsg(Message *message) -{ - return msgSchedule_.PutMsg(message); -} - -Message *SingleVerDataSync::MoveNextDataMsg(SingleVerSyncTaskContext *context, bool &isNeedHandle, - bool &isNeedContinue) -{ - return msgSchedule_.MoveNextMsg(context, isNeedHandle, isNeedContinue); -} - -bool SingleVerDataSync::IsNeedReloadQueue() -{ - return msgSchedule_.IsNeedReloadQueue(); -} - -void SingleVerDataSync::ScheduleInfoHandle(bool isNeedHandleStatus, bool isNeedClearMap, const Message *message) -{ - msgSchedule_.ScheduleInfoHandle(isNeedHandleStatus, isNeedClearMap, message); -} - -void SingleVerDataSync::ClearDataMsg() -{ - msgSchedule_.ClearMsg(); -} - -int SingleVerDataSync::QuerySyncCheck(SingleVerSyncTaskContext *context) -{ - if (context == nullptr) { - return -E_INVALID_ARGS; - } - bool isCheckStatus = false; - int errCode = SingleVerDataSyncUtils::QuerySyncCheck(context, isCheckStatus); - if (errCode != E_OK) { - return errCode; - } - if (!isCheckStatus) { - context->SetTaskErrCode(-E_NOT_SUPPORT); - return -E_NOT_SUPPORT; - } - return E_OK; -} - -void SingleVerDataSync::RemoveSubscribeIfNeed(const std::string &queryId, - const std::shared_ptr &subscribeManager) -{ - if (!subscribeManager->IsQueryExistSubscribe(queryId)) { - storage_->RemoveSubscribe(queryId); - } -} } // namespace DistributedDB 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 e98503c76c5e1848a4bc8af2a2b61853e1f98b88..abe0b5a0e952403e127f02ca38b4a1e77fda6af3 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 @@ -118,7 +118,7 @@ public: void ClearDataMsg(); void GetLocalWaterMark(SyncType syncType, const std::string &queryIdentify, const SingleVerSyncTaskContext *context, - WaterMark &warterMark) const; + WaterMark &waterMark) const; void GetLocalDeleteSyncWaterMark(const SingleVerSyncTaskContext *context, WaterMark &waterMark) const; @@ -229,8 +229,8 @@ protected: void FillRequestReSendPacket(SingleVerSyncTaskContext *context, DataRequestPacket *packet, DataSyncReSendInfo reSendInfo, SyncEntry &syncData, int sendCode); - - void FillRequestReSendPacketV2(SingleVerSyncTaskContext *context, DataRequestPacket *packet); + + 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_extend.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_sync_extend.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b9f50390043db06260124c3177d6e1ec50b80eb9 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_sync_extend.cpp @@ -0,0 +1,340 @@ +/* + * Copyright (c) 2021 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 "single_ver_data_sync.h" + +#include "db_common.h" +#include "db_types.h" +#include "generic_single_ver_kv_entry.h" +#include "intercepted_data_impl.h" +#include "log_print.h" +#include "message_transform.h" +#include "performance_analysis.h" +#include "single_ver_data_sync_utils.h" +#include "single_ver_sync_state_machine.h" +#include "subscribe_manager.h" +#ifdef RELATIONAL_STORE +#include "relational_db_sync_interface.h" +#endif + +namespace DistributedDB { + int SingleVerDataSync::ControlCmdAckRecv(SingleVerSyncTaskContext *context, const Message *message) +{ + std::shared_ptr subManager = context->GetSubscribeManager(); + if (subManager == nullptr) { + return -E_INVALID_ARGS; + } + int errCode = SingleVerDataSyncUtils::AckMsgErrnoCheck(context, message); + if (errCode != E_OK) { + SingleVerDataSyncUtils::ControlAckErrorHandle(context, subManager); + return errCode; + } + const ControlAckPacket *packet = message->GetObject(); + if (packet == nullptr) { + return -E_INVALID_ARGS; + } + int32_t recvCode = packet->GetRecvCode(); + uint32_t cmdType = packet->GetcontrolCmdType(); + if (recvCode != E_OK) { + LOGE("[DataSync][AckRecv] control sync abort,recvCode=%d,label=%s,dev=%s,type=%u", recvCode, label_.c_str(), + STR_MASK(GetDeviceId()), cmdType); + // for unsubscribe no need to do something + SingleVerDataSyncUtils::ControlAckErrorHandle(context, subManager); + return recvCode; + } + if (cmdType == ControlCmdType::SUBSCRIBE_QUERY_CMD) { + errCode = subManager->ActiveLocalSubscribeQuery(context->GetDeviceId(), context->GetQuery()); + } else if (cmdType == ControlCmdType::UNSUBSCRIBE_QUERY_CMD) { + subManager->RemoveLocalSubscribeQuery(context->GetDeviceId(), context->GetQuery()); + } + if (errCode != E_OK) { + LOGE("[DataSync] ack handle failed,label =%s,dev=%s,type=%u", label_.c_str(), STR_MASK(GetDeviceId()), cmdType); + return errCode; + } + return -E_NO_DATA_SEND; // means control msg send finished +} + +int SingleVerDataSync::ControlCmdStartCheck(SingleVerSyncTaskContext *context) +{ + if ((context->GetMode() != SyncModeType::SUBSCRIBE_QUERY) && + (context->GetMode() != SyncModeType::UNSUBSCRIBE_QUERY)) { + LOGE("[ControlCmdStartCheck] not support controlCmd"); + return -E_INVALID_ARGS; + } + if (context->GetMode() == SyncModeType::SUBSCRIBE_QUERY && + context->GetQuery().HasInKeys() && + context->IsNotSupportAbility(SyncConfig::INKEYS_QUERY)) { + return -E_NOT_SUPPORT; + } + if ((context->GetMode() != SyncModeType::SUBSCRIBE_QUERY) || context->GetReceivcPermitCheck()) { + return E_OK; + } + bool permitReceive = SingleVerDataSyncUtils::CheckPermitReceiveData(context, communicateHandle_, storage_); + if (permitReceive) { + context->SetReceivcPermitCheck(true); + } else { + return -E_SECURITY_OPTION_CHECK_ERROR; + } + return E_OK; +} + +int SingleVerDataSync::SendControlPacket(ControlRequestPacket *packet, SingleVerSyncTaskContext *context) +{ + Message *message = new (std::nothrow) Message(CONTROL_SYNC_MESSAGE); + if (message == nullptr) { + LOGE("[DataSync][SendControlPacket] new message error"); + delete packet; + packet = nullptr; + return -E_OUT_OF_MEMORY; + } + uint32_t packetLen = packet->CalculateLen(); + int errCode = message->SetExternalObject(packet); + if (errCode != E_OK) { + delete packet; + packet = nullptr; + delete message; + message = nullptr; + LOGE("[DataSync][SendControlPacket] set external object failed errCode=%d", errCode); + return errCode; + } + SingleVerDataSyncUtils::SetMessageHeadInfo(*message, TYPE_REQUEST, context->GetDeviceId(), + context->GetSequenceId(), context->GetRequestSessionId()); + CommErrHandler handler = [this, context, sessionId = message->GetSessionId()](int ret) { + SyncTaskContext::CommErrHandlerFunc(ret, context, sessionId); + }; + errCode = Send(context, message, handler, packetLen); + if (errCode != E_OK) { + delete message; + message = nullptr; + } + return errCode; +} + +int SingleVerDataSync::SendControlAck(SingleVerSyncTaskContext *context, const Message *message, int32_t recvCode, + uint32_t controlCmdType, const CommErrHandler &handler) +{ + Message *ackMessage = new (std::nothrow) Message(message->GetMessageId()); + if (ackMessage == nullptr) { + LOGE("[DataSync][SendControlAck] new message error"); + return -E_OUT_OF_MEMORY; + } + uint32_t version = std::min(context->GetRemoteSoftwareVersion(), SOFTWARE_VERSION_CURRENT); + ControlAckPacket ack; + ack.SetPacketHead(recvCode, version, static_cast(controlCmdType), 0); + int errCode = ackMessage->SetCopiedObject(ack); + if (errCode != E_OK) { + delete ackMessage; + ackMessage = nullptr; + LOGE("[DataSync][SendControlAck] set copied object failed, errcode=%d", errCode); + return errCode; + } + SingleVerDataSyncUtils::SetMessageHeadInfo(*ackMessage, TYPE_RESPONSE, context->GetDeviceId(), + message->GetSequenceId(), message->GetSessionId()); + errCode = Send(context, ackMessage, handler, 0); + if (errCode != E_OK) { + delete ackMessage; + ackMessage = nullptr; + } + return errCode; +} + +int SingleVerDataSync::ControlCmdRequestRecvPre(SingleVerSyncTaskContext *context, const Message *message) +{ + if (context == nullptr || message == nullptr) { + return -E_INVALID_ARGS; + } + const ControlRequestPacket *packet = message->GetObject(); + if (packet == nullptr) { + return -E_INVALID_ARGS; + } + uint32_t controlCmdType = packet->GetcontrolCmdType(); + if (context->GetRemoteSoftwareVersion() <= SOFTWARE_VERSION_BASE) { + return DoAbilitySyncIfNeed(context, message, true); + } + if (controlCmdType >= ControlCmdType::INVALID_CONTROL_CMD) { + SendControlAck(context, message, -E_NOT_SUPPORT, controlCmdType); + return -E_WAIT_NEXT_MESSAGE; + } + return E_OK; +} + +int SingleVerDataSync::SubscribeRequestRecvPre(SingleVerSyncTaskContext *context, const SubscribeRequest *packet, + const Message *message) +{ + uint32_t controlCmdType = packet->GetcontrolCmdType(); + if (controlCmdType != ControlCmdType::SUBSCRIBE_QUERY_CMD) { + return E_OK; + } + QuerySyncObject syncQuery = packet->GetQuery(); + int errCode; + if (!packet->IsAutoSubscribe()) { + errCode = storage_->CheckAndInitQueryCondition(syncQuery); + if (errCode != E_OK) { + LOGE("[SingleVerDataSync] check sync query failed,errCode=%d", errCode); + SendControlAck(context, message, errCode, controlCmdType); + return -E_WAIT_NEXT_MESSAGE; + } + } + int mode = SingleVerDataSyncUtils::GetModeByControlCmdType( + static_cast(packet->GetcontrolCmdType())); + if (mode >= SyncModeType::INVALID_MODE) { + LOGE("[SingleVerDataSync] invalid mode"); + SendControlAck(context, message, -E_INVALID_ARGS, controlCmdType); + return -E_WAIT_NEXT_MESSAGE; + } + errCode = CheckPermitSendData(mode, context); + if (errCode != E_OK) { + LOGE("[SingleVerDataSync] check sync query failed,errCode=%d", errCode); + SendControlAck(context, message, errCode, controlCmdType); + } + return errCode; +} + +int SingleVerDataSync::SubscribeRequestRecv(SingleVerSyncTaskContext *context, const Message *message) +{ + const SubscribeRequest *packet = message->GetObject(); + if (packet == nullptr) { + return -E_INVALID_ARGS; + } + int errCode = SubscribeRequestRecvPre(context, packet, message); + if (errCode != E_OK) { + return errCode; + } + uint32_t controlCmdType = packet->GetcontrolCmdType(); + std::shared_ptr subscribeManager = context->GetSubscribeManager(); + if (subscribeManager == nullptr) { + LOGE("[SingleVerDataSync] subscribeManager check failed"); + SendControlAck(context, message, -E_NOT_REGISTER, controlCmdType); + return -E_INVALID_ARGS; + } + errCode = storage_->AddSubscribe(packet->GetQuery().GetIdentify(), packet->GetQuery(), packet->IsAutoSubscribe()); + if (errCode != E_OK) { + LOGE("[SingleVerDataSync] add trigger failed,err=%d,label=%s,dev=%s", errCode, label_.c_str(), + STR_MASK(GetDeviceId())); + SendControlAck(context, message, errCode, controlCmdType); + return errCode; + } + errCode = subscribeManager->ReserveRemoteSubscribeQuery(context->GetDeviceId(), packet->GetQuery()); + if (errCode != E_OK) { + LOGE("[SingleVerDataSync] add remote subscribe query failed,err=%d,label=%s,dev=%s", errCode, label_.c_str(), + STR_MASK(GetDeviceId())); + RemoveSubscribeIfNeed(packet->GetQuery().GetIdentify(), subscribeManager); + SendControlAck(context, message, errCode, controlCmdType); + return errCode; + } + errCode = SendControlAck(context, message, E_OK, controlCmdType); + if (errCode != E_OK) { + subscribeManager->DeleteRemoteSubscribeQuery(context->GetDeviceId(), packet->GetQuery()); + RemoveSubscribeIfNeed(packet->GetQuery().GetIdentify(), subscribeManager); + LOGE("[SingleVerDataSync] send control msg failed,err=%d,label=%s,dev=%s", errCode, label_.c_str(), + STR_MASK(GetDeviceId())); + return errCode; + } + subscribeManager->ActiveRemoteSubscribeQuery(context->GetDeviceId(), packet->GetQuery()); + DBInfo dbInfo; + storage_->GetDBInfo(dbInfo); + RuntimeContext::GetInstance()->RecordRemoteSubscribe(dbInfo, context->GetDeviceId(), packet->GetQuery()); + return errCode; +} + +int SingleVerDataSync::UnsubscribeRequestRecv(SingleVerSyncTaskContext *context, const Message *message) +{ + const SubscribeRequest *packet = message->GetObject(); + if (packet == nullptr) { + return -E_INVALID_ARGS; + } + uint32_t controlCmdType = packet->GetcontrolCmdType(); + std::shared_ptr subscribeManager = context->GetSubscribeManager(); + if (subscribeManager == nullptr) { + LOGE("[SingleVerDataSync] subscribeManager check failed"); + SendControlAck(context, message, -E_NOT_REGISTER, controlCmdType); + return -E_INVALID_ARGS; + } + int errCode; + std::lock_guard autoLock(unsubscribeLock_); + if (subscribeManager->IsLastRemoteContainSubscribe(context->GetDeviceId(), packet->GetQuery().GetIdentify())) { + errCode = storage_->RemoveSubscribe(packet->GetQuery().GetIdentify()); + if (errCode != E_OK) { + LOGE("[SingleVerDataSync] remove trigger failed,err=%d,label=%s,dev=%s", errCode, label_.c_str(), + STR_MASK(GetDeviceId())); + SendControlAck(context, message, errCode, controlCmdType); + return errCode; + } + } + errCode = SendControlAck(context, message, E_OK, controlCmdType); + if (errCode != E_OK) { + LOGE("[SingleVerDataSync] send control msg failed,err=%d,label=%s,dev=%s", errCode, label_.c_str(), + STR_MASK(GetDeviceId())); + return errCode; + } + subscribeManager->RemoveRemoteSubscribeQuery(context->GetDeviceId(), packet->GetQuery()); + DBInfo dbInfo; + storage_->GetDBInfo(dbInfo); + RuntimeContext::GetInstance()->RemoveRemoteSubscribe(dbInfo, context->GetDeviceId(), packet->GetQuery()); + metadata_->RemoveQueryFromRecordSet(context->GetDeviceId(), packet->GetQuery().GetIdentify()); + return errCode; +} + +void SingleVerDataSync::PutDataMsg(Message *message) +{ + return msgSchedule_.PutMsg(message); +} + +Message *SingleVerDataSync::MoveNextDataMsg(SingleVerSyncTaskContext *context, bool &isNeedHandle, + bool &isNeedContinue) +{ + return msgSchedule_.MoveNextMsg(context, isNeedHandle, isNeedContinue); +} + +bool SingleVerDataSync::IsNeedReloadQueue() +{ + return msgSchedule_.IsNeedReloadQueue(); +} + +void SingleVerDataSync::ScheduleInfoHandle(bool isNeedHandleStatus, bool isNeedClearMap, const Message *message) +{ + msgSchedule_.ScheduleInfoHandle(isNeedHandleStatus, isNeedClearMap, message); +} + +void SingleVerDataSync::ClearDataMsg() +{ + msgSchedule_.ClearMsg(); +} + +int SingleVerDataSync::QuerySyncCheck(SingleVerSyncTaskContext *context) +{ + if (context == nullptr) { + return -E_INVALID_ARGS; + } + bool isCheckStatus = false; + int errCode = SingleVerDataSyncUtils::QuerySyncCheck(context, isCheckStatus); + if (errCode != E_OK) { + return errCode; + } + if (!isCheckStatus) { + context->SetTaskErrCode(-E_NOT_SUPPORT); + return -E_NOT_SUPPORT; + } + return E_OK; +} + +void SingleVerDataSync::RemoveSubscribeIfNeed(const std::string &queryId, + const std::shared_ptr &subscribeManager) +{ + if (!subscribeManager->IsQueryExistSubscribe(queryId)) { + storage_->RemoveSubscribe(queryId); + } +} +} // namespace DistributedDB \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_sync_utils.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_sync_utils.cpp index 8a729af6e95e59a64a61668788c4d89c3be51e46..ee31265048802341fef98287170dac43c0ca8f7e 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_sync_utils.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_data_sync_utils.cpp @@ -577,7 +577,7 @@ int SingleVerDataSyncUtils::SchemaVersionMatchCheck(const SingleVerSyncTaskConte return E_OK; } -int SingleVerDataSyncUtils::GetUnsyncTotal(SingleVerSyncTaskContext *context, const SyncGenericInterface *storage, +int SingleVerDataSyncUtils::GetUnsyncTotal(const SingleVerSyncTaskContext *context, const SyncGenericInterface *storage, uint32_t &total) { SyncTimeRange waterRange; @@ -591,7 +591,7 @@ int SingleVerDataSyncUtils::GetUnsyncTotal(SingleVerSyncTaskContext *context, co return GetUnsyncTotal(context, storage, waterRange, total); } -int SingleVerDataSyncUtils::GetUnsyncTotal(SingleVerSyncTaskContext *context, const SyncGenericInterface *storage, +int SingleVerDataSyncUtils::GetUnsyncTotal(const SingleVerSyncTaskContext *context, const SyncGenericInterface *storage, SyncTimeRange &waterMarkInfo, uint32_t &total) { int errCode; @@ -613,17 +613,24 @@ bool SingleVerDataSyncUtils::IsSupportRequestTotal(uint32_t version) return version >= SOFTWARE_VERSION_RELEASE_10_0; } -void SingleVerDataSyncUtils::UpdateSyncProcess(SingleVerSyncTaskContext *context, const DataRequestPacket *packet, - uint32_t dataSize) +void SingleVerDataSyncUtils::UpdateSyncProcess(SingleVerSyncTaskContext *context, const DataRequestPacket *packet) { - LOGD("[DataSync][UpdateSyncProcess] mode=%d, total=%" PRIu64 ", size=%" PRIu64, packet->GetMode(), + const std::vector &data = packet->GetData(); + int32_t dataSize = std::count_if(data.begin(), data.end(), [](SendDataItem item) { + return (item->GetFlag() & DataItem::REMOTE_DEVICE_DATA_MISS_QUERY) == 0; + }); + if (dataSize < 0) { + return; + } + + LOGD("[DataSync][UpdateSyncProcess] mode=%d, total=%" PRIu64 ", size=%d", packet->GetMode(), packet->GetTotalDataCount(), dataSize); if (packet->GetMode() == SyncModeType::PUSH || packet->GetMode() == SyncModeType::QUERY_PUSH) { // save total count to sync process if (packet->GetTotalDataCount() > 0) { context->SetOperationSyncProcessTotal(context->GetDeviceId(), packet->GetTotalDataCount()); } - context->UpdateOperationFinishedCount(context->GetDeviceId(), dataSize); + context->UpdateOperationFinishedCount(context->GetDeviceId(), static_cast(dataSize)); } } 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 275b6d8e54079af1842e88c9f2e7f06aaa82f154..97569cc8762bddcd45a191a397c81032be37df9e 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 @@ -104,16 +104,15 @@ public: static int SchemaVersionMatchCheck(const SingleVerSyncTaskContext &context, const DataRequestPacket &packet, std::shared_ptr &metadata); - static int GetUnsyncTotal(SingleVerSyncTaskContext *context, const SyncGenericInterface *storage, + static int GetUnsyncTotal(const SingleVerSyncTaskContext *context, const SyncGenericInterface *storage, uint32_t &total); - static int GetUnsyncTotal(SingleVerSyncTaskContext *context, const SyncGenericInterface *storage, + 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, - uint32_t dataSize); - + static void UpdateSyncProcess(SingleVerSyncTaskContext *context, const DataRequestPacket *packet); + static void CacheInitWaterMark(SingleVerSyncTaskContext *context, SingleVerDataSync *dataSync); private: static int RunPermissionCheckInner(const SingleVerSyncTaskContext *context, const SyncGenericInterface* storage, diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_engine.h b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_engine.h index 7ae4abd209ed8aba3780ec4a949042623615b033..785588e155e73ae28ded6f5fc992d88d1de7ddc2 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_engine.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_engine.h @@ -16,6 +16,7 @@ #ifndef SINGLE_VER_SYNC_ENGINE_H #define SINGLE_VER_SYNC_ENGINE_H +#include #include "sync_engine.h" namespace DistributedDB { 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 81d63f122a7bd94fdb6a75d652ff144c364b507d..703c701735bc1fb3e64f8aee6b9dff3567e37afa 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 @@ -535,8 +535,9 @@ Event SingleVerSyncStateMachine::DoSyncTaskFinished() { StopWatchDog(); dataSync_->ClearSyncStatus(); + auto timeout = communicator_->GetTimeout(syncContext_->GetDeviceId()); RefObject::AutoLock lock(syncContext_); - int errCode = ExecNextTask(); + int errCode = ExecNextTask(timeout); if (errCode == E_OK) { return Event::START_SYNC_EVENT; } diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_target.h b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_target.h index d0c405c6b8f59ec8ff7b6a5088ae935edcb8efcf..7f8020274de616b7a5918e7c7893f3794c14cf20 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_target.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_target.h @@ -16,6 +16,7 @@ #ifndef SINGLE_VER_SYNC_TARGET_H #define SINGLE_VER_SYNC_TARGET_H +#include #include "db_types.h" #include "query_sync_object.h" #include "sync_target.h" 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 43f28afd6074710918aa846ac7deb306509e9cec..43c156a2e540e2c3cf53db8c1fd709d3b457cb34 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 @@ -661,6 +661,7 @@ int SyncEngine::ExecSyncTask(ISyncTaskContext *context) if (IsKilled()) { return -E_OBJ_IS_KILLED; } + auto timeout = GetTimeout(context->GetDeviceId()); AutoLock lockGuard(context); int status = context->GetTaskExecStatus(); if ((status == SyncTaskContext::RUNNING) || context->IsKilled()) { @@ -668,7 +669,7 @@ int SyncEngine::ExecSyncTask(ISyncTaskContext *context) } context->SetTaskExecStatus(ISyncTaskContext::RUNNING); while (!context->IsTargetQueueEmpty()) { - int errCode = context->GetNextTarget(); + int errCode = context->GetNextTarget(timeout); if (errCode != E_OK) { // current task execute failed, try next task context->ClearSyncOperation(); @@ -1316,4 +1317,21 @@ void SyncEngine::SetSyncInterface(ISyncInterface *syncInterface) std::lock_guard autoLock(storageMutex_); syncInterface_ = syncInterface; } + +uint32_t SyncEngine::GetTimeout(const std::string &dev) +{ + ICommunicator *communicator = nullptr; + { + std::lock_guard autoLock(communicatorProxyLock_); + if (communicatorProxy_ == nullptr) { + LOGW("[SyncEngine] Communicator is null when get %.3s timeout", dev.c_str()); + return DBConstant::MIN_TIMEOUT; + } + communicator = communicatorProxy_; + RefObject::IncObjRef(communicator); + } + uint32_t timeout = communicator->GetTimeout(dev); + RefObject::DecObjRef(communicator); + return timeout; +} } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_engine.h b/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_engine.h index 76fffde847c9de2ba80e5eef9d615195fcd05e72..4b0cc7379a0c7efdd42e23966f6c2f169710d3b1 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_engine.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_engine.h @@ -222,6 +222,8 @@ private: void AddQuerySubscribe(SyncGenericInterface *storage, const std::string &device, const QuerySyncObject &query); + uint32_t GetTimeout(const std::string &dev); + ICommunicator *communicator_; DeviceManager *deviceManager_; std::function onRemoteDataChanged_; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_state_machine.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_state_machine.cpp index df617b6b9319a9d7a0b66046e7894d7fc7b658a1..11bfd3213e2dc0167caf51b6040b2b0654c89d63 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_state_machine.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_state_machine.cpp @@ -170,11 +170,11 @@ void SyncStateMachine::SwitchStateAndStep(uint8_t event) } } -int SyncStateMachine::ExecNextTask() +int SyncStateMachine::ExecNextTask(uint32_t timeout) { syncContext_->Clear(); while (!syncContext_->IsTargetQueueEmpty()) { - int errCode = syncContext_->GetNextTarget(); + int errCode = syncContext_->GetNextTarget(timeout); if (errCode != E_OK) { continue; } diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_state_machine.h b/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_state_machine.h index 040fb9b7f27497fc5265f206f729c2e44424e861..42d97dee0a9630c01cdfae9f0bf5063f53bbac89 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_state_machine.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_state_machine.h @@ -123,7 +123,7 @@ protected: virtual void SwitchStateAndStep(uint8_t event); // To Exec next sync task in context targetQueue - int ExecNextTask(); + int ExecNextTask(uint32_t timeout = DBConstant::MIN_TIMEOUT); // Start a watchdog used for manual sync, when begin a manual sync int StartWatchDog(); diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_target.h b/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_target.h index 11df7813e03996f62ceb7a890f6b68a5d5d8f41c..4347cee97c22e8d145fb9d8f3a4fc67eb4c4b7b2 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_target.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_target.h @@ -16,6 +16,7 @@ #ifndef SYNC_TARGET_H #define SYNC_TARGET_H +#include #include "isync_target.h" namespace DistributedDB { 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 8493a8e0221d0abcfec7b09669dd6cfc4cf09c19..97a27ae7235fbd3607afd7a3d6df3a0e22558184 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 @@ -230,12 +230,12 @@ int SyncTaskContext::GetMode() const return mode_; } -void SyncTaskContext::MoveToNextTarget() +void SyncTaskContext::MoveToNextTarget(uint32_t timeout) { ClearSyncOperation(); TaskParam param; // call other system api without lock - param.timeout = communicator_->GetTimeout(deviceId_); + param.timeout = timeout; std::lock_guard lock(targetQueueLock_); while (!requestTargetQueue_.empty() || !responseTargetQueue_.empty()) { ISyncTarget *tmpTarget = nullptr; @@ -265,9 +265,9 @@ void SyncTaskContext::MoveToNextTarget() } } -int SyncTaskContext::GetNextTarget() +int SyncTaskContext::GetNextTarget(uint32_t timeout) { - MoveToNextTarget(); + MoveToNextTarget(timeout); int checkErrCode = RunPermissionCheck(GetPermissionCheckFlag(IsAutoSync(), GetMode())); if (checkErrCode != E_OK) { SetOperationStatus(SyncOperation::OP_PERMISSION_CHECK_FAILED); 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 ad61d8e82f3655820583504564c6b252f38c9b4f..685baabf64dcd1979ec14a4f7b78e8ac2d766ba8 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 @@ -68,9 +68,9 @@ public: int GetMode() const override; // Move to next target to sync - void MoveToNextTarget() override; + void MoveToNextTarget(uint32_t timeout) override; - int GetNextTarget() override; + int GetNextTarget(uint32_t timeout) override; // Get the current task syncId uint32_t GetSyncId() const override; 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 c96e14579a1d2d1361a2238e57ec11c915a58c5d..4c762676d0be9c460c552e2574287891a097ba27 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/sync_operation.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/sync_operation.h @@ -201,7 +201,7 @@ private: // The device id we syncProcess with std::map syncProcessMap_; - // Can be canceled + // Can be cancelled bool canCancel_ = false; void ExeSyncProcessCallFun(const std::map &syncProcessMap); diff --git a/kv_store/frameworks/libs/distributeddb/test/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/BUILD.gn index 0b9c63217094f88ab9be94601dd60f7c3d9a1d6e..e4661333445b0839d0d03b73870fd7858fdd5347 100644 --- a/kv_store/frameworks/libs/distributeddb/test/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/BUILD.gn @@ -127,6 +127,33 @@ ohos_source_set("src_file") { sources = distributeddb_src sources += [ + "../gaussdb_rd/src/common/src/collection_option.cpp", + "../gaussdb_rd/src/common/src/db_config.cpp", + "../gaussdb_rd/src/common/src/grd_api_manager.cpp", + "../gaussdb_rd/src/common/src/json_common.cpp", + "../gaussdb_rd/src/common/src/os_api.cpp", + "../gaussdb_rd/src/common/src/rd_log_print.cpp", + "../gaussdb_rd/src/executor/base/grd_db_api.cpp", + "../gaussdb_rd/src/executor/base/grd_db_api_inner.cpp", + "../gaussdb_rd/src/executor/document/check_common.cpp", + "../gaussdb_rd/src/executor/document/grd_document_api.cpp", + "../gaussdb_rd/src/executor/document/grd_document_api_inner.cpp", + "../gaussdb_rd/src/executor/document/grd_resultset_api.cpp", + "../gaussdb_rd/src/executor/document/grd_resultset_api_inner.cpp", + "../gaussdb_rd/src/executor/kv/grd_kv_api.cpp", + "../gaussdb_rd/src/executor/kv/grd_kv_api_inner.cpp", + "../gaussdb_rd/src/interface/src/collection.cpp", + "../gaussdb_rd/src/interface/src/doc_errno.cpp", + "../gaussdb_rd/src/interface/src/document_key.cpp", + "../gaussdb_rd/src/interface/src/document_store.cpp", + "../gaussdb_rd/src/interface/src/document_store_manager.cpp", + "../gaussdb_rd/src/interface/src/projection_tree.cpp", + "../gaussdb_rd/src/interface/src/result_set.cpp", + "../gaussdb_rd/src/interface/src/result_set_common.cpp", + "../gaussdb_rd/src/oh_adapter/src/kv_store_manager.cpp", + "../gaussdb_rd/src/oh_adapter/src/rd_json_object.cpp", + "../gaussdb_rd/src/oh_adapter/src/rd_sqlite_utils.cpp", + "../gaussdb_rd/src/oh_adapter/src/sqlite_store_executor_impl.cpp", "unittest/common/common/distributeddb_data_generate_unit_test.cpp", "unittest/common/common/distributeddb_tools_unit_test.cpp", "unittest/common/common/native_sqlite.cpp", @@ -168,7 +195,6 @@ ohos_source_set("src_file") { configs += [ "//third_party/jsoncpp:jsoncpp_config" ] ldflags = [ "-Wl,--exclude-libs,ALL" ] deps += [ - "../gaussdb_rd:gaussdb_rd", "//third_party/jsoncpp:jsoncpp", "//third_party/openssl:libcrypto_shared", ] @@ -207,7 +233,6 @@ template("distributeddb_unittest") { configs += [ "//third_party/jsoncpp:jsoncpp_config" ] ldflags = [ "-Wl,--exclude-libs,ALL" ] deps += [ - "../gaussdb_rd:gaussdb_rd", "//third_party/jsoncpp:jsoncpp", "//third_party/openssl:libcrypto_shared", ] @@ -611,7 +636,7 @@ distributeddb_unittest("DistributedInterfacesRelationalTest") { ] } -distributeddb_unittest("DistributedInterfacesRelationalTrackerTableTest") { +distributeddb_unittest("DistributedDBInterfacesRelationalTrackerTableTest") { sources = [ "unittest/common/interfaces/distributeddb_interfaces_relational_tracker_table_test.cpp" ] } @@ -781,7 +806,7 @@ distributeddb_unittest("DistributedDBCloudTaskMergeTest") { distributeddb_unittest( "DistributedDBStorageMemoryRdSingleVerNaturalStoreTest") { sources = [ - "unittest/common/storage/distributeddb_storage_memory_rd_single_ver_naturall_store_test.cpp", + "unittest/common/storage/distributeddb_storage_memory_rd_single_ver_natural_store_test.cpp", "unittest/common/storage/distributeddb_storage_rd_single_ver_natural_store_testcase.cpp", ] } @@ -791,7 +816,7 @@ distributeddb_unittest("DistributedDBStorageRdRegisterObserverTest") { } distributeddb_unittest("DistributedDBStorageRdResultAndJsonOptimizeTest") { - sources = [ "unittest/common/storage/distributeddb_storage_rd_resultset_and_json_optimize.cpp" ] + sources = [ "unittest/common/storage/distributeddb_storage_rd_result_and_json_optimize_test.cpp" ] } distributeddb_unittest("DistributedDBStorageRdSingleVerNaturalExecutorTest") { @@ -840,6 +865,11 @@ distributeddb_unittest("DistributedDBCloudKvTest") { sources = [ "unittest/common/syncer/cloud/distributeddb_cloud_kv_test.cpp" ] } +distributeddb_unittest("DistributedDBCloudKvStoreTest") { + sources = + [ "unittest/common/syncer/cloud/distributeddb_cloud_kvstore_test.cpp" ] +} + ############################################################################### group("unittest") { testonly = true @@ -857,6 +887,8 @@ group("unittest") { ":DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest", ":DistributedDBCloudInterfacesRelationalSyncTest", ":DistributedDBCloudInterfacesSetCloudSchemaTest", + ":DistributedDBCloudKvStoreTest", + ":DistributedDBCloudKvSyncerTest", ":DistributedDBCloudKvTest", ":DistributedDBCloudReferenceSyncTest", ":DistributedDBCloudSaveCloudDataTest", @@ -868,11 +900,13 @@ group("unittest") { ":DistributedDBCloudSyncerUploadTest", ":DistributedDBCloudTableCompoundPrimaryKeySyncTest", ":DistributedDBCloudTableWithoutPrimaryKeySyncTest", + ":DistributedDBCloudTaskMergeTest", ":DistributedDBCommonTest", ":DistributedDBCommunicatorDeepTest", ":DistributedDBCommunicatorProxyTest", ":DistributedDBCommunicatorSendReceiveTest", ":DistributedDBCommunicatorTest", + ":DistributedDBDataCompressionTest", ":DistributedDBDeviceIdentifierTest", ":DistributedDBEventLoopTimerTest", ":DistributedDBFilePackageTest", @@ -898,6 +932,7 @@ group("unittest") { ":DistributedDBInterfacesRelationalObserverTest", ":DistributedDBInterfacesRelationalRoutinesTest", ":DistributedDBInterfacesRelationalSyncTest", + ":DistributedDBInterfacesRelationalTrackerTableTest", ":DistributedDBInterfacesSchemaDatabaseUpgradeTest", ":DistributedDBInterfacesSpaceManagementTest", ":DistributedDBInterfacesTransactionOptimizationTest", @@ -913,6 +948,7 @@ group("unittest") { ":DistributedDBRelationalCloudSyncableStorageTest", ":DistributedDBRelationalEncryptedDbTest", ":DistributedDBRelationalGetDataTest", + ":DistributedDBRelationalMultiUserTest", ":DistributedDBRelationalRemoteQueryTest", ":DistributedDBRelationalResultSetTest", ":DistributedDBRelationalSchemaObjectTest", diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/cloudsync_fuzzer/cloudsync_fuzzer.cpp b/kv_store/frameworks/libs/distributeddb/test/fuzztest/cloudsync_fuzzer/cloudsync_fuzzer.cpp index 88fdeb087cc03355230e19a61e2ef600f5e46d20..a0bc7988d8f851b2ce04c4c1c76ba3ecbafa271f 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/cloudsync_fuzzer/cloudsync_fuzzer.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/cloudsync_fuzzer/cloudsync_fuzzer.cpp @@ -405,7 +405,7 @@ public: context->WaitForFinish(); } - void OptionBlockSync(std::vector devices, SyncMode mode = SYNC_MODE_CLOUD_MERGE) + void OptionBlockSync(const std::vector &devices, SyncMode mode = SYNC_MODE_CLOUD_MERGE) { Query query = Query::Select().FromTable({ g_table }); auto context = std::make_shared(); diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/json_fuzzer/json_fuzzer.cpp b/kv_store/frameworks/libs/distributeddb/test/fuzztest/json_fuzzer/json_fuzzer.cpp index a1bbce8aebbfa502b4af3a67abe8b643b5dcaeef..8b4ff2d79c11e40bc7f0dfd01048ea3cb657934d 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/json_fuzzer/json_fuzzer.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/json_fuzzer/json_fuzzer.cpp @@ -133,7 +133,7 @@ std::string getMaxString() } } // namespace -void InsertDocOneFuzz(const std::string documentData) +void InsertDocOneFuzz(const std::string &documentData) { std::string document2 = "{\"_id\":2,\"field\":\"" + documentData + "\"}"; GRD_InsertDoc(g_db, COLLECTION_NAME, document2.c_str(), 0); @@ -183,7 +183,7 @@ void InsertDocOneFuzz(const std::string documentData) GRD_InsertDoc(g_db, COLLECTION_NAME, document20.c_str(), 0); } -void InsertDocTwoFuzz(const std::string documentData) +void InsertDocTwoFuzz(const std::string &documentData) { std::string documentPart1 = "{ \"_id\" : \"15\", \"textVal\" : \" "; std::string documentPart2 = "\" }"; @@ -227,7 +227,7 @@ void InsertDocTwoFuzz(const std::string documentData) GRD_InsertDoc(g_db, collectionName5.c_str(), document30.c_str(), 0); } -void InsertDocThreeFuzz(const std::string documentData) +void InsertDocThreeFuzz(const std::string &documentData) { std::string collectionName5 = "gm_sys_collectionName"; std::string document31 = "{\"_id\" : \"24_4\", \"name\" : \"" + documentData + "\"}"; @@ -279,7 +279,7 @@ void InsertDocThreeFuzz(const std::string documentData) GRD_InsertDoc(g_db, COLLECTION_NAME, document38.c_str(), 0); } -void InsertDocFourFuzz(const std::string longId, const std::string documentData) +void InsertDocFourFuzz(const std::string &longId, const std::string &documentData) { std::string document39 = "{\"_id\" : \"35\", \"A_aBdk_324_\" : \"" + documentData + "\", \"name\" : \"" + documentData + "\"}"; @@ -444,7 +444,7 @@ void TearDownTestCase() g_db = nullptr; } -void FindDocResultSetFuzz(const char *collName, const std::string filter, const std::string projectionInfo) +void FindDocResultSetFuzz(const char *collName, const std::string &filter, const std::string &projectionInfo) { GRD_ResultSet *resultSet = nullptr; Query query = { filter.c_str(), projectionInfo.c_str() }; @@ -457,7 +457,7 @@ void FindDocResultSetFuzz(const char *collName, const std::string filter, const GRD_FreeResultSet(resultSet); } -void FindDocWithFlagFuzz(const std::string filter, const std::string projectionInfo, int flag) +void FindDocWithFlagFuzz(const std::string &filter, const std::string &projectionInfo, int flag) { GRD_ResultSet *resultSet = nullptr; Query query = { filter.c_str(), projectionInfo.c_str() }; @@ -469,7 +469,7 @@ void FindDocWithFlagFuzz(const std::string filter, const std::string projectionI GRD_FreeResultSet(resultSet); } -void FindDocNextTwiceFuzz(const std::string filter, const std::string projectionInfo) +void FindDocNextTwiceFuzz(const std::string &filter, const std::string &projectionInfo) { GRD_ResultSet *resultSet = nullptr; Query query = { filter.c_str(), projectionInfo.c_str() }; @@ -939,7 +939,7 @@ void FindDocFuzz(const uint8_t *data, size_t size) GRD_DropCollection(g_db, COLLECTION_NAME, 0); } -void UpdateDocOneFuzz(std::string s, const std::string input) +void UpdateDocOneFuzz(std::string s, const std::string &input) { std::string inputJson = "{\"field5\": \"" + s + "\"}"; GRD_UpdateDoc(g_db, COLLECTION_NAME, "{\"_id\":\"2\"}", inputJson.c_str(), 0); @@ -988,7 +988,7 @@ void UpdateDocOneFuzz(std::string s, const std::string input) GRD_UpdateDoc(g_db, COLLECTION_NAME, "{\"name\":\"doc8\"}", "{\"c0.0\":\"ac\"}", 1); } -void UpdateDocTwoFuzz(const char *newCollName, std::string s, const std::string input) +void UpdateDocTwoFuzz(const char *newCollName, std::string s, const std::string &input) { std::string inputJson = "{\"field5\": \"" + s + "\"}"; GRD_UpdateDoc(g_db, newCollName, "{\"_id\":\"2\"}", inputJson.c_str(), 0); @@ -1115,7 +1115,7 @@ void UpdateDocFuzz(const uint8_t *data, size_t size) UpdateDocFilterFuzz(); } -void UpsertDocNewFuzz(const std::string input, GRD_DB *db1) +void UpsertDocNewFuzz(const std::string &input, GRD_DB *db1) { GRD_CreateCollection(g_db, "student", "", 0); std::string documentNew = @@ -1181,7 +1181,7 @@ void UpsertDocFuzz(const uint8_t *data, size_t size) UpsertDocNewFuzz(input, db1); } -void DeleteDocResultFuzz(const std::string input) +void DeleteDocResultFuzz(const std::string &input) { const char *filter = "{\"age\" : 15}"; GRD_DeleteDoc(g_db, COLLECTION_NAME, filter, 0); @@ -1319,7 +1319,7 @@ void FindAndRelease(Query query) } } // namespace -void FindAndReleaseFuzz(std::string document, std::string filter, Query query, const std::string input) +void FindAndReleaseFuzz(std::string document, std::string filter, Query query, const std::string &input) { GRD_InsertDoc(g_db, COLLECTION_NAME, document.c_str(), 0); query.filter = filter.c_str(); @@ -1412,18 +1412,28 @@ void FreeResultSetFuzz() GRD_DropCollection(g_db, COLLECTION_NAME, 0); } +void DbOpenCloseFuzz(const char *dbFileVal, const char *configStr, GRD_DB *dbVal) +{ + int ret = GRD_DBOpen(dbFileVal, configStr, GRD_DB_OPEN_CREATE, &dbVal); + if (ret == GRD_OK) { + GRD_DBClose(dbVal, GRD_DB_CLOSE); + } +} + void DbOpenOneFuzz(GRD_DB *dbVal) { std::string path = "./documentFuzz.db"; - GRD_DBOpen(path.c_str(), "", GRD_DB_OPEN_ONLY, &dbVal); + int ret = GRD_DBOpen(path.c_str(), "", GRD_DB_OPEN_ONLY, &dbVal); + if (ret == GRD_OK) { + GRD_DBClose(dbVal, GRD_DB_CLOSE); + } (void)remove(path.c_str()); path = "./document.db"; - GRD_DBOpen(path.c_str(), R""({"pageSize":64, "redopubbufsize":4033})"", GRD_DB_OPEN_CREATE, &dbVal); - GRD_DBClose(dbVal, 0); - GRD_DBOpen(path.c_str(), R""({"pageSize":64, "redopubbufsize":4032})"", GRD_DB_OPEN_CREATE, &dbVal); - GRD_DBOpen(path.c_str(), R""({"redopubbufsize":255})"", GRD_DB_OPEN_CREATE, &dbVal); - GRD_DBOpen(path.c_str(), R""({"redopubbufsize":16385})"", GRD_DB_OPEN_CREATE, &dbVal); + DbOpenCloseFuzz(path.c_str(), R""({"pageSize":64, "redopubbufsize":4033})"", dbVal); + DbOpenCloseFuzz(path.c_str(), R""({"pageSize":64, "redopubbufsize":4032})"", dbVal); + DbOpenCloseFuzz(path.c_str(), R""({"redopubbufsize":255})"", dbVal); + DbOpenCloseFuzz(path.c_str(), R""({"redopubbufsize":16385})"", dbVal); } void DbOpenFuzz(const uint8_t *data, size_t size) @@ -1438,46 +1448,47 @@ void DbOpenFuzz(const uint8_t *data, size_t size) GRD_DropCollection(g_db, COLLECTION_NAME, 0); std::string stringMax = getMaxString(); const char *configStrMaxLen = stringMax.data(); - GRD_DBOpen(dbFileVal, configStrMaxLen, GRD_DB_OPEN_CREATE, &dbVal); + DbOpenCloseFuzz(dbFileVal, configStrMaxLen, dbVal); std::string fieldStringValue = "{\"bufferPoolSize\": \"1024.5\"}"; const char *configStrStringValue = fieldStringValue.data(); - GRD_DBOpen(dbFileVal, configStrStringValue, GRD_DB_OPEN_CREATE, &dbVal); + DbOpenCloseFuzz(dbFileVal, configStrStringValue, dbVal); std::string fieldBoolValue = "{\"bufferPoolSize\":}"; const char *configStrBool = fieldBoolValue.data(); - GRD_DBOpen(dbFileVal, configStrBool, GRD_DB_OPEN_CREATE, &dbVal); + DbOpenCloseFuzz(dbFileVal, configStrBool, dbVal); std::string fieldStringValueAppend = "{\"bufferPoolSize\":\"8192\"}"; const char *configStrStr = fieldStringValueAppend.data(); - GRD_DBOpen(dbFileVal, configStrStr, GRD_DB_OPEN_CREATE, &dbVal); + DbOpenCloseFuzz(dbFileVal, configStrStr, dbVal); std::string fieldStringValueFlush = "{\"bufferPoolSize\":\"8192\",\"redoFlushBtTrx\":\"1\"}"; const char *configStrFlush = fieldStringValueFlush.data(); - GRD_DBOpen(dbFileVal, configStrFlush, GRD_DB_OPEN_CREATE, &dbVal); + DbOpenCloseFuzz(dbFileVal, configStrFlush, dbVal); std::string fieldStringValueRedoBufsize = "{\"bufferPoolSize\":\"8192\",\"redoBufSize\":\"16384\"}"; const char *configStrBs = fieldStringValueRedoBufsize.data(); - GRD_DBOpen(dbFileVal, configStrBs, GRD_DB_OPEN_CREATE, &dbVal); + DbOpenCloseFuzz(dbFileVal, configStrBs, dbVal); std::string fieldStringValueMaxConnNum = "{\"bufferPoolSize\":\"8192\",\"maxConnNum\":\"1024\"}"; const char *configStrMcn = fieldStringValueMaxConnNum.data(); - GRD_DBOpen(dbFileVal, configStrMcn, GRD_DB_OPEN_CREATE, &dbVal); + DbOpenCloseFuzz(dbFileVal, configStrMcn, dbVal); GRD_DropCollection(g_db, COLLECTION_NAME, 0); std::string fieldStringValueAll = "{\"bufferPoolSize\":\"8192\",\"redoFlushBtTrx\":\"1\",\"redoBufSize\":" "\"16384\",\"maxConnNum\":\"1024\"}"; const char *configStrAll = fieldStringValueAll.data(); - GRD_DBOpen(dbFileVal, configStrAll, GRD_DB_OPEN_CREATE, &dbVal); + DbOpenCloseFuzz(dbFileVal, configStrAll, dbVal); std::string fieldLowNumber = "{\"bufferPoolSize\": 102}"; const char *configStrLowNumber = fieldLowNumber.data(); - GRD_DBOpen(dbFileVal, configStrLowNumber, GRD_DB_OPEN_CREATE, &dbVal); + DbOpenCloseFuzz(dbFileVal, configStrLowNumber, dbVal); - GRD_DBOpen(nullptr, configStrVal, GRD_DB_OPEN_CREATE, &dbVal); - GRD_DBOpen(dbFileVal, configStrVal, GRD_DB_OPEN_CREATE, &dbVal); - GRD_DBClose(nullptr, GRD_DB_CLOSE); - GRD_DBClose(dbVal, GRD_DB_CLOSE); + int ret = GRD_DBOpen(nullptr, configStrVal, GRD_DB_OPEN_CREATE, &dbVal); + if (ret == GRD_OK) { + GRD_DBClose(nullptr, GRD_DB_CLOSE); + } + DbOpenCloseFuzz(dbFileVal, configStrVal, dbVal); DbOpenOneFuzz(dbVal); } @@ -1490,27 +1501,30 @@ void DbCloseFuzz(const uint8_t *data, size_t size) std::string configStrData(reinterpret_cast(data), size); const char *configStrVal = configStrData.data(); GRD_DB *dbVal = nullptr; - GRD_DBOpen(dbFileVal, configStrVal, GRD_DB_OPEN_CREATE, &dbVal); - GRD_DBClose(dbVal, GRD_DB_CLOSE); + DbOpenCloseFuzz(dbFileVal, configStrVal, dbVal); } void DbCloseResultSetFuzz() { GRD_DB *db = nullptr; GRD_DB *db2 = nullptr; - GRD_DBOpen(TEST_DB_FILE, CONFIG_STR, GRD_DB_OPEN_CREATE, &db); - GRD_DBOpen(TEST_DB_FILE, CONFIG_STR, GRD_DB_OPEN_CREATE, &db2); - GRD_CreateCollection(db, "collection1", "{\"maxdoc\" : 5}", 0); + int ret = GRD_DBOpen(TEST_DB_FILE, CONFIG_STR, GRD_DB_OPEN_CREATE, &db); + int errCode = GRD_DBOpen(TEST_DB_FILE, CONFIG_STR, GRD_DB_OPEN_CREATE, &db2); + if (ret == GRD_OK) { + GRD_CreateCollection(db, "collection1", "{\"maxdoc\" : 5}", 0); - GRD_ResultSet *resultSet = nullptr; - Query query = { "{}", "{}" }; - GRD_FindDoc(db, "collection1", query, 0, &resultSet); + GRD_ResultSet *resultSet = nullptr; + Query query = { "{}", "{}" }; + GRD_FindDoc(db, "collection1", query, 0, &resultSet); - GRD_FreeResultSet(resultSet); + GRD_FreeResultSet(resultSet); - GRD_DBClose(db, GRD_DB_CLOSE); + GRD_DBClose(db, GRD_DB_CLOSE); + } - GRD_DBClose(db2, GRD_DB_CLOSE); + if (errCode == GRD_OK) { + GRD_DBClose(db2, GRD_DB_CLOSE); + } } void CreateCollectionFuzz(const uint8_t *data, size_t size) @@ -1553,19 +1567,21 @@ void DbFlushFuzz(const uint8_t *data, size_t size) { GRD_DB *db = nullptr; GRD_DB *db2 = nullptr; - GRD_DBOpen(TEST_DB_FILE, CONFIG_STR, GRD_DB_OPEN_CREATE, &db); - GRD_Flush(db, 0); - GRD_Flush(db, 1); + int ret = GRD_DBOpen(TEST_DB_FILE, CONFIG_STR, GRD_DB_OPEN_CREATE, &db); + if (ret == GRD_OK) { + GRD_Flush(db, 0); + GRD_Flush(db, 1); + GRD_DBClose(db, GRD_DB_CLOSE); + } GRD_Flush(db2, 0); GRD_Flush(db2, 1); - GRD_DBClose(db, GRD_DB_CLOSE); } void TestGrdDbApGrdGetItem002Fuzz() { const char *config = CONFIG_STR; GRD_DB *db = nullptr; - GRD_DBOpen(TEST_DB_FILE, config, GRD_DB_OPEN_CREATE, &db); + DbOpenCloseFuzz(TEST_DB_FILE, config, db); GRD_IndexPreload(nullptr, COLLECTION_NAME); GRD_IndexPreload(nullptr, "invalid_name"); GRD_IndexPreload(g_db, COLLECTION_NAME); @@ -1610,7 +1626,7 @@ void TestGrdKvBatchCoupling003Fuzz() { const char *config = CONFIG_STR; GRD_DB *db = nullptr; - GRD_DBOpen(TEST_DB_FILE, config, GRD_DB_OPEN_CREATE, &db); + DbOpenCloseFuzz(TEST_DB_FILE, config, db); GRD_ResultSet *resultSet = nullptr; GRD_KVScan(g_db, COLLECTION_NAME, nullptr, KV_SCAN_PREFIX, &resultSet); diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/jsoninner_fuzzer/jsoninner_fuzzer.cpp b/kv_store/frameworks/libs/distributeddb/test/fuzztest/jsoninner_fuzzer/jsoninner_fuzzer.cpp index ec07c6f7afc492112bd9582c523c079d77d9a3c4..d619d96602751698dc71b84775861800a7773ed6 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/jsoninner_fuzzer/jsoninner_fuzzer.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/jsoninner_fuzzer/jsoninner_fuzzer.cpp @@ -142,7 +142,7 @@ std::string getMaxString() } } // namespace -void InsertDocOneFuzz(const std::string documentData) +void InsertDocOneFuzz(const std::string &documentData) { std::string document2 = "{\"_id\":2,\"field\":\"" + documentData + "\"}"; GRD_InsertDocInner(g_db, COLLECTION_NAME, document2.c_str(), 0); @@ -192,7 +192,7 @@ void InsertDocOneFuzz(const std::string documentData) GRD_InsertDocInner(g_db, COLLECTION_NAME, document20.c_str(), 0); } -void InsertDocTwoFuzz(const std::string documentData) +void InsertDocTwoFuzz(const std::string &documentData) { std::string documentPart1 = "{ \"_id\" : \"15\", \"textVal\" : \" "; std::string documentPart2 = "\" }"; @@ -236,7 +236,7 @@ void InsertDocTwoFuzz(const std::string documentData) GRD_InsertDocInner(g_db, collectionName5.c_str(), document30.c_str(), 0); } -void InsertDocThreeFuzz(const std::string documentData) +void InsertDocThreeFuzz(const std::string &documentData) { std::string collectionName5 = "gm_sys_collectionName"; std::string document31 = "{\"_id\" : \"24_4\", \"name\" : \"" + documentData + "\"}"; @@ -288,7 +288,7 @@ void InsertDocThreeFuzz(const std::string documentData) GRD_InsertDocInner(g_db, COLLECTION_NAME, document38.c_str(), 0); } -void InsertDocFourFuzz(const std::string longId, const std::string documentData) +void InsertDocFourFuzz(const std::string &longId, const std::string &documentData) { std::string document39 = "{\"_id\" : \"35\", \"A_aBdk_324_\" : \"" + documentData + "\", \"name\" : \"" + documentData + "\"}"; @@ -453,7 +453,7 @@ void TearDownTestCase() g_db = nullptr; } -void FindDocResultSetFuzz(const char *collName, const std::string filter, const std::string projectionInfo) +void FindDocResultSetFuzz(const char *collName, const std::string &filter, const std::string &projectionInfo) { GRD_ResultSet *resultSet = nullptr; Query query = { filter.c_str(), projectionInfo.c_str() }; @@ -466,7 +466,7 @@ void FindDocResultSetFuzz(const char *collName, const std::string filter, const GRD_FreeResultSetInner(resultSet); } -void FindDocWithFlagFuzz(const std::string filter, const std::string projectionInfo, int flag) +void FindDocWithFlagFuzz(const std::string &filter, const std::string &projectionInfo, int flag) { GRD_ResultSet *resultSet = nullptr; Query query = { filter.c_str(), projectionInfo.c_str() }; @@ -478,7 +478,7 @@ void FindDocWithFlagFuzz(const std::string filter, const std::string projectionI GRD_FreeResultSetInner(resultSet); } -void FindDocNextTwiceFuzz(const std::string filter, const std::string projectionInfo) +void FindDocNextTwiceFuzz(const std::string &filter, const std::string &projectionInfo) { GRD_ResultSet *resultSet = nullptr; Query query = { filter.c_str(), projectionInfo.c_str() }; @@ -948,7 +948,7 @@ void FindDocFuzz(const uint8_t *data, size_t size) GRD_DropCollectionInner(g_db, COLLECTION_NAME, 0); } -void UpdateDocOneFuzz(std::string s, const std::string input) +void UpdateDocOneFuzz(std::string s, const std::string &input) { std::string inputJson = "{\"field5\": \"" + s + "\"}"; GRD_UpdateDocInner(g_db, COLLECTION_NAME, "{\"_id\":\"2\"}", inputJson.c_str(), 0); @@ -997,7 +997,7 @@ void UpdateDocOneFuzz(std::string s, const std::string input) GRD_UpdateDocInner(g_db, COLLECTION_NAME, "{\"name\":\"doc8\"}", "{\"c0.0\":\"ac\"}", 1); } -void UpdateDocTwoFuzz(const char *newCollName, std::string s, const std::string input) +void UpdateDocTwoFuzz(const char *newCollName, std::string s, const std::string &input) { std::string inputJson = "{\"field5\": \"" + s + "\"}"; GRD_UpdateDocInner(g_db, newCollName, "{\"_id\":\"2\"}", inputJson.c_str(), 0); @@ -1124,7 +1124,7 @@ void UpdateDocFuzz(const uint8_t *data, size_t size) UpdateDocFilterFuzz(); } -void UpsertDocNewFuzz(const std::string input, GRD_DB *db1) +void UpsertDocNewFuzz(const std::string &input, GRD_DB *db1) { GRD_CreateCollectionInner(g_db, "student", "", 0); std::string documentNew = @@ -1190,7 +1190,7 @@ void UpsertDocFuzz(const uint8_t *data, size_t size) UpsertDocNewFuzz(input, db1); } -void DeleteDocResultFuzz(const std::string input) +void DeleteDocResultFuzz(const std::string &input) { const char *filter = "{\"age\" : 15}"; GRD_DeleteDocInner(g_db, COLLECTION_NAME, filter, 0); @@ -1328,7 +1328,7 @@ void FindAndRelease(Query query) } } // namespace -void FindAndReleaseFuzz(std::string document, std::string filter, Query query, const std::string input) +void FindAndReleaseFuzz(std::string document, std::string filter, Query query, const std::string &input) { GRD_InsertDocInner(g_db, COLLECTION_NAME, document.c_str(), 0); query.filter = filter.c_str(); @@ -1421,18 +1421,28 @@ void FreeResultSetFuzz() GRD_DropCollectionInner(g_db, COLLECTION_NAME, 0); } +void DbOpenCloseFuzz(const char *dbFileVal, const char *configStr, GRD_DB *dbVal) +{ + int ret = GRD_DBOpenInner(dbFileVal, configStr, GRD_DB_OPEN_CREATE, &dbVal); + if (ret == GRD_OK) { + GRD_DBCloseInner(dbVal, GRD_DB_CLOSE); + } +} + void DbOpenOneFuzz(GRD_DB *dbVal) { std::string path = "./documentFuzz.db"; - GRD_DBOpenInner(path.c_str(), "", GRD_DB_OPEN_ONLY, &dbVal); + int ret = GRD_DBOpenInner(path.c_str(), "", GRD_DB_OPEN_ONLY, &dbVal); + if (ret == GRD_OK) { + GRD_DBCloseInner(dbVal, GRD_DB_CLOSE); + } (void)remove(path.c_str()); path = "./document.db"; - GRD_DBOpenInner(path.c_str(), R""({"pageSize":64, "redopubbufsize":4033})"", GRD_DB_OPEN_CREATE, &dbVal); - GRD_DBCloseInner(dbVal, 0); - GRD_DBOpenInner(path.c_str(), R""({"pageSize":64, "redopubbufsize":4032})"", GRD_DB_OPEN_CREATE, &dbVal); - GRD_DBOpenInner(path.c_str(), R""({"redopubbufsize":255})"", GRD_DB_OPEN_CREATE, &dbVal); - GRD_DBOpenInner(path.c_str(), R""({"redopubbufsize":16385})"", GRD_DB_OPEN_CREATE, &dbVal); + DbOpenCloseFuzz(path.c_str(), R""({"pageSize":64, "redopubbufsize":4033})"", dbVal); + DbOpenCloseFuzz(path.c_str(), R""({"pageSize":64, "redopubbufsize":4032})"", dbVal); + DbOpenCloseFuzz(path.c_str(), R""({"redopubbufsize":255})"", dbVal); + DbOpenCloseFuzz(path.c_str(), R""({"redopubbufsize":16385})"", dbVal); } void DbOpenFuzz(const uint8_t *data, size_t size) @@ -1447,46 +1457,47 @@ void DbOpenFuzz(const uint8_t *data, size_t size) GRD_DropCollectionInner(g_db, COLLECTION_NAME, 0); std::string stringMax = getMaxString(); const char *configStrMaxLen = stringMax.data(); - GRD_DBOpenInner(dbFileVal, configStrMaxLen, GRD_DB_OPEN_CREATE, &dbVal); + DbOpenCloseFuzz(dbFileVal, configStrMaxLen, dbVal); std::string fieldStringValue = "{\"bufferPoolSize\": \"1024.5\"}"; const char *configStrStringValue = fieldStringValue.data(); - GRD_DBOpenInner(dbFileVal, configStrStringValue, GRD_DB_OPEN_CREATE, &dbVal); + DbOpenCloseFuzz(dbFileVal, configStrStringValue, dbVal); std::string fieldBoolValue = "{\"bufferPoolSize\":}"; const char *configStrBool = fieldBoolValue.data(); - GRD_DBOpenInner(dbFileVal, configStrBool, GRD_DB_OPEN_CREATE, &dbVal); + DbOpenCloseFuzz(dbFileVal, configStrBool, dbVal); std::string fieldStringValueAppend = "{\"bufferPoolSize\":\"8192\"}"; const char *configStrStr = fieldStringValueAppend.data(); - GRD_DBOpenInner(dbFileVal, configStrStr, GRD_DB_OPEN_CREATE, &dbVal); + DbOpenCloseFuzz(dbFileVal, configStrStr, dbVal); std::string fieldStringValueFlush = "{\"bufferPoolSize\":\"8192\",\"redoFlushBtTrx\":\"1\"}"; const char *configStrFlush = fieldStringValueFlush.data(); - GRD_DBOpenInner(dbFileVal, configStrFlush, GRD_DB_OPEN_CREATE, &dbVal); + DbOpenCloseFuzz(dbFileVal, configStrFlush, dbVal); std::string fieldStringValueRedoBufsize = "{\"bufferPoolSize\":\"8192\",\"redoBufSize\":\"16384\"}"; const char *configStrBs = fieldStringValueRedoBufsize.data(); - GRD_DBOpenInner(dbFileVal, configStrBs, GRD_DB_OPEN_CREATE, &dbVal); + DbOpenCloseFuzz(dbFileVal, configStrBs, dbVal); std::string fieldStringValueMaxConnNum = "{\"bufferPoolSize\":\"8192\",\"maxConnNum\":\"1024\"}"; const char *configStrMcn = fieldStringValueMaxConnNum.data(); - GRD_DBOpenInner(dbFileVal, configStrMcn, GRD_DB_OPEN_CREATE, &dbVal); + DbOpenCloseFuzz(dbFileVal, configStrMcn, dbVal); GRD_DropCollectionInner(g_db, COLLECTION_NAME, 0); std::string fieldStringValueAll = "{\"bufferPoolSize\":\"8192\",\"redoFlushBtTrx\":\"1\",\"redoBufSize\":" "\"16384\",\"maxConnNum\":\"1024\"}"; const char *configStrAll = fieldStringValueAll.data(); - GRD_DBOpenInner(dbFileVal, configStrAll, GRD_DB_OPEN_CREATE, &dbVal); + DbOpenCloseFuzz(dbFileVal, configStrAll, dbVal); std::string fieldLowNumber = "{\"bufferPoolSize\": 102}"; const char *configStrLowNumber = fieldLowNumber.data(); - GRD_DBOpenInner(dbFileVal, configStrLowNumber, GRD_DB_OPEN_CREATE, &dbVal); + DbOpenCloseFuzz(dbFileVal, configStrLowNumber, dbVal); - GRD_DBOpenInner(nullptr, configStrVal, GRD_DB_OPEN_CREATE, &dbVal); - GRD_DBOpenInner(dbFileVal, configStrVal, GRD_DB_OPEN_CREATE, &dbVal); - GRD_DBCloseInner(nullptr, GRD_DB_CLOSE); - GRD_DBCloseInner(dbVal, GRD_DB_CLOSE); + int ret = GRD_DBOpenInner(nullptr, configStrVal, GRD_DB_OPEN_CREATE, &dbVal); + if (ret == GRD_OK) { + GRD_DBCloseInner(nullptr, GRD_DB_CLOSE); + } + DbOpenCloseFuzz(dbFileVal, configStrVal, dbVal); DbOpenOneFuzz(dbVal); } @@ -1499,27 +1510,30 @@ void DbCloseFuzz(const uint8_t *data, size_t size) std::string configStrData(reinterpret_cast(data), size); const char *configStrVal = configStrData.data(); GRD_DB *dbVal = nullptr; - GRD_DBOpenInner(dbFileVal, configStrVal, GRD_DB_OPEN_CREATE, &dbVal); - GRD_DBCloseInner(dbVal, GRD_DB_CLOSE); + DbOpenCloseFuzz(dbFileVal, configStrVal, dbVal); } void DbCloseResultSetFuzz() { GRD_DB *db = nullptr; GRD_DB *db2 = nullptr; - GRD_DBOpenInner(TEST_DB_FILE, CONFIG_STR, GRD_DB_OPEN_CREATE, &db); - GRD_DBOpenInner(TEST_DB_FILE, CONFIG_STR, GRD_DB_OPEN_CREATE, &db2); - GRD_CreateCollectionInner(db, "collection1", "{\"maxdoc\" : 5}", 0); + int ret = GRD_DBOpenInner(TEST_DB_FILE, CONFIG_STR, GRD_DB_OPEN_CREATE, &db); + int errCode = GRD_DBOpenInner(TEST_DB_FILE, CONFIG_STR, GRD_DB_OPEN_CREATE, &db2); + if (ret == GRD_OK) { + GRD_CreateCollectionInner(db, "collection1", "{\"maxdoc\" : 5}", 0); - GRD_ResultSet *resultSet = nullptr; - Query query = { "{}", "{}" }; - GRD_FindDocInner(db, "collection1", query, 0, &resultSet); + GRD_ResultSet *resultSet = nullptr; + Query query = { "{}", "{}" }; + GRD_FindDocInner(db, "collection1", query, 0, &resultSet); - GRD_FreeResultSetInner(resultSet); + GRD_FreeResultSetInner(resultSet); - GRD_DBCloseInner(db, GRD_DB_CLOSE); + GRD_DBCloseInner(db, GRD_DB_CLOSE); + } - GRD_DBCloseInner(db2, GRD_DB_CLOSE); + if (errCode == GRD_OK) { + GRD_DBCloseInner(db2, GRD_DB_CLOSE); + } } void CreateCollectionFuzz(const uint8_t *data, size_t size) @@ -1562,19 +1576,21 @@ void DbFlushFuzz(const uint8_t *data, size_t size) { GRD_DB *db = nullptr; GRD_DB *db2 = nullptr; - GRD_DBOpenInner(TEST_DB_FILE, CONFIG_STR, GRD_DB_OPEN_CREATE, &db); - GRD_FlushInner(db, 0); - GRD_FlushInner(db, 1); + int ret = GRD_DBOpenInner(TEST_DB_FILE, CONFIG_STR, GRD_DB_OPEN_CREATE, &db); + if (ret == GRD_OK) { + GRD_FlushInner(db, 0); + GRD_FlushInner(db, 1); + GRD_DBCloseInner(db, GRD_DB_CLOSE); + } GRD_FlushInner(db2, 0); GRD_FlushInner(db2, 1); - GRD_DBCloseInner(db, GRD_DB_CLOSE); } void TestGrdDbApGrdGetItem002Fuzz() { const char *config = CONFIG_STR; GRD_DB *db = nullptr; - GRD_DBOpenInner(TEST_DB_FILE, config, GRD_DB_OPEN_CREATE, &db); + DbOpenCloseFuzz(TEST_DB_FILE, config, db); GRD_IndexPreloadInner(nullptr, COLLECTION_NAME); GRD_IndexPreloadInner(nullptr, "invalid_name"); GRD_IndexPreloadInner(g_db, COLLECTION_NAME); @@ -1619,7 +1635,7 @@ void TestGrdKvBatchCoupling003Fuzz() { const char *config = CONFIG_STR; GRD_DB *db = nullptr; - GRD_DBOpenInner(TEST_DB_FILE, config, GRD_DB_OPEN_CREATE, &db); + DbOpenCloseFuzz(TEST_DB_FILE, config, db); GRD_ResultSet *resultSet = nullptr; GRD_KVScanInner(g_db, COLLECTION_NAME, nullptr, KV_SCAN_PREFIX, &resultSet); diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoredelegate_fuzzer/relationalstoredelegate_fuzzer.cpp b/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoredelegate_fuzzer/relationalstoredelegate_fuzzer.cpp index b484b62b9d04ff1164ad6ea19a215efacc6cf0af..e2d3e45b2a42dfa65d3606156408f77809fdf43d 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoredelegate_fuzzer/relationalstoredelegate_fuzzer.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoredelegate_fuzzer/relationalstoredelegate_fuzzer.cpp @@ -98,7 +98,7 @@ void TearDown() } void MultiCombineTest(const uint8_t *data, const std::string &tableName, const std::string &extendColName, - std::set trackerColNames, bool isDeleted) + const std::set &trackerColNames, const bool isDeleted) { TrackerSchema schema; schema.tableName = tableName; @@ -128,11 +128,11 @@ void CombineTest(const uint8_t *data, size_t size) observer = nullptr; return; } - g_delegate->RegisterObserver(observer); if (g_delegate == nullptr) { LOGI("delegate is null"); return; } + g_delegate->RegisterObserver(observer); FuzzerData fuzzerData(data, size); uint32_t len = fuzzerData.GetUInt32(); const int lenMod = 30; // 30 is mod for string vector size diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/storage_fuzzer/storage_fuzzer.cpp b/kv_store/frameworks/libs/distributeddb/test/fuzztest/storage_fuzzer/storage_fuzzer.cpp index 7abf7d7d99767119453ab691cc2e14117cb88f9d..f28a29cf2dfeb0679aeb46cebdb0376615646d59 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/storage_fuzzer/storage_fuzzer.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/storage_fuzzer/storage_fuzzer.cpp @@ -243,7 +243,7 @@ public: } }; -void ClientObserverFunc(ClientChangedData &clientChangedData) +void ClientObserverFunc(const ClientChangedData &clientChangedData) { for (const auto &tableEntry : clientChangedData.tableData) { LOGD("client observer failed, table: %s", tableEntry.first.c_str()); @@ -257,7 +257,7 @@ void ClientObserverFunc(ClientChangedData &clientChangedData) g_cv.notify_one(); } -void CreateTableForStoreObserver(sqlite3 *db, const std::string tableName) +void CreateTableForStoreObserver(sqlite3 *db, const std::string &tableName) { std::string sql = "create table " + tableName + "(id INTEGER primary key, name TEXT);"; RdbTestUtils::ExecSql(db, sql); @@ -308,10 +308,10 @@ void GetHashKey(const std::string &tableName, const std::string &condition, sqli SQLiteUtils::ResetStatement(stmt, true, errCode); } -void ClientObserverFuzz(std::string tableName) +void ClientObserverFuzz(const std::string &tableName) { sqlite3 *db = RdbTestUtils::CreateDataBase(g_dbDir + STOREID + DBSUFFIX); - ClientObserver clientObserver = [](ClientChangedData &data) { return ClientObserverFunc(data); }; + ClientObserver clientObserver = [](const ClientChangedData &data) { return ClientObserverFunc(data); }; RegisterClientObserver(db, clientObserver); std::string sql = "insert into " + tableName + " VALUES(1, 'zhangsan'), (2, 'lisi'), (3, 'wangwu');"; RdbTestUtils::ExecSql(db, sql); @@ -319,7 +319,7 @@ void ClientObserverFuzz(std::string tableName) sqlite3_close_v2(db); } -void StoreObserverFuzz(std::string tableName) +void StoreObserverFuzz(const std::string &tableName) { sqlite3 *db = RdbTestUtils::CreateDataBase(g_dbDir + STOREID + DBSUFFIX); RdbTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"); diff --git a/kv_store/frameworks/libs/distributeddb/test/moduletest/common/distributeddb/include/distributed_test_tools.h b/kv_store/frameworks/libs/distributeddb/test/moduletest/common/distributeddb/include/distributed_test_tools.h index 6e1e512d949dca0996bdd9650df6564e623e9e30..47dc06df5d5164f3343b93bb323e7e8f2c63d37e 100644 --- a/kv_store/frameworks/libs/distributeddb/test/moduletest/common/distributeddb/include/distributed_test_tools.h +++ b/kv_store/frameworks/libs/distributeddb/test/moduletest/common/distributeddb/include/distributed_test_tools.h @@ -362,7 +362,7 @@ public: static DistributedDB::DBStatus GetDelegateNotGood( DistributedDB::KvStoreDelegateManager *&outManager, DistributedDB::KvStoreDelegate *&outDelegate, - const std::string &storeId, const std::string &appId, const std::string &userId, const KvOption &optionParam); + const std::string &storeId, const KvOption &optionParam); static DistributedDB::DBStatus Put(DistributedDB::KvStoreDelegate &kvStoreDelegate, const DistributedDB::Key &key, const DistributedDB::Value &value); 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 63fec97cf4d48e54045b833283e777d0da03c83d..abca43468f7d057a76336900e96883aff6f3e5af 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 @@ -619,7 +619,7 @@ KvStoreDelegate* DistributedTestTools::GetDelegateStatus(KvStoreDelegateManager // This static method is for moduleTest of distributed to try-get KvStoreDelegate with invalid params. DBStatus DistributedTestTools::GetDelegateNotGood(KvStoreDelegateManager *&manager, KvStoreDelegate *&outDelegate, - const string &storeId, const string &appId, const string &userId, const KvOption &optionParam) + const string &storeId, const KvOption &optionParam) { SetDir(DIRECTOR); @@ -628,12 +628,6 @@ DBStatus DistributedTestTools::GetDelegateNotGood(KvStoreDelegateManager *&manag function callFunction = bind(&DelegateKvMgrCallback::Callback, &delegateKvMgrCallback, _1, _2); - // use appid and userid to initialize a kvStoreDelegateManager, and set the default cfg. - manager = new (std::nothrow) KvStoreDelegateManager(appId, userId); - if (manager == nullptr) { - MST_LOG("new delegate failed nullptr."); - return DBStatus::DB_ERROR; - } DBStatus status = manager->SetKvStoreConfig(KV_CONFIG); if (status != DBStatus::OK) { MST_LOG("%s SetConfig failed! Status= %d", TAG.c_str(), status); 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 76341c65b1eee961e44e48df93157349acdbd372..0a414765e2f075904bb9bcb51e808aa44caf31ea 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 @@ -202,7 +202,7 @@ HWTEST_F(DistributeddbKvCreateTest, Open003, TestSize.Level1) KvOption option = g_kvOption; option.createIfNecessary = IS_NOT_NEED_CREATE; option.localOnly = IS_LOCAL_ONLY; - status = DistributedTestTools::GetDelegateNotGood(manager, delegate, STORE_ID_1, APP_ID_1, USER_ID_1, option); + status = DistributedTestTools::GetDelegateNotGood(manager, delegate, STORE_ID_1, option); ASSERT_NE(status, DBStatus::OK); EXPECT_EQ(delegate, nullptr); EXPECT_EQ(manager->CloseKvStore(delegate), INVALID_ARGS); @@ -263,10 +263,14 @@ HWTEST_F(DistributeddbKvCreateTest, Open004, TestSize.Level1) */ HWTEST_F(DistributeddbKvCreateTest, Open005, TestSize.Level1) { - KvStoreDelegateManager *manager1 = nullptr; - KvStoreDelegateManager *manager2 = nullptr; - KvStoreDelegateManager *manager3 = nullptr; - KvStoreDelegateManager *manager4 = nullptr; + KvStoreDelegateManager *manager1 = new (std::nothrow) KvStoreDelegateManager(APP_ID_1, USER_ID_1); + ASSERT_NE(manager1, nullptr); + KvStoreDelegateManager *manager2 = new (std::nothrow) KvStoreDelegateManager("", USER_ID_1); + ASSERT_NE(manager2, nullptr); + KvStoreDelegateManager *manager3 = new (std::nothrow) KvStoreDelegateManager(APP_ID_1, ""); + ASSERT_NE(manager3, nullptr); + KvStoreDelegateManager *manager4 = new (std::nothrow) KvStoreDelegateManager(APP_ID_1, USER_ID_1); + ASSERT_NE(manager4, nullptr); KvStoreDelegate *delegate1 = nullptr; KvStoreDelegate *delegate2 = nullptr; KvStoreDelegate *delegate3 = nullptr; @@ -279,7 +283,7 @@ HWTEST_F(DistributeddbKvCreateTest, Open005, TestSize.Level1) KvOption option1 = g_kvOption; option1.createIfNecessary = IS_NEED_CREATE; option1.localOnly = IS_LOCAL_ONLY; - DBStatus status = DistributedTestTools::GetDelegateNotGood(manager1, delegate1, "", APP_ID_1, USER_ID_1, option1); + DBStatus status = DistributedTestTools::GetDelegateNotGood(manager1, delegate1, "", option1); ASSERT_EQ(status, DBStatus::INVALID_ARGS); EXPECT_TRUE(delegate1 == nullptr); EXPECT_TRUE(manager1->CloseKvStore(delegate1) == INVALID_ARGS); @@ -291,7 +295,7 @@ HWTEST_F(DistributeddbKvCreateTest, Open005, TestSize.Level1) KvOption option2 = g_kvOption; option2.createIfNecessary = IS_NEED_CREATE; option2.localOnly = IS_LOCAL_ONLY; - status = DistributedTestTools::GetDelegateNotGood(manager2, delegate2, STORE_ID_1, "", USER_ID_1, option2); + status = DistributedTestTools::GetDelegateNotGood(manager2, delegate2, STORE_ID_1, option2); ASSERT_EQ(status, DBStatus::INVALID_ARGS); EXPECT_TRUE(delegate2 == nullptr); EXPECT_TRUE(manager2->CloseKvStore(delegate2) == INVALID_ARGS); @@ -303,7 +307,7 @@ HWTEST_F(DistributeddbKvCreateTest, Open005, TestSize.Level1) KvOption option3 = g_kvOption; option3.createIfNecessary = IS_NEED_CREATE; option3.localOnly = IS_LOCAL_ONLY; - status = DistributedTestTools::GetDelegateNotGood(manager3, delegate3, STORE_ID_1, APP_ID_1, "", option3); + status = DistributedTestTools::GetDelegateNotGood(manager3, delegate3, STORE_ID_1, option3); ASSERT_EQ(status, DBStatus::INVALID_ARGS); EXPECT_TRUE(delegate3 == nullptr); EXPECT_TRUE(manager3->CloseKvStore(delegate3) == INVALID_ARGS); @@ -315,7 +319,7 @@ HWTEST_F(DistributeddbKvCreateTest, Open005, TestSize.Level1) KvOption option4 = g_kvOption; option4.createIfNecessary = IS_NOT_NEED_CREATE; option4.localOnly = IS_LOCAL_ONLY; - status = DistributedTestTools::GetDelegateNotGood(manager4, delegate4, STORE_ID_1, APP_ID_1, USER_ID_1, option4); + status = DistributedTestTools::GetDelegateNotGood(manager4, delegate4, STORE_ID_1, option4); ASSERT_NE(status, DBStatus::OK); EXPECT_TRUE(delegate4 == nullptr); EXPECT_TRUE(manager4->CloseKvStore(delegate4) == INVALID_ARGS); @@ -988,9 +992,12 @@ HWTEST_F(DistributeddbKvCreateTest, PathException004, TestSize.Level2) appTooLongID.append(TWO_M_LONG_STRING, 'b'); userTooLongID.append(TWO_M_LONG_STRING, 'c'); - KvStoreDelegateManager *manager1 = nullptr; - KvStoreDelegateManager *manager2 = nullptr; - KvStoreDelegateManager *manager3 = nullptr; + KvStoreDelegateManager *manager1 = new (std::nothrow) KvStoreDelegateManager(APP_ID_1, USER_ID_1); + ASSERT_NE(manager1, nullptr); + KvStoreDelegateManager *manager2 = new (std::nothrow) KvStoreDelegateManager(appTooLongID, USER_ID_1); + ASSERT_NE(manager2, nullptr); + KvStoreDelegateManager *manager3 = new (std::nothrow) KvStoreDelegateManager(APP_ID_1, userTooLongID); + ASSERT_NE(manager3, nullptr); KvStoreDelegate *delegate1 = nullptr; KvStoreDelegate *delegate2 = nullptr; KvStoreDelegate *delegate3 = nullptr; @@ -998,24 +1005,21 @@ HWTEST_F(DistributeddbKvCreateTest, PathException004, TestSize.Level2) * @tc.steps: step1. create kv db with storeId=storeTooLongID. * @tc.expected: step1. create db failed. */ - DBStatus status1 = DistributedTestTools::GetDelegateNotGood(manager1, delegate1, - storeTooLongID, APP_ID_1, USER_ID_1, g_kvOption); + DBStatus status1 = DistributedTestTools::GetDelegateNotGood(manager1, delegate1, storeTooLongID, g_kvOption); EXPECT_EQ(delegate1, nullptr); EXPECT_EQ(manager1->CloseKvStore(delegate1), INVALID_ARGS); /** * @tc.steps: step2. create kv db with appId=appTooLongID. * @tc.expected: step2. create db failed. */ - DBStatus status2 = DistributedTestTools::GetDelegateNotGood(manager2, delegate2, - USER_ID_1, appTooLongID, USER_ID_1, g_kvOption); + DBStatus status2 = DistributedTestTools::GetDelegateNotGood(manager2, delegate2, USER_ID_1, g_kvOption); EXPECT_EQ(delegate2, nullptr); EXPECT_EQ(manager2->CloseKvStore(delegate2), INVALID_ARGS); /** * @tc.steps: step3. create kv db with userId=userTooLongID. * @tc.expected: step3. create db failed. */ - DBStatus status3 = DistributedTestTools::GetDelegateNotGood(manager3, delegate3, - USER_ID_1, APP_ID_1, userTooLongID, g_kvOption); + DBStatus status3 = DistributedTestTools::GetDelegateNotGood(manager3, delegate3, USER_ID_1, g_kvOption); EXPECT_EQ(delegate3, nullptr); EXPECT_EQ(manager3->CloseKvStore(delegate3), INVALID_ARGS); @@ -1121,7 +1125,8 @@ HWTEST_F(DistributeddbKvCreateTest, PathException006, TestSize.Level2) HWTEST_F(DistributeddbKvCreateTest, PathException007, TestSize.Level2) { KvStoreDelegateManager *manager1 = nullptr; - KvStoreDelegateManager *manager2 = nullptr; + KvStoreDelegateManager *manager2 = new (std::nothrow) KvStoreDelegateManager(APP_ID_1, USER_ID_2); + ASSERT_NE(manager2, nullptr); KvStoreDelegate *delegate1 = nullptr; KvStoreDelegate *delegate2 = nullptr; /** @@ -1147,8 +1152,7 @@ HWTEST_F(DistributeddbKvCreateTest, PathException007, TestSize.Level2) KvOption option = g_kvOption; option.createIfNecessary = IS_NOT_NEED_CREATE; option.localOnly = IS_LOCAL_ONLY; - DBStatus status = DistributedTestTools::GetDelegateNotGood(manager2, delegate2, - STORE_ID_1, APP_ID_1, USER_ID_2, option); + DBStatus status = DistributedTestTools::GetDelegateNotGood(manager2, delegate2, STORE_ID_1, option); EXPECT_TRUE(delegate2 == nullptr); EXPECT_EQ(manager2->CloseKvStore(delegate2), INVALID_ARGS); ASSERT_NE(status, OK); 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 9e2f6633cb1335a9588dbdc7a122170d7b359439..802bd8d66834499308ceedac2bb031a8dd3da49e 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 @@ -228,10 +228,7 @@ HWTEST_F(DistributedDBCommonTest, DiffProcessLockFile, TestSize.Level1) LOGI("begin fork new process!!"); pid_t pid = fork(); ASSERT_TRUE(pid >= 0); - if (pid < 0) { - return; - } - else if (pid == 0) { + if (pid == 0) { LOGI("child process begin!"); OS::FileHandle ChildFd; EXPECT_EQ(OS::OpenFile(g_testDir + DBConstant::DB_LOCK_POSTFIX, ChildFd), E_OK); @@ -268,10 +265,7 @@ HWTEST_F(DistributedDBCommonTest, DiffProcessLockFileBlocked, TestSize.Level1) int count = 10; // wait 10 times 10 ms for block wait pid_t pid = fork(); ASSERT_TRUE(pid >= 0); - if (pid < 0) { - return; - } - else if (pid == 0) { + if (pid == 0) { LOGI("child process begin!"); EXPECT_FALSE(OS::CheckPathExistence(g_testDir + "/LOCK_step_1")); OS::FileHandle ChildFd; @@ -581,7 +575,7 @@ HWTEST_F(DistributedDBCommonTest, PerformanceAnalysisTest001, TestSize.Level1) * @tc.name: PerformanceAnalysisTest002 * @tc.desc: Test PerformanceAnalysis interfaces. * @tc.type: FUNC - * @tc.require: DTS2024073106613 + * @tc.require: * @tc.author: suyue */ HWTEST_F(DistributedDBCommonTest, PerformanceAnalysisTest002, TestSize.Level1) @@ -611,7 +605,7 @@ HWTEST_F(DistributedDBCommonTest, PerformanceAnalysisTest002, TestSize.Level1) * @tc.name: UserChangeMonitorTest * @tc.desc: Test UserChangeMonitor interfaces. * @tc.type: FUNC - * @tc.require: DTS2024073106613 + * @tc.require: * @tc.author: suyue */ HWTEST_F(DistributedDBCommonTest, UserChangeMonitorTest, TestSize.Level1) @@ -648,7 +642,7 @@ HWTEST_F(DistributedDBCommonTest, UserChangeMonitorTest, TestSize.Level1) * @tc.name: ValueObjectConstructorTest * @tc.desc: Test ValueObjectTest. * @tc.type: FUNC - * @tc.require: DTS2024073106613 + * @tc.require: * @tc.author: suyue */ HWTEST_F(DistributedDBCommonTest, ValueObjectConstructorTest, TestSize.Level1) @@ -673,7 +667,7 @@ HWTEST_F(DistributedDBCommonTest, ValueObjectConstructorTest, TestSize.Level1) * @tc.name: TimeTickMonitorTest * @tc.desc: Test TimeTickMonitor interfaces. * @tc.type: FUNC - * @tc.require: DTS2024073106613 + * @tc.require: * @tc.author: suyue */ HWTEST_F(DistributedDBCommonTest, TimeTickMonitorTest, TestSize.Level1) @@ -713,7 +707,7 @@ HWTEST_F(DistributedDBCommonTest, TimeTickMonitorTest, TestSize.Level1) * @tc.name: LockStatusObserverTest * @tc.desc: Test LockStatusObserver interfaces. * @tc.type: FUNC - * @tc.require: DTS2024073106613 + * @tc.require: * @tc.author: suyue */ HWTEST_F(DistributedDBCommonTest, LockStatusObserverTest, TestSize.Level1) @@ -748,7 +742,7 @@ HWTEST_F(DistributedDBCommonTest, LockStatusObserverTest, TestSize.Level1) * @tc.name: TaskQueueTest * @tc.desc: Test TaskQueue interfaces. * @tc.type: FUNC - * @tc.require: DTS2024073106613 + * @tc.require: * @tc.author: suyue */ HWTEST_F(DistributedDBCommonTest, TaskQueueTest, TestSize.Level1) @@ -776,7 +770,7 @@ HWTEST_F(DistributedDBCommonTest, TaskQueueTest, TestSize.Level1) * @tc.name: AbnormalTrackerTableTest * @tc.desc: Test LockStatusObserver interfaces. * @tc.type: FUNC - * @tc.require: DTS2024073106613 + * @tc.require: * @tc.author: suyue */ HWTEST_F(DistributedDBCommonTest, AbnormalTrackerTableTest, TestSize.Level1) 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 69b156b6850177f7add3d3b6f8706920b92cabe7..43b8cc5937114fbb806b7ea830700210daddefb6 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 @@ -682,7 +682,7 @@ HWTEST_F(DistributedDBParcelTest, WriteString006, TestSize.Level2) * @tc.name: WriteBoolTest * @tc.desc: write and read a bool. * @tc.type: FUNC - * @tc.require: DTS2024073106613 + * @tc.require: * @tc.author: suyue */ HWTEST_F(DistributedDBParcelTest, WriteBoolTest, TestSize.Level1) @@ -717,7 +717,7 @@ HWTEST_F(DistributedDBParcelTest, WriteBoolTest, TestSize.Level1) * @tc.name: ParcelErrTest * @tc.desc: write and read a bool. * @tc.type: FUNC - * @tc.require: DTS2024073106613 + * @tc.require: * @tc.author: suyue */ HWTEST_F(DistributedDBParcelTest, ParcelErrTest, TestSize.Level1) @@ -752,4 +752,5 @@ HWTEST_F(DistributedDBParcelTest, ParcelErrTest, TestSize.Level1) EXPECT_EQ(ret, -E_PARSE_FAIL); EXPECT_EQ(parcel.ReadBlob("", 1), expectedVal); } + #endif \ No newline at end of file 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 4cc98103d235ca1790058be9b66ac43b29bc8e4c..6ebac3f096600219e7016a5ff9dc73a914c74844 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 @@ -843,7 +843,7 @@ HWTEST_F(DistributedDBRelationalSchemaObjectTest, TableCompareTest002, TestSize. * @tc.name: FieldInfoCompareTest * @tc.desc: Test field info compare * @tc.type: FUNC - * @tc.require: DTS2024073106613 + * @tc.require: * @tc.author: suyue */ HWTEST_F(DistributedDBRelationalSchemaObjectTest, FieldInfoCompareTest, TestSize.Level1) @@ -870,7 +870,7 @@ HWTEST_F(DistributedDBRelationalSchemaObjectTest, FieldInfoCompareTest, TestSize * @tc.name: TableInfoInterfacesTest * @tc.desc: Test TableInfo interfaces * @tc.type: FUNC - * @tc.require: DTS2024073106613 + * @tc.require: * @tc.author: suyue */ HWTEST_F(DistributedDBRelationalSchemaObjectTest, TableInfoInterfacesTest, TestSize.Level1) @@ -899,7 +899,7 @@ HWTEST_F(DistributedDBRelationalSchemaObjectTest, TableInfoInterfacesTest, TestS * @tc.name: SchemaTableCompareTest * @tc.desc: Test LiteSchemaTable Compare * @tc.type: FUNC - * @tc.require: DTS2024073106613 + * @tc.require: * @tc.author: suyue */ HWTEST_F(DistributedDBRelationalSchemaObjectTest, SchemaTableCompareTest, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_schema_object_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_schema_object_test.cpp index b492092fc69ae701f860d3620f4615b71741b97d..388d6597609ecee7c464c42bc952510403e50d47 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_schema_object_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_schema_object_test.cpp @@ -1092,7 +1092,7 @@ HWTEST_F(DistributedDBSchemaObjectTest, ValueLackField002, TestSize.Level1) * @tc.name: SchemaObjectErrTest * @tc.desc: Parse Schema Object err scene * @tc.type: FUNC - * @tc.require: DTS2024073106613 + * @tc.require: * @tc.author: suyue */ HWTEST_F(DistributedDBSchemaObjectTest, SchemaObjectErrTest001, TestSize.Level1) @@ -1133,7 +1133,7 @@ HWTEST_F(DistributedDBSchemaObjectTest, SchemaObjectErrTest001, TestSize.Level1) * @tc.name: SchemaObjectErrTest002 * @tc.desc: Parse Schema Object err scene * @tc.type: FUNC - * @tc.require: DTS2024073106613 + * @tc.require: * @tc.author: suyue */ HWTEST_F(DistributedDBSchemaObjectTest, SchemaObjectErrTest002, TestSize.Level1) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_schema_unit_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_schema_unit_test.cpp index 8cb1e704bdeb953c5b9081174e52a4652dd45b50..f8824a6cb22fc91e4975b68769ff9af18b12761b 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_schema_unit_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_schema_unit_test.cpp @@ -516,7 +516,7 @@ HWTEST_F(DistributedDBSchemalTest, ParseAndCheckFieldPath002, TestSize.Level1) * @tc.name: ParseTrackerSchemaAndName * @tc.desc: Correctly identify illegal shema index fields * @tc.type: FUNC - * @tc.require: DTS2024073106613 + * @tc.require: * @tc.author: suyue */ HWTEST_F(DistributedDBSchemalTest, ParseTrackerSchemaAndName, TestSize.Level1) 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 b28f832f3a6a87a7d8dc4b4fadfb3d78dbe30158..31df882bf6c9776f89cdd34878af642fb412dd08 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; } -bool CheckStatusAndSyncProcess(DBStatus status, std::map &syncProcessMap) +static bool CheckSyncCondVarWaitResult(DBStatus status, std::map &syncProcessMap) { if (status != OK) { return true; @@ -1021,7 +1021,7 @@ DBStatus DistributedDBToolsUnitTest::SyncTest(KvStoreNbDelegate *delegate, Devic if (!option.isWait) { std::unique_lock lock(this->syncLock_); this->syncCondVar_.wait(lock, [status, &syncProcessMap]() { - return CheckStatusAndSyncProcess(status, syncProcessMap); + return CheckSyncCondVarWaitResult(status, syncProcessMap); }); } return status; 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 26cbe1fde4dacbe8010731aff2c59b95fe85bf97..dbdc9612a615f6a4894f99693fd761a2e465ea31 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 @@ -1210,7 +1210,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, FfrtTest003, TestSize.Le count++; } }, nullptr, nullptr); - waitVec.push_back(h1); + waitVec.push_back(std::move(h1)); } for (const auto &item : waitVec) { ADAPTER_WAIT(item); @@ -1725,7 +1725,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, RegisterStoreObserverTes * @tc.name: AbnormalDelegateImplTest001 * @tc.desc: Test delegateImpl interface after delegate is closed * @tc.type: FUNC - * @tc.require: DTS2024073106613 + * @tc.require: * @tc.author: suyue */ HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, AbnormalDelegateImplTest001, TestSize.Level0) @@ -1783,7 +1783,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, AbnormalDelegateImplTest * @tc.name: AbnormalDelegateImplTest002 * @tc.desc: Test delegate interface after delegate is closed * @tc.type: FUNC - * @tc.require: DTS2024073106613 + * @tc.require: * @tc.author: suyue */ HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, AbnormalDelegateImplTest002, TestSize.Level0) 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 08cbc88c0b967e265d086b59e445b4e7b994cbac..4ec5e21d144cbc8389a1b10f31d2885599acb03e 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 @@ -20,6 +20,7 @@ #include "distributeddb_data_generate_unit_test.h" #include "distributeddb_tools_unit_test.h" #include "process_system_api_adapter_impl.h" +#include "relational_store_client.h" #include "relational_store_instance.h" #include "relational_store_manager.h" #include "runtime_config.h" @@ -30,6 +31,7 @@ #include "virtual_asset_loader.h" #include "virtual_cloud_data_translate.h" #include "virtual_cloud_db.h" +#include "virtual_communicator_aggregator.h" #include "mock_asset_loader.h" #include "cloud_db_sync_utils_test.h" @@ -58,6 +60,7 @@ namespace { DistributedDB::RelationalStoreManager g_mgr(APP_ID, USER_ID); RelationalStoreObserverUnitTest *g_observer = nullptr; RelationalStoreDelegate *g_delegate = nullptr; + VirtualCommunicatorAggregator *communicatorAggregator_ = nullptr; SyncProcess g_syncProcess; using CloudSyncStatusCallback = std::function &onProcess)>; const std::string CREATE_LOCAL_TABLE_SQL = @@ -329,8 +332,21 @@ namespace { { int i = 0; for (const auto &tableName: tableList) { - std::string sql = "select count(*) from " + DBCommon::GetLogTableName(tableName) +" where device = 'cloud'"; - sql += " and cloud_gid is not null and cloud_gid != '' and (flag & 0x2 = 0 or flag & 0x20 = 0);"; + std::string sql = "select count(*) from " + DBCommon::GetLogTableName(tableName) + + " where device = 'cloud'" + " and cloud_gid is not null and cloud_gid != '' and " + + "(flag & 0x2 = 0 or flag & 0x20 = 0);"; + EXPECT_EQ(sqlite3_exec(db, sql.c_str(), QueryCountCallback, + reinterpret_cast(countList[i]), nullptr), SQLITE_OK); + i++; + } + } + + void CheckCompensatedNum(sqlite3 *&db, std::vector tableList, std::vector countList) + { + int i = 0; + for (const auto &tableName: tableList) { + 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); i++; @@ -531,7 +547,9 @@ namespace { void CloseDb() { - g_delegate->UnRegisterObserver(g_observer); + if (g_delegate != nullptr) { + g_delegate->UnRegisterObserver(g_observer); + } delete g_observer; g_virtualCloudDb = nullptr; if (g_delegate != nullptr) { @@ -592,6 +610,9 @@ namespace { DataBaseSchema dataBaseSchema; GetCloudDbSchema(dataBaseSchema); ASSERT_EQ(g_delegate->SetCloudDbSchema(dataBaseSchema), DBStatus::OK); + communicatorAggregator_ = new (std::nothrow) VirtualCommunicatorAggregator(); + ASSERT_TRUE(communicatorAggregator_ != nullptr); + RuntimeContext::GetInstance()->SetCommunicatorAggregator(communicatorAggregator_); } void DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest::TearDown(void) @@ -600,6 +621,9 @@ namespace { if (DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir) != 0) { LOGE("rm test db files error."); } + RuntimeContext::GetInstance()->SetCommunicatorAggregator(nullptr); + communicatorAggregator_ = nullptr; + RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(nullptr); } /* @@ -1301,15 +1325,226 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD CheckLogoutLogCount(db, g_tables, {10, 10}); CloseDb(); } +/* + * @tc.name: CleanCloudDataTest016 + * @tc.desc: Test compensated flag should be clear after remove device data. + * @tc.type: FUNC + * @tc.require: + * @tc.author: wangxiangdong + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest016, TestSize.Level0) +{ + /** + * @tc.steps: step1. Set data is logicDelete + */ + bool logicDelete = true; + auto data = static_cast(&logicDelete); + g_delegate->Pragma(LOGIC_DELETE_SYNC_DATA, data); + /** + * @tc.steps: step2. make data: 20 records on local + */ + int64_t paddingSize = 20; + int localCount = 20; + InsertUserTableRecord(db, 0, localCount, paddingSize, false); + /** + * @tc.steps: step3. make 2th data exist + */ + 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); + } + }); + /* + * @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); + g_virtualCloudDb->ForkUpload(nullptr); + CheckCompensatedNum(db, g_tables, {1, 0}); + /** + * @tc.steps: step5. remove device data and check flag do not has compensated. + * @tc.expected: OK. + */ + std::string device; + ASSERT_EQ(g_delegate->RemoveDeviceData(device, DistributedDB::FLAG_ONLY), DBStatus::OK); + CheckCompensatedNum(db, g_tables, {0, 0}); + CloseDb(); +} /* - * @tc.name: CleanCloudDataTest022 + * @tc.name: CleanCloudDataTest017 + * @tc.desc: Test deleted data and logic delete will not have flag logout. + * @tc.type: FUNC + * @tc.require: + * @tc.author: wangxiangdong + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest017, TestSize.Level0) +{ + /** + * @tc.steps: step1. Set data is logicDelete + */ + bool logicDelete = true; + auto data = static_cast(&logicDelete); + g_delegate->Pragma(LOGIC_DELETE_SYNC_DATA, data); + /** + * @tc.steps: step2. make data: 20 records on local + */ + int64_t paddingSize = 20; + int localCount = 20; + InsertUserTableRecord(db, 0, localCount, paddingSize, false); + /** + * @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); + DeleteUserTableRecord(db, 5, 10); + CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate); + /** + * @tc.steps: step5. remove device data and check flag do not has logout. + * @tc.expected: OK. + */ + std::string device; + ASSERT_EQ(g_delegate->RemoveDeviceData(device, DistributedDB::FLAG_AND_DATA), DBStatus::OK); + CheckLogoutLogCount(db, g_tables, {10, 15}); + CloseDb(); +} + +/* + * @tc.name: CleanCloudDataTest018 + * @tc.desc: Test remove device data then sync, check cursor do not increase twice. + * @tc.type: FUNC + * @tc.require: + * @tc.author: wangxiangdong + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest018, TestSize.Level0) +{ + /** + * @tc.steps: step1. Set data is logicDelete + */ + bool logicDelete = true; + auto data = static_cast(&logicDelete); + g_delegate->Pragma(LOGIC_DELETE_SYNC_DATA, data); + /** + * @tc.steps: step2. make data: 10 records on local + */ + int64_t paddingSize = 10; + int localCount = 10; + InsertUserTableRecord(db, 0, localCount, paddingSize, false); + /** + * @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.remove device data. + * @tc.expected: OK. + */ + std::string device; + ASSERT_EQ(g_delegate->RemoveDeviceData(device, DistributedDB::FLAG_AND_DATA), DBStatus::OK); + /** + * @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]) + + " where cursor='40';"; + EXPECT_EQ(sqlite3_exec(db, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback, + reinterpret_cast(1), nullptr), SQLITE_OK); + CloseDb(); +} + +/* + * @tc.name: CleanCloudDataTest019 + * @tc.desc: Test remove device data then sync, check cursor do not increase twice. + * @tc.type: FUNC + * @tc.require: + * @tc.author: wangxiangdong + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest019, TestSize.Level0) +{ + /** + * @tc.steps: step1. make data: 20 records on local + */ + int64_t paddingSize = 20; + int localCount = 20; + InsertUserTableRecord(db, 0, localCount, paddingSize, false); + /** + * @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]) + + " where cursor='20';"; + EXPECT_EQ(sqlite3_exec(db, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback, + reinterpret_cast(1), nullptr), SQLITE_OK); + CloseDb(); +} + +/* + * @tc.name: CleanCloudDataTest020 + * @tc.desc: Test drop logic delete data will not have flag logout. + * @tc.type: FUNC + * @tc.require: + * @tc.author: wangxiangdong + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest020, TestSize.Level0) +{ + /** + * @tc.steps: step1. Set data is logicDelete + */ + bool logicDelete = true; + auto data = static_cast(&logicDelete); + g_delegate->Pragma(LOGIC_DELETE_SYNC_DATA, data); + /** + * @tc.steps: step2. make data: 20 records on local + */ + int64_t paddingSize = 20; + int localCount = 20; + InsertUserTableRecord(db, 0, localCount, paddingSize, false); + /** + * @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); + DeleteUserTableRecord(db, 5, 10); + CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate); + /** + * @tc.steps: step5. remove device data and check flag do not has logout. + * @tc.expected: OK. + */ + std::string device; + ASSERT_EQ(g_delegate->RemoveDeviceData(device, DistributedDB::FLAG_AND_DATA), DBStatus::OK); + CheckLogoutLogCount(db, g_tables, {10, 15}); + /** + * @tc.steps: step6. drop logic delete data and check flag do not has logout. + * @tc.expected: OK. + */ + EXPECT_EQ(DropLogicDeletedData(db, g_tables[0], 0u), OK); + EXPECT_EQ(DropLogicDeletedData(db, g_tables[1], 0u), OK); + CheckLogoutLogCount(db, g_tables, {0, 0}); + CloseDb(); +} + +/* + * @tc.name: CleanCloudDataTest021 * @tc.desc: Test conflict, not dound, exis errCode will deal. * @tc.type: FUNC * @tc.require: * @tc.author: wangxiangdong */ -HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest022, TestSize.Level0) +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest021, TestSize.Level0) { /** * @tc.steps: step1. Set data is logicDelete @@ -1318,7 +1553,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD auto data = static_cast(&logicDelete); g_delegate->Pragma(LOGIC_DELETE_SYNC_DATA, data); /** - * @tc.steps: step2. make data: 20 records on local. + * @tc.steps: step2. make data: 20 records on local */ int64_t paddingSize = 20; int localCount = 20; @@ -1355,5 +1590,226 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD reinterpret_cast(18), nullptr), SQLITE_OK); CloseDb(); } + +/* + * @tc.name: CleanCloudDataTest022 + * @tc.desc: Test deleted data and flag_and_data mode, flag have no logout. + * @tc.type: FUNC + * @tc.require: + * @tc.author: wangxiangdong + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest022, TestSize.Level0) +{ + /** + * @tc.steps: step1. make data: 20 records on local + */ + int64_t paddingSize = 20; + int localCount = 20; + InsertUserTableRecord(db, 0, localCount, paddingSize, false); + /** + * @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); + /** + * @tc.steps: step4. remove device data and check flag has no logout. + * @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 & 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]) + + " where flag & 0x800 != 0;"; + EXPECT_EQ(sqlite3_exec(db, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback, + reinterpret_cast(0), nullptr), SQLITE_OK); + CloseDb(); +} + +/* + * @tc.name: CleanCloudDataTest023 + * @tc.desc: Test deleted data and logic deletedata will clear gid but no logout. + * @tc.type: FUNC + * @tc.require: + * @tc.author: wangxiangdong + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest023, TestSize.Level0) +{ + /** + * @tc.steps: step1. Set data is logicDelete + */ + bool logicDelete = true; + auto data = static_cast(&logicDelete); + g_delegate->Pragma(LOGIC_DELETE_SYNC_DATA, data); + /** + * @tc.steps: step2. make data: 20 records on local + */ + int64_t paddingSize = 20; + int localCount = 20; + InsertUserTableRecord(db, 0, localCount, paddingSize, false); + /** + * @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. + */ + 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.expected: OK. + */ + DeleteUserTableRecord(db, 10, 15); + 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); + std::string device; + ASSERT_EQ(g_delegate->RemoveDeviceData(device, DistributedDB::FLAG_AND_DATA), DBStatus::OK); + // check flag no logout + sql = "select count(*) from " + DBCommon::GetLogTableName(g_tables[0]) + + " where flag & 0x800 == 0 and cloud_gid = '' and version = '' and sharing_resource = '';"; + EXPECT_EQ(sqlite3_exec(db, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback, + reinterpret_cast(15), nullptr), SQLITE_OK); + // check flag has logout + 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); + // check flag has no logout and delete + sql = "select count(*) from " + DBCommon::GetLogTableName(g_tables[0]) + + " where flag & 0x800 == 0 and data_key = -1;"; + EXPECT_EQ(sqlite3_exec(db, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback, + reinterpret_cast(10), nullptr), SQLITE_OK); + // check flag has no logout and delete + sql = "select count(*) from " + DBCommon::GetLogTableName(g_tables[0]) + + " where flag & 0x800 == 0 and data_key = -1 and cloud_gid = '' and version = '' and sharing_resource = '';"; + EXPECT_EQ(sqlite3_exec(db, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback, + reinterpret_cast(10), nullptr), SQLITE_OK); + // check flag has no logout and logic delete + sql = "select count(*) from " + DBCommon::GetLogTableName(g_tables[0]) + + " where flag & 0x800 == 0 and flag & 0x08 != 0 and cloud_gid = '' and version = '' and sharing_resource = '';"; + EXPECT_EQ(sqlite3_exec(db, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback, + reinterpret_cast(5), nullptr), SQLITE_OK); + // check cursor has been increase to 50 + sql = "select count(*) from " + DBCommon::GetLogTableName(g_tables[0]) + + " where cursor = '30';"; + EXPECT_EQ(sqlite3_exec(db, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback, + reinterpret_cast(1), nullptr), SQLITE_OK); + CloseDb(); +} + +/* + * @tc.name: CleanCloudDataTest024 + * @tc.desc: Test logic deleted data and log will deleted after DropLogicDeleteData. + * @tc.type: FUNC + * @tc.require: + * @tc.author: wangxiangdong + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest024, TestSize.Level0) +{ + /** + * @tc.steps: step1. Set data is logicDelete + */ + bool logicDelete = true; + auto data = static_cast(&logicDelete); + g_delegate->Pragma(LOGIC_DELETE_SYNC_DATA, data); + /** + * @tc.steps: step2. make data: 20 records on local + */ + int64_t paddingSize = 20; + int localCount = 20; + InsertUserTableRecord(db, 0, localCount, paddingSize, false); + /** + * @tc.steps: step3. call Sync, 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. + */ + 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;"; + 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. + */ + EXPECT_EQ(DropLogicDeletedData(db, g_tables[0], 0u), OK); + 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(); +} + +/* + * @tc.name: CleanCloudDataTest025 + * @tc.desc: Test sync after dropping logic deleted device data, cursor do not decrease. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyuchen + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest025, TestSize.Level0) +{ + /** + * @tc.steps: step1. Set logicDelete + */ + bool logicDelete = true; + auto data = static_cast(&logicDelete); + g_delegate->Pragma(LOGIC_DELETE_SYNC_DATA, data); + + /** + * @tc.steps: step2. insert 10 records locally, then sync to cloud + */ + int64_t paddingSize = 10; + int localCount = 10; + 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); + CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate); + + /** + * @tc.steps: step6. check cursor + */ + std::string sql = "select count(*) from " + DBCommon::GetLogTableName(g_tables[0]) + + " where cursor='13';"; + EXPECT_EQ(sqlite3_exec(db, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback, + reinterpret_cast(1), 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 7716d6455baf6a0b5e30556b6df7e2cdd9f17991..39565217ec48a61bc86ff21455d70322ebbf0585 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 @@ -31,6 +31,7 @@ #include "virtual_asset_loader.h" #include "virtual_cloud_data_translate.h" #include "virtual_cloud_db.h" +#include "virtual_communicator_aggregator.h" #include "cloud_db_sync_utils_test.h" using namespace testing::ext; @@ -82,6 +83,7 @@ namespace { std::string g_dbDir; std::string g_storePath; DistributedDB::RelationalStoreManager g_mgr(APP_ID, USER_ID); + RelationalStoreObserverUnitTest *g_observer = nullptr; RelationalStoreDelegate *g_delegate = nullptr; std::shared_ptr g_virtualCloudDb = nullptr; std::shared_ptr g_virtualCloudDataTranslate; @@ -133,6 +135,7 @@ namespace { void InitCloudEnv(); sqlite3 *db_ = nullptr; std::function forkInsertFunc_; + VirtualCommunicatorAggregator *communicatorAggregator_ = nullptr; }; void DistributedDBCloudInterfacesSetCloudSchemaTest::SetUpTestCase(void) @@ -155,12 +158,17 @@ namespace { db_ = RelationalTestUtils::CreateDataBase(g_storePath); ASSERT_NE(db_, nullptr); CreateUserDBAndTable(); - DBStatus status = g_mgr.OpenStore(g_storePath, STORE_ID, {}, g_delegate); - ASSERT_EQ(status, OK); + g_observer = new (std::nothrow) RelationalStoreObserverUnitTest(); + ASSERT_NE(g_observer, nullptr); + ASSERT_EQ(g_mgr.OpenStore(g_storePath, STORE_ID, RelationalStoreDelegate::Option { .observer = g_observer }, + g_delegate), DBStatus::OK); ASSERT_NE(g_delegate, nullptr); g_virtualCloudDb = std::make_shared(); ASSERT_EQ(g_delegate->SetCloudDB(g_virtualCloudDb), DBStatus::OK); ASSERT_EQ(g_delegate->SetIAssetLoader(std::make_shared()), DBStatus::OK); + communicatorAggregator_ = new (std::nothrow) VirtualCommunicatorAggregator(); + ASSERT_TRUE(communicatorAggregator_ != nullptr); + RuntimeContext::GetInstance()->SetCommunicatorAggregator(communicatorAggregator_); } void DistributedDBCloudInterfacesSetCloudSchemaTest::TearDown(void) @@ -170,6 +178,9 @@ namespace { g_delegate = nullptr; EXPECT_EQ(sqlite3_close_v2(db_), SQLITE_OK); DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir); + RuntimeContext::GetInstance()->SetCommunicatorAggregator(nullptr); + communicatorAggregator_ = nullptr; + RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(nullptr); } void DistributedDBCloudInterfacesSetCloudSchemaTest::CreateUserDBAndTable() @@ -260,6 +271,23 @@ namespace { + " where sharing_resource like 'uri%'"; } + std::string QueryLogicDeleteCountSql(const std::string &tableName) + { + return "SELECT COUNT(*) FROM " + DBCommon::GetLogTableName(tableName) + + " where flag&0x08!=0"; + } + + std::string QueryAllCountSql(const std::string &tableName) + { + return "SELECT COUNT(*) FROM " + DBCommon::GetLogTableName(tableName); + } + + std::string QueryByCursorCountSql(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=''"; + } + void DistributedDBCloudInterfacesSetCloudSchemaTest::InsertCloudTableRecord(int64_t begin, int64_t count, bool isShare, int64_t beginGid) { @@ -349,6 +377,9 @@ namespace { void DistributedDBCloudInterfacesSetCloudSchemaTest::CloseDb() { + 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); @@ -1851,8 +1882,258 @@ namespace { */ EXPECT_EQ(DropLogicDeletedData(db_, g_tableName2, 0u), OK); sql = "SELECT COUNT(*) FROM " + DBCommon::GetLogTableName(g_tableName2) + " where sharing_resource=''"; + EXPECT_EQ(sqlite3_exec(db_, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback, + reinterpret_cast(0), nullptr), SQLITE_OK); + } + + /** + * @tc.name: SharedTableSync014 + * @tc.desc: Test shared table logic delete + * @tc.type: FUNC + * @tc.require: + * @tc.author: wangxiangdong + */ + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync014, TestSize.Level0) + { + /** + * @tc.steps:step1. Set data is logicDelete + * @tc.expected: step1. return OK + */ + bool logicDelete = true; + auto data = static_cast(&logicDelete); + g_delegate->Pragma(LOGIC_DELETE_SYNC_DATA, data); + + /** + * @tc.steps:step2. init cloud data and sync + * @tc.expected: step2. return OK + */ + InitCloudEnv(); + int cloudCount = 10; + forkInsertFunc_ = InsertSharingUri; + InsertCloudTableRecord(0, cloudCount, false); + InsertCloudTableRecord(0, cloudCount); + Query query = Query::Select().FromTable({ g_tableName2, g_sharedTableName1 }); + BlockSync(query, g_delegate, DBStatus::OK); + forkInsertFunc_ = nullptr; + + /** + * @tc.steps:step3. delete cloud data + * @tc.expected: step3. return OK + */ + int beginGid = 0; + int delCount = 5; + DeleteCloudTableRecord(beginGid, delCount, false); + DeleteCloudTableRecord(cloudCount, delCount); + BlockSync(query, g_delegate, DBStatus::OK); + + /** + * @tc.steps:step4. sync and check count + * @tc.expected: step4. return OK + */ + std::string sql = QueryLogicDeleteCountSql(g_tableName2); + EXPECT_EQ(sqlite3_exec(db_, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback, + reinterpret_cast(cloudCount - delCount), nullptr), SQLITE_OK); + sql = QueryLogicDeleteCountSql(g_sharedTableName1); + EXPECT_EQ(sqlite3_exec(db_, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback, + reinterpret_cast(cloudCount - delCount), nullptr), SQLITE_OK); + } + + /** + * @tc.name: SharedTableSync015 + * @tc.desc: Test shared table logic delete + * @tc.type: FUNC + * @tc.require: + * @tc.author: wangxiangdong + */ + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync015, TestSize.Level0) + { + /** + * @tc.steps:step1. Set data is logicDelete + * @tc.expected: step1. return OK + */ + bool logicDelete = true; + auto data = static_cast(&logicDelete); + g_delegate->Pragma(LOGIC_DELETE_SYNC_DATA, data); + + /** + * @tc.steps:step2. init cloud data and sync + * @tc.expected: step2. return OK + */ + InitCloudEnv(); + int cloudCount = 10; + forkInsertFunc_ = InsertSharingUri; + InsertCloudTableRecord(0, cloudCount, false); + InsertCloudTableRecord(0, cloudCount); + Query query = Query::Select().FromTable({ g_tableName2, g_sharedTableName1 }); + BlockSync(query, g_delegate, DBStatus::OK); + forkInsertFunc_ = nullptr; + + /** + * @tc.steps:step3. delete cloud data + * @tc.expected: step3. return OK + */ + int beginGid = 0; + int delCount = 5; + DeleteCloudTableRecord(beginGid, delCount, false); + DeleteCloudTableRecord(cloudCount, delCount); + BlockSync(query, g_delegate, DBStatus::OK); + + /** + * @tc.steps:step4. sync and check count + * @tc.expected: step4. return OK + */ + std::string sql = QueryResourceCountSql(g_sharedTableName1); EXPECT_EQ(sqlite3_exec(db_, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback, reinterpret_cast(cloudCount), nullptr), SQLITE_OK); + sql = QueryLogicDeleteCountSql(g_sharedTableName1); + EXPECT_EQ(sqlite3_exec(db_, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback, + reinterpret_cast(cloudCount - delCount), nullptr), SQLITE_OK); + + /** + * @tc.steps:step6. drop logic data, check sharing_resource + * @tc.expected: step6. return OK + */ + g_delegate->RemoveDeviceData("", CLEAR_SHARED_TABLE); + sql = QueryResourceCountSql(g_sharedTableName1); + EXPECT_EQ(sqlite3_exec(db_, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback, + reinterpret_cast(0L), nullptr), SQLITE_OK); + 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); + 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.expected: step6. return OK + */ + EXPECT_EQ(DropLogicDeletedData(db_, g_sharedTableName1, 0u), OK); + sql = QueryAllCountSql(g_sharedTableName1); + EXPECT_EQ(sqlite3_exec(db_, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback, + reinterpret_cast(0L), nullptr), SQLITE_OK); + } + + /** + * @tc.name: SharedTableSync016 + * @tc.desc: Test remove device data of shared table and notify + * @tc.type: FUNC + * @tc.require: + * @tc.author: wangxiangdong + */ + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync016, TestSize.Level0) + { + /** + * @tc.steps:step1. Set data is logicDelete + * @tc.expected: step1. return OK + */ + bool logicDelete = true; + auto data = static_cast(&logicDelete); + g_delegate->Pragma(LOGIC_DELETE_SYNC_DATA, data); + + /** + * @tc.steps:step2. init cloud data and sync + * @tc.expected: step2. return OK + */ + InitCloudEnv(); + int cloudCount = 10; + forkInsertFunc_ = InsertSharingUri; + InsertCloudTableRecord(0, cloudCount, false); + InsertCloudTableRecord(0, cloudCount); + Query query = Query::Select().FromTable({ g_tableName2, g_sharedTableName1 }); + BlockSync(query, g_delegate, DBStatus::OK); + forkInsertFunc_ = nullptr; + + /** + * @tc.steps:step3. delete cloud data + * @tc.expected: step3. return OK + */ + int beginGid = 0; + int delCount = 5; + DeleteCloudTableRecord(beginGid, delCount, false); + DeleteCloudTableRecord(cloudCount, delCount); + BlockSync(query, g_delegate, DBStatus::OK); + + /** + * @tc.steps:step4. removeDeviceData and check notify + * @tc.expected: step4. return OK + */ + g_delegate->RemoveDeviceData("", CLEAR_SHARED_TABLE); + ChangedData changedData; + changedData.type = ChangedDataType::DATA; + changedData.tableName = g_sharedTableName1; + std::vector dataVec; + DistributedDB::Type type = std::string(CloudDbConstant::FLAG_AND_DATA_MODE_NOTIFY); + dataVec.push_back(type); + changedData.primaryData[ChangeType::OP_DELETE].push_back(dataVec); + g_observer->SetExpectedResult(changedData); + EXPECT_EQ(g_observer->IsAllChangedDataEq(), true); + + /** + * @tc.steps:step5. drop logic delete data and check count + * @tc.expected: step5. return OK + */ + EXPECT_EQ(DropLogicDeletedData(db_, g_sharedTableName1, 0u), OK); + std::string sql = QueryAllCountSql(g_sharedTableName1); + EXPECT_EQ(sqlite3_exec(db_, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback, + reinterpret_cast(0L), nullptr), SQLITE_OK); + } + + /** + * @tc.name: SharedTableSync017 + * @tc.desc: Test Inconsistent Data Between Devices and Clouds after Remove Device Data. + * @tc.type: FUNC + * @tc.require: + * @tc.author: luoguo + */ + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync017, TestSize.Level0) + { + /** + * @tc.steps: step1. Set data is logicDelete + * @tc.expected: step1. return OK + */ + bool logicDelete = true; + auto data = static_cast(&logicDelete); + g_delegate->Pragma(LOGIC_DELETE_SYNC_DATA, data); + + /** + * @tc.steps:step2. init cloud share data and sync + * @tc.expected: step2. return OK + */ + InitCloudEnv(); + int cloudCount = 20; + forkInsertFunc_ = InsertSharingUri; + InsertCloudTableRecord(0, cloudCount, false); + InsertCloudTableRecord(0, cloudCount); + Query query = Query::Select().FromTable({ g_tableName2, g_sharedTableName1 }); + BlockSync(query, g_delegate, DBStatus::OK); + forkInsertFunc_ = nullptr; + + /** + * @tc.steps:step3. update local share data + * @tc.expected: step3. return OK + */ + InsertLocalSharedTableRecords(11, 10, g_sharedTableName1, true); + + /** + * @tc.steps:step4. insert local share data + * @tc.expected: step4. return OK + */ + InsertLocalSharedTableRecords(21, 10, g_sharedTableName1); + + /** + * @tc.steps:step5. remove device data and check notify + * @tc.expected: step5. return OK + */ + g_delegate->RemoveDeviceData("", CLEAR_SHARED_TABLE); + std::string sql = "select count(*) from " + DBCommon::GetLogTableName(g_sharedTableName1) + + " where flag & 0x08 == 0x08;"; + EXPECT_EQ(sqlite3_exec(db_, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback, + reinterpret_cast(20), nullptr), SQLITE_OK); + sql = "select count(*) from " + DBCommon::GetLogTableName(g_sharedTableName1) + + " where flag & 0x800 == 0x800;"; + EXPECT_EQ(sqlite3_exec(db_, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback, + reinterpret_cast(20), nullptr), SQLITE_OK); } /** @@ -1879,4 +2160,39 @@ namespace { EXPECT_EQ(relationalStoreImpl->Close(), OK); EXPECT_EQ(g_delegate->SetCloudDbSchema(dataBaseSchema), DBStatus::DB_ERROR); } + + /** + * @tc.name: SharedTableSync019 + * @tc.desc: Test falg_only has notify. + * @tc.type: FUNC + * @tc.require: + * @tc.author: wangxiangdong + */ + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync019, TestSize.Level0) + { + /** + * @tc.steps:step1. init cloud data and sync + * @tc.expected: step1. return OK + */ + InitCloudEnv(); + int cloudCount = 10; + InsertCloudTableRecord(0, cloudCount); + Query query = Query::Select().FromTable({ g_tableName2 }); + BlockSync(query, g_delegate, DBStatus::OK); + + /** + * @tc.steps:step2. remove device data and check notify + * @tc.expected: step2. return OK + */ + g_delegate->RemoveDeviceData("", FLAG_ONLY); + ChangedData changedData; + changedData.type = ChangedDataType::DATA; + changedData.tableName = g_tableName2; + std::vector dataVec; + DistributedDB::Type type = std::string(CloudDbConstant::FLAG_ONLY_MODE_NOTIFY); + dataVec.push_back(type); + changedData.primaryData[ChangeType::OP_DELETE].push_back(dataVec); + g_observer->SetExpectedResult(changedData); + EXPECT_EQ(g_observer->IsAllChangedDataEq(), true); + } } // namespace \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_data_operation_syncdb_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_data_operation_syncdb_test.cpp index 46eac7dff8efd25e880fc56b95230a870f4e2979..d15bab16830272e61800ee416cd6157dd50265dc 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_data_operation_syncdb_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_data_operation_syncdb_test.cpp @@ -1340,10 +1340,6 @@ HWTEST_F(DistributedDBInterfacesDataOperationSyncDBTest, TransactionException001 */ IKvDBFactory *factory = IKvDBFactory::GetCurrent(); ASSERT_NE(factory, nullptr); - if (factory == nullptr) { - LOGE("failed to get DefaultFactory!"); - return; - } int result = E_OK; IKvDBCommitStorage *commitStorage = factory->CreateMultiVerCommitStorage(result); ASSERT_EQ(result, E_OK); diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_database_corrupt_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_database_corrupt_test.cpp index 2c66de2fc50a2c21d7b29385a901a2965443edb1..982cf0ea16eabc6034b7cb1740a61168e15506db 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_database_corrupt_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_database_corrupt_test.cpp @@ -277,6 +277,8 @@ HWTEST_F(DistributedDBInterfacesDatabaseCorruptTest, DatabaseCorruptionHandleTes g_mgr.GetKvStore("corrupt5", nbOption, g_kvNbDelegateCallback); ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); ASSERT_EQ(PutDataIntoDatabaseSingleVer(g_kvNbDelegatePtr), OK); + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + g_kvNbDelegatePtr = nullptr; /** * @tc.steps: step4. Modify the database file. @@ -309,13 +311,13 @@ HWTEST_F(DistributedDBInterfacesDatabaseCorruptTest, DatabaseCorruptionHandleTes EXPECT_EQ(g_mgr.DeleteKvStore("corrupt4"), OK); infoSize++; #endif // OMIT_MULTI_VER + g_mgr.GetKvStore("corrupt5", nbOption, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr == nullptr); ASSERT_NE(PutDataIntoDatabaseSingleVer(g_kvNbDelegatePtr), OK); infoSize++; std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_CALLBACK_TIME)); EXPECT_TRUE(corruptInfo.GetDatabaseInfoSize() >= infoSize); // 2 more callback EXPECT_EQ(corruptInfo.IsDataBaseCorrupted(APP_NAME, USER_NAME, "corrupt5"), true); - EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); - g_kvNbDelegatePtr = nullptr; EXPECT_EQ(g_mgr.DeleteKvStore("corrupt5"), OK); } @@ -343,6 +345,8 @@ HWTEST_F(DistributedDBInterfacesDatabaseCorruptTest, DatabaseCorruptionHandleTes g_mgr.GetKvStore("corrupt7", nbOption, g_kvNbDelegateCallback); ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); ASSERT_EQ(PutDataIntoDatabaseSingleVer(g_kvNbDelegatePtr), OK); + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + g_kvNbDelegatePtr = nullptr; /** * @tc.steps: step4. Modify the database file. @@ -364,6 +368,8 @@ HWTEST_F(DistributedDBInterfacesDatabaseCorruptTest, DatabaseCorruptionHandleTes * @tc.steps: step5. Re-obtain the kvStore. * @tc.expected: step5. Returns null kvstore. */ + g_mgr.GetKvStore("corrupt7", nbOption, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr == nullptr); size_t infoSize = 0; ASSERT_NE(PutDataIntoDatabaseSingleVer(g_kvNbDelegatePtr), OK); infoSize++; @@ -371,8 +377,6 @@ HWTEST_F(DistributedDBInterfacesDatabaseCorruptTest, DatabaseCorruptionHandleTes EXPECT_EQ(corruptInfo.GetDatabaseInfoSize(), 0UL); // no callback EXPECT_TRUE(corruptInfoNew.GetDatabaseInfoSize() >= infoSize); // 2 more callback EXPECT_EQ(corruptInfoNew.IsDataBaseCorrupted(APP_NAME, USER_NAME, "corrupt7"), true); - EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); - g_kvNbDelegatePtr = nullptr; EXPECT_EQ(g_mgr.DeleteKvStore("corrupt7"), OK); } @@ -520,6 +524,43 @@ void TestDatabaseIntegrityCheckOption(const std::string &storeId, bool isEncrypt } } +/** + * @tc.name: DatabaseRebuildTest001 + * @tc.desc: Test DB rebuild. + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(DistributedDBInterfacesDatabaseCorruptTest, DatabaseRebuildTest001, TestSize.Level0) +{ + /** + * @tc.steps: step1. Get the kv store + * @tc.expected: step1. Returns OK. + */ + KvStoreNbDelegate::Option nbOption; + nbOption.isNeedIntegrityCheck = false; + nbOption.isNeedRmCorruptedDb = true; + std::string storeId = "DatabaseRebuildTest001"; + auto filePath = GetKvStoreDirectory(storeId, DBConstant::DB_TYPE_SINGLE_VER); + g_mgr.GetKvStore(storeId, nbOption, g_kvNbDelegateCallback); + ASSERT_EQ(g_kvNbDelegateStatus, OK); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + ASSERT_EQ(PutDataIntoDatabaseSingleVer(g_kvNbDelegatePtr), OK); + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + /** + * @tc.steps: step2. Modify database file and get the kv store + * @tc.expected: step2. Check database status OK. + */ + DistributedDBToolsUnitTest::ModifyDatabaseFile(filePath, 0, MODIFY_SIZE, MODIFY_VALUE); + g_mgr.GetKvStore(storeId, nbOption, g_kvNbDelegateCallback); + ASSERT_EQ(g_kvNbDelegateStatus, OK); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + KvStoreNbDelegate::DatabaseStatus actualStatus = g_kvNbDelegatePtr->GetDatabaseStatus(); + EXPECT_EQ(actualStatus.isRebuild, true); + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + EXPECT_EQ(g_mgr.DeleteKvStore(storeId), OK); +} + /** * @tc.name: DatabaseIntegrityCheck001 * @tc.desc: Test the integrity check option. diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_database_rd_kernel_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_database_rd_kernel_test.cpp index 6676d063de645def7730046a36b7e60efd79d875..f86972bcfcd476c4fa7ce463892fc14a7195bd92 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_database_rd_kernel_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_database_rd_kernel_test.cpp @@ -361,7 +361,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, GetKvStore007, TestSize.Le option.storageEngineType = GAUSSDB_RD; option.rdconfig.readOnly = true; g_mgr.GetKvStore("distributed_getkvstore_007", option, g_kvNbDelegateCallback); - EXPECT_EQ(g_kvDelegateStatus, INVALID_ARGS); + EXPECT_EQ(g_kvDelegateStatus, DB_ERROR); ASSERT_EQ(g_kvNbDelegatePtr, nullptr); } 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 2119fddcb40415ef211cbe71e52379b28113c543..2bd696666c1e485f7a479e87595b900c92dd9660 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 @@ -244,20 +244,9 @@ int DistributedDBInterfacesImportAndExportRdTest::ModifyDataInPage(int modifyPos printf("Failed to open file"); return 1; } - if (fseek(fp, modifyPos, SEEK_SET) != 0) { - printf("Failed to seek to position"); - fclose(fp); - return 1; - } - size_t ret = fwrite(&newVal, sizeof(char), 1, fp); - if (ret != 1) { - printf("Failed to write file"); - return 1; - } - if (fclose(fp) == EOF) { - printf("Failed to close file"); - return 1; - } + (void)fseek(fp, modifyPos, SEEK_SET); + (void)fwrite(&newVal, sizeof(char), 1, fp); + (void)fclose(fp); return 0; } @@ -1037,7 +1026,6 @@ HWTEST_F(DistributedDBInterfacesImportAndExportRdTest, PasswordIndependence003, /** * @tc.steps: step1. Back up the (passwd1) encryption single-version (passwd2) database. */ - std::string singleExportFileName = g_exportFileDir + "/passwordIndependence003.$$"; std::string singleStoreId = "distributed_ExportSingle_009"; KvStoreNbDelegate::Option option = {true, false, true, CipherType::DEFAULT, g_passwd2}; option.storageEngineType = DistributedDB::GAUSSDB_RD; @@ -1287,10 +1275,6 @@ HWTEST_F(DistributedDBInterfacesImportAndExportRdTest, ImportTest001, TestSize.L std::this_thread::sleep_for(std::chrono::microseconds(millsecondsPerSecond)); EXPECT_EQ(g_kvNbDelegatePtr->Import(singleFileName, passwd), OK); - std::mutex rekeyMtx; - std::unique_lock lck(rekeyMtx); - backupVar.wait(lck, [&]{ return readyFlag.load(); }); - EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); EXPECT_EQ(g_mgr.DeleteKvStore(singleStoreId), OK); } 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 d2e28ae87021da367587ecd8950d071dda68d79e..2332acf1781c98abb6bc650b97ce063c4b6f92f8 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 @@ -1071,7 +1071,7 @@ HWTEST_F(DistributedDBInterfacesImportAndExportTest, SeparaDbExportAndImport, Te RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(adapter); std::string singleExportFileName = g_exportFileDir + "/SeparaDbExportAndImport.$$"; - std::string singleStoreId = "distributed_ExportSingle_010"; + std::string singleStoreId = "distributed_ExportSingle_0101"; KvStoreNbDelegate::Option option = {true, false, false}; SecurityOption secOption{SecurityLabel::S3, SecurityFlag::SECE}; option.secOption = secOption; @@ -1362,10 +1362,6 @@ HWTEST_F(DistributedDBInterfacesImportAndExportTest, ImportTest001, TestSize.Lev std::this_thread::sleep_for(std::chrono::microseconds(millsecondsPerSecond)); EXPECT_EQ(g_kvNbDelegatePtr->Import(singleFileName, passwd), OK); - std::mutex rekeyMtx; - std::unique_lock lck(rekeyMtx); - backupVar.wait(lck, [&]{ return readyFlag.load(); }); - EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); EXPECT_EQ(g_mgr.DeleteKvStore(singleStoreId), OK); } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_rd_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_rd_test.cpp index d5f71900b8dee7574d25498b2078eb97276773be..0534b91dd9d3f16d5e7e55fcfd9998afa476d221 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_rd_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_rd_test.cpp @@ -1864,7 +1864,7 @@ void PutRangeDataIntoDB() * @tc.name: RdRangeQuery001 * @tc.desc: Test GetEntries and the out of the parameter is entries. * @tc.type: FUNC - * @tc.require: AR.SR.IR20230714002092.017.001 + * @tc.require: * @tc.author: mazhao */ HWTEST_F(DistributedDBInterfacesNBDelegateRdTest, RdRangeQuery001, TestSize.Level1) @@ -1948,7 +1948,7 @@ void ChkRangeResultSet(KvStoreResultSet *resultSet, int beginNum, int EndNum) * @tc.name: RdRangeQuery002 * @tc.desc:Test GetEntries and the out of the parameter is resultSet. * @tc.type: FUNC - * @tc.require: AR.SR.IR20230714002092.017.001 + * @tc.require: * @tc.author: mazhao */ HWTEST_F(DistributedDBInterfacesNBDelegateRdTest, RdRangeQuery002, TestSize.Level1) @@ -2028,7 +2028,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateRdTest, RdRangeQuery002, TestSize.Leve * @tc.name: RdRangeQuery003 * @tc.desc: Test GetEntries and the in put paramter is invalid. * @tc.type: FUNC - * @tc.require: AR.SR.IR20230714002092.017.001 + * @tc.require: * @tc.author: mazhao */ HWTEST_F(DistributedDBInterfacesNBDelegateRdTest, RdRangeQuery003, TestSize.Level1) @@ -2107,7 +2107,7 @@ void ChkRangeResultSetMoveFuc(KvStoreResultSet *resultSet, int beginNum, int end * @tc.name: RdRangeQuery004 * @tc.desc: Test resultSet fuction. * @tc.type: FUNC - * @tc.require: AR.SR.IR20230714002092.017.001 + * @tc.require: * @tc.author: mazhao */ HWTEST_F(DistributedDBInterfacesNBDelegateRdTest, RdRangeQuery004, TestSize.Level1) @@ -2232,6 +2232,83 @@ HWTEST_F(DistributedDBInterfacesNBDelegateRdTest, RdRangeQuery005, TestSize.Leve g_kvNbDelegatePtr = nullptr; } +/** + * @tc.name: RdRangeQuery006 + * @tc.desc: Test GetEntries with rd kernel and the query filter is not Range. + * @tc.type: FUNC + * @tc.require: DTS2024022106199 + * @tc.author: mazhao + */ +HWTEST_F(DistributedDBInterfacesNBDelegateRdTest, RdRangeQuery006, TestSize.Level1) +{ + /** + * @tc.steps:step1. Get the nb delegate. + * @tc.expected: step1. Get results OK and non-null delegate. + */ + std::vector entries; + g_mgr.GetKvStore("RdRangeQuery006", g_option, g_kvNbDelegateCallback); + ASSERT_NE(g_kvNbDelegatePtr, nullptr); + EXPECT_EQ(g_kvDelegateStatus, OK); + + /** + * @tc.steps: step2. Use invalid range query conditions to obtain the resultset. + * @tc.expected: step2. return INVALID_ARGS. + */ + KvStoreResultSet *resultSet = nullptr; + Query inValidQuery = Query::Select(); + EXPECT_EQ(g_kvNbDelegatePtr->GetEntries(inValidQuery, resultSet), INVALID_ARGS); + EXPECT_EQ(g_kvNbDelegatePtr->GetEntries(inValidQuery, entries), INVALID_ARGS); + + /** + * @tc.steps: step3. Use invalid range query conditions to obtain the resultset. + * @tc.expected: step3. return INVALID_ARGS. + */ + Query inValidQuery2 = Query::Select().PrefixKey({}); + EXPECT_EQ(g_kvNbDelegatePtr->GetEntries(inValidQuery2, resultSet), INVALID_ARGS); + EXPECT_EQ(g_kvNbDelegatePtr->GetEntries(inValidQuery2, entries), INVALID_ARGS); + + /** + * @tc.steps:step4. Close and delete KV store + * @tc.expected: step4. Returns OK. + */ + g_mgr.CloseKvStore(g_kvNbDelegatePtr); + EXPECT_EQ(g_mgr.DeleteKvStore("RdRangeQuery006"), OK); + g_kvNbDelegatePtr = nullptr; +} + +/** + * @tc.name: RdGetWaterMarkInfo001 + * @tc.desc:Test get watermark info func with rd. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBInterfacesNBDelegateRdTest, RdGetWaterMarkInfo001, TestSize.Level0) +{ + /** + * @tc.steps:step1. Get the nb delegate. + * @tc.expected: step1. Get results OK and non-null delegate. + */ + g_mgr.GetKvStore("RdGetWaterMarkInfo001", g_option, g_kvNbDelegateCallback); + ASSERT_NE(g_kvNbDelegatePtr, nullptr); + EXPECT_EQ(g_kvDelegateStatus, OK); + /** + * @tc.steps:step2. Get watermark info + * @tc.expected: step2. Return NOT_SUPPORT. + */ + auto [res, waterMark] = g_kvNbDelegatePtr->GetWatermarkInfo("device"); + EXPECT_EQ(res, NOT_SUPPORT); + EXPECT_EQ(waterMark.sendMark, 0u); + EXPECT_EQ(waterMark.receiveMark, 0u); + /** + * @tc.steps:step3. Close and delete KV store + * @tc.expected: step3. Returns OK. + */ + g_mgr.CloseKvStore(g_kvNbDelegatePtr); + EXPECT_EQ(g_mgr.DeleteKvStore("RdGetWaterMarkInfo001"), OK); + g_kvNbDelegatePtr = nullptr; +} + /** * @tc.name: RdSync001 * @tc.desc:Test sync func with rd. @@ -2319,5 +2396,37 @@ HWTEST_F(DistributedDBInterfacesNBDelegateRdTest, RdSetCloudDB001, TestSize.Leve EXPECT_EQ(g_mgr.DeleteKvStore("RdSetCloudDB001"), OK); g_kvNbDelegatePtr = nullptr; } + +/** + * @tc.name: RdGetCloudVersion001 + * @tc.desc:Test get cloud version func with rd. + * @tc.type: FUNC + * @tc.require: + * @tc.author: caihaoting + */ +HWTEST_F(DistributedDBInterfacesNBDelegateRdTest, RdGetCloudVersion001, TestSize.Level0) +{ + /** + * @tc.steps:step1. Get the nb delegate. + * @tc.expected: step1. Get results OK and non-null delegate. + */ + g_mgr.GetKvStore("RdGetCloudVersion001", g_option, g_kvNbDelegateCallback); + ASSERT_NE(g_kvNbDelegatePtr, nullptr); + EXPECT_EQ(g_kvDelegateStatus, OK); + /** + * @tc.steps:step2. Get cloud version + * @tc.expected: step2. Return NOT_SUPPORT. + */ + auto [res, versionMap] = g_kvNbDelegatePtr->GetCloudVersion("device"); + EXPECT_EQ(res, NOT_SUPPORT); + EXPECT_EQ(versionMap.size(), 0u); + /** + * @tc.steps:step3. Close and delete KV store + * @tc.expected: step3. Returns OK. + */ + g_mgr.CloseKvStore(g_kvNbDelegatePtr); + EXPECT_EQ(g_mgr.DeleteKvStore("RdGetCloudVersion001"), OK); + g_kvNbDelegatePtr = nullptr; +} } -#endif // USE_RD_KERNEL \ No newline at end of file +#endif // USE_RD_KERNEL 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 420da19e94bd54b77f6ea763e9b3f0940bf19879..bfe33284f6e9429bc454727f779140c34742096f 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 @@ -363,6 +363,125 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, CombineTest001, TestSize.Level1) g_kvNbDelegatePtr = nullptr; } +/** + * @tc.name: CombineTest002 + * @tc.desc: Test the NbDelegate for combined operation, try to use GAUSSDB_RD. + * @tc.type: FUNC + * @tc.require: AR000CCPOM + * @tc.author: zhujinlin + */ +HWTEST_F(DistributedDBInterfacesNBDelegateTest, CombineTest002, TestSize.Level1) +{ + /** + * @tc.steps:step1. Get the nb delegate. + * @tc.expected: step1. Get results OK and non-null delegate. + */ + KvStoreNbDelegate::Option option = {true, false, false}; + option.storageEngineType = GAUSSDB_RD; + g_mgr.GetKvStore("distributed_nb_delegate_test_rd", option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + std::string keyStr("acd"); + Key key(keyStr.begin(), keyStr.end()); + std::string valueStr("acd"); + Value value(valueStr.begin(), valueStr.end()); + Value valueRead; + /** + * @tc.steps:step2. Try to get the data before put. + * @tc.expected: step2. Get returns NOT_FOUND. + */ + EXPECT_EQ(g_kvNbDelegatePtr->Get(key, valueRead), NOT_FOUND); + /** + * @tc.steps:step3. Put the local data. + * @tc.expected: step3. Returns OK. + */ + EXPECT_EQ(g_kvNbDelegatePtr->Put(key, value), OK); + std::this_thread::sleep_for(std::chrono::milliseconds(OBSERVER_SLEEP_TIME)); + /** + * @tc.steps:step4. Check the local data. + * @tc.expected: step4. The get data is equal to the put data. + */ + EXPECT_EQ(g_kvNbDelegatePtr->Get(key, valueRead), OK); + /** + * @tc.steps:step5. Delete the local data. + * @tc.expected: step5. Delete return OK. + */ + EXPECT_EQ(g_kvNbDelegatePtr->Delete(key), OK); + std::this_thread::sleep_for(std::chrono::milliseconds(OBSERVER_SLEEP_TIME)); + /** + * @tc.steps:step6. Check the local data. + * @tc.expected: step6. Couldn't find the deleted data. + */ + EXPECT_EQ(g_kvNbDelegatePtr->Get(key, valueRead), NOT_FOUND); + /** + * @tc.steps:step7. Close the kv store. + * @tc.expected: step7. Results OK and delete successfully. + */ + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + EXPECT_EQ(g_mgr.DeleteKvStore("distributed_nb_delegate_test_rd"), OK); + g_kvNbDelegatePtr = nullptr; +} + +/** + * @tc.name: CombineTest003 + * @tc.desc: Test the NbDelegate for combined operation, try to use GAUSSDB_RD and index type with hash. + * @tc.type: FUNC + * @tc.require: AR000CCPOM + * @tc.author: zhujinlin + */ +HWTEST_F(DistributedDBInterfacesNBDelegateTest, CombineTest003, TestSize.Level1) +{ + /** + * @tc.steps:step1. Get the nb delegate. + * @tc.expected: step1. Get results OK and non-null delegate. + */ + KvStoreNbDelegate::Option option = {true, false, false}; + option.storageEngineType = GAUSSDB_RD; + option.rdconfig.type = HASH; + g_mgr.GetKvStore("distributed_nb_delegate_test_rd_combine_003", option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + std::string keyStr("acd"); + Key key(keyStr.begin(), keyStr.end()); + std::string valueStr("acd"); + Value value(valueStr.begin(), valueStr.end()); + Value valueRead; + /** + * @tc.steps:step2. Try to get the data before put. + * @tc.expected: step2. Get returns NOT_FOUND. + */ + EXPECT_EQ(g_kvNbDelegatePtr->Get(key, valueRead), NOT_FOUND); + /** + * @tc.steps:step3. Put the local data. + * @tc.expected: step3. Returns OK. + */ + EXPECT_EQ(g_kvNbDelegatePtr->Put(key, value), OK); + std::this_thread::sleep_for(std::chrono::milliseconds(OBSERVER_SLEEP_TIME)); + /** + * @tc.steps:step4. Check the local data. + * @tc.expected: step4. The get data is equal to the put data. + */ + EXPECT_EQ(g_kvNbDelegatePtr->Get(key, valueRead), OK); + /** + * @tc.steps:step5. Delete the local data. + * @tc.expected: step5. Delete return OK. + */ + EXPECT_EQ(g_kvNbDelegatePtr->Delete(key), OK); + std::this_thread::sleep_for(std::chrono::milliseconds(OBSERVER_SLEEP_TIME)); + /** + * @tc.steps:step6. Check the local data. + * @tc.expected: step6. Couldn't find the deleted data. + */ + EXPECT_EQ(g_kvNbDelegatePtr->Get(key, valueRead), NOT_FOUND); + /** + * @tc.steps:step7. Close the kv store. + * @tc.expected: step7. Results OK and delete successfully. + */ + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + EXPECT_EQ(g_mgr.DeleteKvStore("distributed_nb_delegate_test_rd_combine_003"), OK); + g_kvNbDelegatePtr = nullptr; +} + /** * @tc.name: CreateMemoryDb001 * @tc.desc: Create memory database after. @@ -2933,7 +3052,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, MigrateDeadLockTest001, TestSize * @tc.name: InvalidQueryTest001 * @tc.desc: Test GetEntries with range query filter by sqlite * @tc.type: FUNC - * @tc.require: AR.SR.IR20230714002092.017.001 + * @tc.require: * @tc.author: mazhao */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, InvalidQueryTest001, TestSize.Level1) @@ -3008,6 +3127,40 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, InvalidQueryTest002, TestSize.Le 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 @@ -3052,7 +3205,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, OptionModeValidCheck001, TestSiz * @tc.name: AbnormalKvStoreTest001 * @tc.desc: Test KvStoreNbDelegateImpl interface while conn is nullptr. * @tc.type: FUNC - * @tc.require: DTS2024073106613 + * @tc.require: * @tc.author: suyue */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, AbnormalKvStoreTest001, TestSize.Level1) @@ -3110,7 +3263,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, AbnormalKvStoreTest001, TestSize * @tc.name: AbnormalKvStoreTest002 * @tc.desc: Test KvStoreNbDelegateImpl interface while conn is nullptr. * @tc.type: FUNC - * @tc.require: DTS2024073106613 + * @tc.require: * @tc.author: suyue */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, AbnormalKvStoreTest002, TestSize.Level1) @@ -3166,7 +3319,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, AbnormalKvStoreTest002, TestSize * @tc.name: AbnormalKvStoreResultSetTest * @tc.desc: Test KvStoreResultSetImpl interface when class para is nullptr. * @tc.type: FUNC - * @tc.require: DTS2024073106613 + * @tc.require: * @tc.author: suyue */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, AbnormalKvStoreResultSetTest, TestSize.Level1) @@ -3214,4 +3367,66 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, AbnormalKvStoreResultSetTest, Te 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 d109fd5249021f7a7ee39255b383e7e75ddadf18..f5a1264b6a9a707409b9c0ba870b58fd92110af2 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 @@ -231,7 +231,7 @@ HWTEST_F(DistributedDBInterfacesQueryTest, Query003, TestSize.Level1) * @tc.name: Query004 * @tc.desc: Check QueryExpression abnormal scene * @tc.type: FUNC - * @tc.require: DTS2024073106613 + * @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_tracker_table_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_tracker_table_test.cpp index 17ad56bc41225387d590c04703c4d9b567c9aee8..3ead474087391c0c6ac94bbdf4a34513c2bc814f 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 @@ -1132,7 +1132,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest020, sql = "select count(*) from " + DBConstant::RELATIONAL_PREFIX + TABLE_NAME2 + "_log where extend_field is NULL " + " AND cursor is NULL"; EXPECT_EQ(sqlite3_exec(g_db, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback, - reinterpret_cast(num + num), nullptr), SQLITE_OK); + reinterpret_cast(0), nullptr), SQLITE_OK); CloseStore(); } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_single_version_result_set_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_single_version_result_set_test.cpp index db872744705a0ca38595a1480398e708a090b8d3..1f222b69182a36e465f1a4e61fcd5f0ec9c46a0e 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_single_version_result_set_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_single_version_result_set_test.cpp @@ -531,4 +531,45 @@ HWTEST_F(DistributedDBInterfacesSingleVersionResultSetTest, SingleVersionResultS EXPECT_EQ(resultWindow.GetEntry(entry), E_OK); EXPECT_EQ(entry.key, LOCAL_KEY_1); EXPECT_EQ(entry.value, VALUE_1); -} \ No newline at end of file +} + +/** + * @tc.name: SingleVerNaturalStoreTest + * @tc.desc: Test SingleVerNaturalStore interfaces with invalid db. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBInterfacesSingleVersionResultSetTest, SingleVerNaturalStoreTest, TestSize.Level1) +{ + /** + * @tc.steps: step1. Call interfaces when db not open. + * @tc.expected: step1. return failInfo. + */ + SQLiteSingleVerNaturalStore storeObj; + Key key; + Value value; + EXPECT_EQ(storeObj.GetMetaData(key, value), -E_INVALID_DB); + const std::string deviceName = "test"; + ClearMode mode = ClearMode::DEFAULT; + EXPECT_EQ(storeObj.RemoveDeviceData("", ClearMode::DEFAULT), -E_INVALID_DB); + const std::string user = ""; + EXPECT_EQ(storeObj.RemoveDeviceData(deviceName, user, mode), -E_INVALID_DB); + Timestamp stamp = 0; + storeObj.GetMaxTimestamp(stamp); + CloudSyncConfig config; + EXPECT_EQ(storeObj.SetCloudSyncConfig(config), -E_INTERNAL_ERROR); + std::map versionMap; + EXPECT_EQ(storeObj.GetCloudVersion("", versionMap), -E_INTERNAL_ERROR); + EXPECT_EQ(storeObj.UnRegisterObserverAction(nullptr), -E_INTERNAL_ERROR); + ObserverAction action; + EXPECT_EQ(storeObj.RegisterObserverAction(nullptr, action), -E_INTERNAL_ERROR); + Key keyPrefix; + EXPECT_EQ(storeObj.DeleteMetaDataByPrefixKey(keyPrefix), -E_INVALID_ARGS); + keyPrefix.push_back(0); + EXPECT_EQ(storeObj.DeleteMetaDataByPrefixKey(keyPrefix), -E_INVALID_DB); + EXPECT_EQ(storeObj.GetAndIncreaseCacheRecordVersion(), static_cast(0)); + EXPECT_EQ(storeObj.TriggerToMigrateData(), E_OK); + storeObj.SetConnectionFlag(true); + EXPECT_EQ(storeObj.IsDataMigrating(), false); +} 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 1c14b65c9da93bf87cb807f9bc3fc63d3584e46e..8d592cf5ae1775d3f69aea24bafb93830994b3fd 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 @@ -22,6 +22,7 @@ #include "log_print.h" #include "process_system_api_adapter_impl.h" #include "runtime_context.h" +#include "virtual_communicator_aggregator.h" using namespace testing::ext; using namespace DistributedDB; @@ -298,4 +299,87 @@ HWTEST_F(RuntimeContextProcessSystemApiAdapterImplTest, SetSystemApiAdapterTest0 */ RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(g_adapter); EXPECT_TRUE(g_mgr.IsProcessSystemApiAdapterValid()); +} + +/** + * @tc.name: SecurityOptionUpgrade001 + * @tc.desc: Test upgrade security label from s1 to s3. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(RuntimeContextProcessSystemApiAdapterImplTest, SecurityOptionUpgrade001, TestSize.Level0) +{ + /** + * @tc.steps: step1. set g_adapter and open with s1 + * @tc.expected: step1. return true + */ + RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(g_adapter); + EXPECT_TRUE(g_mgr.IsProcessSystemApiAdapterValid()); + g_config.dataDir = g_testDir; + EXPECT_EQ(g_mgr.SetKvStoreConfig(g_config), OK); + + const std::string storeId = "SecurityOptionUpgrade001"; + 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 s3 + * @tc.expected: step2. open ok + */ + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + option.secOption = { S3, SECE }; + g_mgr.GetKvStore(storeId, option, g_kvNbDelegateCallback); + EXPECT_EQ(g_kvDelegateStatus, OK); + ASSERT_NE(g_kvNbDelegatePtr, nullptr); + /** + * @tc.steps: step3. re open with s4 + * @tc.expected: step3. open ok + */ + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + option.secOption = { S4, SECE }; + 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); + RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(nullptr); +} + +/** + * @tc.name: SecurityOptionUpgrade002 + * @tc.desc: Test upgrade security label from NOT_SET to s3. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(RuntimeContextProcessSystemApiAdapterImplTest, SecurityOptionUpgrade002, TestSize.Level0) +{ + /** + * @tc.steps: step1. set g_adapter and open with s1 + * @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 = "SecurityOptionUpgrade002"; + 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); + option.secOption = { S3, SECE }; + 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); + 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 80711fea688143d3babb9aeb5ea77b90a67c6d22..249139cedad8d00e236e1bdc316cf6fb6dfe28c1 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 @@ -25,8 +25,10 @@ #include "virtual_asset_loader.h" #include "virtual_cloud_data_translate.h" #include "virtual_cloud_db.h" +#include "virtual_communicator_aggregator.h" #include "sqlite_relational_utils.h" #include "cloud/cloud_storage_utils.h" +#include "cloud_db_sync_utils_test.h" namespace { using namespace testing::ext; @@ -98,6 +100,7 @@ protected: void UpdateCloudTableRecord(int64_t begin, int64_t count, bool assetIsNull); void ForkDownloadAndRemoveAsset(DBStatus removeStatus, int &downLoadCount, int &removeCount); std::vector GetAssets(const std::string &baseName, const Assets &templateAsset, size_t assetCount); + void CheckAssetData(); std::string testDir_; std::string storePath_; sqlite3 *db_ = nullptr; @@ -107,6 +110,7 @@ protected: std::shared_ptr virtualTranslator_ = nullptr; std::shared_ptr mgr_ = nullptr; std::string tableName_ = "DistributedDBCloudAssetsOperationSyncTest"; + VirtualCommunicatorAggregator *communicatorAggregator_ = nullptr; }; void DistributedDBCloudAssetsOperationSyncTest::SetUpTestCase() @@ -141,6 +145,9 @@ void DistributedDBCloudAssetsOperationSyncTest::SetUp() virtualTranslator_ = std::make_shared(); DataBaseSchema dataBaseSchema = GetSchema(); ASSERT_EQ(delegate_->SetCloudDbSchema(dataBaseSchema), DBStatus::OK); + communicatorAggregator_ = new (std::nothrow) VirtualCommunicatorAggregator(); + ASSERT_TRUE(communicatorAggregator_ != nullptr); + RuntimeContext::GetInstance()->SetCommunicatorAggregator(communicatorAggregator_); } void DistributedDBCloudAssetsOperationSyncTest::TearDown() @@ -150,6 +157,9 @@ void DistributedDBCloudAssetsOperationSyncTest::TearDown() if (DistributedDBToolsUnitTest::RemoveTestDbFiles(testDir_) != E_OK) { LOGE("rm test db files error."); } + RuntimeContext::GetInstance()->SetCommunicatorAggregator(nullptr); + communicatorAggregator_ = nullptr; + RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(nullptr); } void DistributedDBCloudAssetsOperationSyncTest::InitTestDir() @@ -249,7 +259,7 @@ void DistributedDBCloudAssetsOperationSyncTest::UpdateCloudTableRecord(int64_t b asset.status = AssetStatus::UPDATE; assets.push_back(asset); } - data.insert_or_assign("assets", assets); + assetIsNull ? data.insert_or_assign("assets", Nil()) : data.insert_or_assign("assets", assets); record.push_back(data); VBucket log; log.insert_or_assign(CloudDbConstant::CREATE_FIELD, static_cast( @@ -309,6 +319,27 @@ 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 @@ -441,6 +472,144 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation004, T CheckAssetsCount(expectCount); } +/** + * @tc.name: SyncWithAssetOperation005 + * @tc.desc: check asset when update in fill before upload sync process + * @tc.type: FUNC + * @tc.require: + * @tc.author: luoguo + */ +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation005, TestSize.Level0) +{ + /** + * @tc.steps:step1. Insert 60 records. + * @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) { + if (isUpload == true) { + return; + } + isUpload = true; + std::this_thread::sleep_for(std::chrono::milliseconds(2000)); + }); + Query query = Query::Select().FromTable({tableName_}); + + bool finish = false; + auto callback = [&finish](const std::map &process) { + for (const auto &item: process) { + if (item.second.process == DistributedDB::FINISHED) { + { + finish = true; + } + } + } + }; + 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)); + } + + /** + * @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); + + /** + * @tc.steps:step4. check asset data. + * @tc.expected: step4. ok. + */ + while (finish == false) { + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + } + CheckAssetData(); +} + +/** + * @tc.name: SyncWithAssetOperation006 + * @tc.desc: Remove Local Datas When local assets was empty + * @tc.type: FUNC + * @tc.require: + * @tc.author: lijun + */ +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation006, TestSize.Level0) +{ + const int actualCount = 5; + InsertUserTableRecord(tableName_, 0, actualCount); + Query query = Query::Select().FromTable({ tableName_ }); + BlockSync(query, delegate_); + + UpdateCloudTableRecord(0, 2, true); + BlockSync(query, delegate_); + + int removeCount = 0; + virtualAssetLoader_->ForkRemoveLocalAssets([&removeCount](const std::vector &assets) { + removeCount = assets.size(); + return DBStatus::OK; + }); + std::string device = ""; + ASSERT_EQ(delegate_->RemoveDeviceData(device, FLAG_AND_DATA), DBStatus::OK); + ASSERT_EQ(9, removeCount); + virtualAssetLoader_->ForkRemoveLocalAssets(nullptr); +} + +/** + * @tc.name: SyncWithAssetOperation007 + * @tc.desc: Test assetId fill when assetId changed + * @tc.type: FUNC + * @tc.require: + * @tc.author: wangxiangdong + */ +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation007, TestSize.Level0) +{ + /** + * @tc.steps:step1. Insert 5 records and sync. + * @tc.expected: step1. ok. + */ + const int actualCount = 5; + std::string name = g_localAsset.name + std::to_string(0); + Assets expectAssets = GetAssets(name, {}, 3u); // contain 3 assets + expectAssets[0].hash.append("change"); // modify first asset + InsertUserTableRecord(tableName_, 0, actualCount, expectAssets.size(), expectAssets); + Query query = Query::Select().FromTable({ tableName_ }); + BlockSync(query, delegate_); + /** + * @tc.steps:step2. modify data and sync. + * @tc.expected: step2. ok. + */ + UpdateCloudTableRecord(0, 1, true); + BlockSync(query, delegate_); + /** + * @tc.steps:step3. check modified data cursor. + * @tc.expected: step3. ok. + */ + 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); + 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); +} + /** * @tc.name: IgnoreRecord001 * @tc.desc: Download Assets When local assets was removed @@ -566,6 +735,13 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, UpsertData002, TestSize.Leve * @tc.steps:step2. UpsertData and sync. * @tc.expected: step2. ok. */ + int dataCnt = -1; + std::string checkLogSql = "SELECT count(*) FROM " + DBCommon::GetLogTableName(tableName_) + " where cursor = 5"; + RelationalTestUtils::ExecSql(db_, checkLogSql, nullptr, [&dataCnt](sqlite3_stmt *stmt) { + dataCnt = sqlite3_column_int(stmt, 0); + return E_OK; + }); + EXPECT_EQ(dataCnt, 1); vector records; for (int i = 0; i < actualCount; i++) { VBucket record; @@ -574,6 +750,13 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, UpsertData002, TestSize.Leve records.push_back(record); } EXPECT_EQ(delegate_->UpsertData(tableName_, records), OK); + // check cursor has been increase + 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); + return E_OK; + }); + EXPECT_EQ(dataCnt, 1); BlockSync(query, delegate_); /** @@ -717,6 +900,67 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, UpsertDataInvalid002, TestSi delegate1 = nullptr; mgr1 = nullptr; } +/** + * @tc.name: DownloadAssetStatusTest004 + * @tc.desc: Test upload asset status + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, DownloadAssetStatusTest004, TestSize.Level0) +{ + /** + * @tc.steps:step1. cloud assets {0, 1} + * @tc.expected: step1. OK. + */ + // cloud and local insert same data + // cloud assets {0, 1} local assets {0, 1, 2} + const int actualCount = 1; + RelationalTestUtils::InsertCloudRecord(0, actualCount, tableName_, virtualCloudDb_, 2); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); // sleep 100ms for data conflict + /** + * @tc.steps:step2. local assets {0, 1, 2}, and change assert {0} + * @tc.expected: step2. OK. + */ + std::string name = g_localAsset.name + std::to_string(0); + Assets expectAssets = GetAssets(name, {}, 3u); // contain 3 assets + expectAssets[0].hash.append("change"); // modify first asset + InsertUserTableRecord(tableName_, 0, actualCount, expectAssets.size(), expectAssets); + /** + * @tc.steps:step3. sync + * @tc.expected: step3. upload status is {UPDATE, NORMAL, INSERT} + */ + std::vector expectStatus = { + AssetStatus::UPDATE, AssetStatus::NORMAL, AssetStatus::INSERT + }; + // sync and local asset's status are normal + Query query = Query::Select().FromTable({ tableName_ }); + RelationalTestUtils::CloudBlockSync(query, delegate_); + auto dbSchema = GetSchema(); + ASSERT_GT(dbSchema.tables.size(), 0u); + // cloud asset status is update normal insert + VBucket extend; + extend[CloudDbConstant::CURSOR_FIELD] = std::string(""); + std::vector data; + ASSERT_EQ(virtualCloudDb_->Query(tableName_, extend, data), QUERY_END); + ASSERT_EQ(data.size(), static_cast(actualCount)); + Assets actualAssets; + ASSERT_EQ(CloudStorageUtils::GetValueFromType(data[0]["assets"], actualAssets), E_OK); + ASSERT_EQ(actualAssets.size(), expectStatus.size()); + for (size_t i = 0; i < actualAssets.size(); ++i) { + EXPECT_EQ(actualAssets[i].status, expectStatus[i]); + } + /** + * @tc.steps:step4. check local assets status. + * @tc.expected: step4. all assets status is NORMAL. + */ + auto assets = RelationalTestUtils::GetAllAssets(db_, dbSchema.tables[0], virtualTranslator_); + for (const auto &oneRow : assets) { + for (const auto &asset : oneRow) { + EXPECT_EQ(asset.status, static_cast(AssetStatus::NORMAL)); + } + } +} /** * @tc.name: UploadAssetsTest001 @@ -781,9 +1025,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, 10u); + EXPECT_EQ(table.second.upLoadInfo.total, 9u); EXPECT_EQ(table.second.upLoadInfo.failCount, 3u); - EXPECT_EQ(table.second.upLoadInfo.successCount, 7u); + EXPECT_EQ(table.second.upLoadInfo.successCount, 6u); } virtualCloudDb_->ForkUpload(nullptr); } @@ -865,5 +1109,53 @@ HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, UploadAssetsTest003, TestSiz } virtualCloudDb_->ForkUpload(nullptr); } + +/** + * @tc.name: UploadAssetsTest004 + * @tc.desc: Test batch delete return error CLOUD_RECORD_NOT_FOUND. + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, UploadAssetsTest004, TestSize.Level0) +{ + /** + * @tc.steps:step1. Insert 100 records and sync to cloud. + * @tc.expected: step1. ok. + */ + const int actualCount = 100; + InsertUserTableRecord(tableName_, 0, actualCount); + Query query = Query::Select().FromTable({ tableName_ }); + BlockSync(query, delegate_); + /** + * @tc.steps:step2. delete 50 records in local. + * @tc.expected: step2. ok. + */ + std::string sql = "delete from " + tableName_ + " where CAST(id AS INTEGER) >= " + std::to_string(actualCount / 2); + EXPECT_EQ(RelationalTestUtils::ExecSql(db_, sql), SQLITE_OK); + /** + * @tc.steps:step3. set return error CLOUD_RECORD_NOT_FOUND in batch delete. + * @tc.expected: step3. ok. + */ + int index = 0; + virtualCloudDb_->ForkUpload([&index](const std::string &tableName, VBucket &extend) { + if (extend.count(CloudDbConstant::DELETE_FIELD) != 0 && index % 2 == 0 && + std::get(extend.at(CloudDbConstant::DELETE_FIELD))) { + extend[CloudDbConstant::ERROR_FIELD] = static_cast(DBStatus::CLOUD_RECORD_NOT_FOUND); + } + index++; + }); + /** + * @tc.steps:step4. sync and check result. + * @tc.expected: step4. ok. + */ + BlockSync(query, delegate_); + for (const auto &table : lastProcess_.tableProcess) { + EXPECT_EQ(table.second.upLoadInfo.total, 25u); + EXPECT_EQ(table.second.upLoadInfo.failCount, 0u); + EXPECT_EQ(table.second.upLoadInfo.successCount, 25u); + } + virtualCloudDb_->ForkUpload(nullptr); +} } #endif 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 308e8f105269c2200b8764a172bab0721c4ee7c5..98fa565037adaf6ead387bf2c4af2fe6b9e33f56 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 @@ -30,6 +30,7 @@ #include "virtual_asset_loader.h" #include "virtual_cloud_data_translate.h" #include "virtual_cloud_db.h" +#include "virtual_communicator_aggregator.h" namespace { using namespace testing::ext; @@ -57,7 +58,6 @@ const Asset g_cloudAsset = { }; std::vector g_actualDBStatus; -std::map lastProcess_; void CreateUserDBAndTable(sqlite3 *&db) { @@ -113,8 +113,7 @@ void BlockPrioritySync(const Query &query, RelationalStoreDelegate *delegate, bo std::mutex dataMutex; std::condition_variable cv; bool finish = false; - std::map last; - auto callback = [&last, &cv, &dataMutex, &finish](const std::map &process) { + auto callback = [&cv, &dataMutex, &finish](const std::map &process) { for (const auto &item: process) { if (item.second.process == DistributedDB::FINISHED) { { @@ -124,7 +123,6 @@ void BlockPrioritySync(const Query &query, RelationalStoreDelegate *delegate, bo cv.notify_one(); } } - last = process; }; CloudSyncOption option; PrepareOption(option, query, isPriority, isCompensatedSyncOnly); @@ -135,7 +133,37 @@ void BlockPrioritySync(const Query &query, RelationalStoreDelegate *delegate, bo return finish; }); } - lastProcess_ = last; +} + +void BlockCompensatedSync(const Query &query, RelationalStoreDelegate *delegate, DBStatus expectResult, + const std::function &syncProcess)> &processCallback) +{ + std::mutex dataMutex; + std::condition_variable cv; + bool finish = false; + auto callback = [&processCallback, &cv, &dataMutex, &finish](const std::map &process) { + for (const auto &item: process) { + if (item.second.process == DistributedDB::FINISHED) { + { + std::lock_guard autoLock(dataMutex); + finish = true; + } + cv.notify_one(); + } + } + if (processCallback != nullptr) { + processCallback(process); + } + }; + CloudSyncOption option; + PrepareOption(option, query, false, true); + ASSERT_EQ(delegate->Sync(option, callback), expectResult); + if (expectResult == OK) { + std::unique_lock uniqueLock(dataMutex); + cv.wait(uniqueLock, [&finish]() { + return finish; + }); + } } int QueryCountCallback(void *data, int count, char **colValue, char **colName) @@ -170,17 +198,27 @@ protected: void InsertCloudTableRecord(const std::string &tableName, int64_t begin, int64_t count, int64_t photoSize, bool assetIsNull); void DeleteUserTableRecord(int64_t id); + void DeleteUserTableRecord(int64_t begin, int64_t end); void DeleteCloudTableRecord(int64_t gid); void CheckCloudTableCount(const std::string &tableName, int64_t expectCount); + bool CheckSyncCount(const Info actualInfo, const Info expectInfo); + bool CheckSyncProcessInner(SyncProcess &actualSyncProcess, SyncProcess &expectSyncProcess); + bool CheckSyncProcess(std::vector> &actualSyncProcess, + vector &expectSyncProcessV); void PriorityAndNormalSync(const Query &normalQuery, const Query &priorityQuery, - RelationalStoreDelegate *delegate); + RelationalStoreDelegate *delegate, std::vector> &prioritySyncProcess, + bool isCheckProcess); void DeleteCloudDBData(int64_t begin, int64_t count); void SetForkQueryForCloudPrioritySyncTest007(std::atomic &count); void SetForkQueryForCloudPrioritySyncTest008(std::atomic &count); void InitLogicDeleteDataEnv(int64_t dataCount, bool prioritySync = false); void CheckLocalCount(int64_t expectCount); void CheckLogCleaned(int64_t expectCount); + 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); std::string testDir_; std::string storePath_; sqlite3 *db_ = nullptr; @@ -193,6 +231,7 @@ protected: std::string tableWithoutPrimaryName_ = "NonPrimaryKeyTable"; std::string tableWithoutPrimaryNameShared_ = "NonPrimaryKeyTable_shared"; std::string lowerTableName_ = "distributeddbCloudCheckSyncTest"; + VirtualCommunicatorAggregator *communicatorAggregator_ = nullptr; }; void DistributedDBCloudCheckSyncTest::SetUpTestCase() @@ -227,6 +266,9 @@ void DistributedDBCloudCheckSyncTest::SetUp() ASSERT_EQ(delegate_->SetIAssetLoader(virtualAssetLoader_), DBStatus::OK); DataBaseSchema dataBaseSchema = GetSchema(); ASSERT_EQ(delegate_->SetCloudDbSchema(dataBaseSchema), DBStatus::OK); + communicatorAggregator_ = new (std::nothrow) VirtualCommunicatorAggregator(); + ASSERT_TRUE(communicatorAggregator_ != nullptr); + RuntimeContext::GetInstance()->SetCommunicatorAggregator(communicatorAggregator_); } void DistributedDBCloudCheckSyncTest::TearDown() @@ -238,6 +280,9 @@ void DistributedDBCloudCheckSyncTest::TearDown() if (DistributedDBToolsUnitTest::RemoveTestDbFiles(testDir_) != E_OK) { LOGE("rm test db files error."); } + RuntimeContext::GetInstance()->SetCommunicatorAggregator(nullptr); + communicatorAggregator_ = nullptr; + RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(nullptr); } void DistributedDBCloudCheckSyncTest::InitTestDir() @@ -352,6 +397,20 @@ void DistributedDBCloudCheckSyncTest::DeleteUserTableRecord(int64_t id) ASSERT_EQ(SQLiteUtils::ExecuteRawSQL(db_, sql), E_OK); } +void DistributedDBCloudCheckSyncTest::DeleteUserTableRecord(int64_t begin, int64_t end) +{ + ASSERT_NE(db_, nullptr); + string sql = "DELETE FROM " + tableName_ + " WHERE id IN ("; + for (int64_t i = begin; i <= end; ++i) { + sql += "'" + std::to_string(i) + "',"; + } + if (sql.back() == ',') { + sql.pop_back(); + } + sql += ");"; + ASSERT_EQ(SQLiteUtils::ExecuteRawSQL(db_, sql), E_OK); +} + void DistributedDBCloudCheckSyncTest::DeleteCloudTableRecord(int64_t gid) { VBucket idMap; @@ -376,31 +435,98 @@ void DistributedDBCloudCheckSyncTest::CheckCloudTableCount(const std::string &ta EXPECT_EQ(realCount, expectCount); // ExpectCount represents the total amount of cloud data. } +bool DistributedDBCloudCheckSyncTest::CheckSyncCount(const Info actualInfo, const Info expectInfo) +{ + if (actualInfo.batchIndex != expectInfo.batchIndex) { + return false; + } + if (actualInfo.total != expectInfo.total) { + return false; + } + if (actualInfo.successCount != expectInfo.successCount) { + return false; + } + if (actualInfo.failCount != expectInfo.failCount) { + return false; + } + return true; +} + +bool DistributedDBCloudCheckSyncTest::CheckSyncProcessInner( + SyncProcess &actualSyncProcess, SyncProcess &expectSyncProcess) +{ + for (const auto &itInner : actualSyncProcess.tableProcess) { + std::string tableName = itInner.first; + if (expectSyncProcess.tableProcess.find(tableName) == expectSyncProcess.tableProcess.end()) { + return false; + } + TableProcessInfo actualTableProcessInfo = itInner.second; + TableProcessInfo expectTableProcessInfo = expectSyncProcess.tableProcess.find(tableName)->second; + if (!CheckSyncCount(actualTableProcessInfo.downLoadInfo, expectTableProcessInfo.downLoadInfo)) { + return false; + } + if (!CheckSyncCount(actualTableProcessInfo.upLoadInfo, expectTableProcessInfo.upLoadInfo)) { + return false; + } + } + return true; +} + +bool DistributedDBCloudCheckSyncTest::CheckSyncProcess( + std::vector> &actualSyncProcess, vector &expectSyncProcessV) +{ + vector> expectSyncProcess; + for (auto syncProcess : expectSyncProcessV) { + map expectSyncProcessMap = {{"CLOUD", syncProcess}}; + expectSyncProcess.emplace_back(expectSyncProcessMap); + } + for (int i = 0; i < (int) actualSyncProcess.size(); i++) { + map actualSyncProcessMap = actualSyncProcess[i]; + map expectSyncProcessMap = expectSyncProcess[i]; + for (auto &it : actualSyncProcessMap) { + string mapKey = it.first; + if (expectSyncProcessMap.find(mapKey) == expectSyncProcessMap.end()) { + return false; + } + SyncProcess actualSyncProcess = it.second; + SyncProcess expectSyncProcess = expectSyncProcessMap.find(mapKey)->second; + if (!CheckSyncProcessInner(actualSyncProcess, expectSyncProcess)) { + return false; + } + } + } + return true; +} + void DistributedDBCloudCheckSyncTest::PriorityAndNormalSync(const Query &normalQuery, const Query &priorityQuery, - RelationalStoreDelegate *delegate) + RelationalStoreDelegate *delegate, std::vector> &prioritySyncProcess, + bool isCheckProcess) { std::mutex dataMutex; std::condition_variable cv; bool normalFinish = false; bool priorityFinish = false; - auto normalCallback = [&cv, &dataMutex, &normalFinish, &priorityFinish]( + 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(priorityFinish, true); - cv.notify_one(); + for (const auto &item: process) { + if (item.second.process == DistributedDB::FINISHED) { + normalFinish = true; + ASSERT_EQ(isCheckProcess ? priorityFinish : true, true); + cv.notify_one(); + } } - } - }; - auto priorityCallback = [&cv, &priorityFinish](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 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); + }; CloudSyncOption option; PrepareOption(option, normalQuery, false); virtualCloudDb_->SetBlockTime(500); // 500 ms @@ -504,6 +630,45 @@ void DistributedDBCloudCheckSyncTest::CheckLogCleaned(int64_t expectCount) reinterpret_cast(expectCount), nullptr), SQLITE_OK); } +void DistributedDBCloudCheckSyncTest::CheckUploadInfo(const Info &actualUploadInfo, const Info &expectUploadInfo) +{ + EXPECT_EQ(actualUploadInfo.batchIndex, expectUploadInfo.batchIndex); + EXPECT_EQ(actualUploadInfo.total, expectUploadInfo.total); + EXPECT_EQ(actualUploadInfo.successCount, expectUploadInfo.successCount); + EXPECT_EQ(actualUploadInfo.failCount, expectUploadInfo.failCount); + EXPECT_EQ(actualUploadInfo.insertCount, expectUploadInfo.insertCount); + EXPECT_EQ(actualUploadInfo.updateCount, expectUploadInfo.updateCount); + EXPECT_EQ(actualUploadInfo.deleteCount, expectUploadInfo.deleteCount); +} + +void DistributedDBCloudCheckSyncTest::CheckDownloadInfo(const Info &actualDownloadInfo, const Info &expectDownloadInfo) +{ + EXPECT_EQ(actualDownloadInfo.batchIndex, expectDownloadInfo.batchIndex); + EXPECT_EQ(actualDownloadInfo.total, expectDownloadInfo.total); + EXPECT_EQ(actualDownloadInfo.successCount, expectDownloadInfo.successCount); + EXPECT_EQ(actualDownloadInfo.failCount, expectDownloadInfo.failCount); + EXPECT_EQ(actualDownloadInfo.insertCount, expectDownloadInfo.insertCount); + EXPECT_EQ(actualDownloadInfo.updateCount, expectDownloadInfo.updateCount); + 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 @@ -613,6 +778,189 @@ 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 + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest005, TestSize.Level0) +{ + /** + * @tc.steps:step1. init data and sync + * @tc.expected: step1. ok. + */ + const int localCount = 20; // 20 is count of local + const int cloudCount = 10; // 10 is count of cloud + InsertUserTableRecord(tableName_, localCount); + std::string sql = "update " + DBCommon::GetLogTableName(tableName_) + " SET status = 1 where data_key in (1,11);"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db_, sql), E_OK); + InsertCloudTableRecord(tableName_, 0, cloudCount, 0, false); + + /** + * @tc.steps:step2. check device name in process + * @tc.expected: step2. ok. + */ + Query query = Query::Select().FromTable({tableName_}); + auto callback = [](const std::map &syncProcess) { + EXPECT_TRUE(syncProcess.find("CLOUD") != syncProcess.end()); + }; + BlockCompensatedSync(query, delegate_, OK, callback); +} + +/** + * @tc.name: CloudSyncTest006 + * @tc.desc: check redownload when common sync pause. + * @tc.type: FUNC + * @tc.require: + * @tc.author: luoguo + */ +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); + + /** + * @tc.steps:step2. common sync will pasue. + * @tc.expected: step2. ok. + */ + std::vector tableNames = {tableName_, tableWithoutPrimaryName_}; + Query normalQuery = Query::Select().FromTable({tableNames}); + std::vector idValue = {"0", "1", "2"}; + Query priorityQuery = Query::Select().From(tableName_).In("id", idValue); + CloudSyncOption option; + CloudSyncOption priorityOption; + PrepareOption(option, normalQuery, false); + PrepareOption(priorityOption, priorityQuery, true); + bool isUpload = false; + uint32_t blockTime = 2000; + virtualCloudDb_->ForkUpload([&isUpload, &blockTime](const std::string &tableName, VBucket &extend) { + if (isUpload == false) { + isUpload = true; + std::this_thread::sleep_for(std::chrono::milliseconds(blockTime)); + } + }); + bool isFinsh = false; + bool priorityFinish = false; + auto normalCallback = [&isFinsh, &priorityFinish](const std::map &process) { + for (const auto &item: process) { + if (item.second.process == DistributedDB::FINISHED) { + isFinsh = true; + ASSERT_EQ(priorityFinish, true); + } + } + }; + ASSERT_EQ(delegate_->Sync(option, normalCallback), OK); + + /** + * @tc.steps:step3. wait common upload and pritority 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) { + if (item.second.process == DistributedDB::FINISHED) { + priorityFinish = true; + } + } + }; + ASSERT_EQ(delegate_->Sync(priorityOption, priorityCallback), OK); + while (isFinsh == 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. + */ + WaitCommonUpload(); +} + +/** + * @tc.name: CloudSyncTest007 + * @tc.desc: check process info when version conflict sync process. + * @tc.type: FUNC + * @tc.require: + * @tc.author: luoguo + */ +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest007, TestSize.Level0) +{ + /** + * @tc.steps:step1. init data and sync + * @tc.expected: step1. ok. + */ + const int localCount = 60; + InsertUserTableRecord(tableName_, localCount, 0); + Query query = Query::Select().FromTable({tableName_}); + BlockSync(query, delegate_, g_actualDBStatus); + + /** + * @tc.steps:step2. delete 30 - 59 records in user table, and set callback func. + * @tc.expected: step2. ok. + */ + DeleteUserTableRecord(30, 59); + bool isUpload = false; + virtualCloudDb_->ForkUpload([&isUpload](const std::string &tableName, VBucket &extend) { + if (isUpload == false) { + isUpload = true; + std::this_thread::sleep_for(std::chrono::milliseconds(2000)); + } + }); + bool isFinsh = false; + std::map retSyncProcess; + auto normalCallback = [&isFinsh, &retSyncProcess](const std::map &process) { + for (const auto &item: process) { + if (item.second.process == DistributedDB::FINISHED) { + isFinsh = true; + ASSERT_EQ(process.empty(), false); + auto lastProcess = process.rbegin(); + retSyncProcess = lastProcess->second.tableProcess; + } + } + }; + + /** + * @tc.steps:step3. sync. + * @tc.expected: step3. ok. + */ + std::vector tableNames = {tableName_}; + Query normalQuery = Query::Select().FromTable({tableNames}); + CloudSyncOption option; + PrepareOption(option, normalQuery, false); + ASSERT_EQ(delegate_->Sync(option, normalCallback), OK); + + /** + * @tc.steps:step4. wait upload process and delete 30 record in cloud table. + * @tc.expected: step4. ok. + */ + while (isUpload == false) { + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + } + DeleteCloudTableRecord(30); + + /** + * @tc.steps:step5. wait sync process end and check data. + * @tc.expected: step5. ok. + */ + while (isFinsh == false) { + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + } + ASSERT_EQ(retSyncProcess.empty(), false); + auto taskInfo = retSyncProcess.rbegin(); + ASSERT_EQ(taskInfo->second.upLoadInfo.total, 30u); + virtualCloudDb_->ForkUpload(nullptr); +} /** * @tc.name: CloudSyncObserverTest001 @@ -856,7 +1204,8 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest003, TestSize.Lev Query normalQuery = Query::Select().FromTable({tableName_}); std::vector idValue = {"0", "1", "2"}; Query priorityQuery = Query::Select().From(tableName_).In("id", idValue); - PriorityAndNormalSync(normalQuery, priorityQuery, delegate_); + std::vector> prioritySyncProcess; + PriorityAndNormalSync(normalQuery, priorityQuery, delegate_, prioritySyncProcess, true); EXPECT_EQ(virtualCloudDb_->GetLockCount(), 2); virtualCloudDb_->Reset(); EXPECT_EQ(virtualCloudDb_->GetLockCount(), 0); @@ -1398,6 +1747,188 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest013, TestSize.Lev CheckCloudTableCount(tableName_, 0); } +/** + * @tc.name: CloudPrioritySyncTest014 + * @tc.desc: Check the uploadInfo after the normal sync is paused by the priority sync + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest014, TestSize.Level0) +{ + /** + * @tc.steps:step1. insert data and sync pause. + * @tc.expected: step1. ok. + */ + const int recordCount = 50; // 50 is count of data records + InsertUserTableRecord(tableName_, recordCount, 0); + Query normalQuery = Query::Select().FromTable({tableName_}); + CloudSyncOption normalOption; + PrepareOption(normalOption, normalQuery, false); + bool isUpload = false; + uint32_t blockTime = 1000; + virtualCloudDb_->ForkUpload([&isUpload, &blockTime](const std::string &tableName, VBucket &extend) { + if (isUpload == false) { + isUpload = true; + std::this_thread::sleep_for(std::chrono::milliseconds(blockTime)); + } + }); + bool isFinish = false; + bool priorityFinish = false; + SyncProcess normalLast; + auto normalCallback = [&isFinish, &priorityFinish, &normalLast](const std::map &process) { + for (const auto &item : process) { + if (item.second.process == DistributedDB::FINISHED) { + isFinish = true; + ASSERT_EQ(priorityFinish, true); + normalLast = item.second; + } + } + }; + ASSERT_EQ(delegate_->Sync(normalOption, normalCallback), OK); + + /** + * @tc.steps:step2. priority sync. + * @tc.expected: step2. ok. + */ + while (isUpload == false) { + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + } + std::vector idValues = {"0", "1", "2", "3", "4"}; + Query priorityQuery = Query::Select().From(tableName_).In("id", idValues); + CloudSyncOption priorityOption; + PrepareOption(priorityOption, priorityQuery, true); + auto priorityCallback = [&priorityFinish](const std::map &process) { + for (const auto &item : process) { + if (item.second.process == DistributedDB::FINISHED) { + priorityFinish = true; + } + } + }; + ASSERT_EQ(delegate_->Sync(priorityOption, priorityCallback), OK); + while (isFinish == false || priorityFinish == false) { + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + } + + /** + * @tc.steps:step3. check uploadInfo after sync finished. + * @tc.expected: step3. ok. + */ + CheckUploadInfoAfterSync(recordCount, normalLast); +} + +/** + * @tc.name: CloudPrioritySyncTest015 + * @tc.desc: Check the uploadInfo the downloadInfo after the normal sync is paused by the priority sync + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest015, TestSize.Level0) +{ + /** + * @tc.steps:step1. insert data and sync pause. + * @tc.expected: step1. ok. + */ + const int localCount = 10; // 10 is count of local data records + const int cloudCount = 50; // 50 is count of cloud data records + InsertUserTableRecord(tableName_, localCount, 0); + InsertCloudTableRecord(20, cloudCount, 0, false); // 20 is begin number + uint32_t blockTime = 500; // 500ms + virtualCloudDb_->SetBlockTime(blockTime); + Query normalQuery = Query::Select().FromTable({tableName_}); + CloudSyncOption normalOption; + PrepareOption(normalOption, normalQuery, false); + bool isFinish = false; + bool priorityFinish = false; + SyncProcess normalLast; + auto normalCallback = [&isFinish, &priorityFinish, &normalLast](const std::map &process) { + for (const auto &item : process) { + if (item.second.process == DistributedDB::FINISHED) { + isFinish = true; + ASSERT_EQ(priorityFinish, true); + normalLast = item.second; + } + } + }; + ASSERT_EQ(delegate_->Sync(normalOption, normalCallback), OK); + + /** + * @tc.steps:step2. priority sync. + * @tc.expected: step2. ok. + */ + std::vector idValues = {"10", "11", "12", "13", "14"}; + Query priorityQuery = Query::Select().From(tableName_).In("id", idValues); + CloudSyncOption priorityOption; + PrepareOption(priorityOption, priorityQuery, true); + auto priorityCallback = [&priorityFinish](const std::map &process) { + for (const auto &item : process) { + if (item.second.process == DistributedDB::FINISHED) { + priorityFinish = true; + } + } + }; + ASSERT_EQ(delegate_->Sync(priorityOption, priorityCallback), OK); + while (isFinish == false || priorityFinish == false) { + std::this_thread::sleep_for(std::chrono::milliseconds(50)); // 50ms + } + + /** + * @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}; + for (const auto &table : normalLast.tableProcess) { + CheckUploadInfo(table.second.upLoadInfo, expectUploadInfo); + CheckDownloadInfo(table.second.downLoadInfo, expectDownloadInfo); + EXPECT_EQ(table.second.process, ProcessStatus::FINISHED); + } + CheckUserTableResult(db_, tableName_, 60); +} + +/** + * @tc.name: CloudPrioritySyncTest016 + * @tc.desc: priority sync when normal syncing + * @tc.type: FUNC + * @tc.require: + * @tc.author: wangxiangdong + */ +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest016, TestSize.Level0) +{ + /** + * @tc.steps:step1. insert cloud table record. + * @tc.expected: step1. ok. + */ + 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. + */ + Query normalQuery = Query::Select().FromTable({tableName_}); + std::vector idValue = {"0", "1", "2"}; + Query priorityQuery = Query::Select().From(tableName_).In("id", idValue); + std::vector> prioritySyncProcess; + PriorityAndNormalSync(normalQuery, priorityQuery, delegate_, prioritySyncProcess, false); + virtualCloudDb_->Reset(); + CheckCloudTableCount(tableName_, 60); // 10 is count of cloud records + /** + * @tc.steps:step3. check sync process result. + * @tc.expected: step3. ok. + */ + std::vector expectSyncResult = { + {PROCESSING, OK, {{tableName_, {PROCESSING, {1, 60, 60, 0, 50, 0, 0}, {0, 0, 0, 0, 0, 0, 0}}}}}, + {PROCESSING, OK, {{tableName_, {PROCESSING, {1, 3, 3, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0}}}}}, + {FINISHED, OK, {{tableName_, {FINISHED, {1, 3, 3, 0, 0, 0, 0}, {1, 3, 3, 0, 0, 3, 0}}}}}, + {PROCESSING, OK, {{tableName_, {PROCESSING, {2, 63, 63, 0, 50, 0, 0}, {0, 0, 0, 0, 0, 0, 0}}}}}, + {FINISHED, OK, {{tableName_, {FINISHED, {2, 63, 63, 0, 50, 0, 0}, {1, 7, 7, 0, 0, 7, 0}}}}} + }; + EXPECT_EQ(CheckSyncProcess(prioritySyncProcess, expectSyncResult), true); +} + /** * @tc.name: LogicDeleteSyncTest001 * @tc.desc: sync with logic delete 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 c3ba47dca109e34e5a1be053c4a7d083965197eb..56e7d9e4c1ab28bf00586653052b5ea8c5caee09 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 @@ -30,6 +30,7 @@ #include "virtual_asset_loader.h" #include "virtual_cloud_data_translate.h" #include "virtual_cloud_db.h" +#include "virtual_communicator_aggregator.h" #include "mock_asset_loader.h" using namespace testing::ext; @@ -1087,6 +1088,7 @@ namespace { void TearDown(); protected: sqlite3 *db = nullptr; + VirtualCommunicatorAggregator *communicatorAggregator_ = nullptr; }; @@ -1132,6 +1134,9 @@ namespace { DataBaseSchema dataBaseSchema; GetCloudDbSchema(dataBaseSchema); ASSERT_EQ(g_delegate->SetCloudDbSchema(dataBaseSchema), DBStatus::OK); + communicatorAggregator_ = new (std::nothrow) VirtualCommunicatorAggregator(); + ASSERT_TRUE(communicatorAggregator_ != nullptr); + RuntimeContext::GetInstance()->SetCommunicatorAggregator(communicatorAggregator_); } void DistributedDBCloudInterfacesRelationalSyncTest::TearDown(void) @@ -1140,6 +1145,9 @@ namespace { if (DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir) != 0) { LOGE("rm test db files error."); } + RuntimeContext::GetInstance()->SetCommunicatorAggregator(nullptr); + communicatorAggregator_ = nullptr; + RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(nullptr); } /** @@ -1718,6 +1726,39 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest016, TestS CloseDb(); } +/* + * @tc.name: CloudSyncTest017 + * @tc.desc: Test sync to push when local data deleted and not upload to cloud + * @tc.type: FUNC + * @tc.require: + * @tc.author: wangxiangdong + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncTest017, TestSize.Level0) +{ + /** + * @tc.steps: step1. make data: 20 records on local, 20 records on cloud + */ + int64_t localCount = 20; + int64_t paddingSize = 20; + InsertCloudTableRecord(0, localCount, paddingSize, true); + InsertUserTableRecord(db, 0, localCount, paddingSize, true); + localCount = 10; + /** + * @tc.steps: step2. delete 10 local record before sync + */ + DeleteUserTableRecord(db, 0, localCount); + callSync(g_tables, SYNC_MODE_CLOUD_FORCE_PUSH, DBStatus::OK); + /** + * @tc.steps: step3. check local and cloud num + */ + CheckCloudTotalCount({30L, 20L}); + std::string sql = "select count(*) from " + DBCommon::GetLogTableName(g_tables[0]) + + " where data_key=-1 and cloud_gid='';"; + EXPECT_EQ(sqlite3_exec(db, sql.c_str(), QueryCountCallback, + reinterpret_cast(10), nullptr), SQLITE_OK); + CloseDb(); +} + /* * @tc.name: DataNotifier001 * @tc.desc: Notify data without primary key 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 adf0ce80e14e654d5389085cc946716b127baa88..453d7a0a934684d0ca672b716c53155d4da1facf 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 @@ -205,7 +205,7 @@ namespace { * @tc.name: AbnormalStorageProxyTest001 * @tc.desc: Check StorageProxy interfaces when para is invalid. * @tc.type: FUNC - * @tc.require: DTS2024073106613 + * @tc.require: * @tc.author: suyue */ HWTEST_F(DistributedDBCloudMetaDataTest, AbnormalStorageProxyTest001, TestSize.Level0) @@ -264,7 +264,7 @@ namespace { * @tc.name: AbnormalStorageProxyTest002 * @tc.desc: Check StorageProxy interfaces when para is invalid. * @tc.type: FUNC - * @tc.require: DTS2024073106613 + * @tc.require: * @tc.author: suyue */ HWTEST_F(DistributedDBCloudMetaDataTest, AbnormalStorageProxyTest002, TestSize.Level0) @@ -282,10 +282,9 @@ namespace { EXPECT_EQ(proxyObj.IsSharedTable(TABLE_NAME_1, isSharedTable), -E_INVALID_DB); CloudSyncData data; proxyObj.FillCloudGidIfSuccess(OpType::INSERT, data); - const CloudTaskConfig config; - proxyObj.SetCloudTaskConfig(config); std::vector syncQuery; - EXPECT_EQ(proxyObj.GetCompensatedSyncQuery(syncQuery), -E_INVALID_DB); + std::vector users; + EXPECT_EQ(proxyObj.GetCompensatedSyncQuery(syncQuery, users), -E_INVALID_DB); proxyObj.OnSyncFinish(); proxyObj.OnUploadStart(); std::shared_ptr cloudSchema; @@ -305,7 +304,7 @@ namespace { * @tc.name: AbnormalSyncAbleStorageTest001 * @tc.desc: Check RelationalSyncAbleStorage interfaces. * @tc.type: FUNC - * @tc.require: DTS2024073106613 + * @tc.require: * @tc.author: suyue */ HWTEST_F(DistributedDBCloudMetaDataTest, AbnormalSyncAbleStorageTest001, TestSize.Level0) @@ -358,7 +357,7 @@ namespace { * @tc.name: AbnormalSyncAbleStorageTest002 * @tc.desc: Check RelationalSyncAbleStorage interfaces. * @tc.type: FUNC - * @tc.require: DTS2024073106613 + * @tc.require: * @tc.author: suyue */ HWTEST_F(DistributedDBCloudMetaDataTest, AbnormalSyncAbleStorageTest002, TestSize.Level0) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_reference_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_reference_sync_test.cpp index d3dccb19c893d9772bb21df539289b8319c5422d..c87512c867acca997eb08c3b0d80514eb4657c8e 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_reference_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_reference_sync_test.cpp @@ -28,6 +28,7 @@ #include "virtual_asset_loader.h" #include "virtual_cloud_data_translate.h" #include "virtual_cloud_db.h" +#include "virtual_communicator_aggregator.h" namespace { using namespace testing::ext; @@ -62,6 +63,7 @@ protected: sqlite3 *db_ = nullptr; RelationalStoreDelegate *delegate_ = nullptr; std::shared_ptr virtualCloudDb_ = nullptr; + VirtualCommunicatorAggregator *communicatorAggregator_ = nullptr; std::shared_ptr mgr_ = nullptr; const std::string parentTableName_ = "parent"; const std::string sharedParentTableName_ = "parent_shared"; @@ -110,6 +112,9 @@ void DistributedDBCloudReferenceSyncTest::SetUp() SetReference(); DataBaseSchema dataBaseSchema = GetSchema(); ASSERT_EQ(delegate_->SetCloudDbSchema(dataBaseSchema), DBStatus::OK); + communicatorAggregator_ = new (std::nothrow) VirtualCommunicatorAggregator(); + ASSERT_TRUE(communicatorAggregator_ != nullptr); + RuntimeContext::GetInstance()->SetCommunicatorAggregator(communicatorAggregator_); } void DistributedDBCloudReferenceSyncTest::TearDown() @@ -120,6 +125,9 @@ void DistributedDBCloudReferenceSyncTest::TearDown() if (DistributedDBToolsUnitTest::RemoveTestDbFiles(testDir_) != E_OK) { LOGE("rm test db files error."); } + RuntimeContext::GetInstance()->SetCommunicatorAggregator(nullptr); + communicatorAggregator_ = nullptr; + RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(nullptr); } void DistributedDBCloudReferenceSyncTest::InitTestDir() diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_task_merge_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_task_merge_test.cpp index e67a78bef9d64a0740a317b55c4329012f878a6b..3f793fb2bd7f870862cb23d4400584471c764f56 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_task_merge_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_task_merge_test.cpp @@ -30,6 +30,7 @@ #include "virtual_asset_loader.h" #include "virtual_cloud_data_translate.h" #include "virtual_cloud_db.h" +#include "virtual_communicator_aggregator.h" using namespace testing::ext; using namespace DistributedDB; @@ -113,6 +114,7 @@ protected: std::string tableNameC_ = "worker_c"; std::string tableNameD_ = "worker_d"; std::vector tables_ = { tableNameA_, tableNameB_, tableNameC_, tableNameD_ }; + VirtualCommunicatorAggregator *communicatorAggregator_ = nullptr; }; void DistributedDBCloudTaskMergeTest::SetUpTestCase() @@ -148,6 +150,9 @@ void DistributedDBCloudTaskMergeTest::SetUp() ASSERT_EQ(delegate_->SetIAssetLoader(virtualAssetLoader_), DBStatus::OK); DataBaseSchema dataBaseSchema = GetSchema(); ASSERT_EQ(delegate_->SetCloudDbSchema(dataBaseSchema), DBStatus::OK); + communicatorAggregator_ = new (std::nothrow) VirtualCommunicatorAggregator(); + ASSERT_TRUE(communicatorAggregator_ != nullptr); + RuntimeContext::GetInstance()->SetCommunicatorAggregator(communicatorAggregator_); } void DistributedDBCloudTaskMergeTest::TearDown() @@ -159,6 +164,9 @@ void DistributedDBCloudTaskMergeTest::TearDown() if (DistributedDBToolsUnitTest::RemoveTestDbFiles(testDir_) != E_OK) { LOGE("rm test db files error."); } + RuntimeContext::GetInstance()->SetCommunicatorAggregator(nullptr); + communicatorAggregator_ = nullptr; + RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(nullptr); } void DistributedDBCloudTaskMergeTest::InitTestDir() diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_cloud_schema_mgr_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_cloud_schema_mgr_test.cpp index 15eef8f31d865dac8b8c50ed4213178b26da0cf6..d70fc25fc1d8c89231bfb4263b41142e91394545 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_cloud_schema_mgr_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_cloud_schema_mgr_test.cpp @@ -671,6 +671,31 @@ HWTEST_F(DistributedDBCloudSchemaMgrTest, SchemaMgrTest014, TestSize.Level0) EXPECT_EQ(g_schemaMgr->ChkSchema(TABLE_NAME_2, localSchema), E_OK); } +/** + * @tc.name: SchemaMgrTest0015 + * @tc.desc: Cloud schema has more fields than local schema + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenghuitao + */ +HWTEST_F(DistributedDBCloudSchemaMgrTest, SchemaMgrTest0015, TestSize.Level0) +{ + FieldInfo field = SetField(FIELD_NAME_1, "int", true); + TableInfo table; + table.SetTableName(TABLE_NAME_1); + table.AddField(field); + table.SetPrimaryKey(FIELD_NAME_1, 1); + table.SetTableSyncType(TableSyncType::CLOUD_COOPERATION); + RelationalSchemaObject localSchema; + localSchema.AddRelationalTable(table); + + g_schemaMgr->SetCloudDbSchema(g_schema); + EXPECT_EQ(g_schemaMgr->ChkSchema(TABLE_NAME_1, localSchema), -E_SCHEMA_MISMATCH); + + g_schemaMgr->SetCloudDbSchema(g_schema, localSchema); + EXPECT_EQ(g_schemaMgr->ChkSchema(TABLE_NAME_1, localSchema), E_OK); +} + /** * @tc.name: FieldInfo001 * @tc.desc: Test Relational field info. diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_file_package_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_file_package_test.cpp index 807014182d91aab63e95a9e5f6da747fcb30cacf..2df279cf208753c37d799cb3590118f9d85658a3 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_file_package_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_file_package_test.cpp @@ -189,7 +189,6 @@ HWTEST_F(DistributedDBFilePackageTest, PackageFileTest001, TestSize.Level1) ASSERT_EQ(errCode, E_OK); ComparePath(g_sourcePath, g_unpackResultPath); ASSERT_EQ(fileInfo.dbType, g_fileInfo.dbType); - return; } /** @@ -204,7 +203,6 @@ HWTEST_F(DistributedDBFilePackageTest, PackageFileTest002, TestSize.Level1) int errCode = PackageFile::PackageFiles(g_sourcePath + NON_EXIST_PATH, g_packageResultPath + PACKAGE_RESULT_FILE_NAME, g_fileInfo); ASSERT_EQ(errCode, -E_INVALID_PATH); - return; } /** @@ -219,7 +217,6 @@ HWTEST_F(DistributedDBFilePackageTest, PackageFileTest003, TestSize.Level1) int errCode = PackageFile::PackageFiles(g_sourcePath, g_packageResultPath + NON_EXIST_PATH + PACKAGE_RESULT_FILE_NAME, g_fileInfo); ASSERT_EQ(errCode, -E_INVALID_PATH); - return; } /** @@ -246,7 +243,6 @@ HWTEST_F(DistributedDBFilePackageTest, PackageFileTest004, TestSize.Level1) ASSERT_TRUE(file2.is_open()); file2.write(FILE_CONTENT_2, 4); file2.close(); - return; } /** @@ -261,7 +257,6 @@ HWTEST_F(DistributedDBFilePackageTest, PackageFileTest005, TestSize.Level1) FileInfo fileInfo; int errCode = PackageFile::UnpackFile(g_packageResultPath + PACKAGE_RESULT_FILE_NAME, g_unpackResultPath, fileInfo); ASSERT_EQ(errCode, -E_INVALID_PATH); - return; } /** @@ -279,7 +274,6 @@ HWTEST_F(DistributedDBFilePackageTest, PackageFileTest006, TestSize.Level1) errCode = PackageFile::UnpackFile(g_packageResultPath + PACKAGE_RESULT_FILE_NAME, g_unpackResultPath + NON_EXIST_PATH, fileInfo); ASSERT_EQ(errCode, -E_INVALID_PATH); - return; } /** @@ -304,7 +298,6 @@ HWTEST_F(DistributedDBFilePackageTest, PackageFileTest007, TestSize.Level1) FileInfo fileInfo; errCode = PackageFile::UnpackFile(g_packageResultPath + PACKAGE_RESULT_FILE_NAME, g_unpackResultPath, fileInfo); ASSERT_EQ(errCode, -E_INVALID_FILE); - return; } /** @@ -337,6 +330,4 @@ HWTEST_F(DistributedDBFilePackageTest, PackageFileTest008, TestSize.Level1) FileInfo fileInfo; errCode = PackageFile::UnpackFile(g_packageResultPath + PACKAGE_RESULT_FILE_NAME, g_unpackResultPath, fileInfo); ASSERT_EQ(errCode, -E_INVALID_FILE); - return; } - diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_cloud_syncable_storage_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_cloud_syncable_storage_test.cpp index 4394ca21f22b7ab3e45f163ef69e6ce961609a72..17e8d22245aa394573589a2eb32f1634c55e496d 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_cloud_syncable_storage_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_cloud_syncable_storage_test.cpp @@ -758,10 +758,10 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudGid001, TestS /** * @tc.steps: the field type does not match - * @tc.expected: return -E_INVALID_DATA. + * @tc.expected: return -E_CLOUD_ERROR. */ syncData.tableName = g_tableName; - EXPECT_EQ(g_cloudStore->FillCloudLogAndAsset(OpType::INSERT, syncData, false, false), -E_INVALID_DATA); + EXPECT_EQ(g_cloudStore->FillCloudLogAndAsset(OpType::INSERT, syncData, false, false), -E_CLOUD_ERROR); /** * @tc.steps: missing field GID_FIELD @@ -915,15 +915,72 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData006, TestS /** * @tc.steps:step2. Get cloud data - * @tc.expected: step2. return -E_CLOUD_INVALID_ASSET. + * @tc.expected: step2. return -E_CLOUD_ERROR. */ ContinueToken token = nullptr; CloudSyncData cloudSyncData; EXPECT_EQ(g_storageProxy->StartTransaction(TransactType::IMMEDIATE), E_OK); - ASSERT_EQ(g_storageProxy->GetCloudData(g_tableName, g_startTime, token, cloudSyncData), -E_CLOUD_INVALID_ASSET); + ASSERT_EQ(g_storageProxy->GetCloudData(g_tableName, g_startTime, token, cloudSyncData), -E_CLOUD_ERROR); EXPECT_EQ(g_storageProxy->Rollback(), E_OK); } +/** + * @tc.name: GetCloudData008 + * @tc.desc: GetCloudGid other table after GetCloudData. + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData008, TestSize.Level0) +{ + /** + * @tc.steps:step1. table1 + * @tc.expected: step1. return ok. + */ + CreateLogTable(g_tableName); + int64_t insCount = 10; + int64_t photoSize = 10; + InitLogData(insCount, insCount, insCount, insCount, g_logTblName); + CreateAndInitUserTable(3 * insCount, photoSize, g_localAsset); // 3 is insert,update and delete type data + + /** + * @tc.steps:step2. table2 + * @tc.expected: step2. return ok. + */ + std::string tableName2 = "cloudData2"; + std::string logTblName2 = DBConstant::RELATIONAL_PREFIX + tableName2 + "_log"; + CreateLogTable(tableName2); + InitLogData(insCount, insCount, insCount, insCount, logTblName2); + sqlite3 *db = nullptr; + ASSERT_EQ(sqlite3_open(g_storePath.c_str(), &db), SQLITE_OK); + std::string createTable2Sql = "CREATE TABLE IF NOT EXISTS " + tableName2 + "(name TEXT ,age INT);"; + ASSERT_EQ(SQLiteUtils::ExecuteRawSQL(db, createTable2Sql), E_OK); + sqlite3_close(db); + const std::vector cloudField2 = {{"name", TYPE_INDEX}, {"age", TYPE_INDEX}}; + TableSchema tableSchema2; + tableSchema2.name = tableName2; + tableSchema2.sharedTableName = tableName2 + "_shared"; + tableSchema2.fields = cloudField2; + DataBaseSchema dataBaseSchema; + dataBaseSchema.tables.push_back(g_tableSchema); + dataBaseSchema.tables.push_back(tableSchema2); + EXPECT_EQ(g_delegate->SetCloudDbSchema(dataBaseSchema), DBStatus::OK); + + /** + * @tc.steps:step3. GetCloudData from table1, then GetCloudGid from table2 + * @tc.expected: step3. return ok. + */ + ContinueToken token = nullptr; + CloudSyncData cloudSyncData(g_tableName); + EXPECT_EQ(g_storageProxy->StartTransaction(), E_OK); + EXPECT_EQ(g_storageProxy->GetCloudData(g_tableName, g_startTime, token, cloudSyncData), E_OK); + QuerySyncObject obj; + obj.SetTableName(tableName2); + std::vector cloudGid; + EXPECT_EQ(g_storageProxy->GetCloudGid(obj, false, false, cloudGid), E_OK); + EXPECT_EQ(g_storageProxy->Commit(), E_OK); +} + /** * @tc.name: GetInfoByPrimaryKeyOrGid001 * @tc.desc: Test the query of the GetInfoByPrimaryKeyOrGid interface to obtain assets. @@ -1216,10 +1273,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, CalPrimaryKeyHash001, int errCode = SQLiteUtils::GetStatement(db, querysql, statement); EXPECT_EQ(errCode, E_OK); errCode = SQLiteUtils::BindBlobToStatement(statement, 1, result); // 1 means hashkey index - if (errCode != E_OK) { - SQLiteUtils::ResetStatement(statement, true, errCode); - return; - } + ASSERT_EQ(errCode, E_OK); errCode = SQLiteUtils::StepWithRetry(statement, false); if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { Timestamp timestamp = static_cast(sqlite3_column_int64(statement, 0)); @@ -1272,10 +1326,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, CalPrimaryKeyHash002, int errCode = SQLiteUtils::GetStatement(db, querysql, statement); EXPECT_EQ(errCode, E_OK); errCode = SQLiteUtils::BindBlobToStatement(statement, 1, result); // 1 means hashkey index - if (errCode != E_OK) { - SQLiteUtils::ResetStatement(statement, true, errCode); - return; - } + ASSERT_EQ(errCode, E_OK); errCode = SQLiteUtils::StepWithRetry(statement, false); if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { Timestamp timestamp = static_cast(sqlite3_column_int64(statement, 0)); diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_get_data_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_get_data_test.cpp index 355e40b38de318507caa954e28c4b1e01634ebb9..46cd05b760140274ddc9e4c47a47b61aa400ff7b 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_get_data_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_get_data_test.cpp @@ -1347,8 +1347,7 @@ HWTEST_F(DistributedDBRelationalGetDataTest, SaveNonexistDevdata1, TestSize.Leve query = QueryObject(Query::Select(tableName)); const DeviceID deviceID = "deviceA"; SetRemoteSchema(store, deviceID); - EXPECT_EQ(const_cast(store)->PutSyncDataWithQuery(query, entries, deviceID), - -1); // -1 means error + EXPECT_EQ(const_cast(store)->PutSyncDataWithQuery(query, entries, deviceID), E_OK); SingleVerKvEntry::Release(entries); sqlite3_close(db); diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_sqlite_register_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_sqlite_register_test.cpp index 6219f1edc31702f13be538998a03f5c1a1aa050b..b929172e184e2e58a8466d3694d08f8b4282dfcf 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_sqlite_register_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_sqlite_register_test.cpp @@ -149,10 +149,6 @@ HWTEST_F(DistributedDBSqliteRegisterTest, JsonExtract001, TestSize.Level1) HWTEST_F(DistributedDBSqliteRegisterTest, JsonExtract002, TestSize.Level1) { ASSERT_NE(g_sqliteDb, nullptr); - if (g_sqliteDb == nullptr) { - LOGE("Sqlite DB not exists."); - return; - } int errCode = sqlite3_exec(g_sqliteDb, SQL_JSON_WRONG_PATH, Callback, nullptr, &g_errMsg); if (errCode != SQLITE_OK) { if (g_errMsg != nullptr) { diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_sqlite_utils_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_sqlite_utils_test.cpp index 3692e1502c9b7bd8502a11efea36efdd78adc758..ad3e542f5b1228bc7a2e04da92218978c88d4ddb 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_sqlite_utils_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_sqlite_utils_test.cpp @@ -262,4 +262,127 @@ HWTEST_F(DistributedDBSqliteUtilsTest, KVLogUpgrade001, TestSize.Level0) int errCode = SQLiteUtils::ExecuteRawSQL(g_db, createTableSql); ASSERT_EQ(errCode, E_OK); EXPECT_EQ(SqliteLogTableManager::CreateKvSyncLogTable(g_db), E_OK); -} \ No newline at end of file +} + +/** + * @tc.name: BindErr + * @tc.desc: Test bind err + * @tc.type: FUNC + * @tc.require: + * @tc.author: lijun + */ +HWTEST_F(DistributedDBSqliteUtilsTest, BindErr, TestSize.Level1) +{ + NativeSqlite::ExecSql(g_db, "CREATE TABLE IF NOT EXISTS t1 (a INT, b TEXT);"); + + std::string text; + text.resize(0); + NativeSqlite::ExecSql(g_db, "INSERT INTO t1 VALUES(?, ?)", [&text](sqlite3_stmt *stmt) { + (void)SQLiteUtils::BindInt64ToStatement(stmt, 1, 1); + (void)SQLiteUtils::BindTextToStatement(stmt, 2, "text"); // 2: bind index + EXPECT_NE(SQLiteUtils::BindTextToStatement(stmt, 5, text), E_OK); + EXPECT_EQ(SQLiteUtils::BindTextToStatement(nullptr, 2, text), -E_INVALID_ARGS); + EXPECT_NE(SQLiteUtils::BindInt64ToStatement(nullptr, -6, 0), E_OK); + EXPECT_NE(SQLiteUtils::BindBlobToStatement(stmt, 7, {}), E_OK); + EXPECT_NE(SQLiteUtils::BindPrefixKey(stmt, 8, {}), E_OK); + EXPECT_NE(SQLiteUtils::BindPrefixKey(stmt, 2, {}), E_OK); + return E_OK; + }, nullptr); + + NativeSqlite::ExecSql(g_db, "SELECT b FROM t1", nullptr, [&text](sqlite3_stmt *stmt) { + std::string val; + EXPECT_EQ(SQLiteUtils::GetColumnTextValue(nullptr, 0, val), -E_INVALID_ARGS); + EXPECT_EQ(SQLiteUtils::GetColumnTextValue(stmt, 0, val), E_OK); + EXPECT_EQ(val, text); + return E_OK; + }); +} + +/** + * @tc.name: AbnormalBranchErr + * @tc.desc: Test abnormal branch error + * @tc.type: FUNC + * @tc.require: + * @tc.author: lijun + */ +HWTEST_F(DistributedDBSqliteUtilsTest, AbnormalBranchErr, TestSize.Level1) +{ + CipherPassword passwd; + EXPECT_EQ(-E_INVALID_DB, SQLiteUtils::SetKey(nullptr, CipherType::DEFAULT, passwd, true, + DBConstant::DEFAULT_ITER_TIMES)); + EXPECT_EQ(-1, SQLiteUtils::AttachNewDatabaseInner(g_db, CipherType::DEFAULT, {}, "path", "asname ? ")); + EXPECT_EQ(-E_SQLITE_CANT_OPEN, SQLiteUtils::CreateMetaDatabase("/axxbxxc/d sdsda")); + + EXPECT_EQ(-E_INVALID_DB, SQLiteUtils::CheckIntegrity(nullptr, "")); + TableInfo table; + EXPECT_EQ(-E_INVALID_DB, SQLiteUtils::AnalysisSchema(nullptr, "", table, true)); + EXPECT_EQ(-E_NOT_SUPPORT, SQLiteUtils::AnalysisSchema(g_db, "###", table, true)); + EXPECT_EQ(-E_NOT_FOUND, SQLiteUtils::AnalysisSchema(g_db, "t2", table, true)); + EXPECT_EQ(-E_INVALID_DB, SQLiteUtils::AnalysisSchemaFieldDefine(nullptr, "ttt", table)); + + int version; + EXPECT_EQ(-E_INVALID_DB, SQLiteUtils::GetVersion(nullptr, version)); + EXPECT_EQ(-E_INVALID_DB, SQLiteUtils::SetUserVer(nullptr, version)); + std::string mode; + EXPECT_EQ(-E_INVALID_DB, SQLiteUtils::GetJournalMode(nullptr, mode)); + + EXPECT_EQ(-SQLITE_IOERR, SQLiteUtils::MapSQLiteErrno(SQLITE_IOERR)); + int oldErr = errno; + errno = EKEYREVOKED; + EXPECT_EQ(-E_EKEYREVOKED, SQLiteUtils::MapSQLiteErrno(SQLITE_IOERR)); + EXPECT_EQ(-E_EKEYREVOKED, SQLiteUtils::MapSQLiteErrno(SQLITE_ERROR)); + errno = oldErr; + EXPECT_EQ(-E_SQLITE_CANT_OPEN, SQLiteUtils::MapSQLiteErrno(SQLITE_CANTOPEN)); + std::string strSchema; + EXPECT_EQ(-E_INVALID_DB, SQLiteUtils::SaveSchema(nullptr, strSchema)); + EXPECT_EQ(-E_INVALID_DB, SQLiteUtils::GetSchema(nullptr, strSchema)); + + IndexName name; + IndexInfo info; + EXPECT_EQ(-E_INVALID_DB, SQLiteUtils::IncreaseIndex(nullptr, name, info, SchemaType::JSON, 1)); + EXPECT_EQ(-E_NOT_PERMIT, SQLiteUtils::IncreaseIndex(g_db, name, info, SchemaType::JSON, 1)); + EXPECT_EQ(-E_NOT_PERMIT, SQLiteUtils::ChangeIndex(g_db, name, info, SchemaType::JSON, 1)); + EXPECT_EQ(-E_INVALID_DB, SQLiteUtils::ChangeIndex(nullptr, name, info, SchemaType::JSON, 1)); + + EXPECT_EQ(-E_INVALID_DB, SQLiteUtils::RegisterJsonFunctions(nullptr)); + EXPECT_EQ(-E_INVALID_DB, SQLiteUtils::CloneIndexes(nullptr, strSchema, strSchema)); + EXPECT_EQ(-E_INVALID_DB, SQLiteUtils::GetRelationalSchema(nullptr, strSchema)); + EXPECT_EQ(-E_INVALID_DB, SQLiteUtils::GetLogTableVersion(nullptr, strSchema)); + EXPECT_EQ(-E_INVALID_DB, SQLiteUtils::RegisterFlatBufferFunction(nullptr, strSchema)); + EXPECT_EQ(-E_INTERNAL_ERROR, SQLiteUtils::RegisterFlatBufferFunction(g_db, strSchema)); + EXPECT_EQ(-E_INVALID_ARGS, SQLiteUtils::ExpandedSql(nullptr, strSchema)); + SQLiteUtils::ExecuteCheckPoint(nullptr); + + bool isEmpty; + EXPECT_EQ(-E_INVALID_ARGS, SQLiteUtils::CheckTableEmpty(nullptr, strSchema, isEmpty)); + EXPECT_EQ(-E_INVALID_ARGS, SQLiteUtils::SetPersistWalMode(nullptr)); + EXPECT_EQ(-1, SQLiteUtils::GetLastRowId(nullptr)); + std::string tableName; + EXPECT_EQ(-1, SQLiteUtils::CheckTableExists(nullptr, tableName, isEmpty)); +} + +/** + * @tc.name: AbnormalBranchErrAfterClose + * @tc.desc: Test abnormal branch error after close db + * @tc.type: FUNC + * @tc.require: + * @tc.author: lijun + */ +HWTEST_F(DistributedDBSqliteUtilsTest, AbnormalBranchErrAfterClose, TestSize.Level1) +{ + int version; + std::string mode; + std::string strSchema; + std::string tableName; + bool isEmpty; + + sqlite3_close_v2(g_db); + // After close db + EXPECT_EQ(-SQLITE_MISUSE, SQLiteUtils::GetVersion(g_db, version)); + EXPECT_EQ(-SQLITE_MISUSE, SQLiteUtils::GetJournalMode(g_db, mode)); + EXPECT_EQ(-SQLITE_MISUSE, SQLiteUtils::SaveSchema(g_db, strSchema)); + EXPECT_EQ(-SQLITE_MISUSE, SQLiteUtils::GetSchema(g_db, strSchema)); + EXPECT_EQ(-SQLITE_MISUSE, SQLiteUtils::GetRelationalSchema(g_db, strSchema)); + EXPECT_EQ(-SQLITE_MISUSE, SQLiteUtils::GetLogTableVersion(g_db, strSchema)); + EXPECT_EQ(-SQLITE_MISUSE, SQLiteUtils::CheckTableExists(g_db, tableName, isEmpty)); +} diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_commit_storage_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_commit_storage_test.cpp index e998f40f086bd2b3ef54fb7aa8445067146105df..85c0633d19098af1e56fb6bc0cdf6b120e7c0565 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_commit_storage_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_commit_storage_test.cpp @@ -359,9 +359,6 @@ HWTEST_F(DistributedDBStorageCommitStorageTest, MultiVerCommitStorage002, TestSi */ int result = g_commitStorage->Remove(g_prop); ASSERT_EQ(result, E_OK); - if (result != E_OK) { - return; - } CommitInfo commitInfo = {g_defaultCommitVer1, g_defaultCommitID1, g_defaultCommitID0, g_defaultCommitID0, TIME_STAMP1, true, g_localDevice}; diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_data_operation_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_data_operation_test.cpp index 36dd34d7970569a7e2d18d95f4bf17a60dd6eaa9..81dc4b45f954e367acdb13ffc7f8bc6f72f25fea 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_data_operation_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_data_operation_test.cpp @@ -135,10 +135,7 @@ void DistributedDBStorageDataOperationTest::TearDown(void) */ HWTEST_F(DistributedDBStorageDataOperationTest, Insert001, TestSize.Level1) { - EXPECT_NE(g_connection, nullptr); - if (g_connection == nullptr) { - return; - } + ASSERT_NE(g_connection, nullptr); Key key(3, 'w'); Value value; @@ -177,10 +174,7 @@ HWTEST_F(DistributedDBStorageDataOperationTest, Insert001, TestSize.Level1) */ HWTEST_F(DistributedDBStorageDataOperationTest, InsertBatch001, TestSize.Level1) { - EXPECT_NE(g_connection, nullptr); - if (g_connection == nullptr) { - return; - } + ASSERT_NE(g_connection, nullptr); Key key(3, 'w'); Value value; @@ -232,10 +226,7 @@ HWTEST_F(DistributedDBStorageDataOperationTest, InsertBatch001, TestSize.Level1) */ HWTEST_F(DistributedDBStorageDataOperationTest, Clear001, TestSize.Level1) { - EXPECT_NE(g_connection, nullptr); - if (g_connection == nullptr) { - return; - } + ASSERT_NE(g_connection, nullptr); Key key(3, 'w'); Value value; @@ -303,10 +294,7 @@ HWTEST_F(DistributedDBStorageDataOperationTest, Clear001, TestSize.Level1) */ HWTEST_F(DistributedDBStorageDataOperationTest, Delete001, TestSize.Level1) { - EXPECT_NE(g_connection, nullptr); - if (g_connection == nullptr) { - return; - } + ASSERT_NE(g_connection, nullptr); Key key(3, 'w'); Value value; @@ -384,10 +372,7 @@ HWTEST_F(DistributedDBStorageDataOperationTest, Delete001, TestSize.Level1) */ HWTEST_F(DistributedDBStorageDataOperationTest, DeleteBatch001, TestSize.Level1) { - EXPECT_NE(g_connection, nullptr); - if (g_connection == nullptr) { - return; - } + ASSERT_NE(g_connection, nullptr); Key key(3, 'w'); Value value; diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_memory_rd_single_ver_natural_store_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_memory_rd_single_ver_natural_store_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9163a9efebfb6364e7f294d2ed06a94c6e7a1fe0 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_memory_rd_single_ver_natural_store_test.cpp @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2021 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. + */ +#ifdef USE_RD_KERNEL + +#include + +#include "db_constant.h" +#include "distributeddb_storage_rd_single_ver_natural_store_testcase.h" + +using namespace testing::ext; +using namespace DistributedDB; +using namespace DistributedDBUnitTest; +using namespace std; + +namespace { + DistributedDB::KvStoreConfig g_config; + std::string g_testDir; + const std::string MEM_URL = "file:31?mode=memory&cache=shared"; + DistributedDB::RdSingleVerNaturalStore *g_store = nullptr; + DistributedDB::RdSingleVerNaturalStoreConnection *g_connection = nullptr; +} + +class DistributedDBStorageMemoryRdSingleVerNaturalStoreTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void DistributedDBStorageMemoryRdSingleVerNaturalStoreTest::SetUpTestCase(void) +{ + DistributedDBToolsUnitTest::TestDirInit(g_testDir); + LOGD("Test dir is %s", g_testDir.c_str()); + // IDENTIFIER_DIR is 31 + DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir + "/31/" + DBConstant::SINGLE_SUB_DIR); +} + +void DistributedDBStorageMemoryRdSingleVerNaturalStoreTest::TearDownTestCase(void) {} + +void DistributedDBStorageMemoryRdSingleVerNaturalStoreTest::SetUp(void) +{ + DistributedDBToolsUnitTest::PrintTestCaseInfo(); + KvDBProperties property; + property.SetStringProp(KvDBProperties::DATA_DIR, g_testDir); + property.SetStringProp(KvDBProperties::STORE_ID, "TestGeneralNB"); + property.SetStringProp(KvDBProperties::IDENTIFIER_DIR, "31"); + property.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE_RD_KERNAL); + g_store = new (std::nothrow) RdSingleVerNaturalStore; + ASSERT_NE(g_store, nullptr); + ASSERT_EQ(g_store->Open(property), E_OK); + + int erroCode = E_OK; + g_connection = static_cast(g_store->GetDBConnection(erroCode)); + ASSERT_NE(g_connection, nullptr); + g_store->DecObjRef(g_store); + EXPECT_EQ(erroCode, E_OK); +} + +void DistributedDBStorageMemoryRdSingleVerNaturalStoreTest::TearDown(void) +{ + if (g_connection != nullptr) { + g_connection->Close(); + } + + g_store = nullptr; + DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir + "/31/" + DBConstant::SINGLE_SUB_DIR); +} + +/** + * @tc.name: SyncDatabaseOperate001 + * @tc.desc: To test the function of inserting data of the local device in the synchronization database. + * @tc.type: FUNC + * @tc.require: AR000CCPOM + * @tc.author: wangbingquan + */ +HWTEST_F(DistributedDBStorageMemoryRdSingleVerNaturalStoreTest, SyncDatabaseOperate001, TestSize.Level1) +{ + /** + * @tc.steps: step1/2. Set Ioption to the local data and insert a record of key1 and value1. + * @tc.expected: step1/2. Return OK. + */ + /** + * @tc.steps: step3. Set Ioption to the local data and obtain the value of key1. + * Check whether the value is the same as the value of value1. + * @tc.expected: step3. The obtained value and value2 are the same. + */ + /** + * @tc.steps: step4. Ioption Set this parameter to the local data. Insert key1. + * The value cannot be empty. value2(!=value1) + * @tc.expected: step4. Return OK. + */ + /** + * @tc.steps: step5. Set Ioption to the local data, GetMetaData to obtain the value of key1, + * and check whether the value is the same as the value of value2. + * @tc.expected: step5. The obtained value and value2 are the same. + */ + /** + * @tc.steps: step6. The Ioption parameter is set to the local data. + * The data record whose key is empty and value is not empty is inserted. + * @tc.expected: step6. Return E_INVALID_DATA. + */ + /** + * @tc.steps: step7. Set Ioption to the local data, insert data + * whose key2(!=key1) is not empty, and value is empty. + * @tc.expected: step7. Return OK. + */ + /** + * @tc.steps: step8. Set option to local data, obtain the value of key2, + * and check whether the value is empty. + * @tc.expected: step8. Return OK, value is empty. + */ + /** + * @tc.steps: step9. Ioption Set the local data. + * Insert the data whose key size is 1024 and value size is 4Mb. + * @tc.expected: step9. Return OK. + */ + /** + * @tc.steps: step10/11. Set Ioption to the local data and insert data items + * whose value is greater than 4Mb or key is bigger than 1Kb + * @tc.expected: step10/11. Return E_INVALID_ARGS. + */ + DistributedDBStorageRdSingleVerNaturalStoreTestCase::SyncDatabaseOperate001(g_store, g_connection); +} + +/** + * @tc.name: SyncDatabaseOperate003 + * @tc.desc: test the delete operation in sync database. + * @tc.type: FUNC + * @tc.require: AR000CCPOM + * @tc.author: wangbingquan + */ +HWTEST_F(DistributedDBStorageMemoryRdSingleVerNaturalStoreTest, SyncDatabaseOperate003, TestSize.Level1) +{ + /** + * @tc.steps: step2. Set Ioption to the local data and delete the data whose key is key1 (empty). + * @tc.expected: step2. Return E_INVALID_ARGS. + */ + /** + * @tc.steps: step3. Set Ioption to the local data, insert non-null key1, and non-null value1 data. + * @tc.expected: step3. Return E_OK. + */ + /** + * @tc.steps: step4. Set Ioption to the local data, obtain the value of key1, + * and check whether the value is the same as that of value1. + * @tc.expected: step4. Return E_OK. The obtained value is the same as the value of value1. + */ + /** + * @tc.steps: step5. Set Ioption to the local data and delete the data whose key is key1. + * @tc.expected: step5. Return E_OK. + */ + /** + * @tc.steps: step5. Set Ioption to the local data and obtain the value of Key1. + * @tc.expected: step5. Return E_NOT_FOUND. + */ + DistributedDBStorageRdSingleVerNaturalStoreTestCase::SyncDatabaseOperate003(g_store, g_connection); +} + +/** + * @tc.name: SyncDatabaseOperate005 + * @tc.desc: test the reading for sync database. + * @tc.type: FUNC + * @tc.require: AR000CCPOM + * @tc.author: wangbingquan + */ +HWTEST_F(DistributedDBStorageMemoryRdSingleVerNaturalStoreTest, SyncDatabaseOperate005, TestSize.Level1) +{ + /** + * @tc.steps: step2. Set Ioption to the local data and delete the data whose key is key1 (empty). + * @tc.expected: step2. Return E_INVALID_ARGS. + */ + /** + * @tc.steps: step3. Set Ioption to the local data, insert non-null key1, and non-null value1 data. + * @tc.expected: step3. Return E_OK. + */ + /** + * @tc.steps: step4. Set Ioption to the local data, obtain the value of key1, + * and check whether the value is the same as that of value1. + * @tc.expected: step4. Return E_OK. The obtained value is the same as the value of value1. + */ + /** + * @tc.steps: step5. Set Ioption to the local data and obtain the value data of Key1. + * Check whether the value is the same as the value of value2. + * @tc.expected: step4. Return E_OK, and the value is the same as the value of value2. + */ + /** + * @tc.steps: step5. The Ioption is set to the local. + * The data of the key1 and value2(!=value1) is inserted. + * @tc.expected: step4. Return E_OK. + */ + DistributedDBStorageRdSingleVerNaturalStoreTestCase::SyncDatabaseOperate005(g_store, g_connection); +} + +/** + * @tc.name: SyncDatabaseOperate006 + * @tc.desc: test the get entries for sync database + * @tc.type: FUNC + * @tc.require: AR000CCPOM + * @tc.author: wangbingquan + */ +HWTEST_F(DistributedDBStorageMemoryRdSingleVerNaturalStoreTest, SyncDatabaseOperate006, TestSize.Level1) +{ + /** + * @tc.steps: step2/3/4. Set Ioption to synchronous data. + * Insert the data of key=keyPrefix + 'a', value1. + * Insert the data of key=keyPrefix + 'c', value2. + * Insert the data of key length=keyPrefix length - 1, value3. + * @tc.expected: step2/3/4. Return E_NOT_FOUND. + */ + /** + * @tc.steps: step5. Obtain all data whose prefixKey is keyPrefix. + * @tc.expected: step5. Return OK. The number of obtained data records is 2. + */ + /** + * @tc.steps: step6. Obtain all data whose prefixKey is empty. + * @tc.expected: step6. Return OK. The number of obtained data records is 3. + */ + /** + * @tc.steps: step7. Obtain all data whose prefixKey is keyPrefix. + * @tc.expected: step7. Return E_NOT_SUPPORT. + */ + DistributedDBStorageRdSingleVerNaturalStoreTestCase::SyncDatabaseOperate006(g_store, g_connection); +} +#endif // USE_RD_KERNEL \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_query_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_query_sync_test.cpp index 3db6c1b2e356eb8c3fc627adcd8f942624699255..f5d8e0de25884edbc390152313aabbf59ee512c4 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_query_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_query_sync_test.cpp @@ -626,8 +626,6 @@ HWTEST_F(DistributedDBStorageQuerySyncTest, GetQueryID002, TestSize.Level1) QuerySyncObject querySync(query1); EXPECT_EQ(querySync.GetIdentify().empty(), false); - // same object identify is same - EXPECT_EQ(querySync.GetIdentify(), querySync.GetIdentify()); IOption option; option.dataType = IOption::SYNC_DATA; diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_result_and_json_optimize_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_result_and_json_optimize_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..34d2a21c2bc101cf414a4b83ca9e43a8187b8f0c --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_result_and_json_optimize_test.cpp @@ -0,0 +1,370 @@ +/* + * 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. + */ +#ifdef USE_RD_KERNEL +#ifndef OMIT_JSON +#include + +#include "db_common.h" +#include "db_constant.h" +#include "distributeddb_data_generate_unit_test.h" +#include "distributeddb_tools_unit_test.h" +#include "kvdb_manager.h" +#include "log_print.h" +#include "platform_specific.h" +#include "res_finalizer.h" +#include "rd_single_ver_natural_store_connection.h" +#include "rd_single_ver_result_set.h" +#include "store_types.h" + +using namespace testing::ext; +using namespace DistributedDB; +using namespace DistributedDBUnitTest; + +namespace { + const int INSERT_NUMBER = 10; + const Key EMPTY_KEY; + + string g_testDir; + string g_identifier; + RdSingleVerNaturalStore *g_store = nullptr; + RdSingleVerNaturalStoreConnection *g_connection = nullptr; + KvDBProperties g_Property; + const string STORE_ID = STORE_ID_SYNC; +} +class DistributedDBStorageRdResultAndJsonOptimizeTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void DistributedDBStorageRdResultAndJsonOptimizeTest::SetUpTestCase(void) +{ + DistributedDBToolsUnitTest::TestDirInit(g_testDir); + std::string origIdentifier = USER_ID + "-" + APP_ID + "-" + STORE_ID; + std::string identifier = DBCommon::TransferHashString(origIdentifier); + g_identifier = DBCommon::TransferStringToHex(identifier); + std::string dir = g_testDir + g_identifier + "/" + DBConstant::SINGLE_SUB_DIR; + DIR *dirTmp = opendir(dir.c_str()); + if (dirTmp == nullptr) { + OS::MakeDBDirectory(dir); + } else { + closedir(dirTmp); + } + g_Property.SetStringProp(KvDBProperties::DATA_DIR, g_testDir); + g_Property.SetStringProp(KvDBProperties::STORE_ID, STORE_ID); + g_Property.SetStringProp(KvDBProperties::IDENTIFIER_DIR, g_identifier); + g_Property.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE_RD_KERNAL); +} + +void DistributedDBStorageRdResultAndJsonOptimizeTest::TearDownTestCase(void) +{ + if (DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir) != 0) { + LOGE("rm test db files error!"); + } +} + +void DistributedDBStorageRdResultAndJsonOptimizeTest::SetUp(void) +{ + DistributedDBToolsUnitTest::PrintTestCaseInfo(); + /** + * @tc.setup: 1. Create a RdSingleVerNaturalStore. + * 2. Set the ResultSet cache mode to CACHE_ENTRY_ID_ONLY. + * 3. Put 10 records. + */ + g_store = new (std::nothrow) RdSingleVerNaturalStore; + ASSERT_NE(g_store, nullptr); + ASSERT_EQ(g_store->Open(g_Property), E_OK); + + int errCode = E_OK; + g_connection = static_cast(g_store->GetDBConnection(errCode)); + ASSERT_NE(g_connection, nullptr); + g_store->DecObjRef(g_store); + EXPECT_EQ(errCode, E_OK); + + IOption option; + option.dataType = IOption::SYNC_DATA; + g_connection->Clear(option); + Key insertKey; + ASSERT_EQ(g_connection->StartTransaction(), -E_NOT_SUPPORT); + for (int i = 1; i < INSERT_NUMBER + 1; i++) { + insertKey.clear(); + insertKey.push_back(i); + ASSERT_EQ(g_connection->Put(option, insertKey, VALUE_1), E_OK); + } + ASSERT_EQ(g_connection->Commit(), -E_NOT_SUPPORT); +} + +void DistributedDBStorageRdResultAndJsonOptimizeTest::TearDown(void) +{ + /** + * @tc.teardown: Release the RdSingleVerNaturalStore. + */ + if (g_connection != nullptr) { + g_connection->Close(); + g_connection = nullptr; + } + + g_store = nullptr; + KvDBManager::RemoveDatabase(g_Property); +} + +/** + * @tc.name: ResultSetOpen001 + * @tc.desc: Test the RdSingleVerResultSet Open function + * @tc.type: FUNC + * @tc.require: AR000F3OP0 + * @tc.author: xushaohua + */ +HWTEST_F(DistributedDBStorageRdResultAndJsonOptimizeTest, ResultSetOpen001, TestSize.Level1) +{ + /** + * @tc.steps: step1. Create a RdSingleVerResultSet. + */ + std::unique_ptr resultSet1 = + std::make_unique(g_store, EMPTY_KEY); + + /** + * @tc.steps: step2. Call RdSingleVerResultSet.Open with parameter true. + * @tc.expected: step2. Expect return E_OK. + */ + EXPECT_EQ(resultSet1->Open(false), E_OK); + + /** + * @tc.steps: step3. Create a RdSingleVerResultSet. + */ + std::unique_ptr resultSet2 = + std::make_unique(g_store, EMPTY_KEY); + + /** + * @tc.steps: step4. Call RdSingleVerResultSet.Open with parameter false. + * @tc.expected: step4. Expect return E_OK. + */ + EXPECT_EQ(resultSet2->Open(false), E_OK); + + /** + * @tc.steps: step5. Close all ResultSet. + */ + resultSet1->Close(); + resultSet2->Close(); +} + +/** + * @tc.name: ResultSetGetCount001 + * @tc.desc: Test the RdSingleVerResultSet GetCount function. + * @tc.type: FUNC + * @tc.require: AR000F3OP0 + * @tc.author: xushaohua + */ +HWTEST_F(DistributedDBStorageRdResultAndJsonOptimizeTest, ResultSetGetCount001, TestSize.Level1) +{ + /** + * @tc.steps: step1. Create a RdSingleVerResultSet. + */ + std::unique_ptr resultSet = + std::make_unique(g_store, EMPTY_KEY); + + /** + * @tc.steps: step2. Call RdSingleVerResultSet.Open + * @tc.expected: step2. Expect return E_OK.Gits + */ + EXPECT_EQ(resultSet->Open(false), E_OK); + + /** + * @tc.steps: step2. Call RdSingleVerResultSet.GetCount + * @tc.expected: step2. Expect return INSERT_NUMBER. + */ + EXPECT_EQ(resultSet->GetCount(), INSERT_NUMBER); + + /** + * @tc.steps: step3. Close the ResultSet. + */ + resultSet->Close(); +} + +/** + * @tc.name: ResultSetMoveTo001 + * @tc.desc: Test the RdSingleVerResultSet MoveTo And GetPosition function. + * @tc.type: FUNC + * @tc.require: AR000F3OP0 + * @tc.author: xushaohua + */ +HWTEST_F(DistributedDBStorageRdResultAndJsonOptimizeTest, ResultSetMoveTo001, TestSize.Level1) +{ + /** + * @tc.steps: step1. Create a RdSingleVerResultSet. + */ + std::unique_ptr resultSet = + std::make_unique(g_store, EMPTY_KEY); + + /** + * @tc.steps: step2. Call RdSingleVerResultSet.Open. + * @tc.expected: step2. Expect return E_OK. + */ + EXPECT_EQ(resultSet->Open(false), E_OK); + + /** + * @tc.steps: step3. Call RdSingleVerResultSet MoveTo INSERT_NUMBER - 1 + * @tc.expected: step3. Expect return E_OK. + */ + EXPECT_EQ(resultSet->MoveTo(INSERT_NUMBER - 1), E_OK); + + /** + * @tc.steps: step4. Call RdSingleVerResultSet GetPosition + * @tc.expected: step5. Expect return INSERT_NUMBER - 1. + */ + EXPECT_EQ(resultSet->GetPosition(), INSERT_NUMBER - 1); + + /** + * @tc.steps: step5. Call RdSingleVerResultSet MoveTo INSERT_NUMBER + * @tc.expected: step5. Expect return -E_INVALID_ARGS. + */ + EXPECT_EQ(resultSet->MoveTo(INSERT_NUMBER), -E_INVALID_ARGS); + + /** + * @tc.steps: step6. Call RdSingleVerResultSet GetPosition + * @tc.expected: step6. Expect return INSERT_NUMBER. + */ + EXPECT_EQ(resultSet->GetPosition(), INSERT_NUMBER); + + /** + * @tc.steps: step7. Call RdSingleVerResultSet MoveTo -1 + * @tc.expected: step7. Expect return E_INVALID_ARGS. + */ + EXPECT_EQ(resultSet->MoveTo(-1), -E_INVALID_ARGS); + + /** + * @tc.steps: step8. Call RdSingleVerResultSet GetPosition + * @tc.expected: step8. Expect return 0. + */ + EXPECT_EQ(resultSet->GetPosition(), -1); + + /** + * @tc.steps: step9. Call RdSingleVerResultSet MoveTo 0 + * @tc.expected: step9. Expect return E_OK. + */ + EXPECT_EQ(resultSet->MoveTo(0), E_OK); + + /** + * @tc.steps: step10. Call RdSingleVerResultSet GetPosition + * @tc.expected: step10. Expect return 0. + */ + EXPECT_EQ(resultSet->GetPosition(), 0); + + /** + * @tc.steps: step11. Close the ResultSet. + */ + resultSet->Close(); +} + +/** + * @tc.name: ResultSetGetEntry001 + * @tc.desc: Test the RdSingleVerResultSet GetEntry function. + * @tc.type: FUNC + * @tc.require: AR000F3OP0 + * @tc.author: xushaohua + */ +HWTEST_F(DistributedDBStorageRdResultAndJsonOptimizeTest, ResultSetGetEntry001, TestSize.Level1) +{ + /** + * @tc.steps: step1. Create a RdSingleVerResultSet. + */ + std::unique_ptr resultSet = + std::make_unique(g_store, EMPTY_KEY); + + /** + * @tc.steps: step2. Call RdSingleVerResultSet.Open + * @tc.expected: step2. Expect return E_OK. + */ + EXPECT_EQ(resultSet->Open(false), E_OK); + + /** + * @tc.steps: step2. Call RdSingleVerResultSet MoveTo 0 And GetEntry + * @tc.expected: step2. Expect return E_OK. + */ + Entry entry; + ASSERT_EQ(resultSet->MoveTo(0), E_OK); + EXPECT_EQ(resultSet->GetEntry(entry), E_OK); + + /** + * @tc.expected: step2. Expect return Key == { 1 }, value == VALUE_1. + */ + const Key key = { 1 }; + EXPECT_EQ(entry.key, key); + EXPECT_EQ(entry.value, VALUE_1); + + /** + * @tc.steps: step3. Close the ResultSet. + */ + resultSet->Close(); +} + +/** + * @tc.name: ResultSetTest002 + * @tc.desc: Check the resultSet move,then get + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBStorageRdResultAndJsonOptimizeTest, ResultSetTest002, TestSize.Level1) +{ + /** + * @tc.steps: step1. Check resultSet MoveTo when resultSet is not opened + * @tc.expected: step1. Expect return -E_RESULT_SET_STATUS_INVALID. + */ + std::unique_ptr resultSet1 = + std::make_unique(g_store, EMPTY_KEY); + ASSERT_NE(resultSet1, nullptr); + EXPECT_EQ(resultSet1->MoveTo(INSERT_NUMBER - 1), -E_RESULT_SET_STATUS_INVALID); + + /** + * @tc.steps: step2. Then get the Entry + * @tc.expected: step2. Expect return -E_NO_SUCH_ENTRY. + */ + EXPECT_EQ(resultSet1->Open(false), E_OK); + Entry entry; + EXPECT_EQ(resultSet1->GetEntry(entry), -E_NO_SUCH_ENTRY); + resultSet1->Close(); + + /** + * @tc.steps: step3. Check resultSet MoveTo when db is empty + * @tc.expected: step3. Expect return -E_RESULT_SET_EMPTY. + */ + std::unique_ptr resultSet2 = + std::make_unique(g_store, EMPTY_KEY); + ASSERT_NE(resultSet2, nullptr); + IOption option; + option.dataType = IOption::SYNC_DATA; + Key insertKey; + ASSERT_EQ(g_connection->StartTransaction(), -E_NOT_SUPPORT); + for (int i = 1; i < INSERT_NUMBER + 1; i++) { + insertKey.clear(); + insertKey.push_back(i); + ASSERT_EQ(g_connection->Delete(option, insertKey), E_OK); + } + ASSERT_EQ(g_connection->Commit(), -E_NOT_SUPPORT); + resultSet2->Open(false); + EXPECT_EQ(resultSet2->MoveTo(INSERT_NUMBER - 1), -E_RESULT_SET_EMPTY); + + /** + * @tc.steps: step4. Get resultSet Entry when db is empty + * @tc.expected: step4. Expect return -E_NO_SUCH_ENTRY. + */ + EXPECT_EQ(resultSet2->GetEntry(entry), -E_NO_SUCH_ENTRY); + resultSet2->Close(); +} +#endif +#endif // USE_RD_KERNEL \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_register_conflict_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_register_conflict_test.cpp index 29e4cb74e688d2582805646246b8ff7f44f4c8c0..f90b2bb6ef1843a6bfd900c6b0e6ddc023161859 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_register_conflict_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_register_conflict_test.cpp @@ -61,8 +61,8 @@ namespace { bool newIsDeleted = false; bool oldIsNative = false; bool newIsNative = false; - int getoldValueErrCode = 0; - int getNewValueErrCode = 0; + DBStatus getoldValueErrCode = DBStatus::OK; + DBStatus getNewValueErrCode = DBStatus::OK; bool operator==(const SingleVerConflictData &comparedData) const { if (this->type == comparedData.type && @@ -833,4 +833,4 @@ HWTEST_F(DistributedDBStorageRegisterConflictTest, ConflictNotificationTest017, Value readValue; EXPECT_EQ(g_connection->Get(option, KEY_1, readValue), E_OK); EXPECT_EQ(VALUE_1, readValue); -} +} \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_register_observer_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_register_observer_test.cpp index b6dadf19522c083809123671aa2b3292d8231b8b..7f93cf37c0359d6fbf854216d4c0e9fdc7cf9c03 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_register_observer_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_register_observer_test.cpp @@ -353,7 +353,6 @@ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver001, TestSize */ result = g_singleVerNaturaStoreConnection->UnRegisterObserver(nullptr); EXPECT_EQ(result, -E_INVALID_ARGS); - return; } /** @@ -397,7 +396,6 @@ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver002, TestSize */ TestForOperation(g_entry1, false, false, false); TestForOperation(g_entry2, false, false, false); - return; } /** @@ -441,7 +439,6 @@ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver003, TestSize */ TestForOperation(g_entry1, false, false, false); TestForOperation(g_entry2, false, false, false); - return; } /** @@ -469,7 +466,6 @@ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver004, TestSize EXPECT_EQ(result, E_OK); TestForOperation(g_entry1, false, false, false); TestForOperation(g_entry2, false, false, false); - return; } /** @@ -494,7 +490,6 @@ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver005, TestSize EXPECT_EQ(result, E_OK); TestForOperation(g_entry1, false, false, false); TestForOperation(g_entry2, false, false, false); - return; } /** @@ -518,7 +513,6 @@ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver006, TestSize EXPECT_EQ(result, E_OK); TestForOperation(g_entry1, false, false, false); TestForOperation(g_entry2, false, false, false); - return; } /** @@ -542,7 +536,6 @@ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver007, TestSize EXPECT_EQ(result, E_OK); TestForOperation(g_entry1, false, false, false); TestForOperation(g_entry2, false, false, false); - return; } /** @@ -566,7 +559,6 @@ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver008, TestSize EXPECT_EQ(result, E_OK); TestForOperation(g_entry1, false, false, false); TestForOperation(g_entry2, false, false, false); - return; } /** @@ -591,7 +583,6 @@ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver009, TestSize EXPECT_EQ(result, E_OK); TestForOperation(g_entry1, false, false, false); TestForOperation(g_entry2, false, false, false); - return; } /** @@ -615,7 +606,6 @@ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver010, TestSize g_entry1.key, TestFunc, result); EXPECT_EQ(result, -E_NOT_SUPPORT); EXPECT_EQ(handle, nullptr); - return; } /** @@ -639,7 +629,6 @@ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver011, TestSize g_entry1.key, TestFunc, result); EXPECT_EQ(result, -E_NOT_SUPPORT); EXPECT_EQ(handle, nullptr); - return; } /** @@ -663,7 +652,6 @@ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver012, TestSize g_emptyKey, TestFunc, result); EXPECT_EQ(result, -E_NOT_SUPPORT); EXPECT_EQ(handle, nullptr); - return; } /** @@ -687,7 +675,6 @@ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver013, TestSize g_emptyKey, TestFunc, result); EXPECT_EQ(result, -E_NOT_SUPPORT); EXPECT_EQ(handle, nullptr); - return; } static void PreSyncDataForRegisterObserver014(Timestamp time, vector &dataItems) @@ -788,8 +775,8 @@ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver014, TestSize */ result = g_singleVerNaturaStoreConnection->UnRegisterObserver(handle); EXPECT_EQ(result, E_OK); - return; } + /** * @tc.name: RegisterObserver015 * @tc.desc: Sync multiple records to the sync database, and remove them. @@ -840,5 +827,4 @@ HWTEST_F(DistributedDBStorageRegisterObserverTest, RegisterObserver015, TestSize */ result = g_singleVerNaturaStoreConnection->UnRegisterObserver(handle); EXPECT_EQ(result, E_OK); - return; } 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 42a4ba96a73ca1e644da053eb7fdeffd93cf33ae..514d6fd9aaf2a2657c3b1d3e05756c7bc4faa463 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 @@ -738,6 +738,41 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalExecutorTest, ConnectionTest0 storageEngine->Release(); } +/** + * @tc.name: ConnectionTest006 + * @tc.desc: Test force release engine + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalExecutorTest, ConnectionTest006, TestSize.Level0) +{ + /** + * @tc.steps: step1. open storage engine + * @tc.expected: step1. open ok + */ + auto property = g_property; + property.SetStringProp(KvDBProperties::STORE_ID, "ConnectionTest006"); + property.SetStringProp(KvDBProperties::IDENTIFIER_DATA, "ConnectionTest006ID"); + int errCode = E_OK; + auto storageEngine = + static_cast(StorageEngineManager::GetStorageEngine(property, errCode)); + ASSERT_EQ(errCode, E_OK); + ASSERT_NE(storageEngine, nullptr); + /** + * @tc.steps: step2. inc ref count and release it + */ + RefObject::IncObjRef(storageEngine); + const std::string identifier = property.GetStringProp(KvDBProperties::IDENTIFIER_DATA, ""); + (void)StorageEngineManager::ForceReleaseStorageEngine(identifier); + /** + * @tc.steps: step3. try use engine api and dec ref count + * @tc.expected: step3. call api ok + */ + EXPECT_FALSE(storageEngine->IsEngineCorrupted()); + RefObject::DecObjRef(storageEngine); +} + /** * @tc.name: PragmaTest001 * @tc.desc: Calling Pragma incorrectly @@ -1096,7 +1131,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalExecutorTest, ExecutorCache00 * @tc.name: AbnormalSqlExecutorTest001 * @tc.desc: Check SQLiteStorageExecutor interfaces abnormal scene. * @tc.type: FUNC - * @tc.require: DTS2024073106613 + * @tc.require: * @tc.author: suyue */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalExecutorTest, AbnormalSqlExecutorTest001, TestSize.Level1) @@ -1129,7 +1164,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalExecutorTest, AbnormalSqlExec * @tc.name: AbnormalSqlExecutorTest002 * @tc.desc: Check SQLiteSingleVerStorageExecutor interfaces abnormal scene. * @tc.type: FUNC - * @tc.require: DTS2024073106613 + * @tc.require: * @tc.author: suyue */ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalExecutorTest, AbnormalSqlExecutorTest002, TestSize.Level1) @@ -1169,7 +1204,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalExecutorTest, AbnormalSqlExec * @tc.name: AbnormalSqlExecutorTest003 * @tc.desc: Check SQLiteSingleVerStorageExecutor interfaces abnormal scene. * @tc.type: FUNC - * @tc.require: DTS2024073106613 + * @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 61cff71dc74e0f062f289c5ca1f8d498e5062ef5..09aa6711b405a5e55ea1235e2b463f4339ae2ac3 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 @@ -157,4 +157,69 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerStorageEngineTest, DataTest002, Test EXPECT_EQ(storageEngine->ExecuteMigrate(), -E_BUSY); storageEngine->Release(); storageEngine = nullptr; -} \ No newline at end of file +} + +/** + * @tc.name: DataTest003 + * @tc.desc: Test invalid SQLiteSingleVerNaturalStore and invalid SQLiteSingleVerNaturalStoreConnection + * @tc.type: FUNC + * @tc.require: + * @tc.author: caihaoting + */ +HWTEST_F(DistributedDBStorageSQLiteSingleVerStorageEngineTest, DataTest003, TestSize.Level0) +{ + /** + * @tc.steps::step1. init invalid SQLiteSingleVerNaturalStore and invalid SQLiteSingleVerNaturalStoreConnection + * @tc.expected: step1. return OK. + */ + SQLiteSingleVerNaturalStore *invalidStore = nullptr; + SQLiteSingleVerNaturalStoreConnection *invalidConnection = nullptr; + ASSERT_EQ(invalidStore, nullptr); + invalidConnection = new (std::nothrow) SQLiteSingleVerNaturalStoreConnection(invalidStore); + ASSERT_NE(invalidConnection, nullptr); + /** + * @tc.steps::step2. test RegisterObserver with invalid SQLiteSingleVerNaturalStore + * @tc.expected: step2. return -E_INVALID_CONNECTION. + */ + int errCode = E_OK; + Key key; + key.push_back('a'); + KvDBObserverAction func = [&](const KvDBCommitNotifyData &data) {}; + invalidConnection->RegisterObserver( + static_cast(SQLiteGeneralNSNotificationEventType::SQLITE_GENERAL_NS_LOCAL_PUT_EVENT), key, func, + errCode); + EXPECT_EQ(errCode, -E_INVALID_CONNECTION); + /** + * @tc.steps::step3. test UnRegisterObserver with invalid SQLiteSingleVerNaturalStore + * @tc.expected: step3. return -E_INVALID_CONNECTION. + */ + auto observerHandle = g_connection->RegisterObserver( + static_cast(SQLiteGeneralNSNotificationEventType::SQLITE_GENERAL_NS_LOCAL_PUT_EVENT), key, func, + errCode); + EXPECT_EQ(errCode, E_OK); + errCode = invalidConnection->UnRegisterObserver(observerHandle); + EXPECT_EQ(errCode, -E_INVALID_CONNECTION); + /** + * @tc.steps::step4. test GetSecurityOption with invalid SQLiteSingleVerNaturalStore + * @tc.expected: step4. return -E_INVALID_CONNECTION. + */ + int securityLabel = NOT_SET; + int securityFlag = ECE; + errCode = invalidConnection->GetSecurityOption(securityLabel, securityFlag); + EXPECT_EQ(errCode, -E_INVALID_CONNECTION); + /** + * @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.expected: step6. return OK. + */ + if (invalidConnection != nullptr) { + delete invalidConnection; + invalidConnection = nullptr; + } + ASSERT_EQ(invalidConnection, nullptr); +} diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_subscribe_query_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_subscribe_query_test.cpp index 9da40f841c093df2cab53377cc51756917f5888d..5fa3c9829447111e5fe16d4d2f958b6f65540228 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_subscribe_query_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_subscribe_query_test.cpp @@ -90,7 +90,7 @@ void PreSetData(uint8_t dataNum) validJsonData = R"({"field_name1":false,"field_name2":false,"field_name3":100})"; } value.assign(validJsonData.begin(), validJsonData.end()); - EXPECT_EQ(g_kvNbDelegatePtr->Put(keyA, value), E_OK); + EXPECT_EQ(g_kvNbDelegatePtr->Put(keyA, value), OK); } } @@ -163,7 +163,7 @@ void CheckDataNumByKey(const std::string &storeId, const Key& key, size_t expSiz EXPECT_TRUE(g_kvNbDelegatePtr != nullptr); EXPECT_TRUE(g_kvDelegateStatus == OK); std::vector entries; - EXPECT_EQ(g_kvNbDelegatePtr->GetEntries(key, entries), E_OK); + EXPECT_EQ(g_kvNbDelegatePtr->GetEntries(key, entries), OK); EXPECT_TRUE(entries.size() == expSize); EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); } 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 e35d0311b39d676ee6c84fde6d7e6ca55c167c5a..fe63ac21c4aa402a53c15f56e7e958968c434e53 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,6 +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_); 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 cae789758e9b9f36282623ac6d3e53f775ebbe46..efea28538637d6459db091e2f06b4f65bc15ad3e 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 @@ -25,6 +25,7 @@ #include "mock_icloud_sync_storage_interface.h" #include "virtual_cloud_db.h" #include "virtual_cloud_syncer.h" +#include "virtual_communicator_aggregator.h" using namespace std; using namespace testing::ext; @@ -114,6 +115,7 @@ public: protected: std::shared_ptr virtualCloudDb_ = nullptr; + VirtualCommunicatorAggregator *communicatorAggregator_ = nullptr; }; void DistributedDBCloudDBProxyTest::SetUpTestCase() @@ -128,11 +130,17 @@ void DistributedDBCloudDBProxyTest::SetUp() { DistributedDBUnitTest::DistributedDBToolsUnitTest::PrintTestCaseInfo(); virtualCloudDb_ = std::make_shared(); + communicatorAggregator_ = new (std::nothrow) VirtualCommunicatorAggregator(); + ASSERT_TRUE(communicatorAggregator_ != nullptr); + RuntimeContext::GetInstance()->SetCommunicatorAggregator(communicatorAggregator_); } void DistributedDBCloudDBProxyTest::TearDown() { virtualCloudDb_ = nullptr; + RuntimeContext::GetInstance()->SetCommunicatorAggregator(nullptr); + communicatorAggregator_ = nullptr; + RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(nullptr); } /** @@ -277,6 +285,52 @@ HWTEST_F(DistributedDBCloudDBProxyTest, CloudDBProxyTest003, TestSize.Level0) EXPECT_EQ(proxy.Close(), E_OK); } +/** + * @tc.name: CloudDBProxyTest004 + * @tc.desc: Verify cloud db init and close function with multiple CloudDbs. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangtao + */ +HWTEST_F(DistributedDBCloudDBProxyTest, CloudDBProxyTest004, TestSize.Level0) +{ + /** + * @tc.steps: step1. set cloud db to proxy + * @tc.expected: step1. E_OK + */ + CloudDBProxy proxy; + std::string syncUserA = "SyncUserA"; + std::string syncUserB = "SyncUserB"; + std::string syncUserC = "SyncUserC"; + std::shared_ptr virtualCloudDbB = std::make_shared(); + std::shared_ptr virtualCloudDbC = std::make_shared(); + std::map> cloudDBs = { + {syncUserA, virtualCloudDb_}, {syncUserB, virtualCloudDbB}, {syncUserC, virtualCloudDbC} + }; + proxy.SetCloudDB(cloudDBs); + /** + * @tc.steps: step2. proxy close cloud db with cloud error + * @tc.expected: step2. -E_CLOUD_ERROR + */ + for (const auto &pair : cloudDBs) { + std::shared_ptr basePtr = pair.second; + auto vtrPtr = static_cast(basePtr.get()); + vtrPtr->SetCloudError(true); + } + EXPECT_EQ(proxy.Close(), -E_CLOUD_ERROR); + /** + * @tc.steps: step3. proxy close cloud db again + * @tc.expected: step3. E_OK because cloud db has been set nullptr + */ + EXPECT_EQ(proxy.Close(), E_OK); + for (const auto &pair : cloudDBs) { + std::shared_ptr basePtr = pair.second; + auto vtrPtr = static_cast(basePtr.get()); + vtrPtr->SetCloudError(false); + } + EXPECT_EQ(proxy.Close(), E_OK); +} + /** * @tc.name: CloudDBProxyTest005 * @tc.desc: Verify sync failed after cloud error. @@ -761,7 +815,7 @@ HWTEST_F(DistributedDBCloudDBProxyTest, SameBatchTest002, TestSize.Level0) * @tc.name: CloudDBProxyTest013 * @tc.desc: Verify CloudDBProxy interfaces. * @tc.type: FUNC - * @tc.require: DTS2024073106613 + * @tc.require: * @tc.author: suyue */ HWTEST_F(DistributedDBCloudDBProxyTest, CloudDBProxyTest013, TestSize.Level0) @@ -810,7 +864,7 @@ HWTEST_F(DistributedDBCloudDBProxyTest, CloudDBProxyTest013, TestSize.Level0) * @tc.name: CloudSyncUtilsTest * @tc.desc: Verify CloudSyncUtils interfaces * @tc.type: FUNC - * @tc.require: DTS2024073106613 + * @tc.require: * @tc.author: suyue */ HWTEST_F(DistributedDBCloudDBProxyTest, CloudSyncUtilsTest, TestSize.Level0) 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 5c6edf18261f78562fadc0a29b9e16e31c9bf62f..c191f6b85bc432847b8513c974771ed6d679af61 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 @@ -471,6 +471,28 @@ HWTEST_F(DistributedDBCloudKvSyncerTest, UploadAbnormalSync003, TestSize.Level0) cloudHook->SetDoUploadHook(nullptr); } +/** + * @tc.name: UploadAbnormalSync004 + * @tc.desc: Test sync errCode is not in [27328512, 27394048). + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenghuitao + */ +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; + virtualCloudDb_->SetActionStatus(static_cast(errCode)); + Key key = {'k'}; + Value value = {'v'}; + ASSERT_EQ(kvDelegatePtrS1_->Put(key, value), OK); + BlockSync(kvDelegatePtrS1_, static_cast(errCode), g_CloudSyncoption); + virtualCloudDb_->SetActionStatus(OK); +} + /** * @tc.name: QueryParsingProcessTest001 * @tc.desc: Test Query parsing process. @@ -516,4 +538,304 @@ HWTEST_F(DistributedDBCloudKvSyncerTest, QueryParsingProcessTest001, TestSize.Le syncObject.ParserQueryNodes(bytes, queryNodes); ASSERT_EQ(queryNodes[0].type, QueryNodeType::IN); } + +/** + * @tc.name: UploadFinished001 + * @tc.desc: Test upload update record when do update. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBCloudKvSyncerTest, UploadFinished001, TestSize.Level0) +{ + Key key = {'k'}; + Value value = {'v'}; + ASSERT_EQ(kvDelegatePtrS1_->Put(key, value), OK); + Value newValue = {'v', '1'}; + // update [k,v] to [k,v1] when upload + virtualCloudDb_->ForkUpload([kvDelegatePtrS1 = kvDelegatePtrS1_, key, newValue](const std::string &, VBucket &) { + EXPECT_EQ(kvDelegatePtrS1->Put(key, newValue), OK); + }); + BlockSync(kvDelegatePtrS1_, OK, g_CloudSyncoption); + BlockSync(kvDelegatePtrS2_, OK, g_CloudSyncoption); + Value actualValue; + // cloud download [k,v] + EXPECT_EQ(kvDelegatePtrS2_->Get(key, actualValue), OK); + EXPECT_EQ(actualValue, value); + // sync again and get [k,v1] + BlockSync(kvDelegatePtrS1_, OK, g_CloudSyncoption); + BlockSync(kvDelegatePtrS2_, OK, g_CloudSyncoption); + EXPECT_EQ(kvDelegatePtrS1_->Get(key, actualValue), OK); + EXPECT_EQ(actualValue, newValue); + virtualCloudDb_->ForkUpload(nullptr); +} + +/** + * @tc.name: SyncWithMultipleUsers001. + * @tc.desc: Test sync data with multiple users. + * @tc.type: FUNC + * @tc.require: + * @tc.author: liufuchenxing + */ +HWTEST_F(DistributedDBCloudKvSyncerTest, SyncWithMultipleUsers001, TestSize.Level0) +{ + Key key = {'k'}; + Value value = {'v'}; + ASSERT_EQ(kvDelegatePtrS1_->Put(key, value), 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); + BlockSync(kvDelegatePtrS2_, OK, syncOption); + Value actualValue; + // cloud download [k,v] + EXPECT_EQ(kvDelegatePtrS2_->Get(key, actualValue), OK); + 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) +{ + for (int i = 0; i < TEST_SYNCWITHMULTIPLEUSER002_ENTRISE_NUM; i++) { + std::string keyStr = "k_" + std::to_string(i); + std::string valueStr = "v_" + std::to_string(i); + Key key(keyStr.begin(), keyStr.end()); + Value value(valueStr.begin(), valueStr.end()); + Entry entry; + entry.key = key; + entry.value = value; + 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); + } +} + +/** + * @tc.name: SyncWithMultipleUsers002. + * @tc.desc: test whether upload to the cloud after delete local data that does not have a gid. + * @tc.type: FUNC + * @tc.require: + * @tc.author: luoguo + */ +HWTEST_F(DistributedDBCloudKvSyncerTest, SyncWithMultipleUsers002, TestSize.Level0) +{ + /** + * @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); + + /** + * @tc.steps: step2. kvDelegatePtrS2_ only sync user0 from cloud. + * @tc.expected: step2. return ok. + */ + syncOption.users.clear(); + syncOption.users.push_back(USER_ID); + BlockSync(kvDelegatePtrS2_, OK, syncOption); + + /** + * @tc.steps: step3. kvDelegatePtrS2_ delete 100 data. + * @tc.expected: step3. return ok. + */ + ASSERT_EQ(kvDelegatePtrS2_->DeleteBatch(keys), OK); + + /** + * @tc.steps: step4. kvDelegatePtrS2_ sync to cloud with user0 user2. + * @tc.expected: step4. return ok. + */ + syncOption.users.clear(); + syncOption.users.push_back(USER_ID); + syncOption.users.push_back(USER_ID_2); + + std::mutex dataMutex; + std::condition_variable cv; + bool finish = false; + uint32_t insertCount = 0; + auto callback = [&](const std::map &process) { + size_t notifyCnt = 0; + for (const auto &item : process) { + if (item.second.process != DistributedDB::FINISHED) { + continue; + } + EXPECT_EQ(item.second.errCode, OK); + { + std::lock_guard autoLock(dataMutex); + notifyCnt++; + std::set userSet(syncOption.users.begin(), syncOption.users.end()); + if (notifyCnt == userSet.size()) { + finish = true; + std::map tableProcess(item.second.tableProcess); + insertCount = tableProcess["sync_data"].downLoadInfo.insertCount; + cv.notify_one(); + } + } + } + }; + auto actualRet = kvDelegatePtrS2_->Sync(syncOption, callback); + EXPECT_EQ(actualRet, OK); + if (actualRet == OK) { + std::unique_lock uniqueLock(dataMutex); + cv.wait(uniqueLock, [&finish]() { return finish; }); + } + /** + * @tc.steps: step5. check process info, user2's insertCount should be 0. + * @tc.expected: step5. return ok. + */ + EXPECT_EQ(insertCount, 0u); +} + +/** + * @tc.name: AbnormalCloudKvExecutorTest001 + * @tc.desc: Check SqliteCloudKvExecutorUtils interfaces abnormal scene. + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBCloudKvSyncerTest, AbnormalCloudKvExecutorTest001, TestSize.Level0) +{ + /** + * @tc.steps: step1. Call PutCloudData interface with different opType when para is invalid. + * @tc.expected: step1. return errCode. + */ + SqliteCloudKvExecutorUtils cloudKvObj; + DownloadData downloadData; + downloadData.data = {{}}; + int ret = cloudKvObj.PutCloudData(nullptr, true, downloadData); + EXPECT_EQ(ret, -E_CLOUD_ERROR); + downloadData.opType = {OpType::UPDATE_VERSION}; + ret = cloudKvObj.PutCloudData(nullptr, true, downloadData); + EXPECT_EQ(ret, -E_CLOUD_ERROR); + + downloadData.opType = {OpType::UPDATE_TIMESTAMP}; + ret = cloudKvObj.PutCloudData(nullptr, true, downloadData); + EXPECT_EQ(ret, -E_INVALID_DB); + downloadData.opType = {OpType::DELETE}; + ret = cloudKvObj.PutCloudData(nullptr, true, downloadData); + EXPECT_EQ(ret, -E_INVALID_DB); + + /** + * @tc.steps: step2. Call CountAllCloudData interface when para is invalid. + * @tc.expected: step2. return -E_INVALID_ARGS. + */ + QuerySyncObject querySyncObject; + std::pair res = cloudKvObj.CountAllCloudData({nullptr, true}, {}, "", true, querySyncObject); + EXPECT_EQ(res.first, -E_INVALID_ARGS); + + /** + * @tc.steps: step3. Call SqliteCloudKvExecutorUtils interfaces when db is nullptr. + * @tc.expected: step3. return -E_INVALID_DB. + */ + res = cloudKvObj.CountCloudData(nullptr, true, 0, "", true); + EXPECT_EQ(res.first, -E_INVALID_DB); + std::pair ver = cloudKvObj.GetLocalCloudVersion(nullptr, true, ""); + EXPECT_EQ(ver.first, -E_INVALID_DB); + std::vector dataVector; + ret = cloudKvObj.GetCloudVersionFromCloud(nullptr, true, "", dataVector); + EXPECT_EQ(ret, -E_INVALID_DB); +} + +/** + * @tc.name: AbnormalCloudKvExecutorTest002 + * @tc.desc: Check FillCloudLog interface + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBCloudKvSyncerTest, AbnormalCloudKvExecutorTest002, TestSize.Level0) +{ + /** + * @tc.steps: step1. Call FillCloudLog interface when db and para is nullptr. + * @tc.expected: step1. return -E_INVALID_ARGS. + */ + SqliteCloudKvExecutorUtils cloudKvObj; + sqlite3 *db = nullptr; + CloudSyncData data; + CloudUploadRecorder recorder; + int ret = cloudKvObj.FillCloudLog({db, true}, OpType::INSERT, data, "", recorder); + EXPECT_EQ(ret, -E_INVALID_ARGS); + + /** + * @tc.steps: step2. open db and Call FillCloudLog. + * @tc.expected: step2. return E_OK. + */ + uint64_t flag = SQLITE_OPEN_URI | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; + std::string fileUrl = g_testDir + "/test.db"; + EXPECT_EQ(sqlite3_open_v2(fileUrl.c_str(), &db, flag, nullptr), SQLITE_OK); + ASSERT_NE(db, nullptr); + + data.isCloudVersionRecord = true; + ret = cloudKvObj.FillCloudLog({db, true}, OpType::INSERT, data, "", recorder); + EXPECT_EQ(ret, E_OK); + ret = cloudKvObj.FillCloudLog({db, true}, OpType::DELETE, data, "", recorder); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(sqlite3_close_v2(db), E_OK); +} + +/** + * @tc.name: DeviceCollaborationTest001 + * @tc.desc: Check force override data + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBCloudKvSyncerTest, DeviceCollaborationTest001, TestSize.Level0) +{ + /** + * @tc.steps: step1. open db with DEVICE_COLLABORATION. + * @tc.expected: step1. return E_OK. + */ + KvStoreNbDelegate* kvDelegatePtrS3 = nullptr; + KvStoreNbDelegate::Option option; + option.conflictResolvePolicy = ConflictResolvePolicy::DEVICE_COLLABORATION; + ASSERT_EQ(GetKvStore(kvDelegatePtrS3, STORE_ID_3, option), OK); + ASSERT_NE(kvDelegatePtrS3, nullptr); + KvStoreNbDelegate* kvDelegatePtrS4 = nullptr; + ASSERT_EQ(GetKvStore(kvDelegatePtrS4, STORE_ID_4, option), OK); + ASSERT_NE(kvDelegatePtrS4, nullptr); + /** + * @tc.steps: step2. db3 put (k1,v1) sync to db4. + * @tc.expected: step2. db4 get (k1,v1). + */ + Key key = {'k'}; + Value value = {'v'}; + EXPECT_EQ(kvDelegatePtrS3->Put(key, value), OK); + communicatorAggregator_->SetLocalDeviceId("DB3"); + BlockSync(kvDelegatePtrS3, OK, g_CloudSyncoption); + communicatorAggregator_->SetLocalDeviceId("DB4"); + BlockSync(kvDelegatePtrS4, OK, g_CloudSyncoption); + Value actualValue; + EXPECT_EQ(kvDelegatePtrS4->Get(key, actualValue), OK); + EXPECT_EQ(actualValue, value); + /** + * @tc.steps: step3. db4 delete (k1,v1) db3 sync again to db4. + * @tc.expected: step3. db4 get (k1,v1). + */ + EXPECT_EQ(kvDelegatePtrS4->Delete(key), OK); + communicatorAggregator_->SetLocalDeviceId("DB3"); + EXPECT_EQ(kvDelegatePtrS3->RemoveDeviceData("", ClearMode::FLAG_AND_DATA), OK); + BlockSync(kvDelegatePtrS3, OK, g_CloudSyncoption); + communicatorAggregator_->SetLocalDeviceId("DB4"); + BlockSync(kvDelegatePtrS4, OK, g_CloudSyncoption); + EXPECT_EQ(kvDelegatePtrS4->Get(key, actualValue), OK); + EXPECT_EQ(actualValue, value); + CloseKvStore(kvDelegatePtrS3, STORE_ID_3); + CloseKvStore(kvDelegatePtrS4, STORE_ID_4); +} } \ No newline at end of file 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 ad26f0716a2d160bcc6d5baa397f89bfd0f14780..2a393566ba116ef9656473291e0c6956e9fee782 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 @@ -16,12 +16,13 @@ #include #include "cloud/cloud_db_constant.h" +#include "db_base64_utils.h" #include "distributeddb_data_generate_unit_test.h" #include "distributeddb_tools_unit_test.h" #include "kv_virtual_device.h" #include "kv_store_nb_delegate.h" -#include "platform_specific.h" #include "kv_store_nb_delegate_impl.h" +#include "platform_specific.h" #include "process_system_api_adapter_impl.h" #include "virtual_communicator_aggregator.h" #include "virtual_cloud_db.h" @@ -38,6 +39,12 @@ KvStoreDelegateManager g_mgr(APP_ID, USER_ID); CloudSyncOption g_CloudSyncoption; const std::string USER_ID_2 = "user2"; const std::string USER_ID_3 = "user3"; +const Key KEY_1 = {'k', '1'}; +const Key KEY_2 = {'k', '2'}; +const Key KEY_3 = {'k', '3'}; +const Value VALUE_1 = {'v', '1'}; +const Value VALUE_2 = {'v', '2'}; +const Value VALUE_3 = {'v', '3'}; class DistributedDBCloudKvTest : public testing::Test { public: static void SetUpTestCase(); @@ -57,7 +64,10 @@ protected: bool invalidSchema = false); void CloseKvStore(KvStoreNbDelegate *&delegate, const std::string &storeId); void BlockSync(KvStoreNbDelegate *delegate, DBStatus expectDBStatus, CloudSyncOption option, - int expectSyncResult = OK); + DBStatus expectSyncResult = OK); + void SyncAndGetProcessInfo(KvStoreNbDelegate *delegate, CloudSyncOption option); + bool CheckUserSyncInfo(const vector users, const vector userStatus, + const vector userExpectInfo); static DataBaseSchema GetDataBaseSchema(bool invalidSchema); std::shared_ptr virtualCloudDb_ = nullptr; std::shared_ptr virtualCloudDb2_ = nullptr; @@ -65,6 +75,7 @@ protected: KvStoreNbDelegate* kvDelegatePtrS1_ = nullptr; KvStoreNbDelegate* kvDelegatePtrS2_ = nullptr; SyncProcess lastProcess_; + std::map lastSyncProcess_; VirtualCommunicatorAggregator *communicatorAggregator_ = nullptr; KvVirtualDevice *deviceB_ = nullptr; }; @@ -142,7 +153,7 @@ void DistributedDBCloudKvTest::TearDown() } void DistributedDBCloudKvTest::BlockSync(KvStoreNbDelegate *delegate, DBStatus expectDBStatus, CloudSyncOption option, - int expectSyncResult) + DBStatus expectSyncResult) { if (delegate == nullptr) { return; @@ -163,7 +174,8 @@ void DistributedDBCloudKvTest::BlockSync(KvStoreNbDelegate *delegate, DBStatus e { std::lock_guard autoLock(dataMutex); notifyCnt++; - if (notifyCnt == option.users.size()) { + std::set userSet(option.users.begin(), option.users.end()); + if (notifyCnt == userSet.size()) { finish = true; last = item.second; cv.notify_one(); @@ -206,6 +218,7 @@ DataBaseSchema DistributedDBCloudKvTest::GetDataBaseSchema(bool invalidSchema) return schema; } + DBStatus DistributedDBCloudKvTest::GetKvStore(KvStoreNbDelegate *&delegate, const std::string &storeId, KvStoreNbDelegate::Option option, bool invalidSchema) { @@ -238,6 +251,108 @@ void DistributedDBCloudKvTest::CloseKvStore(KvStoreNbDelegate *&delegate, const } } +void DistributedDBCloudKvTest::SyncAndGetProcessInfo(KvStoreNbDelegate *delegate, CloudSyncOption option) +{ + if (delegate == nullptr) { + return; + } + std::mutex dataMutex; + std::condition_variable cv; + bool isFinish = false; + vector> lists; + auto callback = [&cv, &dataMutex, &isFinish, &option, &lists](const std::map &process) { + size_t notifyCnt = 0; + for (const auto &item: process) { + LOGD("user = %s, status = %d", item.first.c_str(), item.second.process); + if (item.second.process != DistributedDB::FINISHED) { + continue; + } + { + std::lock_guard autoLock(dataMutex); + notifyCnt++; + std::set userSet(option.users.begin(), option.users.end()); + if (notifyCnt == userSet.size()) { + isFinish = true; + cv.notify_one(); + } + lists.push_back(process); + } + } + }; + auto ret = delegate->Sync(option, callback); + EXPECT_EQ(ret, OK); + if (ret == OK) { + std::unique_lock uniqueLock(dataMutex); + cv.wait(uniqueLock, [&isFinish]() { + return isFinish; + }); + } + lastSyncProcess_ = lists.back(); +} + +bool DistributedDBCloudKvTest::CheckUserSyncInfo(const vector users, const vector userStatus, + const vector userExpectInfo) +{ + uint32_t idx = 0; + for (auto &it: lastSyncProcess_) { + if ((idx >= users.size()) || (idx >= userStatus.size()) || (idx >= userExpectInfo.size())) { + return false; + } + string user = it.first; + if (user.compare(0, user.length(), users[idx]) != 0) { + return false; + } + SyncProcess actualSyncProcess = it.second; + EXPECT_EQ(actualSyncProcess.process, FINISHED); + EXPECT_EQ(actualSyncProcess.errCode, userStatus[idx]); + for (const auto &table : actualSyncProcess.tableProcess) { + EXPECT_EQ(table.second.upLoadInfo.total, userExpectInfo[idx].total); + EXPECT_EQ(table.second.upLoadInfo.successCount, userExpectInfo[idx].successCount); + EXPECT_EQ(table.second.upLoadInfo.insertCount, userExpectInfo[idx].insertCount); + EXPECT_EQ(table.second.upLoadInfo.failCount, userExpectInfo[idx].failCount); + } + idx++; + } + return true; +} + +/** + * @tc.name: SubUser001 + * @tc.desc: Test get and delete db with sub user. + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(DistributedDBCloudKvTest, SubUser001, TestSize.Level0) +{ + /** + * @tc.steps: step1. Get db with subUser + * @tc.expected: step1.ok + */ + KvStoreDelegateManager manager(APP_ID, USER_ID, "subUser"); + KvStoreConfig subUserConfig = config_; + subUserConfig.dataDir = config_.dataDir + "/subUser"; + OS::MakeDBDirectory(subUserConfig.dataDir); + manager.SetKvStoreConfig(subUserConfig); + KvStoreNbDelegate::Option option; + DBStatus openRet = OK; + KvStoreNbDelegate* kvDelegatePtrS3_ = nullptr; + manager.GetKvStore(STORE_ID_1, option, + [&openRet, &kvDelegatePtrS3_](DBStatus status, KvStoreNbDelegate *openDelegate) { + openRet = status; + kvDelegatePtrS3_ = openDelegate; + }); + EXPECT_EQ(openRet, OK); + ASSERT_NE(kvDelegatePtrS3_, nullptr); + /** + * @tc.steps: step2. close and delete db + * @tc.expected: step2.ok + */ + ASSERT_EQ(manager.CloseKvStore(kvDelegatePtrS3_), OK); + DBStatus status = manager.DeleteKvStore(STORE_ID_1); + EXPECT_EQ(status, OK); +} + /** * @tc.name: NormalSync001 * @tc.desc: Test normal push sync for add data. @@ -255,6 +370,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync001, TestSize.Level0) return origin + "1"; }); BlockSync(kvDelegatePtrS1_, OK, g_CloudSyncoption); + EXPECT_EQ(virtualCloudDb_->GetPrepareTraceId(), std::string("")); for (const auto &table : lastProcess_.tableProcess) { EXPECT_EQ(table.second.upLoadInfo.total, 1u); EXPECT_EQ(table.second.upLoadInfo.insertCount, 1u); @@ -289,6 +405,14 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync002, TestSize.Level0) * @tc.expected: step1. both put ok */ communicatorAggregator_->SetLocalDeviceId("DEVICES_A"); + kvDelegatePtrS1_->SetGenCloudVersionCallback([](const std::string &origin) { + LOGW("origin is %s", origin.c_str()); + return origin + "1"; + }); + kvDelegatePtrS2_->SetGenCloudVersionCallback([](const std::string &origin) { + LOGW("origin is %s", origin.c_str()); + return origin + "1"; + }); Key key1 = {'k', '1'}; Value expectValue1 = {'v', '1'}; Key key2 = {'k', '2'}; @@ -320,6 +444,13 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync002, TestSize.Level0) LOGW("Store1 sync end"); EXPECT_EQ(kvDelegatePtrS1_->Get(key2, actualValue), OK); EXPECT_EQ(actualValue, expectValue2); + auto result = kvDelegatePtrS2_->GetCloudVersion(""); + EXPECT_EQ(result.first, OK); + for (const auto &item : result.second) { + EXPECT_EQ(DBBase64Utils::DecodeIfNeed(item.first), item.first); + } + kvDelegatePtrS1_->SetGenCloudVersionCallback(nullptr); + kvDelegatePtrS2_->SetGenCloudVersionCallback(nullptr); } /** @@ -945,7 +1076,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync022, TestSize.Level0) ASSERT_NE(memoryDB1, nullptr); /** * @tc.steps:step2. Sync without cloud schema. - * @tc.expected: step2 CLOUD_ERROR. + * @tc.expected: step2 SCHEMA_MISMATCH. */ BlockSync(memoryDB1, OK, g_CloudSyncoption, CLOUD_ERROR); std::map> cloudDbs; @@ -1017,6 +1148,24 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync024, TestSize.Level0) virtualCloudDb_->SetInsertHook(nullptr); } +/** + * @tc.name: NormalSync025 + * @tc.desc: Test merge sync. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBCloudKvTest, NormalSync025, TestSize.Level0) +{ + virtualCloudDb_->SetBlockTime(1000); // block query 1000ms + auto option = g_CloudSyncoption; + option.merge = false; + EXPECT_EQ(kvDelegatePtrS1_->Sync(option, nullptr), OK); + option.merge = true; + EXPECT_EQ(kvDelegatePtrS1_->Sync(option, nullptr), OK); + BlockSync(kvDelegatePtrS1_, CLOUD_SYNC_TASK_MERGED, option); +} + /** * @tc.name: NormalSync026 * @tc.desc: Test delete when sync mode DEVICE_COLLABORATION. @@ -1051,7 +1200,7 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync026, TestSize.Level0) BlockSync(kvDelegatePtrS1_, OK, g_CloudSyncoption); /** * @tc.steps:step4. device1 sync. - * @tc.expected: The record was not covered by the cloud and cloud was covered. + * @tc.expected: step4. The record was not covered by the cloud and cloud was covered. */ BlockSync(kvDelegatePtrS3_, OK, g_CloudSyncoption); Value actualValue1; @@ -1060,6 +1209,36 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync026, TestSize.Level0) CloseKvStore(kvDelegatePtrS3_, STORE_ID_3); } +/** + * @tc.name: NormalSync027 + * @tc.desc: Test lock failed during data insert. + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(DistributedDBCloudKvTest, NormalSync027, TestSize.Level0) +{ + /** + * @tc.steps:step1. put 1 record and sync. + * @tc.expected: step1 OK. + */ + Key key = {'k'}; + Value value = {'v'}; + ASSERT_EQ(kvDelegatePtrS1_->Put(key, value), OK); + /** + * @tc.steps:step2. Lock cloud DB, and do sync. + * @tc.expected: step2 sync failed due to lock fail, and failCount is 1. + */ + virtualCloudDb_->Lock(); + BlockSync(kvDelegatePtrS1_, CLOUD_LOCK_ERROR, g_CloudSyncoption); + for (const auto &table : lastProcess_.tableProcess) { + EXPECT_EQ(table.second.upLoadInfo.total, 1u); + EXPECT_EQ(table.second.upLoadInfo.successCount, 0u); + EXPECT_EQ(table.second.upLoadInfo.failCount, 1u); + } + virtualCloudDb_->UnLock(); +} + /** * @tc.name: NormalSync028 * @tc.desc: Test multi user sync. @@ -1086,6 +1265,138 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync028, TestSize.Level0) EXPECT_EQ(lastProcess_.tableProcess[USER_ID_2].downLoadInfo.total, 0u); } +/** + * @tc.name: NormalSync029 + * @tc.desc: Test lock failed during data insert. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBCloudKvTest, NormalSync029, TestSize.Level3) +{ + /** + * @tc.steps:step1. block virtual cloud. + */ + virtualCloudDb_->SetBlockTime(1000); // block 1s + /** + * @tc.steps:step2. Call sync and let it run with block cloud. + * @tc.expected: step2 sync ok. + */ + auto option = g_CloudSyncoption; + std::mutex finishMutex; + std::condition_variable cv; + std::vector> processRes; + auto callback = [&processRes, &finishMutex, &cv](const std::map &process) { + for (const auto &item : process) { + if (item.second.process != ProcessStatus::FINISHED) { + return; + } + } + { + std::lock_guard autoLock(finishMutex); + processRes.push_back(process); + } + cv.notify_all(); + }; + EXPECT_EQ(kvDelegatePtrS1_->Sync(option, callback), OK); + /** + * @tc.steps:step3. USER0 sync first and USER2 sync second. + * @tc.expected: step3 sync ok and USER2 task has been merged. + */ + option.merge = true; + option.users = {USER_ID}; + EXPECT_EQ(kvDelegatePtrS1_->Sync(option, callback), OK); + option.users = {USER_ID_2}; + EXPECT_EQ(kvDelegatePtrS1_->Sync(option, callback), OK); + /** + * @tc.steps:step4. Wait all task finished. + * @tc.expected: step4 Second sync task has USER0 and USER2. + */ + virtualCloudDb_->SetBlockTime(0); // cancel block for test case run quickly + std::unique_lock uniqueLock(finishMutex); + cv.wait_for(uniqueLock, std::chrono::milliseconds(DBConstant::MAX_TIMEOUT), [&processRes]() { + return processRes.size() >= 3; // call sync 3 times + }); + EXPECT_EQ(processRes[processRes.size() - 1].size(), 2u); // check the last process has 2 user +} + +/** + * @tc.name: NormalSync030 + * @tc.desc: Test sync while set null cloudDB + * @tc.type: FUNC + * @tc.require: + * @tc.author: caihaoting + */ +HWTEST_F(DistributedDBCloudKvTest, NormalSync030, TestSize.Level0) +{ + /** + * @tc.steps:step1. Create a database. + * @tc.expected: step1 OK. + */ + KvStoreNbDelegate* kvDelegatePtrS3_ = nullptr; + KvStoreNbDelegate::Option option; + DBStatus ret = OK; + g_mgr.GetKvStore(STORE_ID_3, option, [&ret, &kvDelegatePtrS3_](DBStatus status, KvStoreNbDelegate *openDelegate) { + ret = status; + kvDelegatePtrS3_ = openDelegate; + }); + EXPECT_EQ(ret, OK); + ASSERT_NE(kvDelegatePtrS3_, nullptr); + /** + * @tc.steps:step2. Put {k, v}. + * @tc.expected: step2 OK. + */ + Key key = {'k'}; + Value value = {'v'}; + ASSERT_EQ(kvDelegatePtrS3_->Put(key, value), OK); + /** + * @tc.steps:step3. Set null cloudDB. + * @tc.expected: step3 CLOUD_ERROR. + */ + BlockSync(kvDelegatePtrS3_, OK, g_CloudSyncoption, CLOUD_ERROR); + std::map> cloudDbs; + cloudDbs[USER_ID] = nullptr; + cloudDbs[USER_ID_2] = virtualCloudDb2_; + EXPECT_EQ(kvDelegatePtrS3_->SetCloudDB(cloudDbs), INVALID_ARGS); + /** + * @tc.steps:step4. Sync while set null cloudDB. + * @tc.expected: step4 CLOUD_ERROR. + */ + BlockSync(kvDelegatePtrS3_, OK, g_CloudSyncoption, CLOUD_ERROR); + EXPECT_EQ(g_mgr.CloseKvStore(kvDelegatePtrS3_), OK); +} + +/** + * @tc.name: NormalSync031 + * @tc.desc: Test sync with error local device + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBCloudKvTest, NormalSync031, TestSize.Level0) +{ + /** + * @tc.steps:step1. put 1 record and sync. + * @tc.expected: step1 OK. + */ + Key key = {'k'}; + Value value = {'v'}; + ASSERT_EQ(kvDelegatePtrS2_->Put(key, value), OK); + BlockSync(kvDelegatePtrS2_, OK, g_CloudSyncoption); + /** + * @tc.steps:step2. Set local devices error and sync. + * @tc.expected: step2 sync fail. + */ + communicatorAggregator_->MockGetLocalDeviceRes(-E_CLOUD_ERROR); + BlockSync(kvDelegatePtrS1_, CLOUD_ERROR, g_CloudSyncoption); + communicatorAggregator_->MockGetLocalDeviceRes(E_OK); + for (const auto &table : lastProcess_.tableProcess) { + EXPECT_EQ(table.second.downLoadInfo.total, 0u); + EXPECT_EQ(table.second.downLoadInfo.failCount, 0u); + EXPECT_EQ(table.second.upLoadInfo.total, 0u); + } +} + /** * @tc.name: NormalSync032 * @tc.desc: Test some record upload fail in 1 batch. @@ -1179,1252 +1490,592 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSync033, TestSize.Level0) } /** - * @tc.name: NormalSync036 - * @tc.desc: test sync data with SetCloudSyncConfig. + * @tc.name: NormalSync034 + * @tc.desc: test sync data which size > maxUploadSize. * @tc.type: FUNC * @tc.require: - * @tc.author: caihaoting + * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync036, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync034, TestSize.Level0) { /** - * @tc.steps:step1. put data and SetCloudSyncConfig. + * @tc.steps:step1. put data which size > maxUploadSize. * @tc.expected: step1 ok. */ CloudSyncConfig config; + int maxUploadSize = 1024000; int maxUploadCount = 40; + config.maxUploadSize = maxUploadSize; config.maxUploadCount = maxUploadCount; kvDelegatePtrS1_->SetCloudSyncConfig(config); - Key key = {'k', '1'}; - Value value = {'v', '1'}; + Key key = {'k'}; + Value value = {'v'}; + value.insert(value.end(), maxUploadSize, '0'); kvDelegatePtrS1_->Put(key, value); /** - * @tc.steps:step2. sync. + * @tc.steps:step2. put entries which count > maxUploadCount. * @tc.expected: step2 ok. */ + vector entries; + for (int i = 0; i < maxUploadCount; i++) { + std::string keyStr = "k_" + std::to_string(i); + std::string valueStr = "v_" + std::to_string(i); + Key key(keyStr.begin(), keyStr.end()); + Value value(valueStr.begin(), valueStr.end()); + entries.push_back({key, value}); + } + EXPECT_EQ(kvDelegatePtrS1_->PutBatch(entries), OK); + /** + * @tc.steps:step3. sync and check upLoadInfo.batchIndex. + * @tc.expected: step3 ok. + */ BlockSync(kvDelegatePtrS1_, OK, g_CloudSyncoption); + for (const auto &table : lastProcess_.tableProcess) { + EXPECT_EQ(table.second.upLoadInfo.batchIndex, 2u); + } } /** - * @tc.name: NormalSync041 - * @tc.desc: Test concurrent sync and close DB. + * @tc.name: NormalSync035 + * @tc.desc:test sync after export and import * @tc.type: FUNC * @tc.require: - * @tc.author: liaoyonghuang + * @tc.author: caihaoting */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync041, TestSize.Level1) +HWTEST_F(DistributedDBCloudKvTest, NormalSync035, TestSize.Level0) { /** - * @tc.steps:step1. put data to cloud. + * @tc.steps:step1. put local records {k1, v1} and sync to cloud. * @tc.expected: step1 ok. */ - Key key = {'k', '1'}; - Value value = {'v', '1'}; - kvDelegatePtrS1_->Put(key, value); + Key key1 = {'k', '1'}; + Value value1 = {'v', '1'}; + ASSERT_EQ(kvDelegatePtrS1_->Put(key1, value1), OK); + kvDelegatePtrS1_->SetGenCloudVersionCallback([](const std::string &origin) { + LOGW("origin is %s", origin.c_str()); + return origin + "1"; + }); BlockSync(kvDelegatePtrS1_, OK, g_CloudSyncoption); - + Value actualValue1; + EXPECT_EQ(kvDelegatePtrS1_->Get(key1, actualValue1), OK); + EXPECT_EQ(actualValue1, value1); + auto result = kvDelegatePtrS1_->GetCloudVersion(""); + EXPECT_EQ(result.first, OK); + for (auto item : result.second) { + EXPECT_EQ(item.second, "1"); + } /** - * @tc.steps:step2. sync and close DB concurrently. - * @tc.expected: step2 ok. + * @tc.steps:step2. export and import. + * @tc.expected: step2 export and import ok. */ - KvStoreNbDelegate* kvDelegatePtrS3_ = nullptr; - KvStoreNbDelegate::Option option; - EXPECT_EQ(GetKvStore(kvDelegatePtrS3_, STORE_ID_3, option), OK); - virtualCloudDb_->ForkQuery([](const std::string &tableName, VBucket &extend) { - std::this_thread::sleep_for(std::chrono::milliseconds(200)); // sleep for 200ms - }); - KvStoreDelegateManager &mgr = g_mgr; - std::thread syncThread([&mgr, &kvDelegatePtrS3_]() { - std::this_thread::sleep_for(std::chrono::milliseconds(100)); // sleep for 100ms - EXPECT_EQ(mgr.CloseKvStore(kvDelegatePtrS3_), OK); - }); - EXPECT_EQ(kvDelegatePtrS3_->Sync(g_CloudSyncoption, nullptr), OK); - syncThread.join(); + std::string singleExportFileName = g_testDir + "/NormalSync034.$$"; + CipherPassword passwd; + EXPECT_EQ(kvDelegatePtrS1_->Export(singleExportFileName, passwd), OK); + EXPECT_EQ(kvDelegatePtrS1_->Import(singleExportFileName, passwd), OK); + /** + * @tc.steps:step3. put {k1, v2} and sync to cloud. + * @tc.expected: step3 ok. + */ + Value value2 = {'v', '2'}; + ASSERT_EQ(kvDelegatePtrS1_->Put(key1, value2), OK); + BlockSync(kvDelegatePtrS1_, OK, g_CloudSyncoption); + Value actualValue2; + EXPECT_EQ(kvDelegatePtrS1_->Get(key1, actualValue2), OK); + EXPECT_EQ(actualValue2, value2); + result = kvDelegatePtrS1_->GetCloudVersion(""); + EXPECT_EQ(result.first, OK); + for (auto item : result.second) { + EXPECT_EQ(item.second, "11"); + } + kvDelegatePtrS1_->SetGenCloudVersionCallback(nullptr); } /** - * @tc.name: NormalSync045 - * @tc.desc: Test some record upload fail in 1 batch and extend size greater than record size + * @tc.name: NormalSync036 + * @tc.desc: test sync data with SetCloudSyncConfig. * @tc.type: FUNC * @tc.require: - * @tc.author: zhangtao + * @tc.author: caihaoting */ -HWTEST_F(DistributedDBCloudKvTest, NormalSync045, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync036, TestSize.Level0) { /** - * @tc.steps:step1. put 10 records. + * @tc.steps:step1. put data and SetCloudSyncConfig. * @tc.expected: step1 ok. */ - vector entries; - int count = 10; // put 10 records. - for (int i = 0; i < count; i++) { - std::string keyStr = "k_" + std::to_string(i); - std::string valueStr = "v_" + std::to_string(i); - Key key(keyStr.begin(), keyStr.end()); - Value value(valueStr.begin(), valueStr.end()); - entries.push_back({key, value}); - } - EXPECT_EQ(kvDelegatePtrS1_->PutBatch(entries), OK); + CloudSyncConfig config; + int maxUploadCount = 40; + config.maxUploadCount = maxUploadCount; + kvDelegatePtrS1_->SetCloudSyncConfig(config); + Key key = {'k', '1'}; + Value value = {'v', '1'}; + kvDelegatePtrS1_->Put(key, value); /** - * @tc.steps:step2. sync and add one empty extend as result - * @tc.expected: step2 sync fail and upLoadInfo.failCount is 10. 1 batch failed. + * @tc.steps:step2. sync. + * @tc.expected: step2 ok. */ - std::atomic missCount = -1; - virtualCloudDb_->SetClearExtend(missCount); - BlockSync(kvDelegatePtrS1_, CLOUD_ERROR, g_CloudSyncoption); - for (const auto &table : lastProcess_.tableProcess) { - EXPECT_EQ(table.second.upLoadInfo.total, 10u); - EXPECT_EQ(table.second.upLoadInfo.successCount, 0u); - EXPECT_EQ(table.second.upLoadInfo.insertCount, 0u); - EXPECT_EQ(table.second.upLoadInfo.failCount, 10u); - } - virtualCloudDb_->ForkUpload(nullptr); + BlockSync(kvDelegatePtrS1_, OK, g_CloudSyncoption); } /** - * @tc.name: SyncOptionCheck001 - * @tc.desc: Test sync without user. + * @tc.name: NormalSync037 + * @tc.desc: test update sync data while local and cloud record device is same and not local device. * @tc.type: FUNC * @tc.require: - * @tc.author: liaoyonghuang + * @tc.author: caihaoting */ -HWTEST_F(DistributedDBCloudKvTest, SyncOptionCheck001, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync037, TestSize.Level0) { /** - * @tc.steps:step1. Device 1 inserts a piece of data. - * @tc.expected: step1 OK. - */ - Key key = {'k'}; - Value value = {'v'}; - ASSERT_EQ(kvDelegatePtrS1_->Put(key, value), OK); - /** - * @tc.steps:step2. Set option without user, and attempt to sync - * @tc.expected: step2 return INVALID_ARGS. + * @tc.steps:step1. deviceA put {k1, v1} and sync to cloud. + * @tc.expected: step1. ok. */ - CloudSyncOption option; - option.mode = SyncMode::SYNC_MODE_CLOUD_MERGE; - option.devices.push_back("cloud"); - BlockSync(kvDelegatePtrS1_, OK, option, INVALID_ARGS); + communicatorAggregator_->SetLocalDeviceId("DEVICES_A"); + Key key = {'k', '1'}; + Value expectValue1 = {'v', '1'}; + ASSERT_EQ(kvDelegatePtrS1_->Put(key, expectValue1), OK); + BlockSync(kvDelegatePtrS1_, OK, g_CloudSyncoption); /** - * @tc.steps:step3. Device 2 sync and attempt to get data. - * @tc.expected: step3 sync OK but data NOT_FOUND. + * @tc.steps:step2. deviceB sync to cloud. + * @tc.expected: step2. ok. */ + communicatorAggregator_->SetLocalDeviceId("DEVICES_B"); BlockSync(kvDelegatePtrS2_, OK, g_CloudSyncoption); - Value actualValue; - EXPECT_EQ(kvDelegatePtrS2_->Get(key, actualValue), NOT_FOUND); -} - -/** - * @tc.name: SyncOptionCheck002 - * @tc.desc: Test sync with invalid waitTime. - * @tc.type: FUNC - * @tc.require: - * @tc.author: liaoyonghuang - */ -HWTEST_F(DistributedDBCloudKvTest, SyncOptionCheck002, TestSize.Level0) -{ - /** - * @tc.steps:step1. Device 1 inserts a piece of data. - * @tc.expected: step1 OK. - */ - Key key = {'k'}; - Value value = {'v'}; - ASSERT_EQ(kvDelegatePtrS1_->Put(key, value), OK); + Value actualValue1; + EXPECT_EQ(kvDelegatePtrS2_->Get(key, actualValue1), OK); + EXPECT_EQ(actualValue1, expectValue1); /** - * @tc.steps:step2. Set invalid waitTime of sync option and sync. - * @tc.expected: step2 return INVALID_ARGS. + * @tc.steps:step3. deviceA put {k1, v2} and sync to cloud. + * @tc.expected: step3. ok. */ - CloudSyncOption option; - option.mode = SyncMode::SYNC_MODE_CLOUD_MERGE; - option.users.push_back(USER_ID); - option.devices.push_back("cloud"); - option.waitTime = -2; // -2 is invalid waitTime. - BlockSync(kvDelegatePtrS1_, OK, option, INVALID_ARGS); + communicatorAggregator_->SetLocalDeviceId("DEVICES_A"); + Value expectValue2 = {'v', '2'}; + ASSERT_EQ(kvDelegatePtrS1_->Put(key, expectValue2), OK); + BlockSync(kvDelegatePtrS1_, OK, g_CloudSyncoption); /** - * @tc.steps:step3. Device 2 sync and attempt to get data. - * @tc.expected: step3 sync OK but data NOT_FOUND. + * @tc.steps:step4. deviceB sync to cloud. + * @tc.expected: step4. ok. */ + communicatorAggregator_->SetLocalDeviceId("DEVICES_B"); BlockSync(kvDelegatePtrS2_, OK, g_CloudSyncoption); - Value actualValue; - EXPECT_EQ(kvDelegatePtrS2_->Get(key, actualValue), NOT_FOUND); + Value actualValue2; + EXPECT_EQ(kvDelegatePtrS2_->Get(key, actualValue2), OK); + EXPECT_EQ(actualValue2, expectValue2); } /** - * @tc.name: SyncOptionCheck003 - * @tc.desc: Test sync with users which have not been sync to cloud. + * @tc.name: NormalSync038 + * @tc.desc: test insert sync data while local and cloud record device is same and not local device. * @tc.type: FUNC * @tc.require: - * @tc.author: liaoyonghuang + * @tc.author: caihaoting */ -HWTEST_F(DistributedDBCloudKvTest, SyncOptionCheck003, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync038, TestSize.Level0) { /** - * @tc.steps:step1. Device 1 inserts a piece of data. - * @tc.expected: step1 OK. - */ - Key key = {'k'}; - Value value = {'v'}; - ASSERT_EQ(kvDelegatePtrS1_->Put(key, value), OK); - /** - * @tc.steps:step2. Set user1 and user3 to option and sync. - * @tc.expected: step2 return INVALID_ARGS. + * @tc.steps:step1. deviceA put {k1, v1} and sync to cloud. + * @tc.expected: step1. ok. */ - CloudSyncOption option; - option.mode = SyncMode::SYNC_MODE_CLOUD_MERGE; - option.users.push_back(USER_ID); - option.users.push_back(USER_ID_3); - option.devices.push_back("cloud"); - BlockSync(kvDelegatePtrS1_, OK, option, INVALID_ARGS); + communicatorAggregator_->SetLocalDeviceId("DEVICES_A"); + Key key1 = {'k', '1'}; + Value expectValue1 = {'v', '1'}; + ASSERT_EQ(kvDelegatePtrS1_->Put(key1, expectValue1), OK); + BlockSync(kvDelegatePtrS1_, OK, g_CloudSyncoption); /** - * @tc.steps:step3. Device 2 sync and attempt to get data. - * @tc.expected: step3 sync OK but data NOT_FOUND. + * @tc.steps:step2. deviceB sync to cloud. + * @tc.expected: step2. ok. */ + communicatorAggregator_->SetLocalDeviceId("DEVICES_B"); BlockSync(kvDelegatePtrS2_, OK, g_CloudSyncoption); - Value actualValue; - EXPECT_EQ(kvDelegatePtrS2_->Get(key, actualValue), NOT_FOUND); -} - -/** - * @tc.name: SyncOptionCheck004 - * @tc.desc: Test sync with user when schema is not same. - * @tc.type: FUNC - * @tc.require: - * @tc.author: caihaoting - */ -HWTEST_F(DistributedDBCloudKvTest, SyncOptionCheck004, TestSize.Level0) -{ + Value actualValue1; + EXPECT_EQ(kvDelegatePtrS2_->Get(key1, actualValue1), OK); + EXPECT_EQ(actualValue1, expectValue1); /** - * @tc.steps:step1. Device 1 inserts a piece of data. - * @tc.expected: step1 OK. + * @tc.steps:step3. deviceA put {k2, v2} and sync to cloud. + * @tc.expected: step3. ok. */ - Key key = {'k'}; - Value value = {'v'}; - ASSERT_EQ(kvDelegatePtrS1_->Put(key, value), OK); + communicatorAggregator_->SetLocalDeviceId("DEVICES_A"); + Key key2 = {'k', '2'}; + Value expectValue2 = {'v', '2'}; + ASSERT_EQ(kvDelegatePtrS1_->Put(key2, expectValue2), OK); + BlockSync(kvDelegatePtrS1_, OK, g_CloudSyncoption); /** - * @tc.steps:step2. Set user1 to option and user2 to schema and sync. - * @tc.expected: step2 return SCHEMA_MISMATCH. + * @tc.steps:step4. deviceB sync to cloud. + * @tc.expected: step4. ok. */ - CloudSyncOption option; - option.mode = SyncMode::SYNC_MODE_CLOUD_MERGE; - option.users.push_back(USER_ID); - option.devices.push_back("cloud"); - std::map schemas; - schemas[USER_ID_2] = GetDataBaseSchema(false); - kvDelegatePtrS1_->SetCloudDbSchema(schemas); - BlockSync(kvDelegatePtrS1_, OK, option, SCHEMA_MISMATCH); + communicatorAggregator_->SetLocalDeviceId("DEVICES_B"); + BlockSync(kvDelegatePtrS2_, OK, g_CloudSyncoption); + actualValue1.clear(); + EXPECT_EQ(kvDelegatePtrS2_->Get(key1, actualValue1), OK); + EXPECT_EQ(actualValue1, expectValue1); + Value actualValue2; + EXPECT_EQ(kvDelegatePtrS2_->Get(key2, actualValue2), OK); + EXPECT_EQ(actualValue2, expectValue2); } /** - * @tc.name: SyncOptionCheck005 - * @tc.desc: Testing registration of observer exceeded the upper limit. + * @tc.name: NormalSync039 + * @tc.desc: test delete sync data while local and cloud record device is same and not local device. * @tc.type: FUNC * @tc.require: - * @tc.author: liaoyonghuang + * @tc.author: caihaoting */ -HWTEST_F(DistributedDBCloudKvTest, SyncOptionCheck005, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync039, TestSize.Level0) { /** - * @tc.steps:step1. Register MAX_OBSERVER_COUNT observers. - * @tc.expected: step1 OK. + * @tc.steps:step1. deviceA put {k1, v1} {k2, v2} and sync to cloud. + * @tc.expected: step1. ok. */ - std::vector observerList; - for (int i = 0; i < DBConstant::MAX_OBSERVER_COUNT; i++) { - auto *observer = new (std::nothrow) KvStoreObserverUnitTest; - observerList.push_back(observer); - EXPECT_EQ(kvDelegatePtrS1_->RegisterObserver({}, OBSERVER_CHANGES_CLOUD, observer), OK); - } + communicatorAggregator_->SetLocalDeviceId("DEVICES_A"); + Key key1 = {'k', '1'}; + Value expectValue1 = {'v', '1'}; + ASSERT_EQ(kvDelegatePtrS1_->Put(key1, expectValue1), OK); + Key key2 = {'k', '2'}; + Value expectValue2 = {'v', '2'}; + ASSERT_EQ(kvDelegatePtrS1_->Put(key2, expectValue2), OK); + BlockSync(kvDelegatePtrS1_, OK, g_CloudSyncoption); /** - * @tc.steps:step2. Register one more observer. - * @tc.expected: step2 Registration failed, return OVER_MAX_LIMITS. + * @tc.steps:step2. deviceB sync to cloud. + * @tc.expected: step2. ok. */ - auto *overMaxObserver = new (std::nothrow) KvStoreObserverUnitTest; - EXPECT_EQ(kvDelegatePtrS1_->RegisterObserver({}, OBSERVER_CHANGES_CLOUD, overMaxObserver), OVER_MAX_LIMITS); + communicatorAggregator_->SetLocalDeviceId("DEVICES_B"); + BlockSync(kvDelegatePtrS2_, OK, g_CloudSyncoption); + Value actualValue1; + EXPECT_EQ(kvDelegatePtrS2_->Get(key1, actualValue1), OK); + EXPECT_EQ(actualValue1, expectValue1); + Value actualValue2; + EXPECT_EQ(kvDelegatePtrS2_->Get(key2, actualValue2), OK); + EXPECT_EQ(actualValue2, expectValue2); /** - * @tc.steps:step3. UnRegister all observers. - * @tc.expected: step3 OK. + * @tc.steps:step3. deviceA delete {k2, v2} and sync to cloud. + * @tc.expected: step3. ok. */ - EXPECT_EQ(kvDelegatePtrS1_->UnRegisterObserver(overMaxObserver), NOT_FOUND); - delete overMaxObserver; - overMaxObserver = nullptr; - for (auto &observer : observerList) { - EXPECT_EQ(kvDelegatePtrS1_->UnRegisterObserver(observer), OK); - delete observer; - observer = nullptr; - } -} - -void DistributedDBCloudKvTest::SetFlag(const Key &key, LogInfoFlag flag) -{ - sqlite3 *db_; - uint64_t openFlag = SQLITE_OPEN_URI | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; - std::string fileUrl = g_testDir + "/" \ - "2d23c8a0ffadafcaa03507a4ec2290c83babddcab07c0e2945fbba93efc7eec0/single_ver/main/gen_natural_store.db"; - ASSERT_TRUE(sqlite3_open_v2(fileUrl.c_str(), &db_, openFlag, nullptr) == SQLITE_OK); - int errCode = E_OK; - std::string sql = "UPDATE sync_data SET flag=? WHERE Key=?"; - sqlite3_stmt *statement = nullptr; - errCode = SQLiteUtils::GetStatement(db_, sql, statement); - if (errCode != E_OK) { - SQLiteUtils::ResetStatement(statement, true, errCode); - } - ASSERT_EQ(errCode, E_OK); - errCode = SQLiteUtils::BindInt64ToStatement(statement, 1, static_cast(flag)); // 1st arg. - ASSERT_EQ(errCode, E_OK); - errCode = SQLiteUtils::BindBlobToStatement(statement, 2, key, true); // 2nd arg. - ASSERT_EQ(errCode, E_OK); - if (errCode != E_OK) { - SQLiteUtils::ResetStatement(statement, true, errCode); - } - EXPECT_EQ(SQLiteUtils::StepWithRetry(statement), SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)); - SQLiteUtils::ResetStatement(statement, true, errCode); - EXPECT_EQ(errCode, E_OK); - sqlite3_close_v2(db_); -} - -int DistributedDBCloudKvTest::CheckFlag(const Key &key, LogInfoFlag flag) -{ - sqlite3 *db_; - uint64_t openFlag = SQLITE_OPEN_URI | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; - std::string fileUrl = g_testDir + "/" \ - "2d23c8a0ffadafcaa03507a4ec2290c83babddcab07c0e2945fbba93efc7eec0/single_ver/main/gen_natural_store.db"; - int errCode = sqlite3_open_v2(fileUrl.c_str(), &db_, openFlag, nullptr); - if (errCode != E_OK) { - return NOT_FOUND; - } - std::string sql = "SELECT * FROM sync_data WHERE Key =? AND (flag=?)"; - sqlite3_stmt *statement = nullptr; - errCode = SQLiteUtils::GetStatement(db_, sql, statement); - if (errCode != E_OK) { - SQLiteUtils::ResetStatement(statement, true, errCode); - return NOT_FOUND; - } - std::vector keyVec(key.begin(), key.end()); - errCode = SQLiteUtils::BindBlobToStatement(statement, 1, keyVec, true); // 1st arg. - if (errCode != E_OK) { - SQLiteUtils::ResetStatement(statement, true, errCode); - return NOT_FOUND; - } - errCode = SQLiteUtils::BindInt64ToStatement(statement, 2, static_cast(flag)); // 2nd arg. - if (errCode != E_OK) { - SQLiteUtils::ResetStatement(statement, true, errCode); - return NOT_FOUND; - } - errCode = SQLiteUtils::StepWithRetry(statement); - if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { - SQLiteUtils::ResetStatement(statement, true, errCode); - sqlite3_close_v2(db_); - return NOT_FOUND; // cant find. - } - if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { - SQLiteUtils::ResetStatement(statement, true, errCode); - sqlite3_close_v2(db_); - return OK; - } - SQLiteUtils::ResetStatement(statement, true, errCode); - EXPECT_EQ(errCode, E_OK); - sqlite3_close_v2(db_); - return NOT_FOUND; -} - -int DistributedDBCloudKvTest::CheckWaterMark(const std::string &user) -{ - sqlite3 *db_; - uint64_t flag = SQLITE_OPEN_URI | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; - std::string fileUrl = g_testDir + "/" \ - "2d23c8a0ffadafcaa03507a4ec2290c83babddcab07c0e2945fbba93efc7eec0/single_ver/main/gen_natural_store.db"; - int errCode = sqlite3_open_v2(fileUrl.c_str(), &db_, flag, nullptr); - if (errCode != E_OK) { - return NOT_FOUND; - } - std::string sql; - if (user.empty()) { - sql = "SELECT * FROM meta_data WHERE KEY LIKE 'naturalbase_cloud_meta_sync_data_%'"; - } else { - sql = "SELECT * FROM meta_data WHERE KEY =?;"; - } - sqlite3_stmt *statement = nullptr; - errCode = SQLiteUtils::GetStatement(db_, sql, statement); - if (errCode != E_OK) { - SQLiteUtils::ResetStatement(statement, true, errCode); - return NOT_FOUND; - } - if (!user.empty()) { - std::string waterMarkKey = HWM_HEAD + user; - std::vector keyVec(waterMarkKey.begin(), waterMarkKey.end()); - errCode = SQLiteUtils::BindBlobToStatement(statement, 1, keyVec, true); // only one arg. - if (errCode != E_OK) { - SQLiteUtils::ResetStatement(statement, true, errCode); - return NOT_FOUND; - } - } - errCode = SQLiteUtils::StepWithRetry(statement); - if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { - SQLiteUtils::ResetStatement(statement, true, errCode); - sqlite3_close_v2(db_); - return NOT_FOUND; // cant find. - } - if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { - SQLiteUtils::ResetStatement(statement, true, errCode); - sqlite3_close_v2(db_); - return OK; - } - SQLiteUtils::ResetStatement(statement, true, errCode); - EXPECT_EQ(errCode, E_OK); - sqlite3_close_v2(db_); - return NOT_FOUND; -} - -void DistributedDBCloudKvTest::SetDeviceId(const Key &key, const std::string &deviceId) -{ - sqlite3 *db_; - uint64_t flag = SQLITE_OPEN_URI | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; - std::string fileUrl = g_testDir + "/" \ - "2d23c8a0ffadafcaa03507a4ec2290c83babddcab07c0e2945fbba93efc7eec0/single_ver/main/gen_natural_store.db"; - ASSERT_TRUE(sqlite3_open_v2(fileUrl.c_str(), &db_, flag, nullptr) == SQLITE_OK); - int errCode = E_OK; - std::string sql = "UPDATE sync_data SET device=? WHERE Key=?"; - sqlite3_stmt *statement = nullptr; - errCode = SQLiteUtils::GetStatement(db_, sql, statement); - if (errCode != E_OK) { - SQLiteUtils::ResetStatement(statement, true, errCode); - } - ASSERT_EQ(errCode, E_OK); - std::string hashDevice = DBCommon::TransferHashString(deviceId); - std::vector deviceIdVec(hashDevice.begin(), hashDevice.end()); - int bindIndex = 1; - errCode = SQLiteUtils::BindBlobToStatement(statement, bindIndex, deviceIdVec, true); // only one arg. - ASSERT_EQ(errCode, E_OK); - if (errCode != E_OK) { - SQLiteUtils::ResetStatement(statement, true, errCode); - } - bindIndex++; - errCode = SQLiteUtils::BindBlobToStatement(statement, bindIndex, key, true); // only one arg. - if (errCode != E_OK) { - SQLiteUtils::ResetStatement(statement, true, errCode); - } - EXPECT_EQ(SQLiteUtils::StepWithRetry(statement), SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)); - SQLiteUtils::ResetStatement(statement, true, errCode); - EXPECT_EQ(errCode, E_OK); - sqlite3_close_v2(db_); -} - -int DistributedDBCloudKvTest::CheckLogTable(const std::string &deviceId) -{ - sqlite3 *db_; - uint64_t flag = SQLITE_OPEN_URI | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; - std::string fileUrl = g_testDir + "/" \ - "2d23c8a0ffadafcaa03507a4ec2290c83babddcab07c0e2945fbba93efc7eec0/single_ver/main/gen_natural_store.db"; - int errCode = sqlite3_open_v2(fileUrl.c_str(), &db_, flag, nullptr); - if (errCode != E_OK) { - return NOT_FOUND; - } - std::string sql = "SELECT * FROM naturalbase_kv_aux_sync_data_log WHERE hash_key IN" \ - "(SELECT hash_key FROM sync_data WHERE device =?);"; - sqlite3_stmt *statement = nullptr; - errCode = SQLiteUtils::GetStatement(db_, sql, statement); - if (errCode != E_OK) { - SQLiteUtils::ResetStatement(statement, true, errCode); - return NOT_FOUND; - } - std::string hashDevice = DBCommon::TransferHashString(deviceId); - std::vector deviceIdVec(hashDevice.begin(), hashDevice.end()); - errCode = SQLiteUtils::BindBlobToStatement(statement, 1, deviceIdVec, true); // only one arg. - if (errCode != E_OK) { - SQLiteUtils::ResetStatement(statement, true, errCode); - return NOT_FOUND; - } - errCode = SQLiteUtils::StepWithRetry(statement); - if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { - SQLiteUtils::ResetStatement(statement, true, errCode); - sqlite3_close_v2(db_); - return NOT_FOUND; // cant find. - } - if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { - SQLiteUtils::ResetStatement(statement, true, errCode); - sqlite3_close_v2(db_); - return OK; - } - SQLiteUtils::ResetStatement(statement, true, errCode); - EXPECT_EQ(errCode, E_OK); - sqlite3_close_v2(db_); - return NOT_FOUND; -} - -int DistributedDBCloudKvTest::ChangeUserId(const std::string &deviceId, const std::string &wantUserId) -{ - sqlite3 *db_; - uint64_t flag = SQLITE_OPEN_URI | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; - std::string fileUrl = g_testDir + "/" \ - "2d23c8a0ffadafcaa03507a4ec2290c83babddcab07c0e2945fbba93efc7eec0/single_ver/main/gen_natural_store.db"; - int errCode = sqlite3_open_v2(fileUrl.c_str(), &db_, flag, nullptr); - if (errCode != E_OK) { - return INVALID_ARGS; - } - std::string sql = "UPDATE naturalbase_kv_aux_sync_data_log SET userid =? WHERE hash_key IN" \ - "(SELECT hash_key FROM sync_data WHERE device =? AND (flag=0x100));"; - sqlite3_stmt *statement = nullptr; - errCode = SQLiteUtils::GetStatement(db_, sql, statement); - if (errCode != E_OK) { - SQLiteUtils::ResetStatement(statement, true, errCode); - return INVALID_ARGS; - } - int bindIndex = 1; - errCode = SQLiteUtils::BindTextToStatement(statement, bindIndex, wantUserId); // only one arg. - if (errCode != E_OK) { - SQLiteUtils::ResetStatement(statement, true, errCode); - return INVALID_ARGS; - } - bindIndex++; - std::string hashDevice = DBCommon::TransferHashString(deviceId); - std::vector deviceIdVec(hashDevice.begin(), hashDevice.end()); - errCode = SQLiteUtils::BindBlobToStatement(statement, bindIndex, deviceIdVec, true); // only one arg. - if (errCode != E_OK) { - SQLiteUtils::ResetStatement(statement, true, errCode); - return INVALID_ARGS; - } - EXPECT_EQ(SQLiteUtils::StepWithRetry(statement), SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)); - SQLiteUtils::ResetStatement(statement, true, errCode); - EXPECT_EQ(errCode, E_OK); - sqlite3_close_v2(db_); - return INVALID_ARGS; -} - -int DistributedDBCloudKvTest::ChangeHashKey(const std::string &deviceId) -{ - sqlite3 *db_; - uint64_t flag = SQLITE_OPEN_URI | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; - std::string fileUrl = g_testDir + "/" \ - "2d23c8a0ffadafcaa03507a4ec2290c83babddcab07c0e2945fbba93efc7eec0/single_ver/main/gen_natural_store.db"; - int errCode = sqlite3_open_v2(fileUrl.c_str(), &db_, flag, nullptr); - if (errCode != E_OK) { - return INVALID_ARGS; - } - std::string updataLogTableSql = "UPDATE naturalbase_kv_aux_sync_data_log SET hash_Key ='99';"; - sqlite3_stmt *statement = nullptr; - errCode = SQLiteUtils::GetStatement(db_, updataLogTableSql, statement); - if (errCode != E_OK) { - SQLiteUtils::ResetStatement(statement, true, errCode); - return INVALID_ARGS; - } - errCode = SQLiteUtils::StepWithRetry(statement); - if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { - SQLiteUtils::ResetStatement(statement, true, errCode); - } - - std::string sql = "UPDATE sync_data SET hash_Key ='99' WHERE device =? AND (flag=0x100);"; - errCode = SQLiteUtils::GetStatement(db_, sql, statement); - if (errCode != E_OK) { - SQLiteUtils::ResetStatement(statement, true, errCode); - return INVALID_ARGS; - } - std::string hashDevice = DBCommon::TransferHashString(deviceId); - std::vector deviceIdVec(hashDevice.begin(), hashDevice.end()); - errCode = SQLiteUtils::BindBlobToStatement(statement, 1, deviceIdVec, true); // only one arg. - if (errCode != E_OK) { - SQLiteUtils::ResetStatement(statement, true, errCode); - sqlite3_close_v2(db_); - return OK; // cant find. - } - EXPECT_EQ(SQLiteUtils::StepWithRetry(statement), SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)); - SQLiteUtils::ResetStatement(statement, true, errCode); - EXPECT_EQ(errCode, E_OK); - sqlite3_close_v2(db_); - return INVALID_ARGS; -} - -void DistributedDBCloudKvTest::InsertRecord(int num) -{ - for (int i = 0; i < num; i++) { - Key key; - key.push_back('k'); - key.push_back('0' + i); - Value value; - value.push_back('k'); - value.push_back('0' + i); - ASSERT_EQ(kvDelegatePtrS1_->Put(key, value), OK); - BlockSync(kvDelegatePtrS1_, OK, g_CloudSyncoption); - SetFlag(key, LogInfoFlag::FLAG_CLOUD_WRITE); - std::this_thread::sleep_for(std::chrono::milliseconds(100)); // sleep for 100ms - } -} - -/** - * @tc.name: RemoveDeviceTest001 - * @tc.desc: remove all log table record with empty deviceId and FLAG_ONLY flag - * @tc.type: FUNC - * @tc.require: - * @tc.author: mazhao - */ -HWTEST_F(DistributedDBCloudKvTest, RemoveDeviceTest001, TestSize.Level0) -{ - /** - * @tc.steps: step1. Insert three record (Key:k0, device:0, userId:user0), (Key:k1, device:1, userId:user0), - * (Key:k2, device:2, userId:0) - * * @tc.expected: step1. insert successfully - */ - int recordNum = 3; - InsertRecord(recordNum); - for (int i = 0; i < recordNum; i++) { - Key key; - key.push_back('k'); - key.push_back('0' + i); - SetFlag(key, LogInfoFlag::FLAG_CLOUD_WRITE); - SetDeviceId(key, std::to_string(i)); - std::this_thread::sleep_for(std::chrono::milliseconds(100)); // sleep for 100ms - } - /** - * @tc.steps: step2. Check three Log record whether exist or not; - * * @tc.expected: step2. record exist - */ - for (int i = 0; i < recordNum; i++) { - Key key; - key.push_back('k'); - key.push_back('0' + i); - Value actualValue; - EXPECT_EQ(kvDelegatePtrS1_->Get(key, actualValue), OK); - std::string deviceId = std::to_string(i); - EXPECT_EQ(CheckLogTable(deviceId), OK); - EXPECT_EQ(CheckFlag(key, LogInfoFlag::FLAG_CLOUD_WRITE), OK); - EXPECT_EQ(CheckWaterMark(""), OK); - } - /** - * @tc.steps: step3. remove log data with empty deviceId. - * * @tc.expected: step3. remove OK, there are not user record exist in log table. - */ - EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData("", ClearMode::FLAG_ONLY), OK); - for (int i = 0; i < recordNum; i++) { - Key key; - key.push_back('k'); - key.push_back('0' + i); - Value actualValue; - EXPECT_EQ(kvDelegatePtrS1_->Get(key, actualValue), OK); - std::string deviceId = std::to_string(i); - EXPECT_EQ(CheckLogTable(deviceId), NOT_FOUND); - EXPECT_EQ(CheckFlag(key, LogInfoFlag::FLAG_LOCAL), OK); - EXPECT_EQ(CheckWaterMark(""), NOT_FOUND); - } -} - -/** - * @tc.name: RemoveDeviceTest002 - * @tc.desc: remove all record with empty deviceId and FLAG_AND_DATA flag - * @tc.type: FUNC - * @tc.require: - * @tc.author: mazhao - */ -HWTEST_F(DistributedDBCloudKvTest, RemoveDeviceTest002, TestSize.Level0) -{ - /** - * @tc.steps: step1. Insert three record (Key:k0, device:0, userId:user0), (Key:k1, device:1, userId:user0), - * (Key:k2, device:2, userId:0) - * * @tc.expected: step1. insert successfully - */ - int recordNum = 3; - InsertRecord(recordNum); - for (int i = 0; i < recordNum; i++) { - Key key; - key.push_back('k'); - key.push_back('0' + i); - SetFlag(key, LogInfoFlag::FLAG_CLOUD_WRITE); - SetDeviceId(key, std::to_string(i)); - std::this_thread::sleep_for(std::chrono::milliseconds(100)); // sleep for 100ms - } - /** - * @tc.steps: step2. Check three Log record whether exist or not; - * * @tc.expected: step2. record exist - */ - for (int i = 0; i < recordNum; i++) { - Key key; - key.push_back('k'); - key.push_back('0' + i); - Value actualValue; - EXPECT_EQ(kvDelegatePtrS1_->Get(key, actualValue), OK); - std::string deviceId = std::to_string(i); - EXPECT_EQ(CheckLogTable(deviceId), OK); - EXPECT_EQ(CheckWaterMark(""), OK); - } - /** - * @tc.steps: step3. remove log data with empty deviceId. - * * @tc.expected: step3. remove OK, there are not user record exist in log table. - */ - EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData("", ClearMode::FLAG_AND_DATA), OK); - for (int i = 0; i < recordNum; i++) { - Key key; - key.push_back('k'); - key.push_back('0' + i); - Value actualValue; - EXPECT_EQ(kvDelegatePtrS1_->Get(key, actualValue), NOT_FOUND); - std::string deviceId = std::to_string(i); - EXPECT_EQ(CheckLogTable(deviceId), NOT_FOUND); - EXPECT_EQ(CheckWaterMark(""), NOT_FOUND); - } -} - -/** - * @tc.name: RemoveDeviceTest003 - * @tc.desc: remove record with deviceId - * @tc.type: FUNC - * @tc.require: - * @tc.author: mazhao - */ -HWTEST_F(DistributedDBCloudKvTest, RemoveDeviceTest003, TestSize.Level0) -{ - /** - * @tc.steps: step1. Insert three record (Key:k0, device:0, userId:user0), (Key:k1, device:1, userId:user0), - * (Key:k2, device:2, userId:0) - * * @tc.expected: step1. insert successfully - */ - int recordNum = 3; - InsertRecord(recordNum); - for (int i = 0; i < recordNum; i++) { - Key key; - key.push_back('k'); - key.push_back('0' + i); - SetFlag(key, LogInfoFlag::FLAG_CLOUD_WRITE); - SetDeviceId(key, std::to_string(i)); - std::this_thread::sleep_for(std::chrono::milliseconds(100)); // sleep for 100ms - } - /** - * @tc.steps: step2. Check three Log record whether exist or not; - * * @tc.expected: step2. record exist - */ - for (int i = 0; i < recordNum; i++) { - Key key; - key.push_back('k'); - key.push_back('0' + i); - Value actualValue; - EXPECT_EQ(kvDelegatePtrS1_->Get(key, actualValue), OK); - std::string deviceId = std::to_string(i); - EXPECT_EQ(CheckLogTable(deviceId), OK); - EXPECT_EQ(CheckFlag(key, LogInfoFlag::FLAG_CLOUD_WRITE), OK); // flag become 0x2; - EXPECT_EQ(CheckWaterMark(""), OK); - } - /** - * @tc.steps: step3. remove "2" deviceId log data with FLAG_AND_DATA, remove "1" with FLAG_ONLY. - * * @tc.expected: step3. remove OK - */ - EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData("1", ClearMode::FLAG_ONLY), OK); - EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData("2", ClearMode::FLAG_AND_DATA), OK); - Key key1({'k', '1'}); - std::string deviceId1 = "1"; - Value actualValue; - EXPECT_EQ(kvDelegatePtrS1_->Get(key1, actualValue), OK); - EXPECT_EQ(CheckLogTable(deviceId1), NOT_FOUND); - EXPECT_EQ(CheckFlag(key1, LogInfoFlag::FLAG_LOCAL), OK); // flag become 0x2; - Key key2({'k', '2'}); - std::string deviceId2 = "2"; - EXPECT_EQ(kvDelegatePtrS1_->Get(key2, actualValue), NOT_FOUND); - EXPECT_EQ(CheckLogTable(deviceId2), NOT_FOUND); - EXPECT_EQ(CheckWaterMark(""), NOT_FOUND); -} - -/** - * @tc.name: RemoveDeviceTest004 - * @tc.desc: remove all record with userId and empty deviceId. - * @tc.type: FUNC - * @tc.require: - * @tc.author: mazhao - */ -HWTEST_F(DistributedDBCloudKvTest, RemoveDeviceTest004, TestSize.Level0) -{ - /** - * @tc.steps: step1. Insert three record (Key:k0, device:0, userId:user0), (Key:k1, device:1, userId:user1), - * (Key:k2, device:2, userId:2) - * * @tc.expected: step1. insert successfully - */ - int recordNum = 3; - std::string userHead = "user"; - InsertRecord(recordNum); - for (int i = 0; i < recordNum; i++) { - Key key; - key.push_back('k'); - key.push_back('0' + i); - SetFlag(key, LogInfoFlag::FLAG_CLOUD_WRITE); - SetDeviceId(key, std::to_string(i)); - ChangeUserId(std::to_string(i), userHead + std::to_string(i)); - std::this_thread::sleep_for(std::chrono::milliseconds(100)); // sleep for 100ms - EXPECT_EQ(CheckFlag(key, LogInfoFlag::FLAG_CLOUD_WRITE), OK); - } - EXPECT_EQ(CheckWaterMark(userHead + "0"), OK); - /** - * @tc.steps: step2. Check three Log record whether exist or not; - * * @tc.expected: step2. record exist - */ - for (int i = 0; i < recordNum; i++) { - Key key; - key.push_back('k'); - key.push_back('0' + i); - Value actualValue; - EXPECT_EQ(kvDelegatePtrS1_->Get(key, actualValue), OK); - std::string deviceId = std::to_string(i); - EXPECT_EQ(CheckLogTable(deviceId), OK); - } + communicatorAggregator_->SetLocalDeviceId("DEVICES_A"); + ASSERT_EQ(kvDelegatePtrS1_->Delete(key2), OK); + BlockSync(kvDelegatePtrS1_, OK, g_CloudSyncoption); /** - * @tc.steps: step3. remove "user1" userid log data with FLAG_AND_DATA, remove "user2" userid with FLAG_ONLY. - * * @tc.expected: step3. remove OK - */ - EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData("", "user0", ClearMode::FLAG_ONLY), OK); - EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData("", "user2", ClearMode::FLAG_AND_DATA), OK); - Key key0({'k', '0'}); - std::string deviceId1 = "0"; - Value actualValue; - EXPECT_EQ(kvDelegatePtrS1_->Get(key0, actualValue), OK); - EXPECT_EQ(CheckLogTable(deviceId1), NOT_FOUND); - EXPECT_EQ(CheckFlag(key0, LogInfoFlag::FLAG_LOCAL), OK); // flag become 0x2; - EXPECT_EQ(CheckWaterMark(userHead + "0"), NOT_FOUND); - Key key2({'k', '2'}); - std::string deviceId2 = "2"; - EXPECT_EQ(kvDelegatePtrS1_->Get(key2, actualValue), NOT_FOUND); - EXPECT_EQ(CheckLogTable(deviceId2), NOT_FOUND); + * @tc.steps:step4. deviceB sync to cloud. + * @tc.expected: step4. ok. + */ + communicatorAggregator_->SetLocalDeviceId("DEVICES_B"); + BlockSync(kvDelegatePtrS2_, OK, g_CloudSyncoption); + actualValue1.clear(); + EXPECT_EQ(kvDelegatePtrS2_->Get(key1, actualValue1), OK); + EXPECT_EQ(actualValue1, expectValue1); + actualValue2.clear(); + EXPECT_EQ(kvDelegatePtrS2_->Get(key2, actualValue2), NOT_FOUND); + EXPECT_NE(actualValue2, expectValue2); } /** - * @tc.name: RemoveDeviceTest005 - * @tc.desc: remove record with userId and deviceId. + * @tc.name: NormalSync040 + * @tc.desc: test update sync data while local and cloud record device is different and not local device. * @tc.type: FUNC * @tc.require: - * @tc.author: mazhao + * @tc.author: caihaoting */ -HWTEST_F(DistributedDBCloudKvTest, RemoveDeviceTest005, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync040, TestSize.Level0) { /** - * @tc.steps: step1. Insert three record (Key:k0, device:0, userId:user0), (Key:k1, device:1, userId:user1), - * (Key:k2, device:2, userId:2) - * * @tc.expected: step1. insert successfully - */ - int recordNum = 3; - InsertRecord(recordNum); - std::string userHead = "user"; - for (int i = 0; i < recordNum; i++) { - Key key; - key.push_back('k'); - key.push_back('0' + i); - SetFlag(key, LogInfoFlag::FLAG_CLOUD_WRITE); - SetDeviceId(key, std::to_string(i)); - ChangeUserId(std::to_string(i), userHead + std::to_string(i)); - std::this_thread::sleep_for(std::chrono::milliseconds(100)); // sleep for 100ms - } - EXPECT_EQ(CheckWaterMark(userHead + "0"), OK); - /** - * @tc.steps: step2. Check three Log record whether exist or not; - * * @tc.expected: step2. record exist - */ - for (int i = 0; i < recordNum; i++) { - Key key; - key.push_back('k'); - key.push_back('0' + i); - Value actualValue; - EXPECT_EQ(kvDelegatePtrS1_->Get(key, actualValue), OK); - std::string deviceId = std::to_string(i); - EXPECT_EQ(CheckLogTable(deviceId), OK); - EXPECT_EQ(CheckFlag(key, LogInfoFlag::FLAG_CLOUD_WRITE), OK); - } - /** - * @tc.steps: step3. remove "user1" userid log data with FLAG_AND_DATA, remove "user0" userid with FLAG_ONLY. - * remove "user2" userid log data with dismatch deviceId, it cant not remove the data. - * * @tc.expected: step3. remove OK - */ - std::string deviceId0 = "0"; - std::string deviceId1 = "1"; - std::string deviceId2 = "2"; - EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(deviceId0, "user0", ClearMode::FLAG_ONLY), OK); - EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(deviceId1, "user1", ClearMode::FLAG_AND_DATA), OK); - EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(deviceId0, "user2", ClearMode::FLAG_AND_DATA), OK); - EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(deviceId0, "user2", ClearMode::FLAG_ONLY), OK); - Key key0({'k', '0'}); - Value actualValue; - EXPECT_EQ(kvDelegatePtrS1_->Get(key0, actualValue), OK); - EXPECT_EQ(CheckLogTable(deviceId0), NOT_FOUND); - EXPECT_EQ(CheckFlag(key0, LogInfoFlag::FLAG_LOCAL), OK); // flag become 0x2; - EXPECT_EQ(CheckWaterMark(userHead + "0"), NOT_FOUND); - Key key1({'k', '1'}); - EXPECT_EQ(kvDelegatePtrS1_->Get(key1, actualValue), NOT_FOUND); - EXPECT_EQ(CheckLogTable(deviceId1), NOT_FOUND); - Key key2({'k', '2'});; - EXPECT_EQ(kvDelegatePtrS1_->Get(key2, actualValue), OK); - EXPECT_EQ(CheckLogTable(deviceId2), OK); -} - -/** - * @tc.name: RemoveDeviceTest006 - * @tc.desc: remove record with userId and deviceId, and there are same hashKey record in log table. - * @tc.type: FUNC - * @tc.require: - * @tc.author: mazhao - */ -HWTEST_F(DistributedDBCloudKvTest, RemoveDeviceTest006, TestSize.Level0) -{ + * @tc.steps:step1. deviceA put {k1, v1} and sync to cloud. + * @tc.expected: step1. ok. + */ + communicatorAggregator_->SetLocalDeviceId("DEVICES_A"); + Key key = {'k', '1'}; + Value expectValue1 = {'v', '1'}; + ASSERT_EQ(kvDelegatePtrS1_->Put(key, expectValue1), OK); + BlockSync(kvDelegatePtrS1_, OK, g_CloudSyncoption); /** - * @tc.steps: step1. Insert three record (Key:k0, device:0, userId:user0), (Key:k1, device:1, userId:user1), - * (Key:k2, device:2, userId:2) - * * @tc.expected: step1. insert successfully - */ - int recordNum = 3; - InsertRecord(recordNum); - std::string userHead = "user"; - for (int i = 0; i < recordNum; i++) { - Key key; - key.push_back('k'); - key.push_back('0' + i); - SetFlag(key, LogInfoFlag::FLAG_CLOUD_WRITE); - SetDeviceId(key, std::to_string(i)); - ChangeUserId(std::to_string(i), userHead + std::to_string(i)); - std::this_thread::sleep_for(std::chrono::milliseconds(100)); // sleep for 100ms - } + * @tc.steps:step2. deviceB sync to cloud. + * @tc.expected: step2. ok. + */ + communicatorAggregator_->SetLocalDeviceId("DEVICES_B"); + BlockSync(kvDelegatePtrS2_, OK, g_CloudSyncoption); + Value actualValue1; + EXPECT_EQ(kvDelegatePtrS2_->Get(key, actualValue1), OK); + EXPECT_EQ(actualValue1, expectValue1); /** - * @tc.steps: step2. Check three Log record whether exist or not; - * * @tc.expected: step2. record exist - */ - for (int i = 0; i < recordNum; i++) { - Key key; - key.push_back('k'); - key.push_back('0' + i); - Value actualValue; - EXPECT_EQ(kvDelegatePtrS1_->Get(key, actualValue), OK); - std::string deviceId = std::to_string(i); - EXPECT_EQ(CheckLogTable(deviceId), OK); - } + * @tc.steps:step3. deviceA put {k1, v2} and sync to cloud. + * @tc.expected: step3. ok. + */ + communicatorAggregator_->SetLocalDeviceId("DEVICES_A"); + Value expectValue2 = {'v', '2'}; + ASSERT_EQ(kvDelegatePtrS1_->Put(key, expectValue2), OK); + BlockSync(kvDelegatePtrS1_, OK, g_CloudSyncoption); /** - * @tc.steps: step3. Make log table all users's hashKey become same hashKey '99', and the hashKey in syncTable - * where device is deviceId1 also become '99',remove data with FLAG_AND_DATA flag. - * * @tc.expected: step3. remove OK - */ - std::string deviceId1 = "1"; - std::string deviceId2 = "2"; - std::string deviceId0 = "0"; - DistributedDBCloudKvTest::ChangeHashKey(deviceId1); - EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(deviceId1, "user1", ClearMode::FLAG_AND_DATA), OK); - Key key1({'k', '1'}); - Value actualValue; - // there are other users with same hash_key connect with this data in sync_data table, cant not remove the data. - EXPECT_EQ(kvDelegatePtrS1_->Get(key1, actualValue), OK); - EXPECT_EQ(CheckLogTable(deviceId1), OK); // match user2 and user0; - EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(deviceId1, "user2", ClearMode::FLAG_AND_DATA), OK); - EXPECT_EQ(kvDelegatePtrS1_->Get(key1, actualValue), OK); - EXPECT_EQ(CheckLogTable(deviceId1), OK); // only user0 match the hash_key that same as device1. - EXPECT_EQ(CheckFlag(key1, LogInfoFlag::FLAG_CLOUD_WRITE), OK); // flag still 0x100; - EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(deviceId1, "user0", ClearMode::FLAG_AND_DATA), OK); - // all log have been deleted, so data would also be deleted. - EXPECT_EQ(kvDelegatePtrS1_->Get(key1, actualValue), NOT_FOUND); - EXPECT_EQ(CheckLogTable(deviceId1), NOT_FOUND); - EXPECT_EQ(CheckWaterMark(userHead + "0"), NOT_FOUND); + * @tc.steps:step4. deviceB put {k1, v3} sync to cloud. + * @tc.expected: step4. ok. + */ + communicatorAggregator_->SetLocalDeviceId("DEVICES_B"); + Value expectValue3 = {'v', '3'}; + ASSERT_EQ(kvDelegatePtrS2_->Put(key, expectValue3), OK); + BlockSync(kvDelegatePtrS2_, OK, g_CloudSyncoption); + Value actualValue2; + EXPECT_EQ(kvDelegatePtrS2_->Get(key, actualValue2), OK); + EXPECT_NE(actualValue2, expectValue2); + EXPECT_EQ(actualValue2, expectValue3); } /** - * @tc.name: RemoveDeviceTest007 - * @tc.desc: remove record with invalid deviceId and mode. + * @tc.name: NormalSync041 + * @tc.desc: Test concurrent sync and close DB. * @tc.type: FUNC * @tc.require: - * @tc.author: mazhao + * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudKvTest, RemoveDeviceTest007, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync041, TestSize.Level1) { /** - * @tc.steps: step1. Test removeDeviceData with invalid length deviceId. - * * @tc.expected: - */ - std::string deviceId = std::string(128, 'a'); - EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(deviceId, ClearMode::FLAG_AND_DATA), OK); - EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(deviceId, "user1", ClearMode::FLAG_AND_DATA), OK); - - std::string invaliDeviceId = std::string(129, 'a'); - EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(invaliDeviceId, ClearMode::FLAG_AND_DATA), INVALID_ARGS); - EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(invaliDeviceId, "user1", ClearMode::FLAG_AND_DATA), INVALID_ARGS); - - /** - * @tc.steps: step2. Test removeDeviceData with invalid mode. - * * @tc.expected: - */ - EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(deviceId, ClearMode::CLEAR_SHARED_TABLE), NOT_SUPPORT); - EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(deviceId, "user1", ClearMode::CLEAR_SHARED_TABLE), NOT_SUPPORT); -} + * @tc.steps:step1. put data to cloud. + * @tc.expected: step1 ok. + */ + Key key = {'k', '1'}; + Value value = {'v', '1'}; + kvDelegatePtrS1_->Put(key, value); + BlockSync(kvDelegatePtrS1_, OK, g_CloudSyncoption); -/** - * @tc.name: RemoveDeviceTest008 - * @tc.desc: remove record without mode. - * @tc.type: FUNC - * @tc.require: - * @tc.author: liaoyonnghuang - */ -HWTEST_F(DistributedDBCloudKvTest, RemoveDeviceTest008, TestSize.Level0) -{ /** - * @tc.steps: step1. Insert three record (Key:k0, device:0, userId:user0), (Key:k1, device:1, userId:user1), - * (Key:k2, device:2, userId:2) - * * @tc.expected: step1. insert successfully - */ - int recordNum = 3; - InsertRecord(recordNum); - for (int i = 0; i < recordNum; i++) { - Key key; - key.push_back('k'); - key.push_back('0' + i); - SetFlag(key, LogInfoFlag::FLAG_CLOUD); - SetDeviceId(key, std::to_string(i)); + * @tc.steps:step2. sync and close DB concurrently. + * @tc.expected: step2 ok. + */ + KvStoreNbDelegate* kvDelegatePtrS3_ = nullptr; + KvStoreNbDelegate::Option option; + EXPECT_EQ(GetKvStore(kvDelegatePtrS3_, STORE_ID_3, option), OK); + virtualCloudDb_->ForkQuery([](const std::string &tableName, VBucket &extend) { + std::this_thread::sleep_for(std::chrono::milliseconds(200)); // sleep for 200ms + }); + KvStoreDelegateManager &mgr = g_mgr; + std::thread syncThread([&mgr, &kvDelegatePtrS3_]() { std::this_thread::sleep_for(std::chrono::milliseconds(100)); // sleep for 100ms - } - - /** - * @tc.steps: step2. Check three Log record whether exist or not; - * * @tc.expected: step2. record exist - */ - for (int i = 0; i < recordNum; i++) { - Key key; - key.push_back('k'); - key.push_back('0' + i); - Value actualValue; - EXPECT_EQ(kvDelegatePtrS1_->Get(key, actualValue), OK); - } - /** - * @tc.steps: step3. Remove data without mode. - * * @tc.expected: step3. remove OK, there are not user record exist in log table. - */ - for (int i = 0; i < recordNum; i++) { - EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(std::to_string(i)), OK); - } - for (int i = 0; i < recordNum; i++) { - Key key; - key.push_back('k'); - key.push_back('0' + i); - Value actualValue; - EXPECT_EQ(kvDelegatePtrS1_->Get(key, actualValue), NOT_FOUND); - } + EXPECT_EQ(mgr.CloseKvStore(kvDelegatePtrS3_), OK); + }); + EXPECT_EQ(kvDelegatePtrS3_->Sync(g_CloudSyncoption, nullptr), OK); + syncThread.join(); } /** - * @tc.name: RemoveDeviceTest009 - * @tc.desc: remove record without mode FLAG_AND_DATA. + * @tc.name: NormalSync042 + * @tc.desc: Test some record upload fail in 1 batch and get cloud version successfully. * @tc.type: FUNC * @tc.require: - * @tc.author: liaoyonnghuang + * @tc.author: caihaoting */ -HWTEST_F(DistributedDBCloudKvTest, RemoveDeviceTest009, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync042, TestSize.Level0) { /** - * @tc.steps: step1. Insert three record (Key:k0, device:0, userId:user0), (Key:k1, device:1, userId:user1), - * (Key:k2, device:2, userId:2) - * * @tc.expected: step1. insert successfully - */ - int recordNum = 3; - InsertRecord(recordNum); - for (int i = 0; i < recordNum; i++) { - Key key; - key.push_back('k'); - key.push_back('0' + i); - SetFlag(key, LogInfoFlag::FLAG_CLOUD); - SetDeviceId(key, std::to_string(i)); - std::this_thread::sleep_for(std::chrono::milliseconds(100)); // sleep for 100ms - } - - /** - * @tc.steps: step2. Check three Log record whether exist or not; - * * @tc.expected: step2. record exist - */ - for (int i = 0; i < recordNum; i++) { - Key key; - key.push_back('k'); - key.push_back('0' + i); - Value actualValue; - EXPECT_EQ(kvDelegatePtrS1_->Get(key, actualValue), OK); - std::string deviceId = std::to_string(i); - EXPECT_EQ(CheckLogTable(deviceId), OK); + * @tc.steps:step1. put 10 records. + * @tc.expected: step1 ok. + */ + vector entries; + int count = 10; // put 10 records. + for (int i = 0; i < count; i++) { + std::string keyStr = "k_" + std::to_string(i); + std::string valueStr = "v_" + std::to_string(i); + Key key(keyStr.begin(), keyStr.end()); + Value value(valueStr.begin(), valueStr.end()); + entries.push_back({key, value}); } + EXPECT_EQ(kvDelegatePtrS1_->PutBatch(entries), OK); + kvDelegatePtrS1_->SetGenCloudVersionCallback([](const std::string &origin) { + LOGW("origin is %s", origin.c_str()); + return origin + "1"; + }); /** - * @tc.steps: step3. Remove data without mode FLAG_AND_DATA. - * * @tc.expected: step3. remove OK, there are not user record exist in log table. - */ - for (int i = 0; i < recordNum; i++) { - EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(std::to_string(i), ClearMode::FLAG_AND_DATA), OK); - } - for (int i = 0; i < recordNum; i++) { - Key key; - key.push_back('k'); - key.push_back('0' + i); - Value actualValue; - EXPECT_EQ(kvDelegatePtrS1_->Get(key, actualValue), OK); - std::string deviceId = std::to_string(i); - EXPECT_EQ(CheckLogTable(deviceId), NOT_FOUND); - } -} - -/** - * @tc.name: RemoveDeviceTest010 - * @tc.desc: remove record with invalid mode. - * @tc.type: FUNC - * @tc.require: - * @tc.author: zhangqiquan - */ -HWTEST_F(DistributedDBCloudKvTest, RemoveDeviceTest010, TestSize.Level0) -{ - std::string deviceId = std::string(128, 'a'); - EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(deviceId, "", ClearMode::FLAG_ONLY), INVALID_ARGS); - EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(deviceId, "", ClearMode::CLEAR_SHARED_TABLE), INVALID_ARGS); - EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(deviceId, "", ClearMode::FLAG_AND_DATA), INVALID_ARGS); - EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(deviceId, "", ClearMode::DEFAULT), OK); - EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData("", "", ClearMode::DEFAULT), OK); - EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData("", ClearMode::DEFAULT), OK); -} - -/** - * @tc.name: RemoveDeviceTest011 - * @tc.desc: remove record while conn is nullptr. - * @tc.type: FUNC - * @tc.require: - * @tc.author: caihaoting - */ -HWTEST_F(DistributedDBCloudKvTest, RemoveDeviceTest011, TestSize.Level0) -{ - const KvStoreNbDelegate::Option option = {true, true}; - KvStoreNbDelegate *kvDelegateInvalidPtrS1_ = nullptr; - ASSERT_EQ(GetKvStore(kvDelegateInvalidPtrS1_, "RemoveDeviceTest011", option), OK); - ASSERT_NE(kvDelegateInvalidPtrS1_, nullptr); - auto kvStoreImpl = static_cast(kvDelegateInvalidPtrS1_); - EXPECT_EQ(kvStoreImpl->Close(), OK); - EXPECT_EQ(kvDelegateInvalidPtrS1_->RemoveDeviceData("", ClearMode::FLAG_ONLY), DB_ERROR); - EXPECT_EQ(kvDelegateInvalidPtrS1_->RemoveDeviceData("", "", ClearMode::FLAG_ONLY), DB_ERROR); - EXPECT_EQ(g_mgr.CloseKvStore(kvDelegateInvalidPtrS1_), OK); -} - -/** - * @tc.name: RemoveDeviceTest012 - * @tc.desc: Test remove all data from other device. - * @tc.type: FUNC - * @tc.require: - * @tc.author: liaoyonghuang - */ -HWTEST_F(DistributedDBCloudKvTest, RemoveDeviceTest012, TestSize.Level0) -{ + * @tc.steps:step2. sync and set the last record upload fail. + * @tc.expected: step2 sync fail and upLoadInfo.failCount is 1. + */ + int uploadFailId = 0; + virtualCloudDb_->ForkInsertConflict([&uploadFailId](const std::string &tableName, VBucket &extend, VBucket &record, + std::vector &cloudDataVec) { + uploadFailId++; + if (uploadFailId == 10) { // 10 is the last record + extend[CloudDbConstant::ERROR_FIELD] = static_cast(DBStatus::CLOUD_ERROR); + return CLOUD_ERROR; + } + return OK; + }); + BlockSync(kvDelegatePtrS1_, CLOUD_ERROR, g_CloudSyncoption); + for (const auto &table : lastProcess_.tableProcess) { + EXPECT_EQ(table.second.upLoadInfo.total, 10u); + EXPECT_EQ(table.second.upLoadInfo.successCount, 9u); + EXPECT_EQ(table.second.upLoadInfo.insertCount, 9u); + EXPECT_EQ(table.second.upLoadInfo.failCount, 1u); + } /** - * @tc.steps: step1. Insert three record, k0 from device sync, k1 from local write, k2 from cloud sync. - * * @tc.expected: step1. insert successfully - */ - int recordNum = 3; - InsertRecord(recordNum); - SetFlag({'k', '0'}, LogInfoFlag::FLAG_CLOUD); - SetFlag({'k', '1'}, LogInfoFlag::FLAG_LOCAL); - /** - * @tc.steps: step2. Remove data from device sync and cloud sync, and remove log. - * * @tc.expected: step2. All data and log are removed except data from local write. - */ - EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(), OK); - Value actualValue; - Value expectValue = {'k', '1'}; - EXPECT_EQ(kvDelegatePtrS1_->Get({'k', '1'}, actualValue), OK); - EXPECT_EQ(actualValue, expectValue); - EXPECT_EQ(kvDelegatePtrS1_->Get({'k', '0'}, actualValue), NOT_FOUND); - EXPECT_EQ(kvDelegatePtrS1_->Get({'k', '2'}, actualValue), NOT_FOUND); + * @tc.steps:step3. get cloud version successfully. + * @tc.expected: step3 OK. + */ + auto result = kvDelegatePtrS1_->GetCloudVersion(""); + EXPECT_EQ(result.first, OK); + for (auto item : result.second) { + EXPECT_EQ(item.second, "1"); + } + kvDelegatePtrS1_->SetGenCloudVersionCallback(nullptr); + virtualCloudDb_->ForkUpload(nullptr); } /** - * @tc.name: NormalSyncInvalid001 - * @tc.desc: Test normal push not sync and get cloud version. + * @tc.name: NormalSync043 + * @tc.desc: Test some record upload fail in 1 batch and get cloud version failed. * @tc.type: FUNC * @tc.require: * @tc.author: caihaoting */ -HWTEST_F(DistributedDBCloudKvTest, NormalSyncInvalid001, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync043, TestSize.Level0) { - Key key = {'k'}; - Value expectValue = {'v'}; - ASSERT_EQ(kvDelegatePtrS1_->Put(key, expectValue), OK); + /** + * @tc.steps:step1. put 10 records. + * @tc.expected: step1 ok. + */ + vector entries; + int count = 10; // put 10 records. + for (int i = 0; i < count; i++) { + std::string keyStr = "k_" + std::to_string(i); + std::string valueStr = "v_" + std::to_string(i); + Key key(keyStr.begin(), keyStr.end()); + Value value(valueStr.begin(), valueStr.end()); + entries.push_back({key, value}); + } + EXPECT_EQ(kvDelegatePtrS1_->PutBatch(entries), OK); kvDelegatePtrS1_->SetGenCloudVersionCallback([](const std::string &origin) { LOGW("origin is %s", origin.c_str()); return origin + "1"; }); - Value actualValue; - EXPECT_EQ(kvDelegatePtrS1_->Get(key, actualValue), OK); - EXPECT_EQ(actualValue, expectValue); - kvDelegatePtrS1_->SetGenCloudVersionCallback(nullptr); + /** + * @tc.steps:step2. sync and set all record upload fail. + * @tc.expected: step2 sync fail and upLoadInfo.failCount is 10. + */ + virtualCloudDb_->ForkInsertConflict([](const std::string &tableName, VBucket &extend, VBucket &record, + std::vector &cloudDataVec) { + extend[CloudDbConstant::ERROR_FIELD] = static_cast(DBStatus::CLOUD_ERROR); + return CLOUD_ERROR; + }); + BlockSync(kvDelegatePtrS1_, CLOUD_ERROR, g_CloudSyncoption); + for (const auto &table : lastProcess_.tableProcess) { + EXPECT_EQ(table.second.upLoadInfo.total, 10u); + EXPECT_EQ(table.second.upLoadInfo.successCount, 0u); + EXPECT_EQ(table.second.upLoadInfo.insertCount, 0u); + EXPECT_EQ(table.second.upLoadInfo.failCount, 10u); + } + /** + * @tc.steps:step3. get cloud version failed. + * @tc.expected: step3 NOT_FOUND. + */ auto result = kvDelegatePtrS1_->GetCloudVersion(""); EXPECT_EQ(result.first, NOT_FOUND); + for (auto item : result.second) { + EXPECT_EQ(item.second, ""); + } + kvDelegatePtrS1_->SetGenCloudVersionCallback(nullptr); + virtualCloudDb_->ForkUpload(nullptr); } /** - * @tc.name: NormalSyncInvalid002 - * @tc.desc: Test normal push sync and use invalidDevice to get cloud version. + * @tc.name: NormalSync044 + * @tc.desc: Test RemoveDeviceData with FLAG_ONLY option * @tc.type: FUNC * @tc.require: - * @tc.author: caihaoting + * @tc.author: zhangtao */ -HWTEST_F(DistributedDBCloudKvTest, NormalSyncInvalid002, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync044, TestSize.Level0) { - Key key = {'k'}; - Value expectValue = {'v'}; - ASSERT_EQ(kvDelegatePtrS1_->Put(key, expectValue), OK); + /** + * @tc.steps:step1. store1 put (k1,v1) and (k2,v2) + * @tc.expected: step1. both put ok + */ + communicatorAggregator_->SetLocalDeviceId("DEVICES_A"); kvDelegatePtrS1_->SetGenCloudVersionCallback([](const std::string &origin) { LOGW("origin is %s", origin.c_str()); return origin + "1"; }); + Key key1 = {'k', '1'}; + Value expectValue1 = {'v', '1'}; + Key key2 = {'k', '2'}; + Value expectValue2 = {'v', '2'}; + ASSERT_EQ(kvDelegatePtrS1_->Put(key1, expectValue1), OK); + ASSERT_EQ(kvDelegatePtrS1_->Put(key2, expectValue2), OK); + /** + * @tc.steps: step2. DEVICE_A with store1 sync and DEVICE_B with store2 sync + * @tc.expected: step2. both sync ok, and store2 got (k1,v1) and (k2,v2) + */ BlockSync(kvDelegatePtrS1_, OK, g_CloudSyncoption); - for (const auto &table : lastProcess_.tableProcess) { - EXPECT_EQ(table.second.upLoadInfo.total, 1u); - EXPECT_EQ(table.second.upLoadInfo.insertCount, 1u); - } + LOGW("Store1 sync end"); + communicatorAggregator_->SetLocalDeviceId("DEVICES_B"); BlockSync(kvDelegatePtrS2_, OK, g_CloudSyncoption); - for (const auto &table : lastProcess_.tableProcess) { - EXPECT_EQ(table.second.downLoadInfo.total, 2u); // download 2 records - EXPECT_EQ(table.second.downLoadInfo.insertCount, 2u); // download 2 records - } + LOGW("Store2 sync end"); Value actualValue; - EXPECT_EQ(kvDelegatePtrS2_->Get(key, actualValue), OK); - EXPECT_EQ(actualValue, expectValue); + EXPECT_EQ(kvDelegatePtrS2_->Get(key1, actualValue), OK); + EXPECT_EQ(actualValue, expectValue1); + EXPECT_EQ(kvDelegatePtrS2_->Get(key2, actualValue), OK); + EXPECT_EQ(actualValue, expectValue2); + /** + * @tc.steps: step3. store2 RevoveDeviceData with FLAG_ONLY option + * @tc.expected: step3. store2 delete DEVICE_A's version CloudVersion data successfully + */ + auto result = kvDelegatePtrS2_->GetCloudVersion(""); + EXPECT_EQ(result.first, OK); + for (auto item : result.second) { + EXPECT_EQ(item.second, "1"); + } + EXPECT_EQ(kvDelegatePtrS2_->RemoveDeviceData("DEVICES_A", ClearMode::FLAG_ONLY), OK); kvDelegatePtrS1_->SetGenCloudVersionCallback(nullptr); - std::string invalidDevice = std::string(DBConstant::MAX_DEV_LENGTH + 1, '0'); - auto result = kvDelegatePtrS2_->GetCloudVersion(invalidDevice); - EXPECT_EQ(result.first, INVALID_ARGS); + result = kvDelegatePtrS2_->GetCloudVersion(""); + EXPECT_EQ(result.first, NOT_FOUND); + for (auto item : result.second) { + EXPECT_EQ(item.second, ""); + } } /** - * @tc.name: NormalSyncInvalid003 - * @tc.desc: Test normal push sync for add data while conn is nullptr. + * @tc.name: NormalSync045 + * @tc.desc: Test some record upload fail in 1 batch and extend size greater than record size * @tc.type: FUNC * @tc.require: - * @tc.author: caihaoting + * @tc.author: zhangtao */ -HWTEST_F(DistributedDBCloudKvTest, NormalSyncInvalid003, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync045, TestSize.Level0) { - const KvStoreNbDelegate::Option option = {true, true}; - KvStoreNbDelegate *kvDelegateInvalidPtrS1_ = nullptr; - ASSERT_EQ(GetKvStore(kvDelegateInvalidPtrS1_, "NormalSyncInvalid003", option), OK); - ASSERT_NE(kvDelegateInvalidPtrS1_, nullptr); - Key key = {'k'}; - Value expectValue = {'v'}; - ASSERT_EQ(kvDelegateInvalidPtrS1_->Put(key, expectValue), OK); - kvDelegateInvalidPtrS1_->SetGenCloudVersionCallback([](const std::string &origin) { - LOGW("origin is %s", origin.c_str()); - return origin + "1"; - }); - BlockSync(kvDelegateInvalidPtrS1_, OK, g_CloudSyncoption); + /** + * @tc.steps:step1. put 10 records. + * @tc.expected: step1 ok. + */ + vector entries; + int count = 10; // put 10 records. + for (int i = 0; i < count; i++) { + std::string keyStr = "k_" + std::to_string(i); + std::string valueStr = "v_" + std::to_string(i); + Key key(keyStr.begin(), keyStr.end()); + Value value(valueStr.begin(), valueStr.end()); + entries.push_back({key, value}); + } + EXPECT_EQ(kvDelegatePtrS1_->PutBatch(entries), OK); + /** + * @tc.steps:step2. sync and add one empty extend as result + * @tc.expected: step2 sync fail and upLoadInfo.failCount is 10. 1 batch failed. + */ + std::atomic missCount = -1; + virtualCloudDb_->SetClearExtend(missCount); + BlockSync(kvDelegatePtrS1_, CLOUD_ERROR, g_CloudSyncoption); for (const auto &table : lastProcess_.tableProcess) { - EXPECT_EQ(table.second.upLoadInfo.total, 1u); - EXPECT_EQ(table.second.upLoadInfo.insertCount, 1u); + EXPECT_EQ(table.second.upLoadInfo.total, 10u); + EXPECT_EQ(table.second.upLoadInfo.successCount, 0u); + EXPECT_EQ(table.second.upLoadInfo.insertCount, 0u); + EXPECT_EQ(table.second.upLoadInfo.failCount, 10u); } - Value actualValue; - EXPECT_EQ(kvDelegateInvalidPtrS1_->Get(key, actualValue), OK); - EXPECT_EQ(actualValue, expectValue); - auto kvStoreImpl = static_cast(kvDelegateInvalidPtrS1_); - EXPECT_EQ(kvStoreImpl->Close(), OK); - kvDelegateInvalidPtrS1_->SetGenCloudVersionCallback(nullptr); - auto result = kvDelegateInvalidPtrS1_->GetCloudVersion(""); - EXPECT_EQ(result.first, DB_ERROR); - EXPECT_EQ(g_mgr.CloseKvStore(kvDelegateInvalidPtrS1_), OK); + virtualCloudDb_->ForkUpload(nullptr); } /** - * @tc.name: NormalSyncInvalid004 - * @tc.desc: Test normal push sync use GetDeviceEntries while conn is nullptr. + * @tc.name: NormalSync046 + * @tc.desc: Test RemoveDeviceData with FLAG_ONLY option and empty deviceName * @tc.type: FUNC * @tc.require: - * @tc.author: caihaoting + * @tc.author: chenghuitao */ -HWTEST_F(DistributedDBCloudKvTest, NormalSyncInvalid004, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync046, TestSize.Level0) { - const KvStoreNbDelegate::Option option = {true, true}; - KvStoreNbDelegate *kvDelegateInvalidPtrS2_ = nullptr; - ASSERT_EQ(GetKvStore(kvDelegateInvalidPtrS2_, "NormalSyncInvalid004", option), OK); - ASSERT_NE(kvDelegateInvalidPtrS2_, nullptr); /** - * @tc.steps: step1. store1 put (k1,v1) store2 put (k2,v2) + * @tc.steps:step1. store1 put (k1,v1) and (k2,v2) * @tc.expected: step1. both put ok */ communicatorAggregator_->SetLocalDeviceId("DEVICES_A"); @@ -2432,171 +2083,194 @@ HWTEST_F(DistributedDBCloudKvTest, NormalSyncInvalid004, TestSize.Level0) LOGW("origin is %s", origin.c_str()); return origin + "1"; }); - kvDelegateInvalidPtrS2_->SetGenCloudVersionCallback([](const std::string &origin) { - LOGW("origin is %s", origin.c_str()); - return origin + "1"; - }); Key key1 = {'k', '1'}; Value expectValue1 = {'v', '1'}; Key key2 = {'k', '2'}; Value expectValue2 = {'v', '2'}; ASSERT_EQ(kvDelegatePtrS1_->Put(key1, expectValue1), OK); - ASSERT_EQ(kvDelegateInvalidPtrS2_->Put(key2, expectValue2), OK); + ASSERT_EQ(kvDelegatePtrS1_->Put(key2, expectValue2), OK); /** - * @tc.steps: step2. both store1 and store2 sync while conn is nullptr - * @tc.expected: step2. both sync ok, and store2 got (k1,v1) store1 not exist (k2,v2) + * @tc.steps: step2. DEVICE_A with store1 sync and DEVICE_B with store2 sync + * @tc.expected: step2. both sync ok, and store2 got (k1,v1) and (k2,v2) */ BlockSync(kvDelegatePtrS1_, OK, g_CloudSyncoption); LOGW("Store1 sync end"); communicatorAggregator_->SetLocalDeviceId("DEVICES_B"); - BlockSync(kvDelegateInvalidPtrS2_, OK, g_CloudSyncoption); + BlockSync(kvDelegatePtrS2_, OK, g_CloudSyncoption); LOGW("Store2 sync end"); Value actualValue; - EXPECT_EQ(kvDelegateInvalidPtrS2_->Get(key1, actualValue), OK); - + EXPECT_EQ(kvDelegatePtrS2_->Get(key1, actualValue), OK); + EXPECT_EQ(actualValue, expectValue1); + EXPECT_EQ(kvDelegatePtrS2_->Get(key2, actualValue), OK); + EXPECT_EQ(actualValue, expectValue2); /** - * @tc.steps: step3. use GetDeviceEntries while conn is nullptr - * @tc.expected: step3. DB_ERROR + * @tc.steps: step3. store2 RevoveDeviceData with FLAG_ONLY option + * @tc.expected: step3. store2 delete DEVICE_A's version CloudVersion data successfully */ - auto kvStoreImpl = static_cast(kvDelegateInvalidPtrS2_); - EXPECT_EQ(kvStoreImpl->Close(), OK); - std::vector entries; - EXPECT_EQ(kvDelegateInvalidPtrS2_->GetDeviceEntries(std::string("DEVICES_A"), entries), DB_ERROR); - EXPECT_EQ(entries.size(), 0u); // 1 record - communicatorAggregator_->SetLocalDeviceId("DEVICES_A"); - EXPECT_EQ(actualValue, expectValue1); - EXPECT_EQ(kvDelegatePtrS1_->Get(key2, actualValue), NOT_FOUND); - + auto result = kvDelegatePtrS2_->GetCloudVersion(""); + EXPECT_EQ(result.first, OK); + for (auto item : result.second) { + EXPECT_EQ(item.second, "1"); + } + EXPECT_EQ(kvDelegatePtrS2_->RemoveDeviceData("", ClearMode::FLAG_ONLY), OK); kvDelegatePtrS1_->SetGenCloudVersionCallback(nullptr); - kvDelegateInvalidPtrS2_->SetGenCloudVersionCallback(nullptr); - EXPECT_EQ(g_mgr.CloseKvStore(kvDelegateInvalidPtrS2_), OK); + result = kvDelegatePtrS2_->GetCloudVersion(""); + EXPECT_EQ(result.first, NOT_FOUND); + for (auto item : result.second) { + EXPECT_EQ(item.second, ""); + } } /** - * @tc.name: NormalSyncInvalid005 - * @tc.desc: Test normal sync with invalid parm. + * @tc.name: NormalSync047 + * @tc.desc: Test multi users sync when user1 sync fail. * @tc.type: FUNC * @tc.require: - * @tc.author: caihaoting + * @tc.author: suyue */ -HWTEST_F(DistributedDBCloudKvTest, NormalSyncInvalid005, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync047, TestSize.Level0) { - Key key = {'k'}; - Value expectValue = {'v'}; - ASSERT_EQ(kvDelegatePtrS1_->Put(key, expectValue), OK); - auto devices = g_CloudSyncoption.devices; - EXPECT_EQ(kvDelegatePtrS1_->Sync(devices, SyncMode::SYNC_MODE_CLOUD_MERGE, nullptr), NOT_SUPPORT); - Query query = Query::Select().Range({}, {}); - EXPECT_EQ(kvDelegatePtrS1_->Sync(devices, SyncMode::SYNC_MODE_CLOUD_MERGE, nullptr, query, true), NOT_SUPPORT); - auto mode = g_CloudSyncoption.mode; - EXPECT_EQ(kvDelegatePtrS1_->Sync(devices, mode, nullptr, query, true), NOT_SUPPORT); - auto kvStoreImpl = static_cast(kvDelegatePtrS1_); - EXPECT_EQ(kvStoreImpl->Close(), OK); - BlockSync(kvDelegatePtrS1_, OK, g_CloudSyncoption, DB_ERROR); - EXPECT_EQ(kvDelegatePtrS1_->Sync(devices, mode, nullptr), DB_ERROR); - EXPECT_EQ(kvDelegatePtrS1_->Sync(devices, mode, nullptr, query, true), DB_ERROR); + /** + * @tc.steps: step1. put 20 records. + * @tc.expected: step1. ok. + */ + vector entries; + int count = 20; // put 20 records. + for (int i = 0; i < count; i++) { + std::string keyStr = "k_" + std::to_string(i); + std::string valueStr = "v_" + std::to_string(i); + Key key(keyStr.begin(), keyStr.end()); + Value value(valueStr.begin(), valueStr.end()); + entries.push_back({key, value}); + } + EXPECT_EQ(kvDelegatePtrS1_->PutBatch(entries), OK); + + /** + * @tc.steps: step2. multi users sync and set user1 fail. + * @tc.expected: step2. user1 sync fail and other user sync success. + */ + int uploadFailId = 0; + virtualCloudDb_->ForkInsertConflict([&uploadFailId](const std::string &tableName, VBucket &extend, VBucket &record, + vector &cloudDataVec) { + uploadFailId++; + if (uploadFailId > 15) { // the first 15 records success + extend[CloudDbConstant::ERROR_FIELD] = static_cast(DBStatus::CLOUD_ERROR); + return CLOUD_ERROR; + } + return OK; + }); + CloudSyncOption option; + option.mode = SyncMode::SYNC_MODE_CLOUD_FORCE_PUSH; + option.users.push_back(USER_ID); + option.users.push_back(USER_ID_2); + option.devices.push_back("cloud"); + SyncAndGetProcessInfo(kvDelegatePtrS1_, option); + + vector userStatus = {CLOUD_ERROR, OK}; + vector userExpectInfo = {{1u, 20u, 15u, 5u, 15u, 0u, 0u}, {1u, 20u, 20u, 0u, 20u, 0u, 0u}}; + EXPECT_TRUE(CheckUserSyncInfo(option.users, userStatus, userExpectInfo)); + virtualCloudDb_->ForkUpload(nullptr); } /** - * @tc.name: NormalSyncInvalid006 - * @tc.desc: Test normal sync set cloudDB while cloudDB is empty and conn is nullptr. + * @tc.name: NormalSync048 + * @tc.desc: test sync data while cloud delete on record and local do not have this record. * @tc.type: FUNC * @tc.require: - * @tc.author: caihaoting + * @tc.author: tankaisheng */ -HWTEST_F(DistributedDBCloudKvTest, NormalSyncInvalid006, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync048, TestSize.Level0) { /** - * @tc.steps: step1. set cloudDB while cloudDB is empty - * @tc.expected: step1. INVALID_ARGS + * @tc.steps: step1. deviceB put {k1, v1} {k2, v2} and sync to cloud + * @tc.expected: step1. ok. */ - std::map> cloudDbs; - EXPECT_EQ(kvDelegatePtrS1_->SetCloudDB(cloudDbs), INVALID_ARGS); + communicatorAggregator_->SetLocalDeviceId("DEVICES_B"); + Key key1 = {'k', '1'}; + Value expectValue1 = {'v', '1'}; + Key key2 = {'k', '2'}; + Value expectValue2 = {'v', '2'}; + ASSERT_EQ(kvDelegatePtrS1_->Put(key1, expectValue1), OK); + ASSERT_EQ(kvDelegatePtrS1_->Put(key2, expectValue2), OK); + BlockSync(kvDelegatePtrS1_, OK, g_CloudSyncoption); + /** - * @tc.steps: step2. set cloudDB while conn is nullptr - * @tc.expected: step2. DB_ERROR + * @tc.steps: step2. deviceB delete {k1, v1} and sync to cloud + * @tc.expected: step2. ok. */ - auto kvStoreImpl = static_cast(kvDelegatePtrS1_); - EXPECT_EQ(kvStoreImpl->Close(), OK); - cloudDbs[USER_ID] = virtualCloudDb_; - EXPECT_EQ(kvDelegatePtrS1_->SetCloudDB(cloudDbs), DB_ERROR); -} + communicatorAggregator_->SetLocalDeviceId("DEVICES_B"); + ASSERT_EQ(kvDelegatePtrS1_->Delete(key1), OK); + BlockSync(kvDelegatePtrS1_, OK, g_CloudSyncoption); -/** - * @tc.name: NormalSyncInvalid007 - * @tc.desc: Test normal sync set cloudDb schema while conn is nullptr. - * @tc.type: FUNC - * @tc.require: - * @tc.author: caihaoting - */ -HWTEST_F(DistributedDBCloudKvTest, NormalSyncInvalid007, TestSize.Level0) -{ /** - * @tc.steps: step1. set cloudDB schema while conn is nullptr - * @tc.expected: step1. DB_ERROR + * @tc.steps: step3. deviceA sync to cloud + * @tc.expected: step3. ok. */ - auto kvStoreImpl = static_cast(kvDelegatePtrS1_); - EXPECT_EQ(kvStoreImpl->Close(), OK); - std::map schemas; - schemas[USER_ID] = GetDataBaseSchema(true); - EXPECT_EQ(kvDelegatePtrS1_->SetCloudDbSchema(schemas), DB_ERROR); + communicatorAggregator_->SetLocalDeviceId("DEVICES_A"); + BlockSync(kvDelegatePtrS2_, OK, g_CloudSyncoption); + Value actualValue2; + ASSERT_EQ(kvDelegatePtrS2_->Get(key2, actualValue2), OK); + ASSERT_EQ(actualValue2, expectValue2); } /** - * @tc.name: NormalSyncInvalid008 - * @tc.desc: Test SetCloudSyncConfig with invalid parm. + * @tc.name: NormalSync049 + * @tc.desc: test sync data with invalid modify_time. * @tc.type: FUNC * @tc.require: - * @tc.author: caihaoting + * @tc.author: liaoyonghuang */ -HWTEST_F(DistributedDBCloudKvTest, NormalSyncInvalid008, TestSize.Level0) +HWTEST_F(DistributedDBCloudKvTest, NormalSync049, TestSize.Level0) { /** - * @tc.steps: step1. SetCloudSyncConfig with invalid maxUploadCount. - * @tc.expected: step1. INVALID_ARGS + * @tc.steps: step1. put {k, v} + * @tc.expected: step1. ok. */ - CloudSyncConfig config; - int maxUploadCount = 0; - config.maxUploadCount = maxUploadCount; - EXPECT_EQ(kvDelegatePtrS1_->SetCloudSyncConfig(config), INVALID_ARGS); - maxUploadCount = 2001; - config.maxUploadCount = maxUploadCount; - EXPECT_EQ(kvDelegatePtrS1_->SetCloudSyncConfig(config), INVALID_ARGS); - maxUploadCount = 50; - config.maxUploadCount = maxUploadCount; - EXPECT_EQ(kvDelegatePtrS1_->SetCloudSyncConfig(config), OK); - + vector entries; + int count = 31; // put 31 records. + for (int i = 0; i < count; i++) { + std::string keyStr = "k_" + std::to_string(i); + std::string valueStr = "v_" + std::to_string(i); + Key key(keyStr.begin(), keyStr.end()); + Value value(valueStr.begin(), valueStr.end()); + entries.push_back({key, value}); + } + kvDelegatePtrS1_->PutBatch(entries); /** - * @tc.steps: step2. SetCloudSyncConfig with invalid maxUploadSize. - * @tc.expected: step2. INVALID_ARGS + * @tc.steps: step2. modify time in local and sync + * @tc.expected: step2. ok. */ - int maxUploadSize = 1023; - config.maxUploadSize = maxUploadSize; - EXPECT_EQ(kvDelegatePtrS1_->SetCloudSyncConfig(config), INVALID_ARGS); - maxUploadSize = 128 * 1024 * 1024 + 1; - config.maxUploadSize = maxUploadSize; - EXPECT_EQ(kvDelegatePtrS1_->SetCloudSyncConfig(config), INVALID_ARGS); - maxUploadSize = 10240; - config.maxUploadSize = maxUploadSize; - EXPECT_EQ(kvDelegatePtrS1_->SetCloudSyncConfig(config), OK); - + sqlite3 *db_; + uint64_t openFlag = SQLITE_OPEN_URI | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; + std::string fileUrl = g_testDir + "/" \ + "2d23c8a0ffadafcaa03507a4ec2290c83babddcab07c0e2945fbba93efc7eec0/single_ver/main/gen_natural_store.db"; + ASSERT_TRUE(sqlite3_open_v2(fileUrl.c_str(), &db_, openFlag, nullptr) == SQLITE_OK); + std::string sql = "UPDATE sync_data SET modify_time = modify_time + modify_time where rowid>0"; + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db_, sql), E_OK); + BlockSync(kvDelegatePtrS1_, OK, g_CloudSyncoption); /** - * @tc.steps: step3. SetCloudSyncConfig with invalid maxRetryConflictTimes. - * @tc.expected: step3. INVALID_ARGS + * @tc.steps: step3. put {k, v2} in another device + * @tc.expected: step3. ok. */ - int maxRetryConflictTimes = -2; - config.maxRetryConflictTimes = maxRetryConflictTimes; - EXPECT_EQ(kvDelegatePtrS1_->SetCloudSyncConfig(config), INVALID_ARGS); - maxRetryConflictTimes = 2; - config.maxRetryConflictTimes = maxRetryConflictTimes; - EXPECT_EQ(kvDelegatePtrS1_->SetCloudSyncConfig(config), OK); - + Value newValue = {'v'}; + for (int i = 0; i < count; i++) { + std::string keyStr = "k_" + std::to_string(i); + Key key(keyStr.begin(), keyStr.end()); + entries.push_back({key, newValue}); + } + kvDelegatePtrS2_->PutBatch(entries); /** - * @tc.steps: step4. SetCloudSyncConfig while conn is nullptr - * @tc.expected: step4. DB_ERROR + * @tc.steps: step4. sync and check data + * @tc.expected: step4. ok. */ - auto kvStoreImpl = static_cast(kvDelegatePtrS1_); - EXPECT_EQ(kvStoreImpl->Close(), OK); - EXPECT_EQ(kvDelegatePtrS1_->SetCloudSyncConfig(config), DB_ERROR); + BlockSync(kvDelegatePtrS2_, OK, g_CloudSyncoption); + BlockSync(kvDelegatePtrS1_, OK, g_CloudSyncoption); + Value actualValue; + for (int i = 0; i < count; i++) { + std::string keyStr = "k_" + std::to_string(i); + Key key(keyStr.begin(), keyStr.end()); + EXPECT_EQ(kvDelegatePtrS1_->Get(key, actualValue), OK); + EXPECT_EQ(actualValue, newValue); + } } } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_kvstore_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_kvstore_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0eee17b00a2028463e57aa52c3962ce9168eac82 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_kvstore_test.cpp @@ -0,0 +1,1719 @@ +/* + * 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 "cloud/cloud_db_constant.h" +#include "db_base64_utils.h" +#include "distributeddb_data_generate_unit_test.h" +#include "distributeddb_tools_unit_test.h" +#include "kv_virtual_device.h" +#include "kv_store_nb_delegate.h" +#include "kv_store_nb_delegate_impl.h" +#include "platform_specific.h" +#include "process_system_api_adapter_impl.h" +#include "virtual_communicator_aggregator.h" +#include "virtual_cloud_db.h" +#include "sqlite_utils.h" +using namespace testing::ext; +using namespace DistributedDB; +using namespace DistributedDBUnitTest; +using namespace std; + +namespace { +static std::string HWM_HEAD = "naturalbase_cloud_meta_sync_data_"; +string g_testDir; +KvStoreDelegateManager g_mgr(APP_ID, USER_ID); +CloudSyncOption g_CloudSyncoption; +const std::string USER_ID_2 = "user2"; +const std::string USER_ID_3 = "user3"; +const Key KEY_1 = {'k', '1'}; +const Key KEY_2 = {'k', '2'}; +const Key KEY_3 = {'k', '3'}; +const Value VALUE_1 = {'v', '1'}; +const Value VALUE_2 = {'v', '2'}; +const Value VALUE_3 = {'v', '3'}; +class DistributedDBCloudKvStoreTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp(); + void TearDown(); + void InsertRecord(int num); + void SetDeviceId(const Key &key, const std::string &deviceId); + void SetFlag(const Key &key, LogInfoFlag flag); + int CheckFlag(const Key &key, LogInfoFlag flag); + int CheckLogTable(const std::string &deviceId); + int CheckWaterMark(const std::string &key); + int ChangeUserId(const std::string &deviceId, const std::string &wantUserId); + int ChangeHashKey(const std::string &deviceId); +protected: + DBStatus GetKvStore(KvStoreNbDelegate *&delegate, const std::string &storeId, KvStoreNbDelegate::Option option, + bool invalidSchema = false); + void CloseKvStore(KvStoreNbDelegate *&delegate, const std::string &storeId); + void BlockSync(KvStoreNbDelegate *delegate, DBStatus expectDBStatus, CloudSyncOption option, + DBStatus expectSyncResult = OK); + void SyncAndGetProcessInfo(KvStoreNbDelegate *delegate, CloudSyncOption option); + bool CheckUserSyncInfo(const vector users, const vector userStatus, + const vector userExpectInfo); + static DataBaseSchema GetDataBaseSchema(bool invalidSchema); + std::shared_ptr virtualCloudDb_ = nullptr; + std::shared_ptr virtualCloudDb2_ = nullptr; + KvStoreConfig config_; + KvStoreNbDelegate* kvDelegatePtrS1_ = nullptr; + KvStoreNbDelegate* kvDelegatePtrS2_ = nullptr; + SyncProcess lastProcess_; + std::map lastSyncProcess_; + VirtualCommunicatorAggregator *communicatorAggregator_ = nullptr; + KvVirtualDevice *deviceB_ = nullptr; +}; + +void DistributedDBCloudKvStoreTest::SetUpTestCase() +{ + DistributedDBToolsUnitTest::TestDirInit(g_testDir); + if (DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir) != 0) { + LOGE("rm test db files error!"); + } + g_CloudSyncoption.mode = SyncMode::SYNC_MODE_CLOUD_MERGE; + g_CloudSyncoption.users.push_back(USER_ID); + g_CloudSyncoption.devices.push_back("cloud"); + + string dir = g_testDir + "/single_ver"; + DIR* dirTmp = opendir(dir.c_str()); + if (dirTmp == nullptr) { + OS::MakeDBDirectory(dir); + } else { + closedir(dirTmp); + } +} + +void DistributedDBCloudKvStoreTest::TearDownTestCase() +{ + if (DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir) != 0) { + LOGE("rm test db files error!"); + } +} + +void DistributedDBCloudKvStoreTest::SetUp() +{ + DistributedDBToolsUnitTest::PrintTestCaseInfo(); + config_.dataDir = g_testDir; + /** + * @tc.setup: create virtual device B and C, and get a KvStoreNbDelegate as deviceA + */ + virtualCloudDb_ = std::make_shared(); + virtualCloudDb2_ = std::make_shared(); + g_mgr.SetKvStoreConfig(config_); + KvStoreNbDelegate::Option option1; + ASSERT_EQ(GetKvStore(kvDelegatePtrS1_, STORE_ID_1, option1), OK); + // set aggregator after get store1, only store2 can sync with p2p + communicatorAggregator_ = new (std::nothrow) VirtualCommunicatorAggregator(); + ASSERT_TRUE(communicatorAggregator_ != nullptr); + RuntimeContext::GetInstance()->SetCommunicatorAggregator(communicatorAggregator_); + KvStoreNbDelegate::Option option2; + ASSERT_EQ(GetKvStore(kvDelegatePtrS2_, STORE_ID_2, option2), OK); + + deviceB_ = new (std::nothrow) KvVirtualDevice("DEVICE_B"); + ASSERT_TRUE(deviceB_ != nullptr); + auto syncInterfaceB = new (std::nothrow) VirtualSingleVerSyncDBInterface(); + ASSERT_TRUE(syncInterfaceB != nullptr); + ASSERT_EQ(deviceB_->Initialize(communicatorAggregator_, syncInterfaceB), E_OK); +} + +void DistributedDBCloudKvStoreTest::TearDown() +{ + CloseKvStore(kvDelegatePtrS1_, STORE_ID_1); + CloseKvStore(kvDelegatePtrS2_, STORE_ID_2); + virtualCloudDb_ = nullptr; + virtualCloudDb2_ = nullptr; + if (DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir) != 0) { + LOGE("rm test db files error!"); + } + + if (deviceB_ != nullptr) { + delete deviceB_; + deviceB_ = nullptr; + } + + RuntimeContext::GetInstance()->SetCommunicatorAggregator(nullptr); + communicatorAggregator_ = nullptr; + RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(nullptr); +} + +void DistributedDBCloudKvStoreTest::BlockSync(KvStoreNbDelegate *delegate, DBStatus expectDBStatus, + CloudSyncOption option, DBStatus expectSyncResult) +{ + if (delegate == nullptr) { + return; + } + std::mutex dataMutex; + std::condition_variable cv; + bool finish = false; + SyncProcess last; + auto callback = [expectDBStatus, &last, &cv, &dataMutex, &finish, &option](const std::map &process) { + size_t notifyCnt = 0; + for (const auto &item: process) { + LOGD("user = %s, status = %d", item.first.c_str(), item.second.process); + if (item.second.process != DistributedDB::FINISHED) { + continue; + } + EXPECT_EQ(item.second.errCode, expectDBStatus); + { + std::lock_guard autoLock(dataMutex); + notifyCnt++; + std::set userSet(option.users.begin(), option.users.end()); + if (notifyCnt == userSet.size()) { + finish = true; + last = item.second; + cv.notify_one(); + } + } + } + }; + auto actualRet = delegate->Sync(option, callback); + EXPECT_EQ(actualRet, expectSyncResult); + if (actualRet == OK) { + std::unique_lock uniqueLock(dataMutex); + cv.wait(uniqueLock, [&finish]() { + return finish; + }); + } + lastProcess_ = last; +} + +DataBaseSchema DistributedDBCloudKvStoreTest::GetDataBaseSchema(bool invalidSchema) +{ + DataBaseSchema schema; + TableSchema tableSchema; + tableSchema.name = invalidSchema ? "invalid_schema_name" : CloudDbConstant::CLOUD_KV_TABLE_NAME; + Field field; + field.colName = CloudDbConstant::CLOUD_KV_FIELD_KEY; + field.type = TYPE_INDEX; + field.primary = true; + tableSchema.fields.push_back(field); + field.colName = CloudDbConstant::CLOUD_KV_FIELD_DEVICE; + field.primary = false; + tableSchema.fields.push_back(field); + field.colName = CloudDbConstant::CLOUD_KV_FIELD_ORI_DEVICE; + tableSchema.fields.push_back(field); + field.colName = CloudDbConstant::CLOUD_KV_FIELD_VALUE; + tableSchema.fields.push_back(field); + field.colName = CloudDbConstant::CLOUD_KV_FIELD_DEVICE_CREATE_TIME; + field.type = TYPE_INDEX; + tableSchema.fields.push_back(field); + schema.tables.push_back(tableSchema); + return schema; +} + + +DBStatus DistributedDBCloudKvStoreTest::GetKvStore(KvStoreNbDelegate *&delegate, const std::string &storeId, + KvStoreNbDelegate::Option option, bool invalidSchema) +{ + DBStatus openRet = OK; + g_mgr.GetKvStore(storeId, option, [&openRet, &delegate](DBStatus status, KvStoreNbDelegate *openDelegate) { + openRet = status; + delegate = openDelegate; + }); + EXPECT_EQ(openRet, OK); + EXPECT_NE(delegate, nullptr); + + std::map> cloudDbs; + cloudDbs[USER_ID] = virtualCloudDb_; + cloudDbs[USER_ID_2] = virtualCloudDb2_; + delegate->SetCloudDB(cloudDbs); + std::map schemas; + schemas[USER_ID] = GetDataBaseSchema(invalidSchema); + schemas[USER_ID_2] = GetDataBaseSchema(invalidSchema); + return delegate->SetCloudDbSchema(schemas); +} + +void DistributedDBCloudKvStoreTest::CloseKvStore(KvStoreNbDelegate *&delegate, const std::string &storeId) +{ + if (delegate != nullptr) { + ASSERT_EQ(g_mgr.CloseKvStore(delegate), OK); + delegate = nullptr; + DBStatus status = g_mgr.DeleteKvStore(storeId); + LOGD("delete kv store status %d store %s", status, storeId.c_str()); + ASSERT_EQ(status, OK); + } +} + +void DistributedDBCloudKvStoreTest::SyncAndGetProcessInfo(KvStoreNbDelegate *delegate, CloudSyncOption option) +{ + if (delegate == nullptr) { + return; + } + std::mutex dataMutex; + std::condition_variable cv; + bool isFinish = false; + vector> lists; + auto callback = [&cv, &dataMutex, &isFinish, &option, &lists](const std::map &process) { + size_t notifyCnt = 0; + for (const auto &item: process) { + LOGD("user = %s, status = %d", item.first.c_str(), item.second.process); + if (item.second.process != DistributedDB::FINISHED) { + continue; + } + { + std::lock_guard autoLock(dataMutex); + notifyCnt++; + std::set userSet(option.users.begin(), option.users.end()); + if (notifyCnt == userSet.size()) { + isFinish = true; + cv.notify_one(); + } + lists.push_back(process); + } + } + }; + auto ret = delegate->Sync(option, callback); + EXPECT_EQ(ret, OK); + if (ret == OK) { + std::unique_lock uniqueLock(dataMutex); + cv.wait(uniqueLock, [&isFinish]() { + return isFinish; + }); + } + lastSyncProcess_ = lists.back(); +} + +bool DistributedDBCloudKvStoreTest::CheckUserSyncInfo(const vector users, + const vector userStatus, const vector userExpectInfo) +{ + uint32_t idx = 0; + for (auto &it: lastSyncProcess_) { + if ((idx >= users.size()) || (idx >= userStatus.size()) || (idx >= userExpectInfo.size())) { + return false; + } + string user = it.first; + if (user.compare(0, user.length(), users[idx]) != 0) { + return false; + } + SyncProcess actualSyncProcess = it.second; + EXPECT_EQ(actualSyncProcess.process, FINISHED); + EXPECT_EQ(actualSyncProcess.errCode, userStatus[idx]); + for (const auto &table : actualSyncProcess.tableProcess) { + EXPECT_EQ(table.second.upLoadInfo.total, userExpectInfo[idx].total); + EXPECT_EQ(table.second.upLoadInfo.successCount, userExpectInfo[idx].successCount); + EXPECT_EQ(table.second.upLoadInfo.insertCount, userExpectInfo[idx].insertCount); + EXPECT_EQ(table.second.upLoadInfo.failCount, userExpectInfo[idx].failCount); + } + idx++; + } + return true; +} + +/** + * @tc.name: SyncOptionCheck001 + * @tc.desc: Test sync without user. + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(DistributedDBCloudKvStoreTest, SyncOptionCheck001, TestSize.Level0) +{ + /** + * @tc.steps:step1. Device 1 inserts a piece of data. + * @tc.expected: step1 OK. + */ + Key key = {'k'}; + Value value = {'v'}; + ASSERT_EQ(kvDelegatePtrS1_->Put(key, value), OK); + /** + * @tc.steps:step2. Set option without user, and attempt to sync + * @tc.expected: step2 return INVALID_ARGS. + */ + CloudSyncOption option; + option.mode = SyncMode::SYNC_MODE_CLOUD_MERGE; + option.devices.push_back("cloud"); + BlockSync(kvDelegatePtrS1_, OK, option, INVALID_ARGS); + /** + * @tc.steps:step3. Device 2 sync and attempt to get data. + * @tc.expected: step3 sync OK but data NOT_FOUND. + */ + BlockSync(kvDelegatePtrS2_, OK, g_CloudSyncoption); + Value actualValue; + EXPECT_EQ(kvDelegatePtrS2_->Get(key, actualValue), NOT_FOUND); +} + +/** + * @tc.name: SyncOptionCheck002 + * @tc.desc: Test sync with invalid waitTime. + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(DistributedDBCloudKvStoreTest, SyncOptionCheck002, TestSize.Level0) +{ + /** + * @tc.steps:step1. Device 1 inserts a piece of data. + * @tc.expected: step1 OK. + */ + Key key = {'k'}; + Value value = {'v'}; + ASSERT_EQ(kvDelegatePtrS1_->Put(key, value), OK); + /** + * @tc.steps:step2. Set invalid waitTime of sync option and sync. + * @tc.expected: step2 return INVALID_ARGS. + */ + CloudSyncOption option; + option.mode = SyncMode::SYNC_MODE_CLOUD_MERGE; + option.users.push_back(USER_ID); + option.devices.push_back("cloud"); + option.waitTime = -2; // -2 is invalid waitTime. + BlockSync(kvDelegatePtrS1_, OK, option, INVALID_ARGS); + /** + * @tc.steps:step3. Device 2 sync and attempt to get data. + * @tc.expected: step3 sync OK but data NOT_FOUND. + */ + BlockSync(kvDelegatePtrS2_, OK, g_CloudSyncoption); + Value actualValue; + EXPECT_EQ(kvDelegatePtrS2_->Get(key, actualValue), NOT_FOUND); +} + +/** + * @tc.name: SyncOptionCheck003 + * @tc.desc: Test sync with users which have not been sync to cloud. + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(DistributedDBCloudKvStoreTest, SyncOptionCheck003, TestSize.Level0) +{ + /** + * @tc.steps:step1. Device 1 inserts a piece of data. + * @tc.expected: step1 OK. + */ + Key key = {'k'}; + Value value = {'v'}; + ASSERT_EQ(kvDelegatePtrS1_->Put(key, value), OK); + /** + * @tc.steps:step2. Set user1 and user3 to option and sync. + * @tc.expected: step2 return INVALID_ARGS. + */ + CloudSyncOption option; + option.mode = SyncMode::SYNC_MODE_CLOUD_MERGE; + option.users.push_back(USER_ID); + option.users.push_back(USER_ID_3); + option.devices.push_back("cloud"); + BlockSync(kvDelegatePtrS1_, OK, option, INVALID_ARGS); + /** + * @tc.steps:step3. Device 2 sync and attempt to get data. + * @tc.expected: step3 sync OK but data NOT_FOUND. + */ + BlockSync(kvDelegatePtrS2_, OK, g_CloudSyncoption); + Value actualValue; + EXPECT_EQ(kvDelegatePtrS2_->Get(key, actualValue), NOT_FOUND); +} + +/** + * @tc.name: SyncOptionCheck004 + * @tc.desc: Test sync with user when schema is not same. + * @tc.type: FUNC + * @tc.require: + * @tc.author: caihaoting + */ +HWTEST_F(DistributedDBCloudKvStoreTest, SyncOptionCheck004, TestSize.Level0) +{ + /** + * @tc.steps:step1. Device 1 inserts a piece of data. + * @tc.expected: step1 OK. + */ + Key key = {'k'}; + Value value = {'v'}; + ASSERT_EQ(kvDelegatePtrS1_->Put(key, value), OK); + /** + * @tc.steps:step2. Set user1 to option and user2 to schema and sync. + * @tc.expected: step2 return SCHEMA_MISMATCH. + */ + CloudSyncOption option; + option.mode = SyncMode::SYNC_MODE_CLOUD_MERGE; + option.users.push_back(USER_ID); + option.devices.push_back("cloud"); + std::map schemas; + schemas[USER_ID_2] = GetDataBaseSchema(false); + kvDelegatePtrS1_->SetCloudDbSchema(schemas); + BlockSync(kvDelegatePtrS1_, OK, option, SCHEMA_MISMATCH); +} + +/** + * @tc.name: SyncOptionCheck005 + * @tc.desc: Testing registration of observer exceeded the upper limit. + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(DistributedDBCloudKvStoreTest, SyncOptionCheck005, TestSize.Level0) +{ + /** + * @tc.steps:step1. Register MAX_OBSERVER_COUNT observers. + * @tc.expected: step1 OK. + */ + std::vector observerList; + for (int i = 0; i < DBConstant::MAX_OBSERVER_COUNT; i++) { + auto *observer = new (std::nothrow) KvStoreObserverUnitTest; + observerList.push_back(observer); + EXPECT_EQ(kvDelegatePtrS1_->RegisterObserver({}, OBSERVER_CHANGES_CLOUD, observer), OK); + } + /** + * @tc.steps:step2. Register one more observer. + * @tc.expected: step2 Registration failed, return OVER_MAX_LIMITS. + */ + auto *overMaxObserver = new (std::nothrow) KvStoreObserverUnitTest; + EXPECT_EQ(kvDelegatePtrS1_->RegisterObserver({}, OBSERVER_CHANGES_CLOUD, overMaxObserver), OVER_MAX_LIMITS); + /** + * @tc.steps:step3. UnRegister all observers. + * @tc.expected: step3 OK. + */ + EXPECT_EQ(kvDelegatePtrS1_->UnRegisterObserver(overMaxObserver), NOT_FOUND); + delete overMaxObserver; + overMaxObserver = nullptr; + for (auto &observer : observerList) { + EXPECT_EQ(kvDelegatePtrS1_->UnRegisterObserver(observer), OK); + delete observer; + observer = nullptr; + } +} + +/** + * @tc.name: SyncOptionCheck006 + * @tc.desc: Test sync with schema db + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBCloudKvStoreTest, SyncOptionCheck006, TestSize.Level0) +{ + KvStoreNbDelegate::Option option; + option.schema = "{\"SCHEMA_VERSION\":\"1.0\"," + "\"SCHEMA_MODE\":\"STRICT\"," + "\"SCHEMA_DEFINE\":{" + "\"field_name1\":\"BOOL\"," + "\"field_name2\":\"INTEGER, NOT NULL\"" + "}," + "\"SCHEMA_INDEXES\":[\"$.field_name1\", \"$.field_name2\"]}"; + KvStoreNbDelegate *kvDelegatePtr = nullptr; + ASSERT_EQ(GetKvStore(kvDelegatePtr, STORE_ID_4, option), OK); + ASSERT_NE(kvDelegatePtr, nullptr); + BlockSync(kvDelegatePtr, NOT_SUPPORT, g_CloudSyncoption, NOT_SUPPORT); + EXPECT_EQ(g_mgr.CloseKvStore(kvDelegatePtr), OK); +} + +/** + * @tc.name: SyncOptionCheck007 + * @tc.desc: Test sync with repetitive user. + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(DistributedDBCloudKvStoreTest, SyncOptionCheck007, TestSize.Level0) +{ + /** + * @tc.steps:step1. Device 1 inserts a piece of data. + * @tc.expected: step1 OK. + */ + Key key = {'k'}; + Value value = {'v'}; + ASSERT_EQ(kvDelegatePtrS1_->Put(key, value), OK); + /** + * @tc.steps:step2. Set user1 2 times to option sync. + * @tc.expected: step2 return OK. + */ + CloudSyncOption option; + option.mode = SyncMode::SYNC_MODE_CLOUD_MERGE; + option.users.push_back(USER_ID); + option.users.push_back(USER_ID); + option.devices.push_back("cloud"); + BlockSync(kvDelegatePtrS1_, OK, option, OK); +} + +/** + * @tc.name: SyncOptionCheck008 + * @tc.desc: Test kc sync with query . + * @tc.type: FUNC + * @tc.require: + * @tc.author: luoguo + */ +HWTEST_F(DistributedDBCloudKvStoreTest, SyncOptionCheck008, TestSize.Level0) +{ + /** + * @tc.steps:step1. Device 1 inserts a piece of data. + * @tc.expected: step1 OK. + */ + Key key = {'k'}; + Value value = {'v'}; + ASSERT_EQ(kvDelegatePtrS1_->Put(key, value), OK); + /** + * @tc.steps:step2. Set query to option sync. + * @tc.expected: step2 return OK. + */ + std::set keys; + CloudSyncOption option; + option.query = Query::Select().InKeys(keys); + option.mode = SyncMode::SYNC_MODE_CLOUD_MERGE; + option.users.push_back(USER_ID); + option.users.push_back(USER_ID); + option.devices.push_back("cloud"); + BlockSync(kvDelegatePtrS1_, OK, option, OK); +} + +void DistributedDBCloudKvStoreTest::SetFlag(const Key &key, LogInfoFlag flag) +{ + sqlite3 *db_; + uint64_t openFlag = SQLITE_OPEN_URI | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; + std::string fileUrl = g_testDir + "/" \ + "2d23c8a0ffadafcaa03507a4ec2290c83babddcab07c0e2945fbba93efc7eec0/single_ver/main/gen_natural_store.db"; + ASSERT_TRUE(sqlite3_open_v2(fileUrl.c_str(), &db_, openFlag, nullptr) == SQLITE_OK); + int errCode = E_OK; + std::string sql = "UPDATE sync_data SET flag=? WHERE Key=?"; + sqlite3_stmt *statement = nullptr; + errCode = SQLiteUtils::GetStatement(db_, sql, statement); + if (errCode != E_OK) { + SQLiteUtils::ResetStatement(statement, true, errCode); + } + ASSERT_EQ(errCode, E_OK); + errCode = SQLiteUtils::BindInt64ToStatement(statement, 1, static_cast(flag)); // 1st arg. + ASSERT_EQ(errCode, E_OK); + errCode = SQLiteUtils::BindBlobToStatement(statement, 2, key, true); // 2nd arg. + ASSERT_EQ(errCode, E_OK); + if (errCode != E_OK) { + SQLiteUtils::ResetStatement(statement, true, errCode); + } + EXPECT_EQ(SQLiteUtils::StepWithRetry(statement), SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)); + SQLiteUtils::ResetStatement(statement, true, errCode); + EXPECT_EQ(errCode, E_OK); + sqlite3_close_v2(db_); +} + +int DistributedDBCloudKvStoreTest::CheckFlag(const Key &key, LogInfoFlag flag) +{ + sqlite3 *db_; + uint64_t openFlag = SQLITE_OPEN_URI | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; + std::string fileUrl = g_testDir + "/" \ + "2d23c8a0ffadafcaa03507a4ec2290c83babddcab07c0e2945fbba93efc7eec0/single_ver/main/gen_natural_store.db"; + int errCode = sqlite3_open_v2(fileUrl.c_str(), &db_, openFlag, nullptr); + if (errCode != E_OK) { + return NOT_FOUND; + } + std::string sql = "SELECT * FROM sync_data WHERE Key =? AND (flag=?)"; + sqlite3_stmt *statement = nullptr; + errCode = SQLiteUtils::GetStatement(db_, sql, statement); + if (errCode != E_OK) { + SQLiteUtils::ResetStatement(statement, true, errCode); + return NOT_FOUND; + } + std::vector keyVec(key.begin(), key.end()); + errCode = SQLiteUtils::BindBlobToStatement(statement, 1, keyVec, true); // 1st arg. + if (errCode != E_OK) { + SQLiteUtils::ResetStatement(statement, true, errCode); + return NOT_FOUND; + } + errCode = SQLiteUtils::BindInt64ToStatement(statement, 2, static_cast(flag)); // 2nd arg. + if (errCode != E_OK) { + SQLiteUtils::ResetStatement(statement, true, errCode); + return NOT_FOUND; + } + errCode = SQLiteUtils::StepWithRetry(statement); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + SQLiteUtils::ResetStatement(statement, true, errCode); + sqlite3_close_v2(db_); + return NOT_FOUND; // cant find. + } + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + SQLiteUtils::ResetStatement(statement, true, errCode); + sqlite3_close_v2(db_); + return OK; + } + SQLiteUtils::ResetStatement(statement, true, errCode); + EXPECT_EQ(errCode, E_OK); + sqlite3_close_v2(db_); + return NOT_FOUND; +} + +int DistributedDBCloudKvStoreTest::CheckWaterMark(const std::string &user) +{ + sqlite3 *db_; + uint64_t flag = SQLITE_OPEN_URI | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; + std::string fileUrl = g_testDir + "/" \ + "2d23c8a0ffadafcaa03507a4ec2290c83babddcab07c0e2945fbba93efc7eec0/single_ver/main/gen_natural_store.db"; + int errCode = sqlite3_open_v2(fileUrl.c_str(), &db_, flag, nullptr); + if (errCode != E_OK) { + return NOT_FOUND; + } + std::string sql; + if (user.empty()) { + sql = "SELECT * FROM meta_data WHERE KEY LIKE 'naturalbase_cloud_meta_sync_data_%'"; + } else { + sql = "SELECT * FROM meta_data WHERE KEY =?;"; + } + sqlite3_stmt *statement = nullptr; + errCode = SQLiteUtils::GetStatement(db_, sql, statement); + if (errCode != E_OK) { + SQLiteUtils::ResetStatement(statement, true, errCode); + return NOT_FOUND; + } + if (!user.empty()) { + std::string waterMarkKey = HWM_HEAD + user; + std::vector keyVec(waterMarkKey.begin(), waterMarkKey.end()); + errCode = SQLiteUtils::BindBlobToStatement(statement, 1, keyVec, true); // only one arg. + if (errCode != E_OK) { + SQLiteUtils::ResetStatement(statement, true, errCode); + return NOT_FOUND; + } + } + errCode = SQLiteUtils::StepWithRetry(statement); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + SQLiteUtils::ResetStatement(statement, true, errCode); + sqlite3_close_v2(db_); + return NOT_FOUND; // cant find. + } + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + SQLiteUtils::ResetStatement(statement, true, errCode); + sqlite3_close_v2(db_); + return OK; + } + SQLiteUtils::ResetStatement(statement, true, errCode); + EXPECT_EQ(errCode, E_OK); + sqlite3_close_v2(db_); + return NOT_FOUND; +} + +void DistributedDBCloudKvStoreTest::SetDeviceId(const Key &key, const std::string &deviceId) +{ + sqlite3 *db_; + uint64_t flag = SQLITE_OPEN_URI | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; + std::string fileUrl = g_testDir + "/" \ + "2d23c8a0ffadafcaa03507a4ec2290c83babddcab07c0e2945fbba93efc7eec0/single_ver/main/gen_natural_store.db"; + ASSERT_TRUE(sqlite3_open_v2(fileUrl.c_str(), &db_, flag, nullptr) == SQLITE_OK); + int errCode = E_OK; + std::string sql = "UPDATE sync_data SET device=? WHERE Key=?"; + sqlite3_stmt *statement = nullptr; + errCode = SQLiteUtils::GetStatement(db_, sql, statement); + if (errCode != E_OK) { + SQLiteUtils::ResetStatement(statement, true, errCode); + } + ASSERT_EQ(errCode, E_OK); + std::string hashDevice = DBCommon::TransferHashString(deviceId); + std::vector deviceIdVec(hashDevice.begin(), hashDevice.end()); + int bindIndex = 1; + errCode = SQLiteUtils::BindBlobToStatement(statement, bindIndex, deviceIdVec, true); // only one arg. + ASSERT_EQ(errCode, E_OK); + if (errCode != E_OK) { + SQLiteUtils::ResetStatement(statement, true, errCode); + } + bindIndex++; + errCode = SQLiteUtils::BindBlobToStatement(statement, bindIndex, key, true); // only one arg. + if (errCode != E_OK) { + SQLiteUtils::ResetStatement(statement, true, errCode); + } + EXPECT_EQ(SQLiteUtils::StepWithRetry(statement), SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)); + SQLiteUtils::ResetStatement(statement, true, errCode); + EXPECT_EQ(errCode, E_OK); + sqlite3_close_v2(db_); +} + +int DistributedDBCloudKvStoreTest::CheckLogTable(const std::string &deviceId) +{ + sqlite3 *db_; + uint64_t flag = SQLITE_OPEN_URI | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; + std::string fileUrl = g_testDir + "/" \ + "2d23c8a0ffadafcaa03507a4ec2290c83babddcab07c0e2945fbba93efc7eec0/single_ver/main/gen_natural_store.db"; + int errCode = sqlite3_open_v2(fileUrl.c_str(), &db_, flag, nullptr); + if (errCode != E_OK) { + return NOT_FOUND; + } + std::string sql = "SELECT * FROM naturalbase_kv_aux_sync_data_log WHERE hash_key IN" \ + "(SELECT hash_key FROM sync_data WHERE device =?);"; + sqlite3_stmt *statement = nullptr; + errCode = SQLiteUtils::GetStatement(db_, sql, statement); + if (errCode != E_OK) { + SQLiteUtils::ResetStatement(statement, true, errCode); + return NOT_FOUND; + } + std::string hashDevice = DBCommon::TransferHashString(deviceId); + std::vector deviceIdVec(hashDevice.begin(), hashDevice.end()); + errCode = SQLiteUtils::BindBlobToStatement(statement, 1, deviceIdVec, true); // only one arg. + if (errCode != E_OK) { + SQLiteUtils::ResetStatement(statement, true, errCode); + return NOT_FOUND; + } + errCode = SQLiteUtils::StepWithRetry(statement); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + SQLiteUtils::ResetStatement(statement, true, errCode); + sqlite3_close_v2(db_); + return NOT_FOUND; // cant find. + } + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + SQLiteUtils::ResetStatement(statement, true, errCode); + sqlite3_close_v2(db_); + return OK; + } + SQLiteUtils::ResetStatement(statement, true, errCode); + EXPECT_EQ(errCode, E_OK); + sqlite3_close_v2(db_); + return NOT_FOUND; +} + +int DistributedDBCloudKvStoreTest::ChangeUserId(const std::string &deviceId, const std::string &wantUserId) +{ + sqlite3 *db_; + uint64_t flag = SQLITE_OPEN_URI | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; + std::string fileUrl = g_testDir + "/" \ + "2d23c8a0ffadafcaa03507a4ec2290c83babddcab07c0e2945fbba93efc7eec0/single_ver/main/gen_natural_store.db"; + int errCode = sqlite3_open_v2(fileUrl.c_str(), &db_, flag, nullptr); + if (errCode != E_OK) { + return INVALID_ARGS; + } + std::string sql = "UPDATE naturalbase_kv_aux_sync_data_log SET userid =? WHERE hash_key IN" \ + "(SELECT hash_key FROM sync_data WHERE device =? AND (flag=0x100));"; + sqlite3_stmt *statement = nullptr; + errCode = SQLiteUtils::GetStatement(db_, sql, statement); + if (errCode != E_OK) { + SQLiteUtils::ResetStatement(statement, true, errCode); + return INVALID_ARGS; + } + int bindIndex = 1; + errCode = SQLiteUtils::BindTextToStatement(statement, bindIndex, wantUserId); // only one arg. + if (errCode != E_OK) { + SQLiteUtils::ResetStatement(statement, true, errCode); + return INVALID_ARGS; + } + bindIndex++; + std::string hashDevice = DBCommon::TransferHashString(deviceId); + std::vector deviceIdVec(hashDevice.begin(), hashDevice.end()); + errCode = SQLiteUtils::BindBlobToStatement(statement, bindIndex, deviceIdVec, true); // only one arg. + if (errCode != E_OK) { + SQLiteUtils::ResetStatement(statement, true, errCode); + return INVALID_ARGS; + } + EXPECT_EQ(SQLiteUtils::StepWithRetry(statement), SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)); + SQLiteUtils::ResetStatement(statement, true, errCode); + EXPECT_EQ(errCode, E_OK); + sqlite3_close_v2(db_); + return INVALID_ARGS; +} + +int DistributedDBCloudKvStoreTest::ChangeHashKey(const std::string &deviceId) +{ + sqlite3 *db_; + uint64_t flag = SQLITE_OPEN_URI | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; + std::string fileUrl = g_testDir + "/" \ + "2d23c8a0ffadafcaa03507a4ec2290c83babddcab07c0e2945fbba93efc7eec0/single_ver/main/gen_natural_store.db"; + int errCode = sqlite3_open_v2(fileUrl.c_str(), &db_, flag, nullptr); + if (errCode != E_OK) { + return INVALID_ARGS; + } + std::string updataLogTableSql = "UPDATE naturalbase_kv_aux_sync_data_log SET hash_Key ='99';"; + sqlite3_stmt *statement = nullptr; + errCode = SQLiteUtils::GetStatement(db_, updataLogTableSql, statement); + if (errCode != E_OK) { + SQLiteUtils::ResetStatement(statement, true, errCode); + return INVALID_ARGS; + } + errCode = SQLiteUtils::StepWithRetry(statement); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + SQLiteUtils::ResetStatement(statement, true, errCode); + } + + std::string sql = "UPDATE sync_data SET hash_Key ='99' WHERE device =? AND (flag=0x100);"; + errCode = SQLiteUtils::GetStatement(db_, sql, statement); + if (errCode != E_OK) { + SQLiteUtils::ResetStatement(statement, true, errCode); + return INVALID_ARGS; + } + std::string hashDevice = DBCommon::TransferHashString(deviceId); + std::vector deviceIdVec(hashDevice.begin(), hashDevice.end()); + errCode = SQLiteUtils::BindBlobToStatement(statement, 1, deviceIdVec, true); // only one arg. + if (errCode != E_OK) { + SQLiteUtils::ResetStatement(statement, true, errCode); + sqlite3_close_v2(db_); + return OK; // cant find. + } + EXPECT_EQ(SQLiteUtils::StepWithRetry(statement), SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)); + SQLiteUtils::ResetStatement(statement, true, errCode); + EXPECT_EQ(errCode, E_OK); + sqlite3_close_v2(db_); + return INVALID_ARGS; +} + +void DistributedDBCloudKvStoreTest::InsertRecord(int num) +{ + for (int i = 0; i < num; i++) { + Key key; + key.push_back('k'); + key.push_back('0' + i); + Value value; + value.push_back('k'); + value.push_back('0' + i); + ASSERT_EQ(kvDelegatePtrS1_->Put(key, value), OK); + BlockSync(kvDelegatePtrS1_, OK, g_CloudSyncoption); + SetFlag(key, LogInfoFlag::FLAG_CLOUD_WRITE); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); // sleep for 100ms + } +} + +/** + * @tc.name: RemoveDeviceTest001 + * @tc.desc: remove all log table record with empty deviceId and FLAG_ONLY flag + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DistributedDBCloudKvStoreTest, RemoveDeviceTest001, TestSize.Level0) +{ + /** + * @tc.steps: step1. Insert three record (Key:k0, device:0, userId:user0), (Key:k1, device:1, userId:user0), + * (Key:k2, device:2, userId:0) + * * @tc.expected: step1. insert successfully + */ + int recordNum = 3; + InsertRecord(recordNum); + for (int i = 0; i < recordNum; i++) { + Key key; + key.push_back('k'); + key.push_back('0' + i); + SetFlag(key, LogInfoFlag::FLAG_CLOUD_WRITE); + SetDeviceId(key, std::to_string(i)); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); // sleep for 100ms + } + /** + * @tc.steps: step2. Check three Log record whether exist or not; + * * @tc.expected: step2. record exist + */ + for (int i = 0; i < recordNum; i++) { + Key key; + key.push_back('k'); + key.push_back('0' + i); + Value actualValue; + EXPECT_EQ(kvDelegatePtrS1_->Get(key, actualValue), OK); + std::string deviceId = std::to_string(i); + EXPECT_EQ(CheckLogTable(deviceId), OK); + EXPECT_EQ(CheckFlag(key, LogInfoFlag::FLAG_CLOUD_WRITE), OK); + EXPECT_EQ(CheckWaterMark(""), OK); + } + /** + * @tc.steps: step3. remove log data with empty deviceId. + * * @tc.expected: step3. remove OK, there are not user record exist in log table. + */ + EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData("", ClearMode::FLAG_ONLY), OK); + for (int i = 0; i < recordNum; i++) { + Key key; + key.push_back('k'); + key.push_back('0' + i); + Value actualValue; + EXPECT_EQ(kvDelegatePtrS1_->Get(key, actualValue), OK); + std::string deviceId = std::to_string(i); + EXPECT_EQ(CheckLogTable(deviceId), NOT_FOUND); + EXPECT_EQ(CheckFlag(key, LogInfoFlag::FLAG_LOCAL), OK); + EXPECT_EQ(CheckWaterMark(""), NOT_FOUND); + } +} + +/** + * @tc.name: RemoveDeviceTest002 + * @tc.desc: remove all record with empty deviceId and FLAG_AND_DATA flag + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DistributedDBCloudKvStoreTest, RemoveDeviceTest002, TestSize.Level0) +{ + /** + * @tc.steps: step1. Insert three record (Key:k0, device:0, userId:user0), (Key:k1, device:1, userId:user0), + * (Key:k2, device:2, userId:0) + * * @tc.expected: step1. insert successfully + */ + int recordNum = 3; + InsertRecord(recordNum); + for (int i = 0; i < recordNum; i++) { + Key key; + key.push_back('k'); + key.push_back('0' + i); + SetFlag(key, LogInfoFlag::FLAG_CLOUD_WRITE); + SetDeviceId(key, std::to_string(i)); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); // sleep for 100ms + } + /** + * @tc.steps: step2. Check three Log record whether exist or not; + * * @tc.expected: step2. record exist + */ + for (int i = 0; i < recordNum; i++) { + Key key; + key.push_back('k'); + key.push_back('0' + i); + Value actualValue; + EXPECT_EQ(kvDelegatePtrS1_->Get(key, actualValue), OK); + std::string deviceId = std::to_string(i); + EXPECT_EQ(CheckLogTable(deviceId), OK); + EXPECT_EQ(CheckWaterMark(""), OK); + } + /** + * @tc.steps: step3. remove log data with empty deviceId. + * * @tc.expected: step3. remove OK, there are not user record exist in log table. + */ + EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData("", ClearMode::FLAG_AND_DATA), OK); + for (int i = 0; i < recordNum; i++) { + Key key; + key.push_back('k'); + key.push_back('0' + i); + Value actualValue; + EXPECT_EQ(kvDelegatePtrS1_->Get(key, actualValue), NOT_FOUND); + std::string deviceId = std::to_string(i); + EXPECT_EQ(CheckLogTable(deviceId), NOT_FOUND); + EXPECT_EQ(CheckWaterMark(""), NOT_FOUND); + } +} + +/** + * @tc.name: RemoveDeviceTest003 + * @tc.desc: remove record with deviceId + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DistributedDBCloudKvStoreTest, RemoveDeviceTest003, TestSize.Level0) +{ + /** + * @tc.steps: step1. Insert three record (Key:k0, device:0, userId:user0), (Key:k1, device:1, userId:user0), + * (Key:k2, device:2, userId:0) + * * @tc.expected: step1. insert successfully + */ + int recordNum = 3; + InsertRecord(recordNum); + for (int i = 0; i < recordNum; i++) { + Key key; + key.push_back('k'); + key.push_back('0' + i); + SetFlag(key, LogInfoFlag::FLAG_CLOUD_WRITE); + SetDeviceId(key, std::to_string(i)); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); // sleep for 100ms + } + /** + * @tc.steps: step2. Check three Log record whether exist or not; + * * @tc.expected: step2. record exist + */ + for (int i = 0; i < recordNum; i++) { + Key key; + key.push_back('k'); + key.push_back('0' + i); + Value actualValue; + EXPECT_EQ(kvDelegatePtrS1_->Get(key, actualValue), OK); + std::string deviceId = std::to_string(i); + EXPECT_EQ(CheckLogTable(deviceId), OK); + EXPECT_EQ(CheckFlag(key, LogInfoFlag::FLAG_CLOUD_WRITE), OK); // flag become 0x2; + EXPECT_EQ(CheckWaterMark(""), OK); + } + /** + * @tc.steps: step3. remove "2" deviceId log data with FLAG_AND_DATA, remove "1" with FLAG_ONLY. + * * @tc.expected: step3. remove OK + */ + EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData("1", ClearMode::FLAG_ONLY), OK); + EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData("2", ClearMode::FLAG_AND_DATA), OK); + Key key1({'k', '1'}); + std::string deviceId1 = "1"; + Value actualValue; + EXPECT_EQ(kvDelegatePtrS1_->Get(key1, actualValue), OK); + EXPECT_EQ(CheckLogTable(deviceId1), NOT_FOUND); + EXPECT_EQ(CheckFlag(key1, LogInfoFlag::FLAG_LOCAL), OK); // flag become 0x2; + Key key2({'k', '2'}); + std::string deviceId2 = "2"; + EXPECT_EQ(kvDelegatePtrS1_->Get(key2, actualValue), NOT_FOUND); + EXPECT_EQ(CheckLogTable(deviceId2), NOT_FOUND); + EXPECT_EQ(CheckWaterMark(""), NOT_FOUND); +} + +/** + * @tc.name: RemoveDeviceTest004 + * @tc.desc: remove all record with userId and empty deviceId. + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DistributedDBCloudKvStoreTest, RemoveDeviceTest004, TestSize.Level0) +{ + /** + * @tc.steps: step1. Insert three record (Key:k0, device:0, userId:user0), (Key:k1, device:1, userId:user1), + * (Key:k2, device:2, userId:2) + * * @tc.expected: step1. insert successfully + */ + int recordNum = 3; + std::string userHead = "user"; + InsertRecord(recordNum); + for (int i = 0; i < recordNum; i++) { + Key key; + key.push_back('k'); + key.push_back('0' + i); + SetFlag(key, LogInfoFlag::FLAG_CLOUD_WRITE); + SetDeviceId(key, std::to_string(i)); + ChangeUserId(std::to_string(i), userHead + std::to_string(i)); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); // sleep for 100ms + EXPECT_EQ(CheckFlag(key, LogInfoFlag::FLAG_CLOUD_WRITE), OK); + } + EXPECT_EQ(CheckWaterMark(userHead + "0"), OK); + /** + * @tc.steps: step2. Check three Log record whether exist or not; + * * @tc.expected: step2. record exist + */ + for (int i = 0; i < recordNum; i++) { + Key key; + key.push_back('k'); + key.push_back('0' + i); + Value actualValue; + EXPECT_EQ(kvDelegatePtrS1_->Get(key, actualValue), OK); + std::string deviceId = std::to_string(i); + EXPECT_EQ(CheckLogTable(deviceId), OK); + } + /** + * @tc.steps: step3. remove "user1" userid log data with FLAG_AND_DATA, remove "user2" userid with FLAG_ONLY. + * * @tc.expected: step3. remove OK + */ + EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData("", "user0", ClearMode::FLAG_ONLY), OK); + EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData("", "user2", ClearMode::FLAG_AND_DATA), OK); + Key key0({'k', '0'}); + std::string deviceId1 = "0"; + Value actualValue; + EXPECT_EQ(kvDelegatePtrS1_->Get(key0, actualValue), OK); + EXPECT_EQ(CheckLogTable(deviceId1), NOT_FOUND); + EXPECT_EQ(CheckFlag(key0, LogInfoFlag::FLAG_LOCAL), OK); // flag become 0x2; + EXPECT_EQ(CheckWaterMark(userHead + "0"), NOT_FOUND); + Key key2({'k', '2'}); + std::string deviceId2 = "2"; + EXPECT_EQ(kvDelegatePtrS1_->Get(key2, actualValue), NOT_FOUND); + EXPECT_EQ(CheckLogTable(deviceId2), NOT_FOUND); +} + +/** + * @tc.name: RemoveDeviceTest005 + * @tc.desc: remove record with userId and deviceId. + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DistributedDBCloudKvStoreTest, RemoveDeviceTest005, TestSize.Level0) +{ + /** + * @tc.steps: step1. Insert three record (Key:k0, device:0, userId:user0), (Key:k1, device:1, userId:user1), + * (Key:k2, device:2, userId:2) + * * @tc.expected: step1. insert successfully + */ + int recordNum = 3; + InsertRecord(recordNum); + std::string userHead = "user"; + for (int i = 0; i < recordNum; i++) { + Key key; + key.push_back('k'); + key.push_back('0' + i); + SetFlag(key, LogInfoFlag::FLAG_CLOUD_WRITE); + SetDeviceId(key, std::to_string(i)); + ChangeUserId(std::to_string(i), userHead + std::to_string(i)); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); // sleep for 100ms + } + EXPECT_EQ(CheckWaterMark(userHead + "0"), OK); + /** + * @tc.steps: step2. Check three Log record whether exist or not; + * * @tc.expected: step2. record exist + */ + for (int i = 0; i < recordNum; i++) { + Key key; + key.push_back('k'); + key.push_back('0' + i); + Value actualValue; + EXPECT_EQ(kvDelegatePtrS1_->Get(key, actualValue), OK); + std::string deviceId = std::to_string(i); + EXPECT_EQ(CheckLogTable(deviceId), OK); + EXPECT_EQ(CheckFlag(key, LogInfoFlag::FLAG_CLOUD_WRITE), OK); + } + /** + * @tc.steps: step3. remove "user1" userid log data with FLAG_AND_DATA, remove "user0" userid with FLAG_ONLY. + * remove "user2" userid log data with dismatch deviceId, it cant not remove the data. + * * @tc.expected: step3. remove OK + */ + std::string deviceId0 = "0"; + std::string deviceId1 = "1"; + std::string deviceId2 = "2"; + EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(deviceId0, "user0", ClearMode::FLAG_ONLY), OK); + EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(deviceId1, "user1", ClearMode::FLAG_AND_DATA), OK); + EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(deviceId0, "user2", ClearMode::FLAG_AND_DATA), OK); + EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(deviceId0, "user2", ClearMode::FLAG_ONLY), OK); + Key key0({'k', '0'}); + Value actualValue; + EXPECT_EQ(kvDelegatePtrS1_->Get(key0, actualValue), OK); + EXPECT_EQ(CheckLogTable(deviceId0), NOT_FOUND); + EXPECT_EQ(CheckFlag(key0, LogInfoFlag::FLAG_LOCAL), OK); // flag become 0x2; + EXPECT_EQ(CheckWaterMark(userHead + "0"), NOT_FOUND); + Key key1({'k', '1'}); + EXPECT_EQ(kvDelegatePtrS1_->Get(key1, actualValue), NOT_FOUND); + EXPECT_EQ(CheckLogTable(deviceId1), NOT_FOUND); + Key key2({'k', '2'});; + EXPECT_EQ(kvDelegatePtrS1_->Get(key2, actualValue), OK); + EXPECT_EQ(CheckLogTable(deviceId2), OK); +} + +/** + * @tc.name: RemoveDeviceTest006 + * @tc.desc: remove record with userId and deviceId, and there are same hashKey record in log table. + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DistributedDBCloudKvStoreTest, RemoveDeviceTest006, TestSize.Level0) +{ + /** + * @tc.steps: step1. Insert three record (Key:k0, device:0, userId:user0), (Key:k1, device:1, userId:user1), + * (Key:k2, device:2, userId:2) + * * @tc.expected: step1. insert successfully + */ + int recordNum = 3; + InsertRecord(recordNum); + std::string userHead = "user"; + for (int i = 0; i < recordNum; i++) { + Key key; + key.push_back('k'); + key.push_back('0' + i); + SetFlag(key, LogInfoFlag::FLAG_CLOUD_WRITE); + SetDeviceId(key, std::to_string(i)); + ChangeUserId(std::to_string(i), userHead + std::to_string(i)); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); // sleep for 100ms + } + /** + * @tc.steps: step2. Check three Log record whether exist or not; + * * @tc.expected: step2. record exist + */ + for (int i = 0; i < recordNum; i++) { + Key key; + key.push_back('k'); + key.push_back('0' + i); + Value actualValue; + EXPECT_EQ(kvDelegatePtrS1_->Get(key, actualValue), OK); + std::string deviceId = std::to_string(i); + EXPECT_EQ(CheckLogTable(deviceId), OK); + } + /** + * @tc.steps: step3. Make log table all users's hashKey become same hashKey '99', and the hashKey in syncTable + * where device is deviceId1 also become '99',remove data with FLAG_AND_DATA flag. + * * @tc.expected: step3. remove OK + */ + std::string deviceId1 = "1"; + std::string deviceId2 = "2"; + std::string deviceId0 = "0"; + DistributedDBCloudKvStoreTest::ChangeHashKey(deviceId1); + EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(deviceId1, "user1", ClearMode::FLAG_AND_DATA), OK); + Key key1({'k', '1'}); + Value actualValue; + // there are other users with same hash_key connect with this data in sync_data table, cant not remove the data. + EXPECT_EQ(kvDelegatePtrS1_->Get(key1, actualValue), OK); + EXPECT_EQ(CheckLogTable(deviceId1), OK); // match user2 and user0; + EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(deviceId1, "user2", ClearMode::FLAG_AND_DATA), OK); + EXPECT_EQ(kvDelegatePtrS1_->Get(key1, actualValue), OK); + EXPECT_EQ(CheckLogTable(deviceId1), OK); // only user0 match the hash_key that same as device1. + EXPECT_EQ(CheckFlag(key1, LogInfoFlag::FLAG_CLOUD_WRITE), OK); // flag still 0x100; + EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(deviceId1, "user0", ClearMode::FLAG_AND_DATA), OK); + // all log have been deleted, so data would also be deleted. + EXPECT_EQ(kvDelegatePtrS1_->Get(key1, actualValue), NOT_FOUND); + EXPECT_EQ(CheckLogTable(deviceId1), NOT_FOUND); + EXPECT_EQ(CheckWaterMark(userHead + "0"), NOT_FOUND); +} + +/** + * @tc.name: RemoveDeviceTest007 + * @tc.desc: remove record with invalid deviceId and mode. + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DistributedDBCloudKvStoreTest, RemoveDeviceTest007, TestSize.Level0) +{ + /** + * @tc.steps: step1. Test removeDeviceData with invalid length deviceId. + * * @tc.expected: + */ + std::string deviceId = std::string(128, 'a'); + EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(deviceId, ClearMode::FLAG_AND_DATA), OK); + EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(deviceId, "user1", ClearMode::FLAG_AND_DATA), OK); + + std::string invaliDeviceId = std::string(129, 'a'); + EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(invaliDeviceId, ClearMode::FLAG_AND_DATA), INVALID_ARGS); + EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(invaliDeviceId, "user1", ClearMode::FLAG_AND_DATA), INVALID_ARGS); + + /** + * @tc.steps: step2. Test removeDeviceData with invalid mode. + * * @tc.expected: + */ + EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(deviceId, ClearMode::CLEAR_SHARED_TABLE), NOT_SUPPORT); + EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(deviceId, "user1", ClearMode::CLEAR_SHARED_TABLE), NOT_SUPPORT); +} + +/** + * @tc.name: RemoveDeviceTest008 + * @tc.desc: remove record without mode. + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonnghuang + */ +HWTEST_F(DistributedDBCloudKvStoreTest, RemoveDeviceTest008, TestSize.Level0) +{ + /** + * @tc.steps: step1. Insert three record (Key:k0, device:0, userId:user0), (Key:k1, device:1, userId:user1), + * (Key:k2, device:2, userId:2) + * * @tc.expected: step1. insert successfully + */ + int recordNum = 3; + InsertRecord(recordNum); + for (int i = 0; i < recordNum; i++) { + Key key; + key.push_back('k'); + key.push_back('0' + i); + SetFlag(key, LogInfoFlag::FLAG_CLOUD); + SetDeviceId(key, std::to_string(i)); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); // sleep for 100ms + } + + /** + * @tc.steps: step2. Check three Log record whether exist or not; + * * @tc.expected: step2. record exist + */ + for (int i = 0; i < recordNum; i++) { + Key key; + key.push_back('k'); + key.push_back('0' + i); + Value actualValue; + EXPECT_EQ(kvDelegatePtrS1_->Get(key, actualValue), OK); + } + /** + * @tc.steps: step3. Remove data without mode. + * * @tc.expected: step3. remove OK, there are not user record exist in log table. + */ + for (int i = 0; i < recordNum; i++) { + EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(std::to_string(i)), OK); + } + for (int i = 0; i < recordNum; i++) { + Key key; + key.push_back('k'); + key.push_back('0' + i); + Value actualValue; + EXPECT_EQ(kvDelegatePtrS1_->Get(key, actualValue), NOT_FOUND); + } +} + +/** + * @tc.name: RemoveDeviceTest009 + * @tc.desc: remove record without mode FLAG_AND_DATA. + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonnghuang + */ +HWTEST_F(DistributedDBCloudKvStoreTest, RemoveDeviceTest009, TestSize.Level0) +{ + /** + * @tc.steps: step1. Insert three record (Key:k0, device:0, userId:user0), (Key:k1, device:1, userId:user1), + * (Key:k2, device:2, userId:2) + * * @tc.expected: step1. insert successfully + */ + int recordNum = 3; + InsertRecord(recordNum); + for (int i = 0; i < recordNum; i++) { + Key key; + key.push_back('k'); + key.push_back('0' + i); + SetFlag(key, LogInfoFlag::FLAG_CLOUD); + SetDeviceId(key, std::to_string(i)); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); // sleep for 100ms + } + + /** + * @tc.steps: step2. Check three Log record whether exist or not; + * * @tc.expected: step2. record exist + */ + for (int i = 0; i < recordNum; i++) { + Key key; + key.push_back('k'); + key.push_back('0' + i); + Value actualValue; + EXPECT_EQ(kvDelegatePtrS1_->Get(key, actualValue), OK); + std::string deviceId = std::to_string(i); + EXPECT_EQ(CheckLogTable(deviceId), OK); + } + /** + * @tc.steps: step3. Remove data without mode FLAG_AND_DATA. + * * @tc.expected: step3. remove OK, there are not user record exist in log table. + */ + for (int i = 0; i < recordNum; i++) { + EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(std::to_string(i), ClearMode::FLAG_AND_DATA), OK); + } + for (int i = 0; i < recordNum; i++) { + Key key; + key.push_back('k'); + key.push_back('0' + i); + Value actualValue; + EXPECT_EQ(kvDelegatePtrS1_->Get(key, actualValue), OK); + std::string deviceId = std::to_string(i); + EXPECT_EQ(CheckLogTable(deviceId), NOT_FOUND); + } +} + +/** + * @tc.name: RemoveDeviceTest010 + * @tc.desc: remove record with invalid mode. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBCloudKvStoreTest, RemoveDeviceTest010, TestSize.Level0) +{ + std::string deviceId = std::string(128, 'a'); + EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(deviceId, "", ClearMode::FLAG_ONLY), INVALID_ARGS); + EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(deviceId, "", ClearMode::CLEAR_SHARED_TABLE), INVALID_ARGS); + EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(deviceId, "", ClearMode::FLAG_AND_DATA), INVALID_ARGS); + EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(deviceId, "", ClearMode::DEFAULT), OK); + EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData("", "", ClearMode::DEFAULT), OK); + EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData("", ClearMode::DEFAULT), OK); +} + +/** + * @tc.name: RemoveDeviceTest011 + * @tc.desc: remove record while conn is nullptr. + * @tc.type: FUNC + * @tc.require: + * @tc.author: caihaoting + */ +HWTEST_F(DistributedDBCloudKvStoreTest, RemoveDeviceTest011, TestSize.Level0) +{ + const KvStoreNbDelegate::Option option = {true, true}; + KvStoreNbDelegate *kvDelegateInvalidPtrS1_ = nullptr; + ASSERT_EQ(GetKvStore(kvDelegateInvalidPtrS1_, "RemoveDeviceTest011", option), OK); + ASSERT_NE(kvDelegateInvalidPtrS1_, nullptr); + auto kvStoreImpl = static_cast(kvDelegateInvalidPtrS1_); + EXPECT_EQ(kvStoreImpl->Close(), OK); + EXPECT_EQ(kvDelegateInvalidPtrS1_->RemoveDeviceData("", ClearMode::FLAG_ONLY), DB_ERROR); + EXPECT_EQ(kvDelegateInvalidPtrS1_->RemoveDeviceData("", "", ClearMode::FLAG_ONLY), DB_ERROR); + EXPECT_EQ(g_mgr.CloseKvStore(kvDelegateInvalidPtrS1_), OK); +} + +/** + * @tc.name: RemoveDeviceTest012 + * @tc.desc: Test remove all data from other device. + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(DistributedDBCloudKvStoreTest, RemoveDeviceTest012, TestSize.Level0) +{ + /** + * @tc.steps: step1. Insert three record, k0 from device sync, k1 from local write, k2 from cloud sync. + * * @tc.expected: step1. insert successfully + */ + int recordNum = 3; + InsertRecord(recordNum); + SetFlag({'k', '0'}, LogInfoFlag::FLAG_CLOUD); + SetFlag({'k', '1'}, LogInfoFlag::FLAG_LOCAL); + /** + * @tc.steps: step2. Remove data from device sync and cloud sync, and remove log. + * * @tc.expected: step2. All data and log are removed except data from local write. + */ + EXPECT_EQ(kvDelegatePtrS1_->RemoveDeviceData(), OK); + Value actualValue; + Value expectValue = {'k', '1'}; + EXPECT_EQ(kvDelegatePtrS1_->Get({'k', '1'}, actualValue), OK); + EXPECT_EQ(actualValue, expectValue); + EXPECT_EQ(kvDelegatePtrS1_->Get({'k', '0'}, actualValue), NOT_FOUND); + EXPECT_EQ(kvDelegatePtrS1_->Get({'k', '2'}, actualValue), NOT_FOUND); +} + +/** + * @tc.name: NormalSyncInvalid001 + * @tc.desc: Test normal push not sync and get cloud version. + * @tc.type: FUNC + * @tc.require: + * @tc.author: caihaoting + */ +HWTEST_F(DistributedDBCloudKvStoreTest, NormalSyncInvalid001, TestSize.Level0) +{ + Key key = {'k'}; + Value expectValue = {'v'}; + ASSERT_EQ(kvDelegatePtrS1_->Put(key, expectValue), OK); + kvDelegatePtrS1_->SetGenCloudVersionCallback([](const std::string &origin) { + LOGW("origin is %s", origin.c_str()); + return origin + "1"; + }); + Value actualValue; + EXPECT_EQ(kvDelegatePtrS1_->Get(key, actualValue), OK); + EXPECT_EQ(actualValue, expectValue); + kvDelegatePtrS1_->SetGenCloudVersionCallback(nullptr); + auto result = kvDelegatePtrS1_->GetCloudVersion(""); + EXPECT_EQ(result.first, NOT_FOUND); +} + +/** + * @tc.name: NormalSyncInvalid002 + * @tc.desc: Test normal push sync and use invalidDevice to get cloud version. + * @tc.type: FUNC + * @tc.require: + * @tc.author: caihaoting + */ +HWTEST_F(DistributedDBCloudKvStoreTest, NormalSyncInvalid002, TestSize.Level0) +{ + Key key = {'k'}; + Value expectValue = {'v'}; + ASSERT_EQ(kvDelegatePtrS1_->Put(key, expectValue), OK); + kvDelegatePtrS1_->SetGenCloudVersionCallback([](const std::string &origin) { + LOGW("origin is %s", origin.c_str()); + return origin + "1"; + }); + BlockSync(kvDelegatePtrS1_, OK, g_CloudSyncoption); + for (const auto &table : lastProcess_.tableProcess) { + EXPECT_EQ(table.second.upLoadInfo.total, 1u); + EXPECT_EQ(table.second.upLoadInfo.insertCount, 1u); + } + BlockSync(kvDelegatePtrS2_, OK, g_CloudSyncoption); + for (const auto &table : lastProcess_.tableProcess) { + EXPECT_EQ(table.second.downLoadInfo.total, 2u); // download 2 records + EXPECT_EQ(table.second.downLoadInfo.insertCount, 2u); // download 2 records + } + Value actualValue; + EXPECT_EQ(kvDelegatePtrS2_->Get(key, actualValue), OK); + EXPECT_EQ(actualValue, expectValue); + kvDelegatePtrS1_->SetGenCloudVersionCallback(nullptr); + std::string invalidDevice = std::string(DBConstant::MAX_DEV_LENGTH + 1, '0'); + auto result = kvDelegatePtrS2_->GetCloudVersion(invalidDevice); + EXPECT_EQ(result.first, INVALID_ARGS); +} + +/** + * @tc.name: NormalSyncInvalid003 + * @tc.desc: Test normal push sync for add data while conn is nullptr. + * @tc.type: FUNC + * @tc.require: + * @tc.author: caihaoting + */ +HWTEST_F(DistributedDBCloudKvStoreTest, NormalSyncInvalid003, TestSize.Level0) +{ + const KvStoreNbDelegate::Option option = {true, true}; + KvStoreNbDelegate *kvDelegateInvalidPtrS1_ = nullptr; + ASSERT_EQ(GetKvStore(kvDelegateInvalidPtrS1_, "NormalSyncInvalid003", option), OK); + ASSERT_NE(kvDelegateInvalidPtrS1_, nullptr); + Key key = {'k'}; + Value expectValue = {'v'}; + ASSERT_EQ(kvDelegateInvalidPtrS1_->Put(key, expectValue), OK); + kvDelegateInvalidPtrS1_->SetGenCloudVersionCallback([](const std::string &origin) { + LOGW("origin is %s", origin.c_str()); + return origin + "1"; + }); + BlockSync(kvDelegateInvalidPtrS1_, OK, g_CloudSyncoption); + for (const auto &table : lastProcess_.tableProcess) { + EXPECT_EQ(table.second.upLoadInfo.total, 1u); + EXPECT_EQ(table.second.upLoadInfo.insertCount, 1u); + } + Value actualValue; + EXPECT_EQ(kvDelegateInvalidPtrS1_->Get(key, actualValue), OK); + EXPECT_EQ(actualValue, expectValue); + auto kvStoreImpl = static_cast(kvDelegateInvalidPtrS1_); + EXPECT_EQ(kvStoreImpl->Close(), OK); + kvDelegateInvalidPtrS1_->SetGenCloudVersionCallback(nullptr); + auto result = kvDelegateInvalidPtrS1_->GetCloudVersion(""); + EXPECT_EQ(result.first, DB_ERROR); + EXPECT_EQ(g_mgr.CloseKvStore(kvDelegateInvalidPtrS1_), OK); +} + +/** + * @tc.name: NormalSyncInvalid004 + * @tc.desc: Test normal push sync use GetDeviceEntries while conn is nullptr. + * @tc.type: FUNC + * @tc.require: + * @tc.author: caihaoting + */ +HWTEST_F(DistributedDBCloudKvStoreTest, NormalSyncInvalid004, TestSize.Level0) +{ + const KvStoreNbDelegate::Option option = {true, true}; + KvStoreNbDelegate *kvDelegateInvalidPtrS2_ = nullptr; + ASSERT_EQ(GetKvStore(kvDelegateInvalidPtrS2_, "NormalSyncInvalid004", option), OK); + ASSERT_NE(kvDelegateInvalidPtrS2_, nullptr); + /** + * @tc.steps: step1. store1 put (k1,v1) store2 put (k2,v2) + * @tc.expected: step1. both put ok + */ + communicatorAggregator_->SetLocalDeviceId("DEVICES_A"); + kvDelegatePtrS1_->SetGenCloudVersionCallback([](const std::string &origin) { + LOGW("origin is %s", origin.c_str()); + return origin + "1"; + }); + kvDelegateInvalidPtrS2_->SetGenCloudVersionCallback([](const std::string &origin) { + LOGW("origin is %s", origin.c_str()); + return origin + "1"; + }); + Key key1 = {'k', '1'}; + Value expectValue1 = {'v', '1'}; + Key key2 = {'k', '2'}; + Value expectValue2 = {'v', '2'}; + ASSERT_EQ(kvDelegatePtrS1_->Put(key1, expectValue1), OK); + ASSERT_EQ(kvDelegateInvalidPtrS2_->Put(key2, expectValue2), OK); + /** + * @tc.steps: step2. both store1 and store2 sync while conn is nullptr + * @tc.expected: step2. both sync ok, and store2 got (k1,v1) store1 not exist (k2,v2) + */ + BlockSync(kvDelegatePtrS1_, OK, g_CloudSyncoption); + LOGW("Store1 sync end"); + communicatorAggregator_->SetLocalDeviceId("DEVICES_B"); + BlockSync(kvDelegateInvalidPtrS2_, OK, g_CloudSyncoption); + LOGW("Store2 sync end"); + Value actualValue; + EXPECT_EQ(kvDelegateInvalidPtrS2_->Get(key1, actualValue), OK); + + /** + * @tc.steps: step3. use GetDeviceEntries while conn is nullptr + * @tc.expected: step3. DB_ERROR + */ + auto kvStoreImpl = static_cast(kvDelegateInvalidPtrS2_); + EXPECT_EQ(kvStoreImpl->Close(), OK); + std::vector entries; + EXPECT_EQ(kvDelegateInvalidPtrS2_->GetDeviceEntries(std::string("DEVICES_A"), entries), DB_ERROR); + EXPECT_EQ(entries.size(), 0u); // 1 record + communicatorAggregator_->SetLocalDeviceId("DEVICES_A"); + EXPECT_EQ(actualValue, expectValue1); + EXPECT_EQ(kvDelegatePtrS1_->Get(key2, actualValue), NOT_FOUND); + + kvDelegatePtrS1_->SetGenCloudVersionCallback(nullptr); + kvDelegateInvalidPtrS2_->SetGenCloudVersionCallback(nullptr); + EXPECT_EQ(g_mgr.CloseKvStore(kvDelegateInvalidPtrS2_), OK); +} + +/** + * @tc.name: NormalSyncInvalid005 + * @tc.desc: Test normal sync with invalid parm. + * @tc.type: FUNC + * @tc.require: + * @tc.author: caihaoting + */ +HWTEST_F(DistributedDBCloudKvStoreTest, NormalSyncInvalid005, TestSize.Level0) +{ + Key key = {'k'}; + Value expectValue = {'v'}; + ASSERT_EQ(kvDelegatePtrS1_->Put(key, expectValue), OK); + auto devices = g_CloudSyncoption.devices; + EXPECT_EQ(kvDelegatePtrS1_->Sync(devices, SyncMode::SYNC_MODE_CLOUD_MERGE, nullptr), NOT_SUPPORT); + Query query = Query::Select().Range({}, {}); + EXPECT_EQ(kvDelegatePtrS1_->Sync(devices, SyncMode::SYNC_MODE_CLOUD_MERGE, nullptr, query, true), NOT_SUPPORT); + auto mode = g_CloudSyncoption.mode; + EXPECT_EQ(kvDelegatePtrS1_->Sync(devices, mode, nullptr, query, true), NOT_SUPPORT); + auto kvStoreImpl = static_cast(kvDelegatePtrS1_); + EXPECT_EQ(kvStoreImpl->Close(), OK); + BlockSync(kvDelegatePtrS1_, OK, g_CloudSyncoption, DB_ERROR); + EXPECT_EQ(kvDelegatePtrS1_->Sync(devices, mode, nullptr), DB_ERROR); + EXPECT_EQ(kvDelegatePtrS1_->Sync(devices, mode, nullptr, query, true), DB_ERROR); +} + +/** + * @tc.name: NormalSyncInvalid006 + * @tc.desc: Test normal sync set cloudDB while cloudDB is empty and conn is nullptr. + * @tc.type: FUNC + * @tc.require: + * @tc.author: caihaoting + */ +HWTEST_F(DistributedDBCloudKvStoreTest, NormalSyncInvalid006, TestSize.Level0) +{ + /** + * @tc.steps: step1. set cloudDB while cloudDB is empty + * @tc.expected: step1. INVALID_ARGS + */ + std::map> cloudDbs; + EXPECT_EQ(kvDelegatePtrS1_->SetCloudDB(cloudDbs), INVALID_ARGS); + /** + * @tc.steps: step2. set cloudDB while conn is nullptr + * @tc.expected: step2. DB_ERROR + */ + auto kvStoreImpl = static_cast(kvDelegatePtrS1_); + EXPECT_EQ(kvStoreImpl->Close(), OK); + cloudDbs[USER_ID] = virtualCloudDb_; + EXPECT_EQ(kvDelegatePtrS1_->SetCloudDB(cloudDbs), DB_ERROR); +} + +/** + * @tc.name: NormalSyncInvalid007 + * @tc.desc: Test normal sync set cloudDb schema while conn is nullptr. + * @tc.type: FUNC + * @tc.require: + * @tc.author: caihaoting + */ +HWTEST_F(DistributedDBCloudKvStoreTest, NormalSyncInvalid007, TestSize.Level0) +{ + /** + * @tc.steps: step1. set cloudDB schema while conn is nullptr + * @tc.expected: step1. DB_ERROR + */ + auto kvStoreImpl = static_cast(kvDelegatePtrS1_); + EXPECT_EQ(kvStoreImpl->Close(), OK); + std::map schemas; + schemas[USER_ID] = GetDataBaseSchema(true); + EXPECT_EQ(kvDelegatePtrS1_->SetCloudDbSchema(schemas), DB_ERROR); +} + +/** + * @tc.name: NormalSyncInvalid008 + * @tc.desc: Test SetCloudSyncConfig with invalid parm. + * @tc.type: FUNC + * @tc.require: + * @tc.author: caihaoting + */ +HWTEST_F(DistributedDBCloudKvStoreTest, NormalSyncInvalid008, TestSize.Level0) +{ + /** + * @tc.steps: step1. SetCloudSyncConfig with invalid maxUploadCount. + * @tc.expected: step1. INVALID_ARGS + */ + CloudSyncConfig config; + int maxUploadCount = 0; + config.maxUploadCount = maxUploadCount; + EXPECT_EQ(kvDelegatePtrS1_->SetCloudSyncConfig(config), INVALID_ARGS); + maxUploadCount = 2001; + config.maxUploadCount = maxUploadCount; + EXPECT_EQ(kvDelegatePtrS1_->SetCloudSyncConfig(config), INVALID_ARGS); + maxUploadCount = 50; + config.maxUploadCount = maxUploadCount; + EXPECT_EQ(kvDelegatePtrS1_->SetCloudSyncConfig(config), OK); + + /** + * @tc.steps: step2. SetCloudSyncConfig with invalid maxUploadSize. + * @tc.expected: step2. INVALID_ARGS + */ + int maxUploadSize = 1023; + config.maxUploadSize = maxUploadSize; + EXPECT_EQ(kvDelegatePtrS1_->SetCloudSyncConfig(config), INVALID_ARGS); + maxUploadSize = 128 * 1024 * 1024 + 1; + config.maxUploadSize = maxUploadSize; + EXPECT_EQ(kvDelegatePtrS1_->SetCloudSyncConfig(config), INVALID_ARGS); + maxUploadSize = 10240; + config.maxUploadSize = maxUploadSize; + EXPECT_EQ(kvDelegatePtrS1_->SetCloudSyncConfig(config), OK); + + /** + * @tc.steps: step3. SetCloudSyncConfig with invalid maxRetryConflictTimes. + * @tc.expected: step3. INVALID_ARGS + */ + int maxRetryConflictTimes = -2; + config.maxRetryConflictTimes = maxRetryConflictTimes; + EXPECT_EQ(kvDelegatePtrS1_->SetCloudSyncConfig(config), INVALID_ARGS); + maxRetryConflictTimes = 2; + config.maxRetryConflictTimes = maxRetryConflictTimes; + EXPECT_EQ(kvDelegatePtrS1_->SetCloudSyncConfig(config), OK); + + /** + * @tc.steps: step4. SetCloudSyncConfig while conn is nullptr + * @tc.expected: step4. DB_ERROR + */ + auto kvStoreImpl = static_cast(kvDelegatePtrS1_); + EXPECT_EQ(kvStoreImpl->Close(), OK); + EXPECT_EQ(kvDelegatePtrS1_->SetCloudSyncConfig(config), DB_ERROR); +} +} 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 9401a1f5b544af815e13db53369b97342eaa468e..06fe29202b63de79726d0c930cf1a362f4b0e5b5 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 @@ -22,6 +22,7 @@ #include "mock_asset_loader.h" #include "process_system_api_adapter_impl.h" #include "relational_store_client.h" +#include "relational_store_delegate_impl.h" #include "relational_store_instance.h" #include "relational_store_manager.h" #include "runtime_config.h" @@ -31,6 +32,7 @@ #include "virtual_asset_loader.h" #include "virtual_cloud_data_translate.h" #include "virtual_cloud_db.h" +#include "virtual_communicator_aggregator.h" #include #include @@ -205,6 +207,20 @@ void UpdateLocalData(sqlite3 *&db, const std::string &tableName, const Assets &a SQLiteUtils::ResetStatement(stmt, true, errCode); } +void UpdateLocalData(sqlite3 *&db, const std::string &tableName, const Assets &assets, int32_t begin, int32_t end) +{ + int errCode; + std::vector assetBlob; + const string sql = "update " + tableName + " set assets=? " + "where id>=" + std::to_string(begin) + + " and id<=" + std::to_string(end) + ";"; + sqlite3_stmt *stmt = nullptr; + ASSERT_EQ(SQLiteUtils::GetStatement(db, sql, stmt), E_OK); + assetBlob = g_virtualCloudDataTranslate->AssetsToBlob(assets); + ASSERT_EQ(SQLiteUtils::BindBlobToStatement(stmt, 1, assetBlob, false), E_OK); + EXPECT_EQ(SQLiteUtils::StepWithRetry(stmt), SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)); + SQLiteUtils::ResetStatement(stmt, true, errCode); +} + void DeleteLocalRecord(sqlite3 *&db, int64_t begin, int64_t count, const std::string &tableName) { ASSERT_NE(db, nullptr); @@ -240,9 +256,9 @@ void UpdateCloudDBData(int64_t begin, int64_t count, int64_t gidStart, int64_t v int QueryStatusCallback(void *data, int count, char **colValue, char **colName) { auto status = static_cast *>(data); - int base = 10; + const int decimal = 10; for (int i = 0; i < count; i++) { - status->push_back(strtol(colValue[0], nullptr, base)); + status->push_back(strtol(colValue[0], nullptr, decimal)); } return 0; } @@ -412,6 +428,7 @@ protected: void DataStatusTest006(); void DataStatusTest007(); sqlite3 *db = nullptr; + VirtualCommunicatorAggregator *communicatorAggregator_ = nullptr; }; void DistributedDBCloudSyncerDownloadAssetsTest::SetUpTestCase(void) @@ -454,6 +471,9 @@ void DistributedDBCloudSyncerDownloadAssetsTest::SetUp(void) ASSERT_EQ(g_delegate->SetCloudDbSchema(dataBaseSchema), DBStatus::OK); g_cloudStoreHook = (ICloudSyncStorageHook *) GetRelationalStore(); ASSERT_NE(g_cloudStoreHook, nullptr); + communicatorAggregator_ = new (std::nothrow) VirtualCommunicatorAggregator(); + ASSERT_TRUE(communicatorAggregator_ != nullptr); + RuntimeContext::GetInstance()->SetCommunicatorAggregator(communicatorAggregator_); } void DistributedDBCloudSyncerDownloadAssetsTest::TearDown(void) @@ -465,6 +485,9 @@ void DistributedDBCloudSyncerDownloadAssetsTest::TearDown(void) if (DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir) != 0) { LOGE("rm test db files error."); } + RuntimeContext::GetInstance()->SetCommunicatorAggregator(nullptr); + communicatorAggregator_ = nullptr; + RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(nullptr); } void DistributedDBCloudSyncerDownloadAssetsTest::CheckLocaLAssets(const std::string &tableName, @@ -1356,7 +1379,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId017, TestSize.Le * @tc.expected: step2. return OK. */ CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK); - CheckCursorData(ASSETS_TABLE_NAME, localCount + 1); + CheckCursorData(ASSETS_TABLE_NAME, 1); } /** @@ -1743,6 +1766,164 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId022, TestSize.Le g_virtualCloudDb->ForkUpload(nullptr); } +/** + * @tc.name: FillAssetId023 + * @tc.desc: Test if BatchUpdate with local assets missing + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangtao + */ +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId023, TestSize.Level0) +{ + /** + * @tc.steps:step1. set extend size missing then sync, check the asseid. + * @tc.expected: step1. return OK. + */ + int localCount = 50; + InsertLocalData(db, 0, localCount, ASSETS_TABLE_NAME); + std::atomic count = 1; + g_virtualCloudDb->SetClearExtend(count); + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, DBStatus::CLOUD_ERROR); + CheckLocaLAssets(ASSETS_TABLE_NAME, "0", {}); + + /** + * @tc.steps:step2. set extend size normal and BatchUpdate with local assets missing then sync, check the asseid. + * @tc.expected: step2. return OK. + */ + g_virtualCloudDb->SetClearExtend(0); + + int uploadFailId = 0; + g_virtualCloudDb->ForkInsertConflict([&uploadFailId](const std::string &tableName, VBucket &extend, VBucket &record, + std::vector &cloudDataVec) { + uploadFailId++; + if (uploadFailId == 25) { // 25 is the middle record + extend[CloudDbConstant::ERROR_FIELD] = static_cast(DBStatus::LOCAL_ASSET_NOT_FOUND); + return DBStatus::LOCAL_ASSET_NOT_FOUND; + } + return OK; + }); + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK); + CheckLocaLAssets(ASSETS_TABLE_NAME, "10", {}); +} + +/** + * @tc.name: FillAssetId024 + * @tc.desc: Test if BatchUpdate with multiple local assets missing + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangtao + */ +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId024, TestSize.Level0) +{ + /** + * @tc.steps:step1. set extend size missing then sync, check the asseid. + * @tc.expected: step1. return OK. + */ + int localCount = 50; + InsertLocalData(db, 0, localCount, ASSETS_TABLE_NAME); + std::atomic count = 1; + g_virtualCloudDb->SetClearExtend(count); + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, DBStatus::CLOUD_ERROR); + CheckLocaLAssets(ASSETS_TABLE_NAME, "0", {}); + + /** + * @tc.steps:step2. set extend size normal and BatchUpdate with 3 local assets missing then sync, check the asseid. + * @tc.expected: step2. return OK. + */ + g_virtualCloudDb->SetClearExtend(0); + + int uploadFailId = 0; + g_virtualCloudDb->ForkInsertConflict([&uploadFailId](const std::string &tableName, VBucket &extend, VBucket &record, + std::vector &cloudDataVec) { + uploadFailId++; + if (uploadFailId >= 25 && uploadFailId <= 27) { // 25-27 is the middle record + extend[CloudDbConstant::ERROR_FIELD] = static_cast(DBStatus::LOCAL_ASSET_NOT_FOUND); + return DBStatus::LOCAL_ASSET_NOT_FOUND; + } + return OK; + }); + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK); + CheckLocaLAssets(ASSETS_TABLE_NAME, "10", {}); +} + +/** + * @tc.name: FillAssetId025 + * @tc.desc: Test if BatchInsert with local assets missing and missing record added into successCount + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangtao + */ +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId025, TestSize.Level0) +{ + CloudSyncConfig config; + config.maxUploadCount = 200; // max upload 200 + g_delegate->SetCloudSyncConfig(config); + /** + * @tc.steps:step1. insert local data. + * @tc.expected: step1. return OK. + */ + int localCount = 40; + InsertLocalData(db, 0, localCount, ASSETS_TABLE_NAME); + + /** + * @tc.steps:step2. BatchInsert with local assets missing then sync, check the asseid. + * @tc.expected: step2. return OK. + */ + int uploadFailId = 0; + g_virtualCloudDb->ForkInsertConflict([&uploadFailId](const std::string &tableName, VBucket &extend, VBucket &record, + std::vector &cloudDataVec) { + uploadFailId++; + if (uploadFailId == 25) { // 25 is the middle record + extend[CloudDbConstant::ERROR_FIELD] = static_cast(DBStatus::LOCAL_ASSET_NOT_FOUND); + return DBStatus::LOCAL_ASSET_NOT_FOUND; + } + return OK; + }); + g_syncProcess = {}; + Query query = Query::Select().FromTable({ ASSETS_TABLE_NAME }); + std::vector expectProcess = { + { PROCESSING, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } }, + { FINISHED, { 0, 0, 0, 0 }, { 1, 40, 40, 0 } } // 1 is index, 40 is count + }; + + /** + * @tc.steps:step3. Check if sync process consistent with exptectProcess + * @tc.expected: step3. return OK. + */ + int index = 0; + CloudSyncStatusCallback callback = [&index, &expectProcess](const std::map &process) { + g_syncProcess = std::move(process.begin()->second); + ASSERT_LT(index, 2); + for (const auto &[tableName, info]: g_syncProcess.tableProcess) { + EXPECT_EQ(info.process, expectProcess[index].process); + EXPECT_EQ(info.upLoadInfo.batchIndex, expectProcess[index].upLoadInfo.batchIndex); + EXPECT_EQ(info.upLoadInfo.total, expectProcess[index].upLoadInfo.total); + EXPECT_EQ(info.upLoadInfo.successCount, expectProcess[index].upLoadInfo.successCount); + EXPECT_EQ(tableName, ASSETS_TABLE_NAME); + } + index++; + if (g_syncProcess.process == FINISHED) { + g_processCondition.notify_one(); + ASSERT_EQ(g_syncProcess.errCode, DBStatus::OK); + } + }; + ASSERT_EQ(g_delegate->Sync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, query, callback, SYNC_WAIT_TIME), OK); + WaitForSyncFinish(g_syncProcess, SYNC_WAIT_TIME); + + /** + * @tc.steps:step4. Check assets results + * @tc.expected: step4. return OK. + */ + int beginFailFillNum = 49; + int endFailFillNum = 50; + std::set indexes; + for (int i = beginFailFillNum; i <= endFailFillNum; i++) { + indexes.insert(i); + } + CheckLocaLAssets(ASSETS_TABLE_NAME, "10", indexes); + g_virtualCloudDb->ForkUpload(nullptr); +} + /** * @tc.name: ConsistentFlagTest001 * @tc.desc:Assets are the different, check the 0x20 bit of flag after sync @@ -2366,5 +2547,158 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, RecordLockFuncTest001, Test */ CheckLockStatus(db, 0, 99, LockStatus::UNLOCK); } + +/** + * @tc.name: RecordLockFuncTest002 + * @tc.desc: Compensated synchronization, Locked data has not been synchronized. The first synchronization data is + * based on the cloud, and the last synchronization data is based on the device. + * @tc.type: FUNC + * @tc.author: lijun + */ +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, RecordLockFuncTest002, TestSize.Level0) +{ + /** + * @tc.steps:step1. init local data, modify data Status and initiate synchronization + * @tc.expected: step1. return OK. + */ + int localCount = 120; + InsertLocalData(db, 0, localCount, ASSETS_TABLE_NAME, true); + std::vector> hashKey; + CloudDBSyncUtilsTest::GetHashKey(ASSETS_TABLE_NAME, " data_key >=100 ", db, hashKey); + EXPECT_EQ(Lock(ASSETS_TABLE_NAME, hashKey, db), OK); + CheckLockStatus(db, 0, 99, LockStatus::UNLOCK); + CheckLockStatus(db, 100, 119, LockStatus::LOCK); + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_FORCE_PULL, DBStatus::OK); + + /** + * @tc.steps:step2. Check the synchronization result and log table status + * @tc.expected: step2.100-109 is LOCK_CHANGE. + */ + CheckLockStatus(db, 0, 99, LockStatus::UNLOCK); + CheckLockStatus(db, 100, 119, LockStatus::LOCK); + UpdateLocalData(db, ASSETS_TABLE_NAME, ASSETS_COPY1, 100, 109); + CheckLockStatus(db, 100, 109, LockStatus::LOCK_CHANGE); + CheckLockStatus(db, 110, 119, LockStatus::LOCK); + + /** + * @tc.steps:step3. Synchronize and check the lock_change data status + * @tc.expected: step3.100-119 is LOCK_CHANGE. + */ + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK); + CheckLockStatus(db, 0, 99, LockStatus::UNLOCK); + CheckLockStatus(db, 100, 119, LockStatus::LOCK_CHANGE); + + /** + * @tc.steps:step4. Unlock,the lock_change data status changes to unlocking + * @tc.expected: step4.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); + + /** + * @tc.steps:step5. Lock,the unlocking data status changes to lock_change + * @tc.expected: step5.100-119 is LOCK_CHANGE. + */ + EXPECT_EQ(Lock(ASSETS_TABLE_NAME, hashKey, db), OK); + CheckLockStatus(db, 0, 99, LockStatus::UNLOCK); + CheckLockStatus(db, 100, 119, LockStatus::LOCK_CHANGE); + + /** + * @tc.steps:step6. Synchronize and check the lock_change data status + * @tc.expected: step6.100-119 is LOCK_CHANGE. + */ + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_FORCE_PUSH, DBStatus::OK); + CheckLockStatus(db, 0, 99, LockStatus::UNLOCK); + CheckLockStatus(db, 100, 119, LockStatus::LOCK_CHANGE); + + /** + * @tc.steps:step7. Unlock,the lock_change data status changes to unlocking + * @tc.expected: step7.100-119 is UNLOCKING. + */ + EXPECT_EQ(UnLock(ASSETS_TABLE_NAME, hashKey, db), WAIT_COMPENSATED_SYNC); + CheckLockStatus(db, 100, 119, LockStatus::UNLOCKING); + + /** + * @tc.steps:step8. Synchronize data + * @tc.expected: step8.return OK. + */ + std::mutex mtx; + std::condition_variable cv; + int queryIdx = 0; + g_virtualCloudDb->ForkQuery([&](const std::string &, VBucket &) { + LOGD("query index:%d", ++queryIdx); + if (queryIdx == 5) { // 5 is compensated sync + mtx.lock(); + 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); + } + + /** + * @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. + */ + CheckLockStatus(db, 0, 119, LockStatus::UNLOCK); +} + +/** + * @tc.name: CloudTaskStatusTest001 + * @tc.desc: Test get cloud task status + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, CloudTaskStatusTest001, TestSize.Level1) +{ + /** + * @tc.steps:step1. init data + * @tc.expected: step1. return OK. + */ + int cloudCount = 10; // 10 is num of cloud + InsertCloudDBData(0, cloudCount, 0, ASSETS_TABLE_NAME); + + /** + * @tc.steps:step2. Sync and get cloud task status + * @tc.expected: step2. OK + */ + g_virtualCloudDb->SetBlockTime(1000); + std::thread syncThread([&]() { + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, DBStatus::OK); + }); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + SyncProcess process1 = g_delegate->GetCloudTaskStatus(1); + EXPECT_EQ(process1.errCode, OK); + syncThread.join(); + /** + * @tc.steps:step3. Get cloud task status after sync finish + * @tc.expected: step3. NOT_FOUND + */ + SyncProcess process2 = g_delegate->GetCloudTaskStatus(1); + EXPECT_EQ(process2.errCode, NOT_FOUND); + + /** + * @tc.steps:step4. Get cloud task status after DB closed + * @tc.expected: step4. DB_ERROR + */ + auto delegateImpl = static_cast(g_delegate); + EXPECT_EQ(delegateImpl->Close(), DBStatus::OK); + SyncProcess process3 = g_delegate->GetCloudTaskStatus(1); + EXPECT_EQ(process3.errCode, DB_ERROR); +} } // namespace #endif // RELATIONAL_STORE diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_download_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_download_test.cpp index 2d0619ec26a142e95d9c7814c814090c21afdd00..af0442cd21834ec5ba9a72d06a66e41440f5be9b 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_download_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_download_test.cpp @@ -19,6 +19,7 @@ #include "mock_icloud_sync_storage_interface.h" #include "time_helper.h" #include "types_export.h" +#include "virtual_communicator_aggregator.h" using namespace testing::ext; using namespace testing; @@ -35,6 +36,8 @@ public: static void TearDownTestCase(void); void SetUp(); void TearDown(); +protected: + VirtualCommunicatorAggregator *communicatorAggregator_ = nullptr; }; MockICloudSyncStorageInterface *g_iCloud = nullptr; @@ -65,10 +68,16 @@ void DistributedDBCloudSyncerDownloadTest::TearDownTestCase(void) void DistributedDBCloudSyncerDownloadTest::SetUp(void) { DistributedDBToolsUnitTest::PrintTestCaseInfo(); + communicatorAggregator_ = new (std::nothrow) VirtualCommunicatorAggregator(); + ASSERT_TRUE(communicatorAggregator_ != nullptr); + RuntimeContext::GetInstance()->SetCommunicatorAggregator(communicatorAggregator_); } void DistributedDBCloudSyncerDownloadTest::TearDown(void) { + RuntimeContext::GetInstance()->SetCommunicatorAggregator(nullptr); + communicatorAggregator_ = nullptr; + RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(nullptr); } std::vector GetRetCloudData(uint64_t cnt) @@ -762,6 +771,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadTest, DownloadMockTest008, TestSize.Lev g_cloudSyncer->SetCloudWaterMarks(param.tableName, param.cloudWaterMark); ICloudSyncer::SyncParam actualParam; EXPECT_EQ(g_cloudSyncer->CallGetSyncParamForDownload(taskId, actualParam), E_OK); + expectCloudWaterMark = ""; EXPECT_EQ(actualParam.cloudWaterMark, expectCloudWaterMark); g_cloudSyncer->SetTaskResume(taskId, false); 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 b62dadef9f6546dcde0ec84ff645cf53a5f15a2c..74b51338722f54342a699f5257e8506a56c7b800 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 @@ -30,6 +30,7 @@ #include "virtual_asset_loader.h" #include "virtual_cloud_data_translate.h" #include "virtual_cloud_db.h" +#include "virtual_communicator_aggregator.h" #include #include @@ -124,6 +125,7 @@ protected: void UpdateCloudAssets(Asset &asset, Assets &assets, const std::string &version); void CheckUploadAbnormal(OpType opType, int64_t expCnt, bool isCompensated = false); sqlite3 *db = nullptr; + VirtualCommunicatorAggregator *communicatorAggregator_ = nullptr; }; void DistributedDBCloudSyncerLockTest::SetUpTestCase(void) @@ -147,6 +149,9 @@ void DistributedDBCloudSyncerLockTest::SetUp(void) Init(); g_cloudStoreHook = (ICloudSyncStorageHook *) GetRelationalStore(); ASSERT_NE(g_cloudStoreHook, nullptr); + communicatorAggregator_ = new (std::nothrow) VirtualCommunicatorAggregator(); + ASSERT_TRUE(communicatorAggregator_ != nullptr); + RuntimeContext::GetInstance()->SetCommunicatorAggregator(communicatorAggregator_); } void DistributedDBCloudSyncerLockTest::TearDown(void) @@ -158,6 +163,9 @@ void DistributedDBCloudSyncerLockTest::TearDown(void) if (DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir) != 0) { LOGE("rm test db files error."); } + RuntimeContext::GetInstance()->SetCommunicatorAggregator(nullptr); + communicatorAggregator_ = nullptr; + RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(nullptr); } void DistributedDBCloudSyncerLockTest::Init() @@ -670,6 +678,157 @@ HWTEST_F(DistributedDBCloudSyncerLockTest, QueryCursorTest002, TestSize.Level0) CallSync(option); } +/** + * @tc.name: DownloadAssetStatusTest001 + * @tc.desc: Test download assets status for INSERT + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBCloudSyncerLockTest, DownloadAssetStatusTest001, TestSize.Level0) +{ + /** + * @tc.steps:step1. init cloud assert {a, b1, b2} + * @tc.expected: step1. return ok. + */ + int count = 1; + InsertCloudDBData(0, count, 0, ASSETS_TABLE_NAME); + /** + * @tc.steps:step2. sync + * @tc.expected: step2. assets status is INSERT before download. + */ + g_virtualAssetLoader->ForkDownload([](std::map &assets) { + for (const auto &item: assets) { + for (const auto &asset: item.second) { + EXPECT_EQ(asset.status, static_cast(AssetStatus::INSERT)); + } + } + }); + CloudSyncOption option = PrepareOption(Query::Select().FromTable({ ASSETS_TABLE_NAME }), LockAction::INSERT); + CallSync(option); + CheckAssetStatusNormal(); + g_virtualAssetLoader->ForkDownload(nullptr); +} + +/** + * @tc.name: DownloadAssetStatusTest002 + * @tc.desc: Test download assets status for DELETE + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBCloudSyncerLockTest, DownloadAssetStatusTest002, TestSize.Level0) +{ + /** + * @tc.steps:step1. init cloud assert {a, b1, b2} and sync to local + * @tc.expected: step1. return ok. + */ + int count = 1; + InsertCloudDBData(0, count, 0, ASSETS_TABLE_NAME); + CloudSyncOption option = PrepareOption(Query::Select().FromTable({ ASSETS_TABLE_NAME }), LockAction::INSERT); + CallSync(option); + + /** + * @tc.steps:step2. change cloud assets {b1, b3} + * @tc.expected: step2. return ok. + */ + Asset asset = {}; + Asset b1 = ASSET_COPY; + b1.name = ASSET_COPY.name + std::string("0"); + Asset b2 = ASSET_COPY; + b2.name = ASSET_COPY.name + std::string("0") + ASSET_SUFFIX; + Asset b3 = ASSET_COPY; + b3.name = ASSET_COPY.name + std::string("0") + ASSET_SUFFIX + ASSET_SUFFIX; + Assets assets = { b1, b3 }; + UpdateCloudAssets(asset, assets, std::string("0")); // 1 is version + /** + * @tc.steps:step3. sync + * @tc.expected: step3. download status is a -> DELETE, b2 -> DELETE, b3 -> INSERT + */ + g_virtualAssetLoader->ForkDownload([&b1, &b3](std::map &assets) { + auto it = assets.find(COL_ASSETS); + ASSERT_EQ(it != assets.end(), true); + ASSERT_EQ(it->second.size(), 1u); // 1 is download size + for (const auto &b: it->second) { + if (b.name == b3.name) { + EXPECT_EQ(b.status, static_cast(AssetStatus::INSERT)); + } + } + }); + 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->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 + for (const auto &b: it->second) { + if (b.name == b2.name) { + EXPECT_EQ(b.status, static_cast(AssetStatus::DELETE)); + } + } + }); + CallSync(option); + g_virtualAssetLoader->ForkDownload(nullptr); + g_virtualAssetLoader->SetRemoveLocalAssetsCallback(nullptr); +} + +/** + * @tc.name: DownloadAssetStatusTest003 + * @tc.desc: Test download assets status for UPDATE + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBCloudSyncerLockTest, DownloadAssetStatusTest003, TestSize.Level0) +{ + /** + * @tc.steps:step1. init cloud assert {a, b1, b2} and sync to local + * @tc.expected: step1. return ok. + */ + int count = 1; + InsertCloudDBData(0, count, 0, ASSETS_TABLE_NAME); + CloudSyncOption option = PrepareOption(Query::Select().FromTable({ ASSETS_TABLE_NAME }), LockAction::INSERT); + CallSync(option); + /** + * @tc.steps:step2. change cloud assets {a, b2} + * @tc.expected: step2. return ok. + */ + Asset asset = ASSET_COPY; + asset.name = asset.name + "0"; + asset.hash = "new_hash"; + Asset b1 = ASSET_COPY; + b1.name = ASSET_COPY.name + std::string("0"); + Asset b2 = ASSET_COPY; + b2.name = ASSET_COPY.name + std::string("0") + ASSET_SUFFIX; + b2.hash = "new_hash"; + Assets assets = { b1, b2 }; + UpdateCloudAssets(asset, assets, std::string("0")); // 1 is version + /** + * @tc.steps:step3. sync + * @tc.expected: step3. download status is a -> UPDATE, b2 -> UPDATE + */ + g_virtualAssetLoader->ForkDownload([&b1, &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->second[0].status, static_cast(AssetStatus::UPDATE)); + + it = assets.find(COL_ASSETS); + ASSERT_EQ(it != assets.end(), true); + ASSERT_EQ(it->second.size(), 1u); // 1 is download size + for (const auto &b: it->second) { + if (b.name == b2.name) { + EXPECT_EQ(b.status, static_cast(AssetStatus::UPDATE)); + } + } + }); + CallSync(option); + g_virtualAssetLoader->ForkDownload(nullptr); + g_virtualAssetLoader->SetRemoveLocalAssetsCallback(nullptr); +} + /** * @tc.name: RecordConflictTest001 * @tc.desc: Test the asset input param after download return CLOUD_RECORD_EXIST_CONFLICT @@ -796,9 +955,269 @@ HWTEST_F(DistributedDBCloudSyncerLockTest, QueryCursorTest004, TestSize.Level0) * @tc.expected: step3. return ok. */ std::string sql = "select count(*) from " + DBCommon::GetLogTableName(ASSETS_TABLE_NAME) + - " where data_key='0' and extend_field='name10' and cursor='31';"; + " where data_key='0' and extend_field='name10' and cursor='32';"; EXPECT_EQ(sqlite3_exec(db, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback, reinterpret_cast(1), nullptr), SQLITE_OK); } + +/** + * @tc.name: QueryCursorTest006 + * @tc.desc: Test cursor increasing when remove assets fail and download assets success + * @tc.type: FUNC + * @tc.require: + * @tc.author: suyue + */ +HWTEST_F(DistributedDBCloudSyncerLockTest, QueryCursorTest006, TestSize.Level0) +{ + /** + * @tc.steps:step1. insert local and sync + * @tc.expected: step1. return ok. + */ + InsertLocalData(0, 1, ASSETS_TABLE_NAME, false); + CloudSyncOption option = PrepareOption(Query::Select().FromTable({ ASSETS_TABLE_NAME }), LockAction::INSERT); + CallSync(option); + + /** + * @tc.steps:step2. change asset/assets and set RemoveLocalAssets fail + * @tc.expected: step2. return ok. + */ + std::string sql = "SELECT asset, assets FROM " + ASSETS_TABLE_NAME + ";"; + sqlite3_stmt *stmt = nullptr; + ASSERT_EQ(SQLiteUtils::GetStatement(db, sql, stmt), E_OK); + Asset asset; + Assets assets; + while (SQLiteUtils::StepWithRetry(stmt) != SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + ASSERT_EQ(sqlite3_column_type(stmt, 0), SQLITE_BLOB); + ASSERT_EQ(sqlite3_column_type(stmt, 1), SQLITE_BLOB); + Type assetBlob; + ASSERT_EQ(SQLiteRelationalUtils::GetCloudValueByType(stmt, TYPE_INDEX, 0, assetBlob), E_OK); + asset = g_virtualCloudDataTranslate->BlobToAsset(std::get(assetBlob)); + Type assetsBlob; + ASSERT_EQ(SQLiteRelationalUtils::GetCloudValueByType(stmt, TYPE_INDEX, 0, assetsBlob), E_OK); + assets = g_virtualCloudDataTranslate->BlobToAssets(std::get(assetsBlob)); + } + int errCode = E_OK; + SQLiteUtils::ResetStatement(stmt, true, errCode); + asset.hash = "new_hash"; + assets.pop_back(); + UpdateCloudAssets(asset, assets, std::string("0")); + g_virtualAssetLoader->SetRemoveStatus(DBStatus::LOCAL_ASSET_NOT_FOUND); + + /** + * @tc.steps:step3. sync and check cursor + * @tc.expected: step3. return ok. + */ + CallSync(option); + sql = "select count(*) from " + DBCommon::GetLogTableName(ASSETS_TABLE_NAME) + + " where cursor='3';"; + EXPECT_EQ(sqlite3_exec(db, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback, + reinterpret_cast(1), nullptr), SQLITE_OK); + g_virtualAssetLoader->SetRemoveStatus(DBStatus::OK); +} + +/** + * @tc.name: UploadAbnormalSync001 + * @tc.desc: Test upload update record, cloud returned record not found. + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBCloudSyncerLockTest, UploadAbnormalSync001, TestSize.Level0) +{ + /** + * @tc.steps:step1. insert local data and sync + * @tc.expected: step1. return ok. + */ + int cloudCount = 1; + InsertLocalData(0, cloudCount, ASSETS_TABLE_NAME, true); + CloudSyncOption option = PrepareOption(Query::Select().FromTable({ ASSETS_TABLE_NAME }), LockAction::DOWNLOAD); + CallSync(option); + + /** + * @tc.steps:step2. update local data and sync, cloud returned record not found. + * @tc.expected: step2. return ok. + */ + std::string sql = "update " + ASSETS_TABLE_NAME + " set name = 'xxx' where id = 0;"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql.c_str()), SQLITE_OK); + int upIdx = 0; + g_virtualCloudDb->ForkUpload([&upIdx](const std::string &tableName, VBucket &extend) { + LOGD("cloud db upload index:%d", ++upIdx); + if (upIdx == 1) { // 1 is index + extend[CloudDbConstant::ERROR_FIELD] = static_cast(DBStatus::CLOUD_RECORD_NOT_FOUND); + } + }); + int doUpIdx = 0; + g_cloudStoreHook->SetDoUploadHook([&doUpIdx] { + LOGD("begin upload index:%d", ++doUpIdx); + }); + int callCount = 0; + g_cloudStoreHook->SetSyncFinishHook([&callCount, this]() { + LOGD("sync finish times:%d", ++callCount); + if (callCount == 1) { // 1 is the normal sync + CheckUploadAbnormal(OpType::UPDATE, 1L); // 1 is expected count + } else { + CheckUploadAbnormal(OpType::UPDATE, 1L, true); // 1 is expected count + } + g_processCondition.notify_all(); + }); + CallSync(option); + { + std::unique_lock lock(g_processMutex); + bool result = g_processCondition.wait_for(lock, std::chrono::seconds(WAIT_TIME), + [&callCount]() { return callCount == 2; }); // 2 is sync times + ASSERT_EQ(result, true); + } +} + +/** + * @tc.name: UploadAbnormalSync002 + * @tc.desc: Test upload insert record, cloud returned record already existed. + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBCloudSyncerLockTest, UploadAbnormalSync002, TestSize.Level0) +{ + /** + * @tc.steps:step1. insert a and sync + * @tc.expected: step1. return ok. + */ + int cloudCount = 1; + InsertLocalData(0, cloudCount, ASSETS_TABLE_NAME, true); + CloudSyncOption option = PrepareOption(Query::Select().FromTable({ ASSETS_TABLE_NAME }), LockAction::DOWNLOAD); + CallSync(option); + + /** + * @tc.steps:step2. insert b and sync, cloud returned record not found. + * @tc.expected: step2. return ok. + */ + InsertLocalData(cloudCount, cloudCount, ASSETS_TABLE_NAME, true); + 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); + } + }); + int doUpIdx = 0; + g_cloudStoreHook->SetDoUploadHook([&doUpIdx, cloudCount, this] { + LOGD("begin upload index:%d", ++doUpIdx); + if (doUpIdx == 1) { // 1 is index + InsertCloudDBData(cloudCount, cloudCount, cloudCount, ASSETS_TABLE_NAME); + } + }); + int callCount = 0; + g_cloudStoreHook->SetSyncFinishHook([&callCount, this]() { + LOGD("sync finish times:%d", ++callCount); + if (callCount == 1) { // 1 is the normal sync + CheckUploadAbnormal(OpType::INSERT, 1L); // 1 is expected count + } else { + CheckUploadAbnormal(OpType::INSERT, 2L, true); // 1 is expected count + } + g_processCondition.notify_all(); + }); + CallSync(option); + { + std::unique_lock lock(g_processMutex); + bool result = g_processCondition.wait_for(lock, std::chrono::seconds(WAIT_TIME), + [&callCount]() { return callCount == 2; }); // 2 is sync times + ASSERT_EQ(result, true); + } +} + +/** + * @tc.name: UploadAbnormalSync003 + * @tc.desc: Test upload delete record, cloud returned record not found. + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBCloudSyncerLockTest, UploadAbnormalSync003, TestSize.Level0) +{ + /** + * @tc.steps:step1. insert local data and sync + * @tc.expected: step1. return ok. + */ + int cloudCount = 1; + InsertLocalData(0, cloudCount, ASSETS_TABLE_NAME, true); + CloudSyncOption option = PrepareOption(Query::Select().FromTable({ ASSETS_TABLE_NAME }), LockAction::DOWNLOAD); + CallSync(option); + + /** + * @tc.steps:step2. delete local data and sync, cloud returned record not found. + * @tc.expected: step2. return ok. + */ + std::string sql = "delete from " + ASSETS_TABLE_NAME + " where id = 0;"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql.c_str()), SQLITE_OK); + 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_NOT_FOUND); + } + }); + int doUpIdx = 0; + g_cloudStoreHook->SetDoUploadHook([&doUpIdx, cloudCount, this] { + LOGD("begin upload index:%d", ++doUpIdx); + if (doUpIdx == 1) { // 1 is index + DeleteCloudDBData(0, cloudCount, ASSETS_TABLE_NAME); + } + }); + int callCount = 0; + g_cloudStoreHook->SetSyncFinishHook([&callCount, this]() { + LOGD("sync finish times:%d", ++callCount); + if (callCount == 1) { // 1 is the normal sync + CheckUploadAbnormal(OpType::DELETE, 1L); // 1 is expected count + } else { + CheckUploadAbnormal(OpType::DELETE, 1L, true); // 1 is expected count + } + g_processCondition.notify_all(); + }); + CallSync(option); + { + std::unique_lock lock(g_processMutex); + bool result = g_processCondition.wait_for(lock, std::chrono::seconds(WAIT_TIME), + [&callCount]() { return callCount == 1; }); // 1 is sync times + ASSERT_EQ(result, true); + } +} + +/** + * @tc.name: ReviseLocalModTimeTest001 + * @tc.desc: test sync data with invalid timestamp. + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(DistributedDBCloudSyncerLockTest, ReviseLocalModTimeTest001, TestSize.Level0) +{ + /** + * @tc.steps:step1. insert local data + * @tc.expected: step1. return ok. + */ + int cloudCount = 31; // 31 records + InsertLocalData(0, cloudCount, ASSETS_TABLE_NAME, true); + /** + * @tc.steps:step2. Modify time and sync + * @tc.expected: step2. return ok. + */ + uint64_t curTime = 0; + EXPECT_EQ(TimeHelper::GetSysCurrentRawTime(curTime), E_OK); + uint64_t invalidTime = curTime + curTime; + std::string sql = "UPDATE " + DBCommon::GetLogTableName(ASSETS_TABLE_NAME) + + " SET timestamp=" + std::to_string(invalidTime) + " where rowid>0"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql.c_str()), SQLITE_OK); + CloudSyncOption option = PrepareOption(Query::Select().FromTable({ ASSETS_TABLE_NAME }), LockAction::INSERT); + CallSync(option); + /** + * @tc.steps:step3. Check modify time in log table + * @tc.expected: step3. return ok. + */ + EXPECT_EQ(TimeHelper::GetSysCurrentRawTime(curTime), E_OK); + sql = "select count(*) from " + DBCommon::GetLogTableName(ASSETS_TABLE_NAME) + + " where timestamp < " + std::to_string(curTime); + EXPECT_EQ(sqlite3_exec(db, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback, + reinterpret_cast(cloudCount), nullptr), SQLITE_OK); +} } // namespace #endif // RELATIONAL_STORE \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_table_compound_primary_key_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_table_compound_primary_key_sync_test.cpp index 146fc544f91f86f40e726985e42830908af26605..3a1922ecff4a9eb06e15ca0571f34fc432881f7d 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_table_compound_primary_key_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_table_compound_primary_key_sync_test.cpp @@ -30,6 +30,7 @@ #include "virtual_asset_loader.h" #include "virtual_cloud_data_translate.h" #include "virtual_cloud_db.h" +#include "virtual_communicator_aggregator.h" #include "mock_asset_loader.h" #include "cloud_db_sync_utils_test.h" @@ -91,6 +92,7 @@ namespace { void TearDown(); protected: sqlite3 *db = nullptr; + VirtualCommunicatorAggregator *communicatorAggregator_ = nullptr; }; void DistributedDBCloudTableCompoundPrimaryKeySyncTest::SetUpTestCase(void) @@ -117,6 +119,9 @@ namespace { CloudDBSyncUtilsTest::SetStorePath(g_storePath); CloudDBSyncUtilsTest::InitSyncUtils(g_cloudFiledCompoundPrimaryKey, g_observer, g_virtualCloudDb, g_virtualAssetLoader, g_delegate); + communicatorAggregator_ = new (std::nothrow) VirtualCommunicatorAggregator(); + ASSERT_TRUE(communicatorAggregator_ != nullptr); + RuntimeContext::GetInstance()->SetCommunicatorAggregator(communicatorAggregator_); } void DistributedDBCloudTableCompoundPrimaryKeySyncTest::TearDown(void) @@ -126,6 +131,9 @@ namespace { if (DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir) != 0) { LOGE("rm test db files error."); } + RuntimeContext::GetInstance()->SetCommunicatorAggregator(nullptr); + communicatorAggregator_ = nullptr; + RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(nullptr); } /* diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_table_without_primary_key_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_table_without_primary_key_sync_test.cpp index b2137d8ad7ca57509ad69a48c5f996d6e83095b7..d0e8f9db2b295076a3a0e396afa316ed1b89a9fd 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_table_without_primary_key_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_table_without_primary_key_sync_test.cpp @@ -30,6 +30,7 @@ #include "virtual_asset_loader.h" #include "virtual_cloud_data_translate.h" #include "virtual_cloud_db.h" +#include "virtual_communicator_aggregator.h" #include "mock_asset_loader.h" #include "cloud_db_sync_utils_test.h" @@ -49,6 +50,7 @@ namespace { std::shared_ptr g_virtualAssetLoader; RelationalStoreObserverUnitTest *g_observer = nullptr; RelationalStoreDelegate *g_delegate = nullptr; + VirtualCommunicatorAggregator *communicatorAggregator_ = nullptr; TrackerSchema g_trackerSchema = { .tableName = g_tableName, .extendColName = "name", .trackerColNames = {"age"} }; @@ -182,6 +184,9 @@ namespace { CloudDBSyncUtilsTest::SetStorePath(g_storePath); CloudDBSyncUtilsTest::InitSyncUtils(g_cloudFiledWithoutPrimaryKey, g_observer, g_virtualCloudDb, g_virtualAssetLoader, g_delegate); + communicatorAggregator_ = new (std::nothrow) VirtualCommunicatorAggregator(); + ASSERT_TRUE(communicatorAggregator_ != nullptr); + RuntimeContext::GetInstance()->SetCommunicatorAggregator(communicatorAggregator_); } void DistributedDBCloudTableWithoutPrimaryKeySyncTest::TearDown(void) @@ -191,6 +196,9 @@ namespace { if (DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir) != 0) { LOGE("rm test db files error."); } + RuntimeContext::GetInstance()->SetCommunicatorAggregator(nullptr); + communicatorAggregator_ = nullptr; + RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(nullptr); } /* 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 ecbb6e26448148b36fb05d30a7bf8174b654a912..edfb3ae852340f6fe507de331bc981e9d9d5dcfa 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 @@ -49,6 +49,12 @@ DBStatus VirtualAssetLoader::RemoveLocalAssets(const std::vector &assets) DBStatus VirtualAssetLoader::RemoveLocalAssets(const std::string &tableName, const std::string &gid, const Type &prefix, std::map &assets) { + { + std::lock_guard autoLock(dataMutex_); + if (removeStatus_ != OK) { + return removeStatus_; + } + } if (removeLocalAssetsCallBack_) { removeLocalAssetsCallBack_(assets); } @@ -69,6 +75,13 @@ void VirtualAssetLoader::SetDownloadStatus(DBStatus status) downloadStatus_ = status; } +void VirtualAssetLoader::SetRemoveStatus(DBStatus status) +{ + std::lock_guard autoLock(dataMutex_); + LOGD("[VirtualAssetLoader] set remove status :%d", static_cast(status)); + removeStatus_ = status; +} + void VirtualAssetLoader::ForkDownload(const DownloadCallBack &callback) { downloadCallBack_ = callback; 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 a94bbe54fb91f5e51e3071002140920881767543..3ee2b4b042b096c12c6f74860b19c163f05e2d2f 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 @@ -37,6 +37,8 @@ public: void SetDownloadStatus(DBStatus status); + void SetRemoveStatus(DBStatus status); + void ForkDownload(const DownloadCallBack &callback); void ForkRemoveLocalAssets(const RemoveAssetsCallBack &callback); @@ -45,6 +47,7 @@ public: private: std::mutex dataMutex_; DBStatus downloadStatus_ = OK; + DBStatus removeStatus_ = OK; DownloadCallBack downloadCallBack_; RemoveAssetsCallBack removeAssetsCallBack_; RemoveLocalAssetsCallBack removeLocalAssetsCallBack_; 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 030d27e47d9365a47e50704f716620b11b85a251..fb69bc6adab140cbc585f70ad14e4175b3068ca0 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 @@ -443,19 +443,26 @@ DBStatus VirtualCloudDb::InnerUpdateWithoutLock(const std::string &tableName, st LOGE("[VirtualCloudDb] Update data should have gid"); return DB_ERROR; } + if (forkUploadConflictFunc_) { + DBStatus ret = forkUploadConflictFunc_(tableName, extend[i], record[i], cloudData_[tableName]); + if (ret != OK) { + res = ret; + continue; + } + } if (conflictInUpload_) { extend[i][CloudDbConstant::ERROR_FIELD] = static_cast(DBStatus::CLOUD_RECORD_EXIST_CONFLICT); } extend[i][g_cursorField] = std::to_string(currentCursor_++); AddAssetIdForExtend(record[i], extend[i]); - if (forkUploadFunc_) { - forkUploadFunc_(tableName, extend[i]); - } if (isDelete) { extend[i][g_deleteField] = true; } else { extend[i][g_deleteField] = false; } + if (forkUploadFunc_) { + forkUploadFunc_(tableName, extend[i]); + } CloudData cloudData = { .record = std::move(record[i]), .extend = extend[i] diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_meta_data_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_meta_data_test.cpp index f61cc77cf54ea2fb5b43afa9abbacd0ad1cf2029..ed76bab1033c11501a6a37a27c7c4dd91421949b 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_meta_data_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_meta_data_test.cpp @@ -327,4 +327,38 @@ HWTEST_F(DistributedDBMetaDataTest, MetadataTest007, TestSize.Level0) RuntimeContext::GetInstance()->SetTimeChanged(false); RuntimeContext::GetInstance()->StopTimeTickMonitorIfNeed(); } + +/** + * @tc.name: MetadataTest008 + * @tc.desc: Test metadata deserialize v1 local meta. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBMetaDataTest, MetadataTest008, TestSize.Level0) +{ + /** + * @tc.steps: step1. Insert v1 local meta data. + * @tc.expected: step1.Insert OK. + */ + std::string keyStr = "localMetaData"; + Key key(keyStr.begin(), keyStr.end()); + Value value; + value.resize(Parcel::GetUInt32Len() + Parcel::GetUInt64Len()); + Parcel parcel(value.data(), value.size()); + LocalMetaData expectLocalMetaData; + expectLocalMetaData.version = LOCAL_META_DATA_VERSION_V1; + expectLocalMetaData.localSchemaVersion = SOFTWARE_VERSION_RELEASE_9_0; + (void)parcel.WriteUInt32(expectLocalMetaData.version); + (void)parcel.WriteUInt64(expectLocalMetaData.localSchemaVersion); + ASSERT_FALSE(parcel.IsError()); + ASSERT_EQ(storage_->PutMetaData(key, value, false), E_OK); + /** + * @tc.steps: step2. Read v1 local meta data. + * @tc.expected: step2.Read OK. + */ + auto res = metadata_->GetLocalSchemaVersion(); + EXPECT_EQ(res.first, E_OK); + EXPECT_EQ(res.second, expectLocalMetaData.localSchemaVersion); +} } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_mock_sync_module_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_mock_sync_module_test.cpp index 3b34d887b2b9a888738c162ffc068e2252d12b15..6a7c43d3c469d30955b5b05f9f79a44d1cfaaf66 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_mock_sync_module_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_mock_sync_module_test.cpp @@ -473,7 +473,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck003, TestSize.Level1) EXPECT_CALL(syncTaskContext, Clear()).WillRepeatedly([&syncTaskContext]() { syncTaskContext.SetLastRequestSessionId(0u); }); - EXPECT_CALL(syncTaskContext, MoveToNextTarget()).WillRepeatedly(Return()); + EXPECT_CALL(syncTaskContext, MoveToNextTarget(_)).WillRepeatedly(Return()); EXPECT_CALL(syncTaskContext, IsCurrentSyncTaskCanBeSkipped()).WillOnce(Return(true)).WillOnce(Return(false)); // we expect machine don't change context status when queue not empty EXPECT_CALL(syncTaskContext, SetOperationStatus(_)).WillOnce(Return()); @@ -558,7 +558,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck006, TestSize.Level1) .WillOnce(Return(true)); EXPECT_CALL(syncTaskContext, IsCurrentSyncTaskCanBeSkipped()) .WillRepeatedly(Return(syncTaskContext.CallIsCurrentSyncTaskCanBeSkipped())); - EXPECT_CALL(syncTaskContext, MoveToNextTarget()).WillOnce(Return()); + EXPECT_CALL(syncTaskContext, MoveToNextTarget(_)).WillOnce(Return()); // we expect machine don't change context status when queue not empty EXPECT_CALL(syncTaskContext, SetOperationStatus(_)).WillOnce(Return()); EXPECT_CALL(syncTaskContext, SetTaskExecStatus(_)).WillOnce(Return()); @@ -1780,7 +1780,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncTaskContextCheck005, TestSize.Leve }); std::thread copyThread([context]() { for (int i = 0; i < 100; ++i) { // move 100 times - (void) context->MoveToNextTarget(); + (void) context->MoveToNextTarget(DBConstant::MIN_TIMEOUT); std::this_thread::sleep_for(std::chrono::milliseconds(1)); } }); @@ -1825,7 +1825,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncTaskContextCheck006, TestSize.Leve * @tc.expected: retry time will be reset to zero */ context->SetRetryTime(AUTO_RETRY_TIMES); - context->MoveToNextTarget(); + context->MoveToNextTarget(DBConstant::MIN_TIMEOUT); EXPECT_EQ(context->GetRetryTime(), 0); context->Clear(); RefObject::KillAndDecObjRef(context); diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_multi_ver_p2p_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_multi_ver_p2p_sync_test.cpp index 3b9a4067d7a169428ba897335df7c4983d853573..82172bb5b5b857d250d271bcd978fdc0bac916bf 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_multi_ver_p2p_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_multi_ver_p2p_sync_test.cpp @@ -605,7 +605,7 @@ HWTEST_F(DistributedDBMultiVerP2PSyncTest, IsolationSync003, TestSize.Level2) } static void SetTimeSyncPacketField(TimeSyncPacket &inPacket, Timestamp sourceBegin, Timestamp sourceEnd, - Timestamp targetBegin, Timestamp targetEnd, SyncId theId) + Timestamp targetBegin, Timestamp targetEnd) { inPacket.SetSourceTimeBegin(sourceBegin); inPacket.SetSourceTimeEnd(sourceEnd); @@ -637,8 +637,8 @@ HWTEST_F(DistributedDBMultiVerP2PSyncTest, TimesyncPacket001, TestSize.Level1) */ TimeSyncPacket packetA; TimeSyncPacket packetB; - SetTimeSyncPacketField(packetA, 1, 2, 3, 4, 5); // 1, 2, 3, 4, 5 is five field for time sync packet - SetTimeSyncPacketField(packetB, 5, 4, 3, 2, 1); // 1, 2, 3, 4, 5 is five field for time sync packet + SetTimeSyncPacketField(packetA, 1, 2, 3, 4); // 1, 2, 3, 4 is four field for time sync packet + SetTimeSyncPacketField(packetB, 5, 4, 3, 2); // 2, 3, 4, 5 is four field for time sync packet Message oriMsgA; Message oriMsgB; oriMsgA.SetCopiedObject(packetA); 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 01701a653a56a7dbf5f23f3f1c6c64a1071d76ed..9e5bfb679d556c8fef696d4b66e35c955c14266f 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 @@ -716,7 +716,7 @@ HWTEST_F(DistributedDBRelationalMultiUserTest, RdbMultiUser003, TestSize.Level3) * @tc.expected: step6. success. */ Query query = Query::Select(g_tableName); - EXPECT_EQ(g_deviceB->GenericVirtualDevice::Sync(SYNC_MODE_PUSH_ONLY, query, true), OK); + EXPECT_EQ(g_deviceB->GenericVirtualDevice::Sync(SYNC_MODE_PUSH_ONLY, query, true), E_OK); /** * @tc.steps: step7. deviceA have {k1,v1} @@ -1246,4 +1246,59 @@ HWTEST_F(DistributedDBRelationalMultiUserTest, RDBSyncOpt005, TestSize.Level0) OS::RemoveFile(g_storePath1); PrepareEnvironment(g_tableName, g_storePath1, g_rdbDelegatePtr1); g_communicatorAggregator->RegOnDispatch(nullptr); -} \ No newline at end of file +} + +/** + * @tc.name: DropDistributedTableTest001 + * @tc.desc: Test sync after drop distributed table. + * @tc.type: FUNC + * @tc.require: + * @tc.author: liaoyonghuang + */ +HWTEST_F(DistributedDBRelationalMultiUserTest, DropDistributedTableTest001, TestSize.Level1) +{ + /** + * @tc.steps: step1. Prepare db1 and db2. + * @tc.expected: step1. success. + */ + OpenStore1(); + PrepareEnvironment(g_tableName, g_storePath1, g_rdbDelegatePtr1); + CloseStore(); + OpenStore2(); + PrepareEnvironment(g_tableName, g_storePath2, g_rdbDelegatePtr2); + /** + * @tc.steps: step2. Do 1st sync to create distributed table + * @tc.expected: step2. success. + */ + std::vector remoteDev; + remoteDev.push_back(g_deviceB); + PrepareVirtualDeviceEnv(g_tableName, g_storePath1, remoteDev); + Query query = Query::Select(g_tableName); + EXPECT_EQ(g_deviceB->GenericVirtualDevice::Sync(SYNC_MODE_PUSH_ONLY, query, true), E_OK); + /** + * @tc.steps: step3. Drop distributed table + * @tc.expected: step3. success. + */ + std::string distributedTableName = DBCommon::GetDistributedTableName(DEVICE_B, g_tableName); + sqlite3 *db = nullptr; + EXPECT_EQ(GetDB(db, g_storePath2), SQLITE_OK); + EXPECT_EQ(DropTable(db, distributedTableName), SQLITE_OK); + sqlite3_close(db); + /** + * @tc.steps: step4. Do 2nd sync and check result. + * @tc.expected: step4. success. + */ + VirtualRowData virtualRowData; + DataValue d1; + d1 = (int64_t)1; + virtualRowData.objectData.PutDataValue("id", d1); + DataValue d2; + d2.SetText("hello"); + virtualRowData.objectData.PutDataValue("name", d2); + virtualRowData.logInfo.timestamp = 1; + g_deviceB->PutData(g_tableName, {virtualRowData}); + EXPECT_EQ(g_deviceB->GenericVirtualDevice::Sync(SYNC_MODE_PUSH_ONLY, query, true), E_OK); + CheckDataInRealDevice(); + g_currentStatus = 0; + CloseStore(); +} 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 63a08c38d0e77001ea31f3d083fb7650e3fd317a..4aabf268caef0b372c4cf2537ed7f6bebc473032 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 @@ -735,7 +735,7 @@ namespace { } RuntimeConfig::SetProcessSystemAPIAdapter(nullptr); LOGD("CloseStore Start"); - EXPECT_EQ(g_rdbDelegatePtr->RemoveDeviceData(), E_OK); + EXPECT_EQ(g_rdbDelegatePtr->RemoveDeviceData(), OK); ASSERT_EQ(g_mgr.CloseStore(g_rdbDelegatePtr), OK); g_rdbDelegatePtr = nullptr; OpenStore(); @@ -911,15 +911,6 @@ void DistributedDBRelationalVerP2PSyncTest::TearDown(void) LOGD("TearDown FINISH"); } -void WaitCallCount(RelationalStoreObserverUnitTest *observer1) -{ - int reTry = 5; - while (observer1->GetCallCount() != 1u && reTry > 0) { - std::this_thread::sleep_for(std::chrono::seconds(1)); - reTry--; - } -} - /** * @tc.name: Normal Sync 001 * @tc.desc: Test normal push sync for add data. @@ -1828,7 +1819,7 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, Observer006, TestSize.Level3) } return true; }; - EXPECT_EQ(RuntimeConfig::SetPermissionCheckCallback(callback), E_OK); + EXPECT_EQ(RuntimeConfig::SetPermissionCheckCallback(callback), OK); /** * @tc.steps: step3. device A check observer @@ -1966,6 +1957,20 @@ 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 @@ -1990,17 +1995,8 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, Observer008, TestSize.Level3) if (g_id != identifier) { return false; } - param.path = g_dbDir; - param.appId = APP_ID; - param.userId = USER_ID; - param.storeId = STORE_ID_1; + SetAutoLaunchParamForObserver008(param); 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); @@ -2041,7 +2037,11 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, Observer008, TestSize.Level3) * @tc.steps: step6. Call sync expect sync successful and device A check observer */ EXPECT_EQ(autoObserver->GetCallCount(), 1u); - WaitCallCount(observer1); + int reTry = 5; + while (observer1->GetCallCount() != 1u && reTry > 0) { + std::this_thread::sleep_for(std::chrono::seconds(1)); + reTry--; + } EXPECT_EQ(observer1->GetCallCount(), 1u); EXPECT_EQ(autoObserver->GetDataChangeDevice(), DEVICE_B); CheckIdentify(autoObserver); @@ -2376,6 +2376,25 @@ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery012, TestSize.Level1) EXPECT_EQ(result, nullptr); } +/** +* @tc.name: remote query 013 +* @tc.desc: Test rdb remote query deny fts3_tokenizer +* @tc.type: FUNC +* @tc.require: +* @tc.author: zhangqiquan +*/ +HWTEST_F(DistributedDBRelationalVerP2PSyncTest, RemoteQuery013, TestSize.Level0) +{ + std::map dataMap; + PrepareEnvironment(dataMap, {g_deviceB}); + ASSERT_NE(g_rdbDelegatePtr, nullptr); + RemoteCondition condition; + condition.sql = "SELECT hex(fts3_tokenizer('simple'))"; + std::shared_ptr result = nullptr; + EXPECT_EQ(g_deviceB->RemoteQuery(DEVICE_A, condition, DBConstant::MIN_TIMEOUT, result), DB_ERROR); + EXPECT_EQ(result, nullptr); +} + /** * @tc.name: RelationalPemissionTest001 * @tc.desc: deviceB PermissionCheck not pass test, SYNC_MODE_PUSH_ONLY diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_multi_user_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_multi_user_test.cpp index 173c6bb9c59bd7f68032d9d5e13be945b09ea62b..c9a8c64814a488d49c3732bd5d2f25fd7cee9875 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_multi_user_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_multi_user_test.cpp @@ -480,12 +480,12 @@ HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser003, TestSize.Level3) Value value = {'1'}; Timestamp currentTime; (void)OS::GetCurrentSysTimeInMicrosecond(currentTime); - EXPECT_TRUE(g_deviceB->PutData(key, value, currentTime, 0) == OK); + EXPECT_TRUE(g_deviceB->PutData(key, value, currentTime, 0) == E_OK); /** * @tc.steps: step4. device B push sync to A * @tc.expected: step4. success. */ - EXPECT_TRUE(g_deviceB->Sync(SYNC_MODE_PUSH_ONLY, true) == OK); + EXPECT_TRUE(g_deviceB->Sync(SYNC_MODE_PUSH_ONLY, true) == E_OK); std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_TIME)); EXPECT_TRUE(observer->GetCallCount() == 1); // only A /** @@ -905,4 +905,4 @@ HWTEST_F(DistributedDBSingleVerMultiUserTest, MultiUser014, TestSize.Level1) EXPECT_EQ(g_kvDelegatePtr1->RemoveDeviceData(), OK); EXPECT_EQ(callCount, 0u); CloseStore(); -} \ No newline at end of file +} 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 c02cdb5514f512cac57beb21d40d6bf0be8df0a4..a8dd4d825345efcc97cad1890c3f3af0e250c41b 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 @@ -461,7 +461,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, SametimeSync002, TestSize.Lev LOGD("Begin PUSH"); EXPECT_EQ(g_kvDelegatePtr->Sync(devices, DistributedDB::SYNC_MODE_PUSH_ONLY, callback, query, true), OK); ASSERT_TRUE(result.size() == devices.size()); - EXPECT_TRUE(result[DEVICE_A] == OK); + EXPECT_TRUE(result[DEVICE_B] == OK); }); /** * @tc.steps: step3. B pull to A when A is in push task @@ -851,11 +851,11 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, EncryptedAlgoUpgrade001, Test std::string hashDir = DBCommon::TransferHashString(identifier); std::string hexHashDir = DBCommon::TransferStringToHex(hashDir); std::string dbPath = g_testDir + "/" + hexHashDir + "/single_ver"; - ASSERT_TRUE(DBCommon::CreateDirectory(g_testDir + "/" + hexHashDir) == OK); - ASSERT_TRUE(DBCommon::CreateDirectory(dbPath) == OK); + ASSERT_TRUE(DBCommon::CreateDirectory(g_testDir + "/" + hexHashDir) == E_OK); + ASSERT_TRUE(DBCommon::CreateDirectory(dbPath) == E_OK); std::vector dbDir {DBConstant::MAINDB_DIR, DBConstant::METADB_DIR, DBConstant::CACHEDB_DIR}; for (const auto &item : dbDir) { - ASSERT_TRUE(DBCommon::CreateDirectory(dbPath + "/" + item) == OK); + ASSERT_TRUE(DBCommon::CreateDirectory(dbPath + "/" + item) == E_OK); } uint64_t flag = SQLITE_OPEN_URI | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; sqlite3 *db; @@ -1377,6 +1377,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, RebuildSync001, TestSize.Leve (void)OS::GetCurrentSysTimeInMicrosecond(currentTime); EXPECT_EQ(g_deviceB->PutData(key2, value, currentTime, 0), E_OK); EXPECT_EQ(g_deviceB->Sync(DistributedDB::SYNC_MODE_PUSH_ONLY, true), E_OK); + std::this_thread::sleep_for(std::chrono::seconds(1)); Value actualValue; EXPECT_EQ(g_kvDelegatePtr->Get(key1, actualValue), OK); @@ -1403,6 +1404,7 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, RebuildSync001, TestSize.Leve (void)OS::GetCurrentSysTimeInMicrosecond(currentTime); EXPECT_EQ(g_deviceB->PutData(key1, value, currentTime, 0), E_OK); EXPECT_EQ(g_deviceB->Sync(DistributedDB::SYNC_MODE_PUSH_ONLY, true), E_OK); + std::this_thread::sleep_for(std::chrono::seconds(1)); /** * @tc.steps: step4. check data in device A * * @tc.expected: step4. check ok @@ -1739,6 +1741,75 @@ 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 @@ -1797,8 +1868,9 @@ HWTEST_F(DistributedDBSingleVerP2PComplexSyncTest, GetSyncDataFail002, TestSize. * @tc.steps: step2. device B sync to device A and check data * * @tc.expected: step2. interface return ok */ - EXPECT_EQ(g_deviceB->Sync(DistributedDB::SYNC_MODE_PUSH_ONLY, true), E_OK); - std::this_thread::sleep_for(std::chrono::seconds(1)); + std::vector devices = { g_deviceB->GetDeviceId() }; + std::map result; + ASSERT_TRUE(g_tool.SyncTest(g_kvDelegatePtr, devices, SYNC_MODE_PULL_ONLY, result) == OK); Value actualValue; for (int j = 1u; j <= totalSize; j++) { if (j > totalSize / 2) { 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 a1d388779b84e07faf34273b2e6d032fd2d32f22..2229a0b303c80c9466a03f5bce05136310b41877 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 @@ -519,7 +519,7 @@ HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, SecOptionCheck008, TestSize.Lev * @tc.name: SyncProcess001 * @tc.desc: sync process pull mode. * @tc.type: FUNC - * @tc.require: AR.SR.IR-20075207.007.001 + * @tc.require: * @tc.author: chenghuitao */ HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, SyncProcess001, TestSize.Level1) @@ -580,7 +580,7 @@ HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, SyncProcess001, TestSize.Level1 * @tc.name: SyncProcess002 * @tc.desc: sync process pull mode. * @tc.type: FUNC - * @tc.require: AR.SR.IR-20075207.007.001 + * @tc.require: * @tc.author: chenghuitao */ HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, SyncProcess002, TestSize.Level1) @@ -650,7 +650,7 @@ HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, SyncProcess002, TestSize.Level1 * @tc.name: SyncProcess003 * @tc.desc: sync process pull mode with QUERY. * @tc.type: FUNC - * @tc.require: AR.SR.IR-20075207.007.001 + * @tc.require: * @tc.author: chenghuitao */ HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, SyncProcess003, TestSize.Level1) @@ -876,6 +876,131 @@ HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, BigDataSync003, TestSize.Level1 } #endif +void DistributedDBSingleVerP2PSyncCheckTest::CancelTestInit(DeviceSyncOption &option, std::vector &entries, + const uint32_t mtuSize) +{ + option.devices.push_back(g_deviceB->GetDeviceId()); + option.devices.push_back(g_deviceC->GetDeviceId()); + option.mode = SYNC_MODE_PULL_ONLY; + option.isQuery = false; + option.isWait = false; + + std::vector keys; + const uint32_t entriesSize = 14000u; + const int keySize = 20; + DistributedDBUnitTest::GenerateRecords(entriesSize, entries, keys, keySize, mtuSize); + for (uint32_t i = 0; i < entries.size(); i++) { + if (i % option.devices.size() == 0) { + g_deviceB->PutData(entries[i].key, entries[i].value, 0, 0); + } else { + g_deviceC->PutData(entries[i].key, entries[i].value, 0, 0); + } + } + + g_communicatorAggregator->SetDeviceMtuSize("real_device", mtuSize); + g_communicatorAggregator->SetDeviceMtuSize(DEVICE_C, mtuSize); + g_communicatorAggregator->SetDeviceMtuSize(DEVICE_B, mtuSize); +} + +void DistributedDBSingleVerP2PSyncCheckTest::CancelTestEnd(std::vector &entries, const uint32_t mtuSize) +{ + size_t syncSuccCount = 0; + for (uint32_t i = 0; i < entries.size(); i++) { + Value value; + if (g_kvDelegatePtr->Get(entries[i].key, value) == OK) { + syncSuccCount++; + EXPECT_EQ(value, entries[i].value); + } + } + EXPECT_GT(syncSuccCount, static_cast(0)); + EXPECT_LT(syncSuccCount, entries.size()); + uint32_t mtu = 5u; + g_communicatorAggregator->SetDeviceMtuSize("real_device", mtu * mtuSize * mtuSize); + g_communicatorAggregator->SetDeviceMtuSize(DEVICE_C, mtu * mtuSize * mtuSize); + g_communicatorAggregator->SetDeviceMtuSize(DEVICE_B, mtu * mtuSize * mtuSize); + g_communicatorAggregator->RegBeforeDispatch(nullptr); +} + +/** + * @tc.name: CancelSyncProcess001 + * @tc.desc: cancel data sync process pull mode. + * @tc.type: FUNC + * @tc.require: + * @tc.author: lijun + */ +HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, SyncProcessCancel001, TestSize.Level0) +{ + DeviceSyncOption option; + std::vector entries; + const uint32_t mtuSize = 8u; + /** + * @tc.steps: step1. deviceB deviceC put data + */ + CancelTestInit(option, entries, mtuSize); + uint32_t syncId; + std::mutex tempMutex; + bool isFirst = true; + g_communicatorAggregator->RegBeforeDispatch([&](const std::string &dstTarget, const Message *msg) { + if (dstTarget == "real_device" && msg->GetMessageType() == TYPE_REQUEST && + msg->GetMessageId() == DATA_SYNC_MESSAGE) { + tempMutex.lock(); + if (isFirst == true) { + isFirst = false; + /** + * @tc.steps: step3. cancel sync + * @tc.expected: step3. should return OK. + */ + ASSERT_TRUE(g_kvDelegatePtr->CancelSync(syncId) == OK); + tempMutex.unlock(); + std::this_thread::sleep_for(std::chrono::seconds(1)); + return; + } + tempMutex.unlock(); + } + }); + + std::mutex cancelMtx; + std::condition_variable cancelCv; + bool cancalFinished = false; + + DeviceSyncProcessCallback onProcess = [&](const std::map &processMap) { + bool isAllCancel = true; + for (auto &process: processMap) { + syncId = process.second.syncId; + if (process.second.errCode != COMM_FAILURE) { + isAllCancel = false; + } + } + if (isAllCancel) { + std::unique_lock lock(cancelMtx); + cancalFinished = true; + cancelCv.notify_all(); + } + }; + /** + * @tc.steps: step2. deviceA call pull sync + * @tc.expected: step2. sync should return OK. + */ + ASSERT_TRUE(g_kvDelegatePtr->Sync(option, onProcess) == OK); + + // Wait onProcess complete. + { + std::unique_lock lock2(cancelMtx); + cancelCv.wait(lock2, [&cancalFinished]() {return cancalFinished;}); + } + // Wait until all the packets arrive. + std::this_thread::sleep_for(std::chrono::seconds(2)); + + /** + * @tc.steps: step4. Cancel abnormal syncId. + * @tc.expected: step4. return NOT_FOUND. + */ + ASSERT_TRUE(g_kvDelegatePtr->CancelSync(syncId) == NOT_FOUND); + ASSERT_TRUE(g_kvDelegatePtr->CancelSync(0) == NOT_FOUND); + ASSERT_TRUE(g_kvDelegatePtr->CancelSync(4294967295) == NOT_FOUND); // uint32_t max value 4294967295 + CancelTestEnd(entries, mtuSize); +} + /** * @tc.name: PushFinishedNotify 001 * @tc.desc: Test remote device push finished notify function. @@ -1132,7 +1257,7 @@ HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, AckSessionCheck001, TestSize.Le * @tc.steps: step1. deviceB sync to deviceA just for timeSync and abilitySync * @tc.expected: step1. should return OK. */ - ASSERT_TRUE(g_deviceB->Sync(SYNC_MODE_PUSH_ONLY, true) == OK); + ASSERT_TRUE(g_deviceB->Sync(SYNC_MODE_PUSH_ONLY, true) == E_OK); /** * @tc.steps: step2. deviceA StartTransaction for prevent other sync action deviceB sync will fail @@ -1149,7 +1274,7 @@ HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, AckSessionCheck001, TestSize.Le Timestamp currentTime; (void)OS::GetCurrentSysTimeInMicrosecond(currentTime); EXPECT_TRUE(g_deviceB->PutData(key, value, currentTime, 0) == E_OK); - EXPECT_TRUE(g_deviceB->Sync(SYNC_MODE_PUSH_ONLY, true) == OK); + EXPECT_TRUE(g_deviceB->Sync(SYNC_MODE_PUSH_ONLY, true) == E_OK); Value outValue; EXPECT_TRUE(g_kvDelegatePtr->Get(key, outValue) == NOT_FOUND); @@ -1159,9 +1284,9 @@ HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, AckSessionCheck001, TestSize.Le * @tc.expected: step3. should return OK. */ EXPECT_TRUE(g_kvDelegatePtr->Commit() == OK); - EXPECT_TRUE(g_deviceB->Sync(SYNC_MODE_PUSH_ONLY, true) == OK); + EXPECT_TRUE(g_deviceB->Sync(SYNC_MODE_PUSH_ONLY, true) == E_OK); - EXPECT_TRUE(g_kvDelegatePtr->Get(key, outValue) == E_OK); + EXPECT_TRUE(g_kvDelegatePtr->Get(key, outValue) == OK); EXPECT_EQ(outValue, value); } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/generic_virtual_device.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/generic_virtual_device.cpp index 838e21214cd0a4c063defca8bdb6fd0cf16c9239..b68cae6e725fa511b4038f6ec21229fad3360c35 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/generic_virtual_device.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/generic_virtual_device.cpp @@ -201,7 +201,7 @@ int GenericVirtualDevice::StartResponseTask() return E_OK; } context_->SetTaskExecStatus(ISyncTaskContext::RUNNING); - context_->MoveToNextTarget(); + context_->MoveToNextTarget(DBConstant::MIN_TIMEOUT); LOGI("[KvVirtualDevice] machine StartSync"); context_->UnlockObj(); int errCode = context_->StartStateMachine(); diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_sync_task_context.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_sync_task_context.h index 1ba0ec915b8848024417931f5d8290c6253faee4..d21f2acc0e2069bc4c333a6d7f388c28bd9fbc7d 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_sync_task_context.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/mock_sync_task_context.h @@ -49,7 +49,7 @@ public: MOCK_CONST_METHOD0(GetTimerId, TimerId(void)); - MOCK_METHOD0(MoveToNextTarget, void(void)); + MOCK_METHOD1(MoveToNextTarget, void(uint32_t)); MOCK_CONST_METHOD0(IsTargetQueueEmpty, bool(void)); 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 6a1f0479d325447b0e0bca6795a958257b905daf..0ad60442faa20cb9f38b353cbdc40d46a9542db8 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 @@ -127,4 +127,4 @@ private: }; } // namespace DistributedDB -#endif // VIRTUAL_ICOMMUNICATORAGGREGATOR_H \ No newline at end of file +#endif // VIRTUAL_ICOMMUNICATORAGGREGATOR_H diff --git a/kv_store/interfaces/innerkits/distributeddata/include/single_kvstore.h b/kv_store/interfaces/innerkits/distributeddata/include/single_kvstore.h index cd64998cccbdc7750feaa3cddfd594a44687fea0..e504881fd3cb9068702d9b538465cfeef93b0163 100644 --- a/kv_store/interfaces/innerkits/distributeddata/include/single_kvstore.h +++ b/kv_store/interfaces/innerkits/distributeddata/include/single_kvstore.h @@ -331,6 +331,15 @@ public: { return Status::SUCCESS; } + + /** + * @brief get database status. + * @return Return true for db rebuild. + */ + virtual bool IsRebuild() + { + return false; + } }; } // namespace DistributedKv } // namespace OHOS diff --git a/kv_store/kvstoremock/frameworks/innerkitsimpl/kvdb/include/single_store_impl.h b/kv_store/kvstoremock/frameworks/innerkitsimpl/kvdb/include/single_store_impl.h index f8eeb463e2a504554fde034c7bd2818944155baf..f04e603108c421011b584777807286e0dcdaafbc 100644 --- a/kv_store/kvstoremock/frameworks/innerkitsimpl/kvdb/include/single_store_impl.h +++ b/kv_store/kvstoremock/frameworks/innerkitsimpl/kvdb/include/single_store_impl.h @@ -83,6 +83,7 @@ public: Status UnsubscribeWithQuery(const std::vector &devices, const DataQuery &query) override; Status SetIdentifier(const std::string &accountId, const std::string &appId, const std::string &storeId, const std::vector &tagretDev) override; + bool IsRebuild() override; private: static constexpr size_t MAX_VALUE_LENGTH = 4 * 1024 * 1024; static constexpr size_t MAX_OBSERVER_SIZE = 8; diff --git a/kv_store/kvstoremock/frameworks/innerkitsimpl/kvdb/src/single_store_impl.cpp b/kv_store/kvstoremock/frameworks/innerkitsimpl/kvdb/src/single_store_impl.cpp index bd75dcb443f3aab98cfa7e3d0bcb3552711c5efc..0aca6b7fe6bc193b74c217b3bf9bb9bd0b7b0a14 100644 --- a/kv_store/kvstoremock/frameworks/innerkitsimpl/kvdb/src/single_store_impl.cpp +++ b/kv_store/kvstoremock/frameworks/innerkitsimpl/kvdb/src/single_store_impl.cpp @@ -486,4 +486,8 @@ Status SingleStoreImpl::SetIdentifier(const std::string &accountId, const std::s { return SERVER_UNAVAILABLE; } +bool SingleStoreImpl::IsRebuild() +{ + return false; +} } // namespace OHOS::DistributedKv \ No newline at end of file diff --git a/mock/innerkits/appexecfwk_core/include/bundlemgr/bundle_mgr_interface.h b/mock/innerkits/appexecfwk_core/include/bundlemgr/bundle_mgr_interface.h index 62ab7083e0a6051a1b244b38da6ec35fd3b86096..95d83ff110df6a614634596abf8953fd90f76155 100644 --- a/mock/innerkits/appexecfwk_core/include/bundlemgr/bundle_mgr_interface.h +++ b/mock/innerkits/appexecfwk_core/include/bundlemgr/bundle_mgr_interface.h @@ -43,6 +43,23 @@ enum class DumpFlag { DUMP_BUNDLE_INFO, // corresponse to option "-bundle [name]" DUMP_SHORTCUT_INFO, // corresponse to option "-bundle [name] -shortcut-info" }; +enum class GetBundleInfoFlag { + GET_BUNDLE_INFO_DEFAULT = 0x00000000, + GET_BUNDLE_INFO_WITH_APPLICATION = 0x00000001, + GET_BUNDLE_INFO_WITH_HAP_MODULE = 0x00000002, + GET_BUNDLE_INFO_WITH_ABILITY = 0x00000004, + GET_BUNDLE_INFO_WITH_EXTENSION_ABILITY = 0x00000008, + GET_BUNDLE_INFO_WITH_REQUESTED_PERMISSION = 0x00000010, + GET_BUNDLE_INFO_WITH_METADATA = 0x00000020, + GET_BUNDLE_INFO_WITH_DISABLE = 0x00000040, + GET_BUNDLE_INFO_WITH_SIGNATURE_INFO = 0x00000080, + GET_BUNDLE_INFO_WITH_MENU = 0x00000100, + GET_BUNDLE_INFO_WITH_ROUTER_MAP = 0x00000200, + GET_BUNDLE_INFO_WITH_SKILL = 0x00000800, + GET_BUNDLE_INFO_ONLY_WITH_LAUNCHER_ABILITY = 0x00001000, + GET_BUNDLE_INFO_OF_ANY_USER = 0x00002000, + GET_BUNDLE_INFO_EXCLUDE_CLONE = 0x00004000, +}; class IBundleMgr : public IRemoteBroker { public: diff --git a/mock/innerkits/device_manager/devicemanagersdk/include/device_manager.h b/mock/innerkits/device_manager/devicemanagersdk/include/device_manager.h index 9ea3c792df506c2abf5e1acf7f56c1abd5e4d271..cd9bf9c491e70ce71b09eb897f77f45546856fd8 100644 --- a/mock/innerkits/device_manager/devicemanagersdk/include/device_manager.h +++ b/mock/innerkits/device_manager/devicemanagersdk/include/device_manager.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2022-2023 Huawei Device Co., Ltd. +* Copyright (c) 2022-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 @@ -16,6 +16,7 @@ #ifndef OHOS_DEVICE_MANAGER_H #define OHOS_DEVICE_MANAGER_H +#include #include #include #include @@ -29,61 +30,93 @@ namespace OHOS { namespace DistributedHardware { class DeviceManager { public: - static DeviceManager &GetInstance(); + static DeviceManager &GetInstance(); public: - /** + /** * @brief Initialize DeviceManager. * @param pkgName package name. * @param dmInitCallback the callback to be invoked upon InitDeviceManager. * @return Returns 0 if success. */ - virtual int32_t InitDeviceManager(const std::string &pkgName, std::shared_ptr dmInitCallback) = 0; - /** + virtual int32_t InitDeviceManager(const std::string &pkgName, std::shared_ptr dmInitCallback) = 0; + /** * @brief UnInitialize DeviceManager. * @param pkgName package name. * @return Returns 0 if success. */ - virtual int32_t UnInitDeviceManager(const std::string &pkgName) = 0; - /** + virtual int32_t UnInitDeviceManager(const std::string &pkgName) = 0; + /** * @brief Get device info list of trusted devices. * @param pkgName package name. * @param extra extra info.This parameter can be null. * @param deviceList device info list. * @return Returns a list of trusted devices. */ - virtual int32_t GetTrustedDeviceList(const std::string &pkgName, const std::string &extra, - std::vector &deviceList) = 0; - /** + virtual int32_t GetTrustedDeviceList(const std::string &pkgName, const std::string &extra, + std::vector &deviceList) = 0; + /** + * @brief Get device info list of trusted devices. + * @param pkgName package name. + * @param extra extra info.This parameter can be null. + * @param isRefresh refresh the list quickly. + * @param deviceList device info list. + * @return Returns a list of trusted devices. + */ + virtual int32_t GetTrustedDeviceList(const std::string &pkgName, const std::string &extra, bool isRefresh, + std::vector &deviceList) = 0; + /** + * @brief Get device info list of available devices. + * @param pkgName package name. + * @param extra extra info.This parameter can be null. + * @param deviceList device info list. + * @return Returns a list of available devices. + */ + virtual int32_t GetAvailableDeviceList(const std::string &pkgName, std::vector &deviceList) = 0; + /** * @brief Get local device information. * @param pkgName package name. * @param deviceInfo device info. * @return Returns local device info. */ - virtual int32_t GetLocalDeviceInfo(const std::string &pkgName, DmDeviceInfo &deviceInfo) = 0; - /** + virtual int32_t GetLocalDeviceInfo(const std::string &pkgName, DmDeviceInfo &deviceInfo) = 0; + /** * @tc.name: DeviceManagerImpl::GetDeviceInfo * @tc.desc: Get local device information by networkId * @tc.type: FUNC */ - virtual int32_t GetDeviceInfo(const std::string &pkgName, const std::string networkId, - DmDeviceInfo &deviceInfo) = 0; - /** + virtual int32_t GetDeviceInfo(const std::string &pkgName, const std::string networkId, + DmDeviceInfo &deviceInfo) = 0; + /** * @brief Register device status callback. * @param pkgName package name. * @param extra extra info.This parameter can be null. * @param callback device state callback. * @return Returns 0 if success. */ - virtual int32_t RegisterDevStateCallback(const std::string &pkgName, const std::string &extra, - std::shared_ptr callback) = 0; - /** + virtual int32_t RegisterDevStateCallback(const std::string &pkgName, const std::string &extra, + std::shared_ptr callback) = 0; + /** + * @brief Register device status callback. + * @param pkgName package name. + * @param callback device status callback. + * @return Returns 0 if success. + */ + virtual int32_t RegisterDevStatusCallback(const std::string &pkgName, const std::string &extra, + std::shared_ptr callback) = 0; + /** + * @brief Unregister device status callback. + * @param pkgName package name. + * @return Returns 0 if success. + */ + virtual int32_t UnRegisterDevStateCallback(const std::string &pkgName) = 0; + /** * @brief Unregister device status callback. * @param pkgName package name. * @return Returns 0 if success. */ - virtual int32_t UnRegisterDevStateCallback(const std::string &pkgName) = 0; - /** + virtual int32_t UnRegisterDevStatusCallback(const std::string &pkgName) = 0; + /** * @brief Initiate device discovery. * @param pkgName package name. * @param subscribeInfo subscribe info to discovery device. @@ -91,32 +124,49 @@ public: * @param callback discovery callback. * @return Returns 0 if success. */ - virtual int32_t StartDeviceDiscovery(const std::string &pkgName, const DmSubscribeInfo &subscribeInfo, - const std::string &extra, std::shared_ptr callback) = 0; - /** + virtual int32_t StartDeviceDiscovery(const std::string &pkgName, const DmSubscribeInfo &subscribeInfo, + const std::string &extra, std::shared_ptr callback) = 0; + /** + * @brief Initiate device discovery. + * @param pkgName package name. + * @param subscribeId subscribe id to discovery device. + * @param extra extra info.This parameter can be null. + * @param callback discovery callback. + * @return Returns 0 if success. + */ + virtual int32_t StartDeviceDiscovery(const std::string &pkgName, uint64_t tokenId, + const std::string &filterOptions, std::shared_ptr callback) = 0; + /** * @brief Stop device discovery. * @param pkgName package name. * @param subscribeInfo subscribe info to discovery device. * @return Returns 0 if success. */ - virtual int32_t StopDeviceDiscovery(const std::string &pkgName, uint16_t subscribeId) = 0; - /** + virtual int32_t StopDeviceDiscovery(const std::string &pkgName, uint16_t subscribeId) = 0; + /** + * @brief Stop device discovery. + * @param pkgName package name. + * @param tokenId app flag to discovery device. + * @return Returns 0 if success. + */ + virtual int32_t StopDeviceDiscovery(uint64_t tokenId, const std::string &pkgName) = 0; + /** * @brief Publish device discovery. * @param pkgName package name. * @param publishInfo publish info to Publish discovery device. * @param callback the callback to be invoked upon PublishDeviceDiscovery. * @return Returns 0 if success. */ - virtual int32_t PublishDeviceDiscovery(const std::string &pkgName, const DmPublishInfo &publishInfo, - std::shared_ptr callback) = 0; - /** + virtual int32_t PublishDeviceDiscovery(const std::string &pkgName, const DmPublishInfo &publishInfo, + std::shared_ptr callback) = 0; + /** * @brief UnPublish device discovery. * @param pkgName package name. * @param publishId service publish ID, identify a publish operation, should be a unique id in package range. * @return Returns 0 if success. */ - virtual int32_t UnPublishDeviceDiscovery(const std::string &pkgName, int32_t publishId) = 0; - /** + virtual int32_t UnPublishDeviceDiscovery(const std::string &pkgName, int32_t publishId) = 0; + /** * @brief Authenticate the specified device. * @param pkgName package name. * @param authType authType of device to authenticate. @@ -125,79 +175,93 @@ public: * @param callback the callback to be invoked upon AuthenticateDevice. * @return Returns 0 if success. */ - virtual int32_t AuthenticateDevice(const std::string &pkgName, int32_t authType, const DmDeviceInfo &deviceInfo, - const std::string &extra, std::shared_ptr callback) = 0; - /** + virtual int32_t AuthenticateDevice(const std::string &pkgName, int32_t authType, const DmDeviceInfo &deviceInfo, + const std::string &extra, std::shared_ptr callback) = 0; + /** * @brief Cancel complete verification of device. * @param pkgName package name. * @param deviceInfo deviceInfo of device to authenticate. * @return Returns 0 if success. */ - virtual int32_t UnAuthenticateDevice(const std::string &pkgName, const DmDeviceInfo &deviceInfo) = 0; - /** + virtual int32_t UnAuthenticateDevice(const std::string &pkgName, const DmDeviceInfo &deviceInfo) = 0; + /** * @brief Verify device authentication. * @param pkgName package name. * @param authPara authPara of device to authenticate. * @param callback the callback to be invoked upon VerifyAuthentication. * @return Returns 0 if success. */ - virtual int32_t VerifyAuthentication(const std::string &pkgName, const std::string &authPara, - std::shared_ptr callback) = 0; - /** + [[deprecated]] virtual int32_t VerifyAuthentication(const std::string &pkgName, const std::string &authPara, + std::shared_ptr callback) = 0; + /** + * @brief Register Fa callback for device manager. + * @param pkgName package name. + * @param callback device manager Fa callback. + * @return Returns 0 if success. + */ + virtual int32_t RegisterDeviceManagerFaCallback(const std::string &pkgName, + std::shared_ptr callback) = 0; + /** + * @brief Unregister Fa callback for device manager. + * @param pkgName package name. + * @return Returns 0 if success. + */ + virtual int32_t UnRegisterDeviceManagerFaCallback(const std::string &pkgName) = 0; + /** * @brief Get Fa Param. * @param pkgName package name. * @param faParam fa param. * @return Returns 0 if success. */ - virtual int32_t GetFaParam(const std::string &pkgName, DmAuthParam &faParam) = 0; - /** + [[deprecated]] virtual int32_t GetFaParam(const std::string &pkgName, DmAuthParam &faParam) = 0; + /** * @brief Set User Actions. * @param pkgName package name. * @param action user operation action. * @param params indicates the input param of the user. * @return Returns 0 if success. */ - virtual int32_t SetUserOperation(const std::string &pkgName, int32_t action, const std::string ¶ms) = 0; - /** + virtual int32_t SetUserOperation(const std::string &pkgName, int32_t action, const std::string ¶ms) = 0; + /** * @brief Get Udid by NetworkId. * @param pkgName package name. * @param netWorkId netWork Id. * @param udid unique device id. * @return Returns 0 if success. */ - virtual int32_t GetUdidByNetworkId(const std::string &pkgName, const std::string &netWorkId, std::string &udid) = 0; - /** + virtual int32_t GetUdidByNetworkId(const std::string &pkgName, const std::string &netWorkId, std::string &udid) = 0; + /** * @brief Get Uuid by NetworkId. * @param pkgName package name. * @param netWorkId netWork Id. * @param uuid universally unique id. * @return Returns 0 if success. */ - virtual int32_t GetUuidByNetworkId(const std::string &pkgName, const std::string &netWorkId, std::string &uuid) = 0; - /** + virtual int32_t GetUuidByNetworkId(const std::string &pkgName, const std::string &netWorkId, std::string &uuid) = 0; + /** * @brief Unregister device status callback. * @param pkgName package name. * @param extra extra info.This parameter can be null. * @return Returns 0 if success. */ - virtual int32_t RegisterDevStateCallback(const std::string &pkgName, const std::string &extra) = 0; - /** + [[deprecated]] virtual int32_t RegisterDevStateCallback(const std::string &pkgName, const std::string &extra) = 0; + /** * @brief Unregister device status callback. * @param pkgName package name. * @param extra extra info.This parameter can be null. * @return Returns 0 if success. */ - virtual int32_t UnRegisterDevStateCallback(const std::string &pkgName, const std::string &extra) = 0; - /** + [[deprecated]] virtual int32_t UnRegisterDevStateCallback(const std::string &pkgName, const std::string &extra) = 0; + /** * @brief Request credential information. * @param pkgName package name. * @param reqJsonStr request credential params, the params is json string, it includes version and userId. * @param returnJsonStr return json string, it includes deviceId, devicePk, useId and version. * @return Returns 0 if success. */ - virtual int32_t RequestCredential(const std::string &pkgName, const std::string &reqJsonStr, - std::string &returnJsonStr) = 0; - /** + [[deprecated]] virtual int32_t RequestCredential(const std::string &pkgName, const std::string &reqJsonStr, + std::string &returnJsonStr) = 0; + /** * @brief Import credential information. * @param pkgName package name. * @param credentialInfo import credential params, the params is json string, it includes processType, authType, @@ -205,56 +269,362 @@ public: * includes credentialType, credentialId, serverPk, pkInfoSignature, pkInfo, authCode, peerDeviceId. * @return Returns 0 if success. */ - virtual int32_t ImportCredential(const std::string &pkgName, const std::string &credentialInfo) = 0; - /** + [[deprecated]] virtual int32_t ImportCredential(const std::string &pkgName, const std::string &credentialInfo) = 0; + /** * @brief Delete credential information. * @param pkgName package name. * @param deleteInfo delete credential params. the params is json string, it includes processType, authType, userId. * @return Returns 0 if success. */ - virtual int32_t DeleteCredential(const std::string &pkgName, const std::string &deleteInfo) = 0; - /** + [[deprecated]] virtual int32_t DeleteCredential(const std::string &pkgName, const std::string &deleteInfo) = 0; + /** * @brief Register credential callback. * @param pkgName package name. * @param callback credential callback. * @return Returns 0 if success. */ - virtual int32_t RegisterCredentialCallback(const std::string &pkgName, - std::shared_ptr callback) = 0; - /** + [[deprecated]] virtual int32_t RegisterCredentialCallback(const std::string &pkgName, + std::shared_ptr callback) = 0; + /** * @brief UnRegister credential callback. * @param pkgName package name. * @return Returns 0 if success. */ - virtual int32_t UnRegisterCredentialCallback(const std::string &pkgName) = 0; - /** + [[deprecated]] virtual int32_t UnRegisterCredentialCallback(const std::string &pkgName) = 0; + /** * @brief Notify event to device manager. * @param pkgName package name. * @param event event info. * @param event event string. * @return Returns 0 if success. */ - virtual int32_t NotifyEvent(const std::string &pkgName, const int32_t eventId, const std::string &event) = 0; + virtual int32_t NotifyEvent(const std::string &pkgName, const int32_t eventId, const std::string &event) = 0; - /** + /** * @brief Get encrypted uuid. * @param networkId device networkId. * @return Returns encrypted uuid. */ - virtual int32_t GetEncryptedUuidByNetworkId(const std::string &pkgName, const std::string &networkId, - std::string &uuid) = 0; + virtual int32_t GetEncryptedUuidByNetworkId(const std::string &pkgName, const std::string &networkId, + std::string &uuid) = 0; - /** + /** * @brief Get encrypted uuid. * @param uuid device uuid. * @param tokenId tokenId. * @return Returns encrypted uuid. */ - virtual int32_t GenerateEncryptedUuid(const std::string &pkgName, const std::string &uuid, const std::string &appId, - std::string &encryptedUuid) = 0; + virtual int32_t GenerateEncryptedUuid(const std::string &pkgName, const std::string &uuid, + const std::string &appId, std::string &encryptedUuid) = 0; + + /** + * @tc.name: DeviceManagerImpl::CheckAPIAccessPermission + * @tc.desc: check permission for device manager API + * @tc.type: FUNC + */ + virtual int32_t CheckAPIAccessPermission() = 0; - virtual bool IsSameAccount(const std::string &netWorkId) = 0; + /** + * @brief Get local device netWorkId. + * @param pkgName package name. + * @return Returns local device networkId. + */ + virtual int32_t GetLocalDeviceNetWorkId(const std::string &pkgName, std::string &networkId) = 0; + + /** + * @brief Get local deviceId. + * @param pkgName package name. + * @return Returns local deviceId. + */ + virtual int32_t GetLocalDeviceId(const std::string &pkgName, std::string &networkId) = 0; + + /** + * @brief Get local device name. + * @param pkgName package name. + * @return Returns device name. + */ + virtual int32_t GetLocalDeviceName(const std::string &pkgName, std::string &deviceName) = 0; + + /** + * @brief Get local device type. + * @param pkgName package name. + * @return Returns device type. + */ + virtual int32_t GetLocalDeviceType(const std::string &pkgName, int32_t &deviceType) = 0; + + /** + * @brief Get device name. + * @param pkgName package name. + * @param networkId device networkId. + * @return Returns device name. + */ + virtual int32_t GetDeviceName(const std::string &pkgName, const std::string &networkId, + std::string &deviceName) = 0; + + /** + * @brief Get device type. + * @param pkgName package name. + * @param networkId device networkId. + * @return Returns device type. + */ + virtual int32_t GetDeviceType(const std::string &pkgName, const std::string &networkId, int32_t &deviceType) = 0; + + /** + * @brief Bind the specified device. + * @param pkgName package name. + * @param bindType bindType of device to bind. + * @param deviceInfo device id of device to bind. + * @param extra extra info.This parameter can be null. + * @param callback callback. + * @return Returns 0 if success. + */ + virtual int32_t BindDevice(const std::string &pkgName, int32_t bindType, const std::string &deviceId, + const std::string &extra, std::shared_ptr callback) = 0; + + /** + * @brief UnBind the specified device. + * @param pkgName package name. + * @param deviceId device id to UnBindDevice. + * @return Returns 0 if success. + */ + virtual int32_t UnBindDevice(const std::string &pkgName, const std::string &deviceId) = 0; + + virtual int32_t CheckNewAPIAccessPermission() = 0; + + /** + * @brief Get Network Type by NetworkId. + * @param pkgName package name. + * @param netWorkId netWork Id. + * @param netWorkType netWork Type. + * @return Returns 0 if success. + */ + virtual int32_t GetNetworkTypeByNetworkId(const std::string &pkgName, const std::string &netWorkId, + int32_t &netWorkType) = 0; + + /** + * @brief Import Auth Code. + * @param pkgName BindDevice caller package name. + * @param authCode Authentication code. + * @return Returns 0 if success. + */ + virtual int32_t ImportAuthCode(const std::string &pkgName, const std::string &authCode) = 0; + + /** + * @brief Export Auth Code. + * @param authCode Authentication code. + * @return Returns 0 if success. + */ + virtual int32_t ExportAuthCode(std::string &authCode) = 0; + + // The following interfaces are provided since OpenHarmony 4.1 Version. + /** + * @brief Start to discover nearby devices or services. + * @param pkgName package name. + * @param discoverParam discover parameters. + * @param filterOptions filter option parameters. + * @param callback discovery callback. + * @return Returns 0 if success. + */ + virtual int32_t StartDiscovering(const std::string &pkgName, std::map &discoverParam, + const std::map &filterOptions, std::shared_ptr callback) = 0; + + /** + * @brief Stop discovering nearby devices or services. + * @param pkgName package name. + * @param discoverParam discover parameters. + * @return Returns 0 if success. + */ + virtual int32_t StopDiscovering(const std::string &pkgName, std::map &discoverParam) = 0; + + /** + * @brief Registerthe discovery callback. + * @param pkgName package name. + * @param discoverParam discover parameters. + * @param filterOptions filter option parameters. + * @param callback discovery callback. + * @return Returns 0 if success. + */ + virtual int32_t RegisterDiscoveryCallback(const std::string &pkgName, + std::map &discoverParam, const std::map &filterOptions, + std::shared_ptr callback) = 0; + + /** + * @brief UnRegisterthe discovery callback. + * @param pkgName package name. + * @return Returns 0 if success. + */ + virtual int32_t UnRegisterDiscoveryCallback(const std::string &pkgName) = 0; + + /** + * @brief Start to advertise the nearby devices or services. + * @param pkgName package name. + * @param advertiseParam advertise parameters. + * @param callback advertise callback. + * @return Returns 0 if success. + */ + virtual int32_t StartAdvertising(const std::string &pkgName, std::map &advertiseParam, + std::shared_ptr callback) = 0; + + /** + * @brief Stop to advertise the nearby devices or services. + * @param pkgName package name. + * @param advertiseParam advertise parameters. + * @return Returns 0 if success. + */ + virtual int32_t StopAdvertising(const std::string &pkgName, std::map &advertiseParam) = 0; + + /** + * @brief Bind the specified target. + * @param pkgName package name. + * @param targetId id of target to bind. + * @param bindParam bind parameters. + * @param callback bind result callback. + * @return Returns 0 if success. + */ + virtual int32_t BindTarget(const std::string &pkgName, const PeerTargetId &targetId, + std::map &bindParam, std::shared_ptr callback) = 0; + + /** + * @brief Unbind the specified target. + * @param pkgName package name. + * @param targetId id of target to unbind. + * @param unbindParam unbind parameters. + * @param callback bind result callback. + * @return Returns 0 if success. + */ + virtual int32_t UnbindTarget(const std::string &pkgName, const PeerTargetId &targetId, + std::map &unbindParam, std::shared_ptr callback) = 0; + + /** + * @brief Get device info list of trusted devices. + * @param pkgName package name. + * @param filterOptions filter option parameters. + * @param isRefresh refresh the list quickly. + * @param deviceList device info list. + * @return Returns a list of trusted devices. + */ + virtual int32_t GetTrustedDeviceList(const std::string &pkgName, + const std::map &filterOptions, bool isRefresh, + std::vector &deviceList) = 0; + + /** + * @brief Register device state callback. + * @param pkgName package name. + * @param extraParam extra parameters. + * @param callback device status callback. + * @return Returns 0 if success. + */ + virtual int32_t RegisterDevStateCallback(const std::string &pkgName, + const std::map &extraParam, std::shared_ptr callback) = 0; + + /** + * @brief Check the specific caller whether has permission to access the target. + * @param tokenId the caller token id. + * @param targetId the target id. + * @return Returns 0 if success. + */ + virtual int32_t CheckAccessToTarget(uint64_t tokenId, const std::string &targetId) = 0; + + /** + * @brief Register Pin Code Holder Callback + * @param pkgName package name. + * @param callback the callback to be invoked upon CreateAuthCodeHolder or DestroyAuthCodeHolder. + * @return Returns 0 if success. + */ + virtual int32_t RegisterPinHolderCallback(const std::string &pkgName, + std::shared_ptr callback) = 0; + + /** + * @brief Create Pin Code Holder + * @param pkgName package name. + * @param targetId id of target to create pin holder. + * @param pinType pin code holder type. + * @param payload business custom data. + * @return Returns 0 if success. + */ + virtual int32_t CreatePinHolder(const std::string &pkgName, const PeerTargetId &targetId, DmPinType pinType, + const std::string &payload) = 0; + + /** + * @brief Destroy Pin Code Holder + * @param pkgName package name. + * @param targetId id of target to destroy pin holder. + * @param pinType pin code holder type. + * @param payload business custom data. + * @return Returns 0 if success. + */ + virtual int32_t DestroyPinHolder(const std::string &pkgName, const PeerTargetId &targetId, DmPinType pinType, + const std::string &payload) = 0; + + /** + * @brief Request credential information. + * @param pkgName package name. + * @param returnJsonStr return json string, it includes deviceId, devicePk, useId and version. + * @return Returns 0 if success. + */ + virtual int32_t RequestCredential(const std::string &pkgName, std::string &returnJsonStr) = 0; + + /** + * @brief Check credential information. + * @param pkgName package name. + * @param reqJsonStr request credential params, the params is json string, it includes version and userId. + * @param returnJsonStr return json string, it includes deviceId, devicePk, useId and version. + * @return Returns 0 if success. + */ + virtual int32_t CheckCredential(const std::string &pkgName, const std::string &reqJsonStr, + std::string &returnJsonStr) = 0; + + /** + * @brief Import credential information. + * @param pkgName package name. + * @param reqJsonStr request credential params, the params is json string, it includes version and userId. + * @param returnJsonStr return json string, it includes deviceId, devicePk, useId and version. + * @return Returns 0 if success. + */ + virtual int32_t ImportCredential(const std::string &pkgName, const std::string &reqJsonStr, + std::string &returnJsonStr) = 0; + + /** + * @brief Delete credential information. + * @param pkgName package name. + * @param reqJsonStr request credential params, the params is json string, it includes version and userId. + * @param returnJsonStr return json string, it includes deviceId, devicePk, useId and version. + * @return Returns 0 if success. + */ + virtual int32_t DeleteCredential(const std::string &pkgName, const std::string &reqJsonStr, + std::string &returnJsonStr) = 0; + + virtual int32_t DpAclAdd(const int64_t accessControlId, const std::string &udid, const int32_t bindType) = 0; + virtual int32_t GetDeviceSecurityLevel(const std::string &pkgName, const std::string &networkId, + int32_t &securityLevel) = 0; + virtual bool IsSameAccount(const std::string &netWorkId) = 0; + virtual bool CheckAccessControl(const DmAccessCaller &caller, const DmAccessCallee &callee) = 0; + virtual bool CheckIsSameAccount(const DmAccessCaller &caller, const DmAccessCallee &callee) = 0; + virtual int32_t GetErrCode(int32_t errCode) = 0; + virtual int32_t ShiftLNNGear(const std::string &pkgName) = 0; + virtual int32_t RegDevTrustChangeCallback(const std::string &pkgName, + std::shared_ptr callback) = 0; + virtual int32_t RegisterDeviceScreenStatusCallback(const std::string &pkgName, + std::shared_ptr callback) = 0; + virtual int32_t UnRegisterDeviceScreenStatusCallback(const std::string &pkgName) = 0; + virtual int32_t GetDeviceScreenStatus(const std::string &pkgName, const std::string &networkId, + int32_t &screenStatus) = 0; + + /** + * @brief Set Dn Policy + * @param pkgName package name. + * @param policy contain DM_POLICY_STRATEGY_FOR_BLE and DM_POLICY_TIMEOUT key and value. + * DM_POLICY_STRATEGY_FOR_BLE: Strategy BLE networking go-online policy, suppress or restore. + * DM_POLICY_TIMEOUT: Indicates the duration for suppressing ble networking. + * @return Returns 0 if success. + */ + virtual int32_t SetDnPolicy(const std::string &pkgName, std::map &policy) = 0; + virtual int32_t StopAuthenticateDevice(const std::string &pkgName) = 0; + virtual int32_t GetNetworkIdByUdid(const std::string &pkgName, const std::string &udid, std::string &networkId) = 0; + virtual int32_t RegisterCredentialAuthStatusCallback(const std::string &pkgName, + std::shared_ptr callback) = 0; + virtual int32_t UnRegisterCredentialAuthStatusCallback(const std::string &pkgName) = 0; }; } // namespace DistributedHardware } // namespace OHOS -#endif // DEVICE_MANAGER_H +#endif // DEVICE_MANAGER_H \ No newline at end of file diff --git a/mock/innerkits/device_manager/devicemanagersdk/include/device_manager_callback.h b/mock/innerkits/device_manager/devicemanagersdk/include/device_manager_callback.h index 48ef479d6894e8e9274c5a6ba3ac4099723f822e..398124da69fbc23f32a5873b37147e306c84926a 100644 --- a/mock/innerkits/device_manager/devicemanagersdk/include/device_manager_callback.h +++ b/mock/innerkits/device_manager/devicemanagersdk/include/device_manager_callback.h @@ -1,17 +1,17 @@ /* - * Copyright (c) 2022 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. - */ +* Copyright (c) 2022-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. +*/ #ifndef OHOS_DM_CALLBACK_H #define OHOS_DM_CALLBACK_H @@ -25,72 +25,107 @@ namespace OHOS { namespace DistributedHardware { class DmInitCallback { public: - virtual ~DmInitCallback() - { - } + virtual ~DmInitCallback() {} virtual void OnRemoteDied() = 0; }; class DeviceStateCallback { public: - virtual ~DeviceStateCallback() - { - } + virtual ~DeviceStateCallback() {} virtual void OnDeviceOnline(const DmDeviceInfo &deviceInfo) = 0; virtual void OnDeviceOffline(const DmDeviceInfo &deviceInfo) = 0; virtual void OnDeviceChanged(const DmDeviceInfo &deviceInfo) = 0; virtual void OnDeviceReady(const DmDeviceInfo &deviceInfo) = 0; }; +class DeviceStatusCallback { +public: + virtual ~DeviceStatusCallback() {} + virtual void OnDeviceOnline(const DmDeviceBasicInfo &deviceBasicInfo) = 0; + virtual void OnDeviceOffline(const DmDeviceBasicInfo &deviceBasicInfo) = 0; + virtual void OnDeviceChanged(const DmDeviceBasicInfo &deviceBasicInfo) = 0; + virtual void OnDeviceReady(const DmDeviceBasicInfo &deviceBasicInfo) = 0; +}; + class DiscoveryCallback { public: - virtual ~DiscoveryCallback() - { - } + virtual ~DiscoveryCallback() {} virtual void OnDiscoverySuccess(uint16_t subscribeId) = 0; virtual void OnDiscoveryFailed(uint16_t subscribeId, int32_t failedReason) = 0; - virtual void OnDeviceFound(uint16_t subscribeId, const DmDeviceInfo &deviceInfo) = 0; + virtual void OnDeviceFound(uint16_t subscribeId, const DmDeviceInfo &deviceInfo){}; + virtual void OnDeviceFound(uint16_t subscribeId, const DmDeviceBasicInfo &deviceBasicInfo){}; }; class PublishCallback { public: - virtual ~PublishCallback() - { - } + virtual ~PublishCallback() {} virtual void OnPublishResult(int32_t publishId, int32_t publishResult) = 0; }; class AuthenticateCallback { public: - virtual ~AuthenticateCallback() - { - } + virtual ~AuthenticateCallback() {} virtual void OnAuthResult(const std::string &deviceId, const std::string &token, int32_t status, - int32_t reason) = 0; + int32_t reason) = 0; +}; + +class BindTargetCallback { +public: + virtual ~BindTargetCallback() {} + virtual void OnBindResult(const PeerTargetId &targetId, int32_t result, int32_t status, std::string content) = 0; +}; + +class UnbindTargetCallback { +public: + virtual ~UnbindTargetCallback() {} + virtual void OnUnbindResult(const PeerTargetId &targetId, int32_t result, std::string content) = 0; }; class VerifyAuthCallback { public: - virtual ~VerifyAuthCallback() - { - } + virtual ~VerifyAuthCallback() {} virtual void OnVerifyAuthResult(const std::string &deviceId, int32_t resultCode, int32_t flag) = 0; }; -class DeviceManagerFaCallback { + +class DeviceManagerUiCallback { public: - virtual ~DeviceManagerFaCallback() - { - } + virtual ~DeviceManagerUiCallback() {} virtual void OnCall(const std::string ¶mJson) = 0; }; class CredentialCallback { public: - virtual ~CredentialCallback() - { - } + virtual ~CredentialCallback() {} virtual void OnCredentialResult(int32_t &action, const std::string &credentialResult) = 0; }; + +class PinHolderCallback { +public: + virtual ~PinHolderCallback() {} + virtual void OnPinHolderCreate(const std::string &deviceId, DmPinType pinType, const std::string &payload) = 0; + virtual void OnPinHolderDestroy(DmPinType pinType, const std::string &payload) = 0; + virtual void OnCreateResult(int32_t result) = 0; + virtual void OnDestroyResult(int32_t result) = 0; + virtual void OnPinHolderEvent(DmPinHolderEvent event, int32_t result, const std::string &content) = 0; +}; + +class DevTrustChangeCallback { +public: + virtual ~DevTrustChangeCallback() {} + virtual void OnDeviceTrustChange(const std::string &udid, const std::string &uuid, DmAuthForm authForm) = 0; +}; + +class DeviceScreenStatusCallback { +public: + virtual ~DeviceScreenStatusCallback() {} + virtual void OnDeviceScreenStatus(const DmDeviceInfo &deviceInfo) = 0; +}; + +class CredentialAuthStatusCallback { +public: + virtual ~CredentialAuthStatusCallback() {} + virtual void OnCredentialAuthStatus(uint16_t deviceTypeId, int32_t errcode) = 0; +}; } // namespace DistributedHardware } // namespace OHOS #endif // OHOS_DM_CALLBACK_H diff --git a/mock/innerkits/device_manager/devicemanagersdk/include/device_manager_impl.h b/mock/innerkits/device_manager/devicemanagersdk/include/device_manager_impl.h index aeb0c3a7039d623e975410a2cc59525d8cb8906c..b8fa7cd2db32ff861c7cf85b8c87e33ba9ebd063 100644 --- a/mock/innerkits/device_manager/devicemanagersdk/include/device_manager_impl.h +++ b/mock/innerkits/device_manager/devicemanagersdk/include/device_manager_impl.h @@ -1,17 +1,17 @@ /* - * Copyright (c) 2022 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. - */ +* Copyright (c) 2022-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. +*/ #ifndef OHOS_DEVICE_MANAGER_IMPL_H #define OHOS_DEVICE_MANAGER_IMPL_H @@ -26,173 +26,370 @@ public: public: /** - * @tc.name: DeviceManagerImpl::InitDeviceManager - * @tc.desc: Initialize DeviceManager - * @tc.type: FUNC - */ + * @tc.name: DeviceManagerImpl::InitDeviceManager + * @tc.desc: Initialize DeviceManager + * @tc.type: FUNC + */ virtual int32_t InitDeviceManager(const std::string &pkgName, - std::shared_ptr dmInitCallback) override; + std::shared_ptr dmInitCallback) override; /** - * @tc.name: DeviceManagerImpl::UnInitDeviceManager - * @tc.desc: UnInitialize DeviceManager - * @tc.type: FUNC - */ + * @tc.name: DeviceManagerImpl::UnInitDeviceManager + * @tc.desc: UnInitialize DeviceManager + * @tc.type: FUNC + */ virtual int32_t UnInitDeviceManager(const std::string &pkgName) override; /** - * @tc.name: DeviceManagerImpl::GetTrustedDeviceList - * @tc.desc: Get device list of trusted devices - * @tc.type: FUNC - */ + * @tc.name: DeviceManagerImpl::GetTrustedDeviceList + * @tc.desc: Get device list of trusted devices + * @tc.type: FUNC + */ virtual int32_t GetTrustedDeviceList(const std::string &pkgName, const std::string &extra, - std::vector &deviceList) override; - /** - * @tc.name: DeviceManagerImpl::GetLocalDeviceInfo - * @tc.desc: Get local device information - * @tc.type: FUNC - */ - virtual int32_t GetLocalDeviceInfo(const std::string &pkgName, DmDeviceInfo &deviceInfo) override; - /** - * @tc.name: DeviceManagerImpl::RegisterDevStateCallback - * @tc.desc: Register device development status callback - * @tc.type: FUNC - */ + std::vector &deviceList) override; + /** + * @tc.name: DeviceManagerImpl::GetTrustedDeviceList + * @tc.desc: Get device list of trusted devices + * @tc.type: FUNC + */ + virtual int32_t GetTrustedDeviceList(const std::string &pkgName, const std::string &extra, bool isRefresh, + std::vector &deviceList) override; + /** + * @tc.name: DeviceManagerImpl::GetAvailableDeviceList + * @tc.desc: Get device list of trusted devices + * @tc.type: FUNC + */ + virtual int32_t GetAvailableDeviceList(const std::string &pkgName, + std::vector &deviceList) override; + /** + * @tc.name: DeviceManagerImpl::GetLocalDeviceInfo + * @tc.desc: Get local device information + * @tc.type: FUNC + */ + virtual int32_t GetLocalDeviceInfo(const std::string &pkgName, DmDeviceInfo &info) override; + /** + * @tc.name: DeviceManagerImpl::GetDeviceInfo + * @tc.desc: Get local device information by networkId + * @tc.type: FUNC + */ + virtual int32_t GetDeviceInfo(const std::string &pkgName, const std::string networkId, + DmDeviceInfo &deviceInfo) override; + /** + * @tc.name: DeviceManagerImpl::RegisterDevStateCallback + * @tc.desc: Register device development status callback + * @tc.type: FUNC + */ virtual int32_t RegisterDevStateCallback(const std::string &pkgName, const std::string &extra, - std::shared_ptr callback) override; + std::shared_ptr callback) override; + /** + * @tc.name: DeviceManagerImpl::RegisterDevStatusCallback + * @tc.desc: Register device development status callback + * @tc.type: FUNC + */ + virtual int32_t RegisterDevStatusCallback(const std::string &pkgName, const std::string &extra, + std::shared_ptr callback) override; /** - * @tc.name: DeviceManagerImpl::UnRegisterDevStateCallback - * @tc.desc: UnRegister device development status callback - * @tc.type: FUNC - */ + * @tc.name: DeviceManagerImpl::UnRegisterDevStateCallback + * @tc.desc: UnRegister device development status callback + * @tc.type: FUNC + */ virtual int32_t UnRegisterDevStateCallback(const std::string &pkgName) override; /** - * @tc.name: DeviceManagerImpl::StartDeviceDiscovery - * @tc.desc: Initiate device discovery - * @tc.type: FUNC - */ + * @tc.name: DeviceManagerImpl::UnRegisterDevStatusCallback + * @tc.desc: UnRegister device development status callback + * @tc.type: FUNC + */ + virtual int32_t UnRegisterDevStatusCallback(const std::string &pkgName) override; + /** + * @tc.name: DeviceManagerImpl::StartDeviceDiscovery + * @tc.desc: Initiate device discovery + * @tc.type: FUNC + */ virtual int32_t StartDeviceDiscovery(const std::string &pkgName, const DmSubscribeInfo &subscribeInfo, - const std::string &extra, - std::shared_ptr callback) override; + const std::string &extra, std::shared_ptr callback) override; + /** + * @tc.name: DeviceManagerImpl::StartDeviceDiscovery + * @tc.desc: Initiate device discovery + * @tc.type: FUNC + */ + virtual int32_t StartDeviceDiscovery(const std::string &pkgName, uint64_t tokenId, + const std::string &filterOptions, std::shared_ptr callback) override; /** - * @tc.name: DeviceManagerImpl::StopDeviceDiscovery - * @tc.desc: Stop device discovery - * @tc.type: FUNC - */ + * @tc.name: DeviceManagerImpl::StopDeviceDiscovery + * @tc.desc: Stop device discovery + * @tc.type: FUNC + */ virtual int32_t StopDeviceDiscovery(const std::string &pkgName, uint16_t subscribeId) override; /** - * @tc.name: DeviceManagerImpl::PublishDeviceDiscovery - * @tc.desc: Publish device discovery - * @tc.type: FUNC - */ + * @brief Stop device discovery. + * @param pkgName package name. + * @param tokenId app flag to discovery device. + * @return Returns 0 if success. + */ + virtual int32_t StopDeviceDiscovery(uint64_t tokenId, const std::string &pkgName) override; + /** + * @tc.name: DeviceManagerImpl::PublishDeviceDiscovery + * @tc.desc: Publish device discovery + * @tc.type: FUNC + */ virtual int32_t PublishDeviceDiscovery(const std::string &pkgName, const DmPublishInfo &publishInfo, std::shared_ptr callback) override; /** - * @tc.name: DeviceManagerImpl::UnPublishDeviceDiscovery - * @tc.desc: UnPublish device discovery - * @tc.type: FUNC - */ + * @tc.name: DeviceManagerImpl::UnPublishDeviceDiscovery + * @tc.desc: UnPublish device discovery + * @tc.type: FUNC + */ virtual int32_t UnPublishDeviceDiscovery(const std::string &pkgName, int32_t publishId) override; /** - * @tc.name: DeviceManagerImpl::AuthenticateDevice - * @tc.desc: Complete verifying the device - * @tc.type: FUNC - */ + * @tc.name: DeviceManagerImpl::AuthenticateDevice + * @tc.desc: Complete verifying the device + * @tc.type: FUNC + */ virtual int32_t AuthenticateDevice(const std::string &pkgName, int32_t authType, const DmDeviceInfo &deviceInfo, - const std::string &extra, - std::shared_ptr callback) override; + const std::string &extra, std::shared_ptr callback) override; /** - * @tc.name: DeviceManagerImpl::UnAuthenticateDevice - * @tc.desc: Cancel complete verification of device - * @tc.type: FUNC - */ + * @tc.name: DeviceManagerImpl::UnAuthenticateDevice + * @tc.desc: Cancel complete verification of device + * @tc.type: FUNC + */ virtual int32_t UnAuthenticateDevice(const std::string &pkgName, const DmDeviceInfo &deviceInfo) override; /** - * @tc.name: DeviceManagerImpl::VerifyAuthentication - * @tc.desc: Verify device authentication - * @tc.type: FUNC - */ + * @tc.name: DeviceManagerImpl::VerifyAuthentication + * @tc.desc: Verify device authentication + * @tc.type: FUNC + */ virtual int32_t VerifyAuthentication(const std::string &pkgName, const std::string &authPara, - std::shared_ptr callback) override; + std::shared_ptr callback) override; /** - * @tc.name: DeviceManagerImpl::GetFaParam - * @tc.desc: Get Fa Param - * @tc.type: FUNC - */ - virtual int32_t GetFaParam(const std::string &pkgName, DmAuthParam &faParam) override; - + * @tc.name: DeviceManagerImpl::RegisterDeviceManagerFaCallback + * @tc.desc: Register Fa callback for device manager + * @tc.type: FUNC + */ + virtual int32_t RegisterDeviceManagerFaCallback(const std::string &pkgName, + std::shared_ptr callback) override; + /** + * @tc.name: DeviceManagerImpl::UnRegisterDeviceManagerFaCallback + * @tc.desc: Unregister Fa callback for device manager + * @tc.type: FUNC + */ + virtual int32_t UnRegisterDeviceManagerFaCallback(const std::string &pkgName) override; /** - * @tc.name: DeviceManagerImpl::GetUdidByNetworkId - * @tc.desc: Get Udid by NetworkId - * @tc.type: FUNC - */ + * @tc.name: DeviceManagerImpl::GetFaParam + * @tc.desc: Get Fa Param + * @tc.type: FUNC + */ + virtual int32_t GetFaParam(const std::string &pkgName, DmAuthParam &dmFaParam) override; + /** + * @tc.name: DeviceManagerImpl::SetUserOperation + * @tc.desc: Set User Actions + * @tc.type: FUNC + */ + virtual int32_t SetUserOperation(const std::string &pkgName, int32_t action, const std::string ¶ms) override; + /** + * @tc.name: DeviceManagerImpl::GetUdidByNetworkId + * @tc.desc: Get Udid by NetworkId + * @tc.type: FUNC + */ virtual int32_t GetUdidByNetworkId(const std::string &pkgName, const std::string &netWorkId, - std::string &udid) override; + std::string &udid) override; /** - * @tc.name: DeviceManagerImpl::GetUuidByNetworkId - * @tc.desc: Get Uuid by NetworkId - * @tc.type: FUNC - */ + * @tc.name: DeviceManagerImpl::GetUuidByNetworkId + * @tc.desc: Get Uuid by NetworkId + * @tc.type: FUNC + */ virtual int32_t GetUuidByNetworkId(const std::string &pkgName, const std::string &netWorkId, - std::string &uuid) override; + std::string &uuid) override; /** - * @tc.name: DeviceManagerImpl::RegisterDevStateCallback - * @tc.desc: Register development status callback - * @tc.type: FUNC - */ + * @tc.name: DeviceManagerImpl::RegisterDevStateCallback + * @tc.desc: Register development status callback + * @tc.type: FUNC + */ virtual int32_t RegisterDevStateCallback(const std::string &pkgName, const std::string &extra) override; /** - * @tc.name: DeviceManagerImpl::UnRegisterDevStateCallback - * @tc.desc: Unregister development status callback - * @tc.type: FUNC - */ + * @tc.name: DeviceManagerImpl::UnRegisterDevStateCallback + * @tc.desc: Unregister development status callback + * @tc.type: FUNC + */ virtual int32_t UnRegisterDevStateCallback(const std::string &pkgName, const std::string &extra) override; /** - * @tc.name: DeviceManagerImpl::RequestCredential - * @tc.desc: RequestCredential - * @tc.type: FUNC - */ + * @tc.name: DeviceManagerImpl::RequestCredential + * @tc.desc: RequestCredential + * @tc.type: FUNC + */ virtual int32_t RequestCredential(const std::string &pkgName, const std::string &reqJsonStr, std::string &returnJsonStr) override; /** - * @tc.name: DeviceManagerImpl::ImportCredential - * @tc.desc: ImportCredential - * @tc.type: FUNC - */ + * @tc.name: DeviceManagerImpl::ImportCredential + * @tc.desc: ImportCredential + * @tc.type: FUNC + */ virtual int32_t ImportCredential(const std::string &pkgName, const std::string &credentialInfo) override; /** - * @tc.name: DeviceManagerImpl::DeleteCredential - * @tc.desc: DeleteCredential - * @tc.type: FUNC - */ + * @tc.name: DeviceManagerImpl::RegisterPinHolderCallback + * @tc.desc: RegisterPinHolderCallback + * @tc.type: FUNC + */ + virtual int32_t RegisterPinHolderCallback(const std::string &pkgName, + std::shared_ptr callback) override; + /** + * @tc.name: DeviceManagerImpl::CreatePinHolder + * @tc.desc: CreatePinHolder + * @tc.type: FUNC + */ + virtual int32_t CreatePinHolder(const std::string &pkgName, const PeerTargetId &targetId, DmPinType pinType, + const std::string &payload) override; + /** + * @tc.name: DeviceManagerImpl::DestroyPinHolder + * @tc.desc: DestroyPinHolder + * @tc.type: FUNC + */ + virtual int32_t DestroyPinHolder(const std::string &pkgName, const PeerTargetId &targetId, DmPinType pinType, + const std::string &payload) override; + /** + * @tc.name: DeviceManagerImpl::DeleteCredential + * @tc.desc: DeleteCredential + * @tc.type: FUNC + */ virtual int32_t DeleteCredential(const std::string &pkgName, const std::string &deleteInfo) override; /** - * @tc.name: DeviceManagerImpl::RegisterCredentialCallback - * @tc.desc: RegisterCredentialCallback - * @tc.type: FUNC - */ + * @tc.name: DeviceManagerImpl::RegisterCredentialCallback + * @tc.desc: RegisterCredentialCallback + * @tc.type: FUNC + */ virtual int32_t RegisterCredentialCallback(const std::string &pkgName, std::shared_ptr callback) override; /** - * @tc.name: DeviceManagerImpl::UnRegisterCredentialCallback - * @tc.desc: UnRegisterCredentialCallback - * @tc.type: FUNC - */ + * @tc.name: DeviceManagerImpl::UnRegisterCredentialCallback + * @tc.desc: UnRegisterCredentialCallback + * @tc.type: FUNC + */ virtual int32_t UnRegisterCredentialCallback(const std::string &pkgName) override; /** - * @tc.name: DeviceManagerImpl::NotifyEvent - * @tc.desc: NotifyEvent - * @tc.type: FUNC - */ + * @tc.name: DeviceManagerImpl::NotifyEvent + * @tc.desc: NotifyEvent + * @tc.type: FUNC + */ virtual int32_t NotifyEvent(const std::string &pkgName, const int32_t eventId, const std::string &event) override; + /** + * @tc.name: DeviceManagerImpl::RequestCredential + * @tc.desc: RequestCredential + * @tc.type: FUNC + */ + virtual int32_t RequestCredential(const std::string &pkgName, std::string &returnJsonStr) override; + /** + * @tc.name: DeviceManagerImpl::CheckCredential + * @tc.desc: CheckCredential + * @tc.type: FUNC + */ + virtual int32_t CheckCredential(const std::string &pkgName, const std::string &reqJsonStr, + std::string &returnJsonStr) override; + /** + * @tc.name: DeviceManagerImpl::ImportCredential + * @tc.desc: ImportCredential + * @tc.type: FUNC + */ + virtual int32_t ImportCredential(const std::string &pkgName, const std::string &reqJsonStr, + std::string &returnJsonStr) override; + /** + * @tc.name: DeviceManagerImpl::DeleteCredential + * @tc.desc: DeleteCredential + * @tc.type: FUNC + */ + virtual int32_t DeleteCredential(const std::string &pkgName, const std::string &reqJsonStr, + std::string &returnJsonStr) override; virtual int32_t GetEncryptedUuidByNetworkId(const std::string &pkgName, const std::string &networkId, std::string &uuid) override; virtual int32_t GenerateEncryptedUuid(const std::string &pkgName, const std::string &uuid, const std::string &appId, std::string &encryptedUuid) override; - bool IsSameAccount(const std::string &netWorkId) override; - int32_t GetDeviceInfo(const std::string &pkgName, const std::string networkId, DmDeviceInfo &deviceInfo) override; - int32_t SetUserOperation(const std::string &pkgName, int32_t action, const std::string ¶ms) override; + + /** + * @tc.name: DeviceManagerImpl::CheckAPIAccessPermission + * @tc.desc: check permission for device manager API + * @tc.type: FUNC + */ + virtual int32_t CheckAPIAccessPermission() override; + virtual int32_t CheckNewAPIAccessPermission() override; + + int32_t OnDmServiceDied(); + int32_t RegisterUiStateCallback(const std::string &pkgName); + int32_t UnRegisterUiStateCallback(const std::string &pkgName); + + virtual int32_t GetLocalDeviceNetWorkId(const std::string &pkgName, std::string &networkId) override; + virtual int32_t GetLocalDeviceId(const std::string &pkgName, std::string &networkId) override; + virtual int32_t GetLocalDeviceType(const std::string &pkgName, int32_t &deviceType) override; + virtual int32_t GetLocalDeviceName(const std::string &pkgName, std::string &deviceName) override; + virtual int32_t GetDeviceName(const std::string &pkgName, const std::string &networkId, + std::string &deviceName) override; + virtual int32_t GetDeviceType(const std::string &pkgName, const std::string &networkId, + int32_t &deviceType) override; + virtual int32_t BindDevice(const std::string &pkgName, int32_t bindType, const std::string &deviceId, + const std::string &extra, std::shared_ptr callback) override; + virtual int32_t UnBindDevice(const std::string &pkgName, const std::string &deviceId) override; + virtual int32_t GetNetworkTypeByNetworkId(const std::string &pkgName, const std::string &netWorkId, + int32_t &netWorkType) override; + virtual int32_t ImportAuthCode(const std::string &pkgName, const std::string &authCode) override; + virtual int32_t ExportAuthCode(std::string &authCode) override; + + // The following interfaces are provided since OpenHarmony 4.1 Version. + virtual int32_t StartDiscovering(const std::string &pkgName, std::map &discoverParam, + const std::map &filterOptions, std::shared_ptr callback) override; + + virtual int32_t StopDiscovering(const std::string &pkgName, + std::map &discoverParam) override; + + virtual int32_t RegisterDiscoveryCallback(const std::string &pkgName, + std::map &discoverParam, const std::map &filterOptions, + std::shared_ptr callback) override; + + virtual int32_t UnRegisterDiscoveryCallback(const std::string &pkgName) override; + + virtual int32_t StartAdvertising(const std::string &pkgName, std::map &advertiseParam, + std::shared_ptr callback) override; + + virtual int32_t StopAdvertising(const std::string &pkgName, + std::map &advertiseParam) override; + + virtual int32_t BindTarget(const std::string &pkgName, const PeerTargetId &targetId, + std::map &bindParam, std::shared_ptr callback) override; + + virtual int32_t UnbindTarget(const std::string &pkgName, const PeerTargetId &targetId, + std::map &unbindParam, std::shared_ptr callback) override; + + virtual int32_t GetTrustedDeviceList(const std::string &pkgName, + const std::map &filterOptions, bool isRefresh, + std::vector &deviceList) override; + + virtual int32_t RegisterDevStateCallback(const std::string &pkgName, + const std::map &extraParam, std::shared_ptr callback) override; + + virtual int32_t CheckAccessToTarget(uint64_t tokenId, const std::string &targetId) override; + + virtual int32_t DpAclAdd(const int64_t accessControlId, const std::string &udid, const int32_t bindType) override; + + virtual int32_t GetDeviceSecurityLevel(const std::string &pkgName, const std::string &networkId, + int32_t &securityLevel) override; + + virtual bool IsSameAccount(const std::string &netWorkId) override; + virtual bool CheckAccessControl(const DmAccessCaller &caller, const DmAccessCallee &callee) override; + virtual bool CheckIsSameAccount(const DmAccessCaller &caller, const DmAccessCallee &callee) override; + virtual int32_t GetErrCode(int32_t errCode) override; + virtual int32_t ShiftLNNGear(const std::string &pkgName) override; + virtual int32_t RegDevTrustChangeCallback(const std::string &pkgName, + std::shared_ptr callback) override; + + virtual int32_t SetDnPolicy(const std::string &pkgName, std::map &policy) override; + virtual int32_t RegisterDeviceScreenStatusCallback(const std::string &pkgName, + std::shared_ptr callback) override; + virtual int32_t UnRegisterDeviceScreenStatusCallback(const std::string &pkgName) override; + virtual int32_t GetDeviceScreenStatus(const std::string &pkgName, const std::string &networkId, + int32_t &screenStatus) override; + virtual int32_t StopAuthenticateDevice(const std::string &pkgName) override; + virtual int32_t GetNetworkIdByUdid(const std::string &pkgName, const std::string &udid, + std::string &networkId) override; + virtual int32_t RegisterCredentialAuthStatusCallback(const std::string &pkgName, + std::shared_ptr callback) override; + virtual int32_t UnRegisterCredentialAuthStatusCallback(const std::string &pkgName) override; private: DeviceManagerImpl() = default; diff --git a/mock/innerkits/device_manager/devicemanagersdk/include/dm_constants.h b/mock/innerkits/device_manager/devicemanagersdk/include/dm_constants.h new file mode 100644 index 0000000000000000000000000000000000000000..3a933cd29092ec89a08a4bf1f0b93e3ee2966181 --- /dev/null +++ b/mock/innerkits/device_manager/devicemanagersdk/include/dm_constants.h @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2022-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. + */ + +#ifndef OHOS_DM_CONSTANTS_H +#define OHOS_DM_CONSTANTS_H + +#include +#include + +#ifdef __LP64__ +constexpr const char* DM_LIB_LOAD_PATH = "/system/lib64/"; +#else +#if !(defined(__LITEOS_M__) || defined(LITE_DEVICE)) +constexpr const char* DM_LIB_LOAD_PATH = "/system/lib/"; +#else +constexpr const char* DM_LIB_LOAD_PATH = "/usr/lib/"; +#endif +#endif + +namespace OHOS { +namespace DistributedHardware { +enum { + DM_OK = 0, + SOFTBUS_OK = 0, + STOP_BIND = 1, + + /* Transfer to the other end device, not define specification error code */ + ERR_DM_NOT_SYSTEM_APP = 202, + ERR_DM_TIME_OUT = -20001, + ERR_DM_UNSUPPORTED_AUTH_TYPE = -20018, + ERR_DM_AUTH_BUSINESS_BUSY = -20019, + ERR_DM_AUTH_PEER_REJECT = -20021, + ERR_DM_AUTH_REJECT = -20022, + ERR_DM_CREATE_GROUP_FAILED = -20026, + ERR_DM_BIND_USER_CANCEL = -20037, + ERR_DM_BIND_USER_CANCEL_ERROR = -20042, + ERR_DM_AUTH_CODE_INCORRECT = -20053, + ERR_DM_BIND_USER_CANCEL_PIN_CODE_DISPLAY = -20056, + ERR_DM_SYNC_DELETE_DEVICE_REPEATED = -20058, + ERR_DM_VERSION_INCOMPATIBLE = -20059, + + ERR_DM_FAILED = 96929744, + ERR_DM_NOT_INIT = 96929746, + ERR_DM_INIT_FAILED = 96929747, + ERR_DM_POINT_NULL = 96929748, + ERR_DM_INPUT_PARA_INVALID = 96929749, + ERR_DM_NO_PERMISSION = 96929750, + ERR_DM_MALLOC_FAILED = 96929751, + ERR_DM_DISCOVERY_FAILED = 96929752, + ERR_DM_MAP_KEY_ALREADY_EXISTS = 96929753, + ERR_DM_IPC_WRITE_FAILED = 96929754, + ERR_DM_IPC_COPY_FAILED = 96929755, + ERR_DM_IPC_SEND_REQUEST_FAILED = 96929756, + ERR_DM_UNSUPPORTED_IPC_COMMAND = 96929757, + ERR_DM_IPC_RESPOND_FAILED = 96929758, + ERR_DM_DISCOVERY_REPEATED = 96929759, + ERR_DM_AUTH_OPEN_SESSION_FAILED = 96929762, + ERR_DM_AUTH_FAILED = 96929765, + ERR_DM_AUTH_NOT_START = 96929766, + ERR_DM_AUTH_MESSAGE_INCOMPLETE = 96929767, + ERR_DM_IPC_READ_FAILED = 96929769, + ERR_DM_ENCRYPT_FAILED = 96929770, + ERR_DM_PUBLISH_FAILED = 96929771, + ERR_DM_PUBLISH_REPEATED = 96929772, + ERR_DM_STOP_DISCOVERY = 96929773, + ERR_DM_ADD_GROUP_FAILED = 96929774, + + // The following error codes are provided since OpenHarmony 4.1 Version. + ERR_DM_ADAPTER_NOT_INIT = 96929775, + ERR_DM_UNSUPPORTED_METHOD = 96929776, + ERR_DM_BIND_COMMON_FAILED = 96929777, + ERR_DM_BIND_INPUT_PARA_INVALID = 96929778, + ERR_DM_BIND_PIN_CODE_ERROR = 96929779, + ERR_DM_BIND_TIMEOUT_FAILED = 96929781, + ERR_DM_BIND_DP_ERROR = 96929782, + ERR_DM_BIND_HICHAIN_ERROR = 96929783, + ERR_DM_BIND_SOFTBUS_ERROR = 96929784, + ERR_DM_STOP_PUBLISH_LNN_FAILED = 96929786, + ERR_DM_REFRESH_LNN_FAILED = 96929787, + ERR_DM_STOP_REFRESH_LNN_FAILED = 96929788, + ERR_DM_START_ADVERTISING_FAILED = 96929789, + ERR_DM_STOP_ADVERTISING_FAILED = 96929790, + ERR_DM_ENABLE_DISCOVERY_LISTENER_FAILED = 96929791, + ERR_DM_DISABLE_DISCOVERY_LISTENER_FAILED = 96929792, + ERR_DM_START_DISCOVERING_FAILED = 96929793, + ERR_DM_STOP_DISCOVERING_FAILED = 96929794, + ERR_DM_SOFTBUS_SERVICE_NOT_INIT = 96929795, + ERR_DM_META_TYPE_INVALID = 96929797, + ERR_DM_LOAD_CUSTOM_META_NODE = 96929798, + ERR_DM_SOFTBUS_PUBLISH_SERVICE = 96929800, + ERR_DM_BIND_PEER_UNSUPPORTED = 96929802, + ERR_DM_HICHAIN_CREDENTIAL_REQUEST_FAILED = 96929803, + ERR_DM_HICHAIN_CREDENTIAL_CHECK_FAILED = 96929804, + ERR_DM_HICHAIN_CREDENTIAL_IMPORT_FAILED = 96929805, + ERR_DM_HICHAIN_CREDENTIAL_DELETE_FAILED = 96929806, + ERR_DM_HICHAIN_UNREGISTER_CALLBACK = 96929807, + ERR_DM_HICHAIN_GET_REGISTER_INFO = 96929808, + ERR_DM_HICHAIN_CREDENTIAL_EXISTS = 96929809, + ERR_DM_HICHAIN_REGISTER_CALLBACK = 96929810, + ERR_DM_HICHAIN_GROUP_CREATE_FAILED = 96929811, + ERR_DM_JSON_PARSE_STRING = 96929812, + ERR_DM_SOFTBUS_SEND_BROADCAST = 96929813, + ERR_DM_SOFTBUS_DISCOVERY_DEVICE = 96929814, + ERR_DM_SOFTBUS_STOP_DISCOVERY_DEVICE = 96929815, + ERR_DM_INVALID_JSON_STRING = 96929816, + ERR_DM_GET_DATA_SHA256_HASH = 96929817, +}; + +constexpr const char* TAG_GROUP_ID = "groupId"; +constexpr const char* TAG_GROUP_NAME = "GROUPNAME"; +constexpr const char* TAG_REQUEST_ID = "REQUESTID"; +constexpr const char* TAG_DEVICE_ID = "DEVICEID"; +constexpr const char* TAG_AUTH_TYPE = "AUTHTYPE"; +constexpr const char* TAG_CRYPTO_SUPPORT = "CRYPTOSUPPORT"; +constexpr const char* TAG_VER = "ITF_VER"; +constexpr const char* TAG_MSG_TYPE = "MSG_TYPE"; +constexpr const char* DM_ITF_VER = "1.1"; +constexpr const char* DM_PKG_NAME = "ohos.distributedhardware.devicemanager"; +constexpr const char* DM_SESSION_NAME = "ohos.distributedhardware.devicemanager.resident"; +constexpr const char* DM_PIN_HOLDER_SESSION_NAME = "ohos.distributedhardware.devicemanager.pinholder"; +constexpr const char* DM_CAPABILITY_OSD = "osdCapability"; +constexpr const char* DM_CAPABILITY_APPROACH = "approach"; +constexpr const char* DM_CAPABILITY_TOUCH = "touch"; +constexpr const char* DM_CAPABILITY_CASTPLUS = "castPlus"; +constexpr const char* DM_CAPABILITY_VIRTUAL_LINK = "virtualLink"; +constexpr const char* DM_CAPABILITY_SHARE = "share"; +constexpr const char* DM_CAPABILITY_WEAR = "wear"; +constexpr const char* DM_CREDENTIAL_TYPE = "CREDENTIAL_TYPE"; +constexpr const char* DM_CREDENTIAL_REQJSONSTR = "CREDENTIAL_REQJSONSTR"; +constexpr const char* DM_CREDENTIAL_RETURNJSONSTR = "CREDENTIAL_RETURNJSONSTR"; +constexpr const char* DEVICE_MANAGER_GROUPNAME = "DMSameAccountGroup"; +constexpr const char* FIELD_CREDENTIAL_EXISTS = "isCredentialExists"; +constexpr int32_t DM_STRING_LENGTH_MAX = 1024; +constexpr int32_t PKG_NAME_SIZE_MAX = 256; +constexpr const char* DM_TYPE_MINE = "MINE"; +constexpr const char* DM_TYPE_OH = "OH"; +constexpr const char* TAG_SESSION_HEARTBEAT = "session_heartbeat"; + +//The following constant are provided only for HiLink. +const static char *EXT_PART = "ext_part"; + +// Auth +constexpr const char* AUTH_TYPE = "authType"; +constexpr const char* APP_OPERATION = "appOperation"; +constexpr const char* CUSTOM_DESCRIPTION = "customDescription"; +constexpr const char* TOKEN = "token"; +constexpr const char* PIN_TOKEN = "pinToken"; +constexpr const char* PIN_CODE_KEY = "pinCode"; +constexpr int32_t CHECK_AUTH_ALWAYS_POS = 0; +constexpr const char AUTH_ALWAYS = '1'; +constexpr const char AUTH_ONCE = '0'; +constexpr const char* TAG_TARGET_DEVICE_NAME = "targetDeviceName"; + +// HiChain +constexpr int32_t SERVICE_INIT_TRY_MAX_NUM = 200; +constexpr int32_t DEVICE_UUID_LENGTH = 65; +constexpr int32_t DEVICE_NETWORKID_LENGTH = 100; +constexpr int32_t GROUP_TYPE_INVALID_GROUP = -1; +constexpr int32_t GROUP_TYPE_IDENTICAL_ACCOUNT_GROUP = 1; +constexpr int32_t GROUP_TYPE_PEER_TO_PEER_GROUP = 256; +constexpr int32_t GROUP_TYPE_ACROSS_ACCOUNT_GROUP = 1282; +constexpr int32_t GROUP_VISIBILITY_PUBLIC = -1; +constexpr int64_t MIN_REQUEST_ID = 1000000000; +constexpr int64_t MAX_REQUEST_ID = 9999999999; +constexpr int32_t AUTH_DEVICE_REQ_NEGOTIATE = 600; +constexpr int32_t AUTH_DEVICE_RESP_NEGOTIATE = 700; +constexpr int32_t DEVICEID_LEN = 8; + +// ACE +constexpr const char* EVENT_CONFIRM = "EVENT_CONFIRM"; +constexpr const char* EVENT_CANCEL = "EVENT_CANCEL"; +constexpr const char* EVENT_INIT = "EVENT_INIT"; +constexpr const char* EVENT_CONFIRM_CODE = "0"; +constexpr const char* EVENT_CANCEL_CODE = "1"; +constexpr const char* EVENT_INIT_CODE = "2"; + +// Key of filter parameter +constexpr const char* FILTER_PARA_RANGE = "FILTER_RANGE"; +constexpr const char* FILTER_PARA_DEVICE_TYPE = "FILTER_DEVICE_TYPE"; +constexpr const char* FILTER_PARA_INCLUDE_TRUST = "FILTER_INCLUDE_TRUST"; + +// Connection address type +constexpr const char* CONN_ADDR_TYPE_ID = "ID_TYPE"; +constexpr const char* CONN_ADDR_TYPE_BR = "BR_TYPE"; +constexpr const char* CONN_ADDR_TYPE_BLE = "BLE_TYPE"; +constexpr const char* CONN_ADDR_TYPE_WLAN_IP = "WLAN_IP_TYPE"; +constexpr const char* CONN_ADDR_TYPE_ETH_IP = "ETH_IP_TYPE"; + +// Parameter Key +constexpr const char* PARAM_KEY_META_TYPE = "META_TYPE"; +constexpr const char* PARAM_KEY_TARGET_ID = "TARGET_ID"; +constexpr const char* PARAM_KEY_BR_MAC = "BR_MAC"; +constexpr const char* PARAM_KEY_BLE_MAC = "BLE_MAC"; +constexpr const char* PARAM_KEY_WIFI_IP = "WIFI_IP"; +constexpr const char* PARAM_KEY_WIFI_PORT = "WIFI_PORT"; +constexpr const char* PARAM_KEY_AUTH_TOKEN = "AUTH_TOKEN"; +constexpr const char* PARAM_KEY_AUTH_TYPE = "AUTH_TYPE"; +constexpr const char* PARAM_KEY_PIN_CODE = "PIN_CODE"; +constexpr const char* PARAM_KEY_APP_OPER = "APP_OPER"; +constexpr const char* PARAM_KEY_APP_DESC = "APP_DESC"; +constexpr const char* PARAM_KEY_BLE_UDID_HASH = "BLE_UDID_HASH"; +constexpr const char* PARAM_KEY_CUSTOM_DATA = "CUSTOM_DATA"; +constexpr const char* PARAM_KEY_CONN_ADDR_TYPE = "CONN_ADDR_TYPE"; +constexpr const char* PARAM_KEY_PUBLISH_ID = "PUBLISH_ID"; +constexpr const char* PARAM_KEY_SUBSCRIBE_ID = "SUBSCRIBE_ID"; +constexpr const char* PARAM_KEY_TARGET_PKG_NAME = "TARGET_PKG_NAME"; +constexpr const char* PARAM_KEY_DISC_FREQ = "DISC_FREQ"; +constexpr const char* PARAM_KEY_DISC_MEDIUM = "DISC_MEDIUM"; +constexpr const char* PARAM_KEY_DISC_CAPABILITY = "DISC_CAPABILITY"; +constexpr const char* PARAM_KEY_DISC_MODE = "DISC_MODE"; +constexpr const char* PARAM_KEY_AUTO_STOP_ADVERTISE = "AUTO_STOP_ADVERTISE"; +constexpr const char* PARAM_KEY_FILTER_OPTIONS = "FILTER_OPTIONS"; +constexpr const char* PARAM_KEY_BIND_EXTRA_DATA = "BIND_EXTRA_DATA"; +constexpr const char* PARAM_KEY_OS_TYPE = "OS_TYPE"; +constexpr const char* PARAM_KEY_OS_VERSION = "OS_VERSION"; +constexpr const char* DM_CONNECTION_DISCONNECTED = "DM_CONNECTION_DISCONNECTED"; +constexpr const char* BIND_LEVEL = "bindLevel"; +constexpr const char* TOKENID = "tokenId"; +constexpr const char* DM_BIND_RESULT_NETWORK_ID = "DM_BIND_RESULT_NETWORK_ID"; +constexpr const char* PARAM_KEY_POLICY_STRATEGY_FOR_BLE = "DM_POLICY_STRATEGY_FOR_BLE"; +constexpr const char* PARAM_KEY_POLICY_TIME_OUT = "DM_POLICY_TIMEOUT"; +constexpr const char* DEVICE_SCREEN_STATUS = "DEVICE_SCREEN_STATUS"; + +// screen state +constexpr int32_t DM_SCREEN_UNKNOWN = -1; +constexpr int32_t DM_SCREEN_ON = 0; +constexpr int32_t DM_SCREEN_OFF = 1; + +// errCode map +const std::map MAP_ERROR_CODE = { + { ERR_DM_TIME_OUT, 96929745 }, { ERR_DM_UNSUPPORTED_AUTH_TYPE, 96929760 }, { ERR_DM_AUTH_BUSINESS_BUSY, 96929761 }, + { ERR_DM_AUTH_PEER_REJECT, 96929763 }, { ERR_DM_AUTH_REJECT, 96929764 }, { ERR_DM_CREATE_GROUP_FAILED, 96929768 }, + { ERR_DM_BIND_USER_CANCEL, 96929780 }, { ERR_DM_BIND_USER_CANCEL_ERROR, 96929785 }, + { ERR_DM_AUTH_CODE_INCORRECT, 96929796 }, { ERR_DM_BIND_USER_CANCEL_PIN_CODE_DISPLAY, 96929799 }, + { ERR_DM_SYNC_DELETE_DEVICE_REPEATED, 96929801 } +}; +} // namespace DistributedHardware +} // namespace OHOS +#endif // OHOS_DM_CONSTANTS_H \ No newline at end of file diff --git a/mock/innerkits/device_manager/devicemanagersdk/include/dm_device_info.h b/mock/innerkits/device_manager/devicemanagersdk/include/dm_device_info.h index f79afd34fc879f63e7ce50fdaf26efd516b33175..533404d41c782293c009f15f40417d83fb49b1c1 100644 --- a/mock/innerkits/device_manager/devicemanagersdk/include/dm_device_info.h +++ b/mock/innerkits/device_manager/devicemanagersdk/include/dm_device_info.h @@ -1,5 +1,5 @@ /* -* Copyright (c) 2022-2023 Huawei Device Co., Ltd. +* Copyright (c) 2022-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 @@ -22,8 +22,8 @@ #include "dm_app_image_info.h" -#define DM_MAX_DEVICE_ID_LEN (96) -#define DM_MAX_DEVICE_NAME_LEN (128) +#define DM_MAX_DEVICE_ID_LEN (97) +#define DM_MAX_DEVICE_NAME_LEN (129) namespace OHOS { namespace DistributedHardware { @@ -39,6 +39,10 @@ typedef enum DmNotifyEvent { * Device manager on ready event. */ DM_NOTIFY_EVENT_ONDEVICEREADY, + /** + * Device manager on pin holder event. + */ + DM_NOTIFY_EVENT_ON_PINHOLDER_EVENT, // Add event here DM_NOTIFY_EVENT_BUTT, } DmNotifyEvent; @@ -91,6 +95,7 @@ typedef enum DmDeviceType { * Indicates 2in1 */ DEVICE_TYPE_2IN1 = 0xA2F, + THIRD_TV = 0x2E, } DmDeviceType; /** @@ -150,11 +155,11 @@ typedef struct DmDeviceInfo { /** * Device Id of the device. */ - char deviceId[DM_MAX_DEVICE_ID_LEN]; + char deviceId[DM_MAX_DEVICE_ID_LEN] = { 0 }; /** * Device name of the device. */ - char deviceName[DM_MAX_DEVICE_NAME_LEN]; + char deviceName[DM_MAX_DEVICE_NAME_LEN] = { 0 }; /** * Device type of the device. */ @@ -162,7 +167,7 @@ typedef struct DmDeviceInfo { /** * NetworkId of the device. */ - char networkId[DM_MAX_DEVICE_ID_LEN]; + char networkId[DM_MAX_DEVICE_ID_LEN] = { 0 }; /** * The distance of discovered device, in centimeter(cm). */ @@ -189,11 +194,11 @@ typedef struct DmDeviceBasicInfo { /** * Device Id of the device. */ - char deviceId[DM_MAX_DEVICE_ID_LEN]; + char deviceId[DM_MAX_DEVICE_ID_LEN] = { 0 }; /** * Device name of the device. */ - char deviceName[DM_MAX_DEVICE_NAME_LEN]; + char deviceName[DM_MAX_DEVICE_NAME_LEN] = { 0 }; /** * Device type of the device. */ @@ -201,7 +206,7 @@ typedef struct DmDeviceBasicInfo { /** * NetworkId of the device. */ - char networkId[DM_MAX_DEVICE_ID_LEN]; + char networkId[DM_MAX_DEVICE_ID_LEN] = { 0 }; } DmDeviceBasicInfo; /** @@ -273,18 +278,21 @@ typedef struct PeerTargetId { /** * wlan ip port. */ - uint16_t wifiPort; + uint16_t wifiPort = 0; - bool operator==(const PeerTargetId& other) const + bool operator==(const PeerTargetId &other) const { return (deviceId == other.deviceId) && (brMac == other.brMac) && (bleMac == other.bleMac) && (wifiIp == other.wifiIp) && (wifiPort == other.wifiPort); } - bool operator<(const PeerTargetId& other) const + bool operator<(const PeerTargetId &other) const { - return (deviceId < other.deviceId) && (brMac < other.brMac) && (bleMac < other.bleMac) && - (wifiIp < other.wifiIp) && (wifiPort < other.wifiPort); + return (deviceId < other.deviceId) || (deviceId == other.deviceId && brMac < other.brMac) || + (deviceId == other.deviceId && brMac == other.brMac && bleMac < other.bleMac) || + (deviceId == other.deviceId && brMac == other.brMac && bleMac == other.bleMac && wifiIp < other.wifiIp) || + (deviceId == other.deviceId && brMac == other.brMac && bleMac == other.bleMac && + wifiIp == other.wifiIp && wifiPort < other.wifiPort); } } PeerTargetId; @@ -304,6 +312,15 @@ typedef enum { SUPER_SONIC, } DmPinType; +typedef enum { + CREATE = 0, + CREATE_RESULT, + DESTROY, + DESTROY_RESULT, + PIN_TYPE_CHANGE, + PIN_TYPE_CHANGE_RESULT, +} DmPinHolderEvent; + typedef enum { STATUS_DM_AUTH_DEFAULT = 0, STATUS_DM_AUTH_FINISH = 7, @@ -325,6 +342,23 @@ const std::string DEVICE_TYPE_WIFICAMERA_STRING = "WiFiCamera"; const std::string DEVICE_TYPE_PC_STRING = "PC"; const std::string DEVICE_TYPE_SMART_DISPLAY_STRING = "SMART_DISPLAY"; const std::string DEVICE_TYPE_2IN1_STRING = "2IN1"; + +typedef struct DmAccessCaller { + std::string accountId; + std::string pkgName; + std::string networkId; + int32_t userId; + uint64_t tokenId; + std::string extra; +} DmAccessCaller; + +typedef struct DmAccessCallee { + std::string accountId; + std::string networkId; + std::string peerId; + int32_t userId; + std::string extra; +} DmAccessCallee; } // namespace DistributedHardware } // namespace OHOS -#endif // OHOS_DM_DEVICE_INFO_H +#endif // OHOS_DM_DEVICE_INFO_H \ No newline at end of file diff --git a/mock/innerkits/device_manager/devicemanagersdk/include/dm_publish_info.h b/mock/innerkits/device_manager/devicemanagersdk/include/dm_publish_info.h index ed35273704d76736acdf7143cc1652f2b6081dc1..de552b7e6dd2893046405bfe3b6e4982812abc0e 100644 --- a/mock/innerkits/device_manager/devicemanagersdk/include/dm_publish_info.h +++ b/mock/innerkits/device_manager/devicemanagersdk/include/dm_publish_info.h @@ -1,35 +1,46 @@ /* - * Copyright (c) 2022 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. - */ +* Copyright (c) 2022-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_DM_PUBLISH_INFO_H #define OHOS_DM_PUBLISH_INFO_H -#include +#include #include "dm_subscribe_info.h" namespace OHOS { namespace DistributedHardware { +/** +* @brief Device Publish Info. +*/ typedef struct { - /** Service ID */ + /** + * Service ID. + */ int32_t publishId; - /** Discovery mode for service publishing. For details, see {@link Discovermode}. */ + /** + * Discovery mode for service publishing. For details, see {@link Discovermode}. + */ DmDiscoverMode mode; - /** Service publishing frequency. For details, see {@link ExchangeFreq}. */ + /** + * Service publishing frequency. For details, see {@link ExchangeFreq}. + */ DmExchangeFreq freq; - /** Discovery ranging. For details, see {@link PublishInfo}. */ + /** + * Discovery ranging. For details, see {@link PublishInfo}. + */ bool ranging; } DmPublishInfo; } // namespace DistributedHardware diff --git a/mock/innerkits/device_manager/devicemanagersdk/include/dm_subscribe_info.h b/mock/innerkits/device_manager/devicemanagersdk/include/dm_subscribe_info.h index 590f228097d9e09a32e000485a798b78b2046f9d..ad2459ae084ed14afc43be0c1f3ccf7faf86768b 100644 --- a/mock/innerkits/device_manager/devicemanagersdk/include/dm_subscribe_info.h +++ b/mock/innerkits/device_manager/devicemanagersdk/include/dm_subscribe_info.h @@ -1,77 +1,124 @@ /* - * Copyright (c) 2022 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. - */ +* Copyright (c) 2022-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_DM_SUBSCRIBE_INFO_H #define OHOS_DM_SUBSCRIBE_INFO_H -#include +#include #define DM_MAX_DEVICE_CAPABILITY_LEN 65 namespace OHOS { namespace DistributedHardware { +/** +* @brief Device manager discover mode. +*/ typedef enum DmDiscoverMode { - /* Passive */ + /** + * Passive. + */ DM_DISCOVER_MODE_PASSIVE = 0x55, - /* Proactive */ + /** + * Proactive. + */ DM_DISCOVER_MODE_ACTIVE = 0xAA } DmDiscoverMode; +/** +* @brief Service subscription medium. +*/ typedef enum DmExchangeMedium { - /** Automatic medium selection */ + /** + * Automatic medium selection. + */ DM_AUTO = 0, - /** Bluetooth */ + /** + * Bluetooth + */ DM_BLE = 1, - /** Wi-Fi */ + /** + * Wi-Fi + */ DM_COAP = 2, - /** USB */ + /** + * USB + */ DM_USB = 3, DM_MEDIUM_BUTT } DmExchangeMedium; /** - * @brief Enumerates frequencies for publishing services. - * - * This enumeration applies only to Bluetooth and is not supported currently. - */ +* @brief Enumerates frequencies for publishing services. +* +* This enumeration applies only to Bluetooth and is not supported currently. +*/ typedef enum DmExchangeFreq { - /** Low */ + /** + * Low + */ DM_LOW = 0, - /** Medium */ + /** + * Medium + */ DM_MID = 1, - /** High */ + /** + * High + */ DM_HIGH = 2, - /** Super-high */ + /** + * Super-high + */ DM_SUPER_HIGH = 3, + /** + * Extreme-high + */ + DM_EXTREME_HIGH = 4, DM_FREQ_BUTT } DmExchangeFreq; +/** +* @brief Service subscribe info for device discover. +*/ typedef struct DmSubscribeInfo { - /** Service ID */ + /** + * Service ID. + */ uint16_t subscribeId; - /** Discovery mode for service subscription. For details, see {@link DmDiscoverMode}. */ + /** + * Discovery mode for service subscription. For details, see {@link DmDiscoverMode}. + */ DmDiscoverMode mode; - /** Service subscription medium. For details, see {@link DmExchangeMedium}. */ + /** + * Service subscription medium. For details, see {@link DmExchangeMedium}. + */ DmExchangeMedium medium; - /** Service subscription frequency. For details, see {@link DmExchangeFreq}. */ + /** + * Service subscription frequency. For details, see {@link DmExchangeFreq}. + */ DmExchangeFreq freq; - /** only find the device with the same account */ + /** + * only find the device with the same account. + */ bool isSameAccount; - /** find the sleeping devices */ + /** + * find the sleeping devices. + */ bool isWakeRemote; - /** Service subscription capability. */ + /** + * Service subscription capability. + */ char capability[DM_MAX_DEVICE_CAPABILITY_LEN]; } DmSubscribeInfo; } // namespace DistributedHardware diff --git a/mock/src/mock_device_manager.cpp b/mock/src/mock_device_manager.cpp index 3360ef894e8d5004ca45c1354dac9bb13668ad29..98621300cdc46787c6a1d38ff765e611f905bd4d 100644 --- a/mock/src/mock_device_manager.cpp +++ b/mock/src/mock_device_manager.cpp @@ -52,8 +52,10 @@ int32_t DeviceManagerImpl::GetTrustedDeviceList(const std::string &pkgName, cons int32_t DeviceManagerImpl::GetLocalDeviceInfo(const std::string &pkgName, DmDeviceInfo &deviceInfo) { // (void)strcpy_s(info->networkId, NETWORK_ID_BUF_LEN, "1252645812135842132135452A3B4C5D6E7F"); - (void)strcpy_s(deviceInfo.networkId, DM_MAX_DEVICE_ID_LEN, "54a0a92a428005db27c40bad46bf145fede38ec37effe0347cd990fcb031f320"); - (void)strcpy_s(deviceInfo.deviceId, DM_MAX_DEVICE_ID_LEN, "54a0a92a428005db27c40bad46bf145fede38ec37effe0347cd990fcb031f320"); + (void)strcpy_s(deviceInfo.networkId, DM_MAX_DEVICE_ID_LEN, + "54a0a92a428005db27c40bad46bf145fede38ec37effe0347cd990fcb031f320"); + (void)strcpy_s(deviceInfo.deviceId, DM_MAX_DEVICE_ID_LEN, + "54a0a92a428005db27c40bad46bf145fede38ec37effe0347cd990fcb031f320"); (void)strcpy_s(deviceInfo.deviceName, DM_MAX_DEVICE_ID_LEN, "demo phone"); deviceInfo.deviceTypeId = SMART_PHONE; return 0; @@ -168,7 +170,8 @@ int32_t DeviceManagerImpl::SetUserOperation(const std::string &pkgName, int32_t return 0; } -int32_t DeviceManagerImpl::GetEncryptedUuidByNetworkId(const std::string &pkgName, const std::string &networkId, std::string &uuid) +int32_t DeviceManagerImpl::GetEncryptedUuidByNetworkId(const std::string &pkgName, const std::string &networkId, + std::string &uuid) { if (pkgName.empty() || networkId.empty() || networkId == std::string("no_exist_device_id") || networkId.find("invalid_device") != std::string::npos || networkId == std::string("1234567890")) { @@ -178,8 +181,8 @@ int32_t DeviceManagerImpl::GetEncryptedUuidByNetworkId(const std::string &pkgNam return 0; } -int32_t DeviceManagerImpl::GenerateEncryptedUuid(const std::string &pkgName, const std::string &uuid, const std::string &appId, - std::string &encryptedUuid) +int32_t DeviceManagerImpl::GenerateEncryptedUuid(const std::string &pkgName, const std::string &uuid, + const std::string &appId, std::string &encryptedUuid) { if (pkgName.empty() || uuid.empty()) { return -1; @@ -192,4 +195,264 @@ bool DeviceManagerImpl::IsSameAccount(const std::string &netWorkId) { return false; } -} \ No newline at end of file +int32_t DeviceManagerImpl::GetTrustedDeviceList(const std::string &pkgName, const std::string &extra, bool isRefresh, + std::vector &deviceList) +{ + return 0; +} +int32_t DeviceManagerImpl::GetAvailableDeviceList(const std::string &pkgName, + std::vector &deviceList) +{ + return 0; +} +int32_t DeviceManagerImpl::RegisterDevStatusCallback(const std::string &pkgName, const std::string &extra, + std::shared_ptr callback) +{ + return 0; +} +int32_t DeviceManagerImpl::UnRegisterDevStatusCallback(const std::string &pkgName) +{ + return 0; +} +int32_t DeviceManagerImpl::StartDeviceDiscovery(const std::string &pkgName, uint64_t tokenId, + const std::string &filterOptions, std::shared_ptr callback) +{ + return 0; +} +int32_t DeviceManagerImpl::StopDeviceDiscovery(uint64_t tokenId, const std::string &pkgName) +{ + return 0; +} +int32_t DeviceManagerImpl::RegisterDeviceManagerFaCallback(const std::string &pkgName, + std::shared_ptr callback) +{ + return 0; +} +int32_t DeviceManagerImpl::UnRegisterDeviceManagerFaCallback(const std::string &pkgName) +{ + return 0; +} +int32_t DeviceManagerImpl::RegisterPinHolderCallback(const std::string &pkgName, + std::shared_ptr callback) +{ + return 0; +} +int32_t DeviceManagerImpl::CreatePinHolder(const std::string &pkgName, const PeerTargetId &targetId, DmPinType pinType, + const std::string &payload) +{ + return 0; +} +int32_t DeviceManagerImpl::DestroyPinHolder(const std::string &pkgName, const PeerTargetId &targetId, + DmPinType pinType, const std::string &payload) +{ + return 0; +} +int32_t DeviceManagerImpl::RequestCredential(const std::string &pkgName, std::string &returnJsonStr) +{ + return 0; +} +int32_t DeviceManagerImpl::CheckCredential(const std::string &pkgName, const std::string &reqJsonStr, + std::string &returnJsonStr) +{ + return 0; +} +int32_t DeviceManagerImpl::ImportCredential(const std::string &pkgName, const std::string &reqJsonStr, + std::string &returnJsonStr) +{ + return 0; +} +int32_t DeviceManagerImpl::DeleteCredential(const std::string &pkgName, const std::string &reqJsonStr, + std::string &returnJsonStr) +{ + return 0; +} +int32_t DeviceManagerImpl::CheckAPIAccessPermission() +{ + return 0; +} +int32_t DeviceManagerImpl::CheckNewAPIAccessPermission() +{ + return 0; +} +int32_t DeviceManagerImpl::OnDmServiceDied() +{ + return 0; +} +int32_t DeviceManagerImpl::RegisterUiStateCallback(const std::string &pkgName) +{ + return 0; +} +int32_t DeviceManagerImpl::UnRegisterUiStateCallback(const std::string &pkgName) +{ + return 0; +} +int32_t DeviceManagerImpl::GetLocalDeviceNetWorkId(const std::string &pkgName, std::string &networkId) +{ + return 0; +} +int32_t DeviceManagerImpl::GetLocalDeviceId(const std::string &pkgName, std::string &networkId) +{ + return 0; +} +int32_t DeviceManagerImpl::GetLocalDeviceType(const std::string &pkgName, int32_t &deviceType) +{ + return 0; +} +int32_t DeviceManagerImpl::GetLocalDeviceName(const std::string &pkgName, std::string &deviceName) +{ + return 0; +} +int32_t DeviceManagerImpl::GetDeviceName(const std::string &pkgName, const std::string &networkId, + std::string &deviceName) +{ + return 0; +} +int32_t DeviceManagerImpl::GetDeviceType(const std::string &pkgName, const std::string &networkId, int32_t &deviceType) +{ + return 0; +} +int32_t DeviceManagerImpl::BindDevice(const std::string &pkgName, int32_t bindType, const std::string &deviceId, + const std::string &extra, std::shared_ptr callback) +{ + return 0; +} +int32_t DeviceManagerImpl::UnBindDevice(const std::string &pkgName, const std::string &deviceId) +{ + return 0; +} +int32_t DeviceManagerImpl::GetNetworkTypeByNetworkId(const std::string &pkgName, const std::string &netWorkId, + int32_t &netWorkType) +{ + return 0; +} +int32_t DeviceManagerImpl::ImportAuthCode(const std::string &pkgName, const std::string &authCode) +{ + return 0; +} +int32_t DeviceManagerImpl::ExportAuthCode(std::string &authCode) +{ + return 0; +} +int32_t DeviceManagerImpl::StartDiscovering(const std::string &pkgName, + std::map &discoverParam, const std::map &filterOptions, + std::shared_ptr callback) +{ + return 0; +} +int32_t DeviceManagerImpl::StopDiscovering(const std::string &pkgName, + std::map &discoverParam) +{ + return 0; +} +int32_t DeviceManagerImpl::RegisterDiscoveryCallback(const std::string &pkgName, + std::map &discoverParam, const std::map &filterOptions, + std::shared_ptr callback) +{ + return 0; +} +int32_t DeviceManagerImpl::UnRegisterDiscoveryCallback(const std::string &pkgName) +{ + return 0; +} +int32_t DeviceManagerImpl::StartAdvertising(const std::string &pkgName, + std::map &advertiseParam, std::shared_ptr callback) +{ + return 0; +} +int32_t DeviceManagerImpl::StopAdvertising(const std::string &pkgName, + std::map &advertiseParam) +{ + return 0; +} +int32_t DeviceManagerImpl::BindTarget(const std::string &pkgName, const PeerTargetId &targetId, + std::map &bindParam, std::shared_ptr callback) +{ + return 0; +} +int32_t DeviceManagerImpl::UnbindTarget(const std::string &pkgName, const PeerTargetId &targetId, + std::map &unbindParam, std::shared_ptr callback) +{ + return 0; +} +int32_t DeviceManagerImpl::GetTrustedDeviceList(const std::string &pkgName, + const std::map &filterOptions, bool isRefresh, std::vector &deviceList) +{ + return 0; +} +int32_t DeviceManagerImpl::RegisterDevStateCallback(const std::string &pkgName, + const std::map &extraParam, std::shared_ptr callback) +{ + return 0; +} +int32_t DeviceManagerImpl::CheckAccessToTarget(uint64_t tokenId, const std::string &targetId) +{ + return 0; +} +int32_t DeviceManagerImpl::DpAclAdd(const int64_t accessControlId, const std::string &udid, const int32_t bindType) +{ + return 0; +} +int32_t DeviceManagerImpl::GetDeviceSecurityLevel(const std::string &pkgName, const std::string &networkId, + int32_t &securityLevel) +{ + return 0; +} +bool DeviceManagerImpl::CheckAccessControl(const DmAccessCaller &caller, const DmAccessCallee &callee) +{ + return false; +} +bool DeviceManagerImpl::CheckIsSameAccount(const DmAccessCaller &caller, const DmAccessCallee &callee) +{ + return false; +} +int32_t DeviceManagerImpl::GetErrCode(int32_t errCode) +{ + return 0; +} +int32_t DeviceManagerImpl::ShiftLNNGear(const std::string &pkgName) +{ + return 0; +} +int32_t DeviceManagerImpl::RegDevTrustChangeCallback(const std::string &pkgName, + std::shared_ptr callback) +{ + return 0; +} +int32_t DeviceManagerImpl::SetDnPolicy(const std::string &pkgName, std::map &policy) +{ + return 0; +} +int32_t DeviceManagerImpl::RegisterDeviceScreenStatusCallback(const std::string &pkgName, + std::shared_ptr callback) +{ + return 0; +} +int32_t DeviceManagerImpl::UnRegisterDeviceScreenStatusCallback(const std::string &pkgName) +{ + return 0; +} +int32_t DeviceManagerImpl::GetDeviceScreenStatus(const std::string &pkgName, const std::string &networkId, + int32_t &screenStatus) +{ + return 0; +} +int32_t DeviceManagerImpl::StopAuthenticateDevice(const std::string &pkgName) +{ + return 0; +} +int32_t DeviceManagerImpl::GetNetworkIdByUdid(const std::string &pkgName, const std::string &udid, + std::string &networkId) +{ + return 0; +} +int32_t DeviceManagerImpl::RegisterCredentialAuthStatusCallback(const std::string &pkgName, + std::shared_ptr callback) +{ + return 0; +} +int32_t DeviceManagerImpl::UnRegisterCredentialAuthStatusCallback(const std::string &pkgName) +{ + return 0; +} + +} // namespace OHOS::DistributedHardware \ No newline at end of file diff --git a/preferences/bundle.json b/preferences/bundle.json index db254b99c168c2287e163b00a58875a7edfce4d3..17709c44a49d7437191b8cfa6aaa19b2faee8c28 100644 --- a/preferences/bundle.json +++ b/preferences/bundle.json @@ -66,7 +66,7 @@ "build": { "sub_component": [ "//foundation/distributeddatamgr/preferences/interfaces/inner_api:native_preferences", - "//foundation/distributeddatamgr/preferences/interfaces/ndk:ohpreferences", + "//foundation/distributeddatamgr/preferences/interfaces/ndk:libohpreferences", "//foundation/distributeddatamgr/preferences/frameworks/cj:cj_preferences_ffi", "//foundation/distributeddatamgr/preferences/frameworks/js/napi/common:preferences_jscommon", "//foundation/distributeddatamgr/preferences/frameworks/js/napi/preferences:preferences", @@ -89,7 +89,7 @@ } }, { - "name": "//foundation/distributeddatamgr/preferences/interfaces/ndk:ohpreferences", + "name": "//foundation/distributeddatamgr/preferences/interfaces/ndk:libohpreferences", "header": { "header_files": [ "oh_preferences.h", @@ -103,6 +103,7 @@ ], "test": [ "//foundation/distributeddatamgr/preferences/test/native:unittest", + "//foundation/distributeddatamgr/preferences/test/ndk:unittest", "//foundation/distributeddatamgr/preferences/test/js:unittest", "//foundation/distributeddatamgr/preferences/test/js:performancetest", "//foundation/distributeddatamgr/preferences/test/js:stage_unittest", diff --git a/preferences/frameworks/js/napi/preferences/include/napi_preferences.h b/preferences/frameworks/js/napi/preferences/include/napi_preferences.h index 952be979db2f392cc9efddd20f2b6b2ae3246cd5..9e2ebe1330e2421ec6b8104e43a8d0f795305f4f 100644 --- a/preferences/frameworks/js/napi/preferences/include/napi_preferences.h +++ b/preferences/frameworks/js/napi/preferences/include/napi_preferences.h @@ -22,6 +22,7 @@ #include #include "js_observer.h" +#include "js_proxy.h" #include "js_common_utils.h" #include "napi/native_api.h" #include "napi/native_common.h" @@ -33,12 +34,14 @@ namespace OHOS { namespace PreferencesJsKit { using RegisterMode = NativePreferences::PreferencesObserver::RegisterMode; -class PreferencesProxy { +using Preferences = NativePreferences::Preferences; +template +using JSProxy = OHOS::JSProxy::JSProxy; +class PreferencesProxy : public JSProxy { public: static void Init(napi_env env, napi_value exports); static napi_value New(napi_env env, napi_callback_info info); - static napi_status NewInstance( - napi_env env, std::shared_ptr value, napi_value *instance); + static napi_status NewInstance(napi_env env, std::shared_ptr value, napi_value *instance); static void Destructor(napi_env env, void *nativeObject, void *finalize_hint); private: @@ -57,14 +60,8 @@ private: static napi_value RegisterObserver(napi_env env, napi_callback_info info); static napi_value UnRegisterObserver(napi_env env, napi_callback_info info); static napi_value GetAll(napi_env env, napi_callback_info info); - static napi_value GetValueSync(napi_env env, napi_callback_info info); - static napi_value SetValueSync(napi_env env, napi_callback_info info); - static napi_value HasKeySync(napi_env env, napi_callback_info info); - static napi_value DeleteSync(napi_env env, napi_callback_info info); - static napi_value FlushSync(napi_env env, napi_callback_info info); - static napi_value ClearSync(napi_env env, napi_callback_info info); - static napi_value GetAllSync(napi_env env, napi_callback_info info); + static std::pair> GetSelfInstance(napi_env env, napi_value self); static RegisterMode ConvertToRegisterMode(const std::string &mode); static napi_value RegisterDataObserver(napi_env env, size_t argc, napi_value *argv, napi_value self); static napi_value UnRegisterDataObserver(napi_env env, size_t argc, napi_value *argv, napi_value self); @@ -74,7 +71,6 @@ private: int UnRegisteredAllObservers(RegisterMode mode, const std::vector &keys = {}); int RegisteredDataObserver(const std::vector &keys, napi_value callback); int UnRegisteredDataObserver(const std::vector &keys, napi_value callback); - std::shared_ptr value_; napi_env env_; std::mutex listMutex_ {}; diff --git a/preferences/frameworks/js/napi/preferences/src/napi_preferences.cpp b/preferences/frameworks/js/napi/preferences/src/napi_preferences.cpp index 82dc2ce9dbe94306d1504a3e19b02d9cb92f8a98..339af282407bcf182cc0834f2a6e67a9517e9754 100644 --- a/preferences/frameworks/js/napi/preferences/src/napi_preferences.cpp +++ b/preferences/frameworks/js/napi/preferences/src/napi_preferences.cpp @@ -34,12 +34,12 @@ namespace PreferencesJsKit { #define MAX_VALUE_LENGTH Preferences::MAX_VALUE_LENGTH struct PreferencesAysncContext : public BaseContext { + std::weak_ptr instance_; std::string key; PreferencesValue defValue = PreferencesValue(static_cast(0)); napi_ref inputValueRef = nullptr; std::map allElements; bool hasKey = false; - std::list keysModified; std::vector> preferencesObservers; PreferencesAysncContext() @@ -51,7 +51,7 @@ struct PreferencesAysncContext : public BaseContext { static __thread napi_ref constructor_; PreferencesProxy::PreferencesProxy() - : value_(nullptr), env_(nullptr), uvQueue_(nullptr) + : env_(nullptr), uvQueue_(nullptr) { } @@ -60,6 +60,7 @@ PreferencesProxy::~PreferencesProxy() UnRegisteredAllObservers(RegisterMode::LOCAL_CHANGE); UnRegisteredAllObservers(RegisterMode::MULTI_PRECESS_CHANGE); UnRegisteredAllObservers(RegisterMode::DATA_CHANGE); + SetInstance(nullptr); } void PreferencesProxy::Destructor(napi_env env, void *nativeObject, void *finalize_hint) @@ -119,7 +120,7 @@ napi_status PreferencesProxy::NewInstance( LOG_ERROR("PreferencesProxy::New new failed, obj is nullptr"); return napi_invalid_arg; } - obj->value_ = value; + obj->SetInstance(value); obj->env_ = env; obj->uvQueue_ = std::make_shared(env); status = napi_wrap(env, *instance, obj, PreferencesProxy::Destructor, nullptr, nullptr); @@ -171,19 +172,35 @@ int GetAllExecute(napi_env env, std::shared_ptr context return OK; } +std::pair> PreferencesProxy::GetSelfInstance( + napi_env env, napi_value self) +{ + void *boundObj = nullptr; + napi_unwrap(env, self, &boundObj); + if (boundObj != nullptr) { + PreferencesProxy *obj = reinterpret_cast(boundObj); + return { obj, obj->GetInstance() }; + } + return { nullptr, std::weak_ptr() }; +} + napi_value PreferencesProxy::GetAll(napi_env env, napi_callback_info info) { LOG_DEBUG("GetAll start"); auto context = std::make_shared(); auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) { PRE_CHECK_RETURN_VOID_SET(argc == 0, std::make_shared("0 or 1")); - napi_unwrap(env, self, &context->boundObj); - PRE_CHECK_RETURN_VOID_SET(context->boundObj != nullptr, + std::tie(context->boundObj, context->instance_) = GetSelfInstance(env, self); + PRE_CHECK_RETURN_VOID_SET(context->boundObj != nullptr && context->instance_.lock() != nullptr, std::make_shared("Failed to unwrap when getting all.")); }; auto exec = [context]() -> int { - PreferencesProxy *obj = reinterpret_cast(context->boundObj); - context->allElements = obj->value_->GetAll(); + auto instance = context->instance_.lock(); + if (instance == nullptr) { + LOG_ERROR("Failed to get instance when GetAll, The instance is nullptr."); + return E_INNER_ERROR; + } + context->allElements = instance->GetAll(); return OK; }; auto output = [context](napi_env env, napi_value &result) { @@ -203,13 +220,17 @@ napi_value PreferencesProxy::GetValue(napi_env env, napi_callback_info info) PRE_CHECK_RETURN_VOID_SET(argc == 2, std::make_shared("2 or 3")); PRE_CHECK_RETURN_VOID(ParseKey(env, argv[0], context) == OK); napi_create_reference(env, argv[1], 1, &context->inputValueRef); - napi_unwrap(env, self, &context->boundObj); - PRE_CHECK_RETURN_VOID_SET(context->boundObj != nullptr, + std::tie(context->boundObj, context->instance_) = GetSelfInstance(env, self); + PRE_CHECK_RETURN_VOID_SET(context->boundObj != nullptr && context->instance_.lock() != nullptr, std::make_shared("Failed to unwrap when getting value.")); }; auto exec = [context]() -> int { - PreferencesProxy *obj = reinterpret_cast(context->boundObj); - context->defValue = obj->value_->Get(context->key, context->defValue); + auto instance = context->instance_.lock(); + if (instance == nullptr) { + LOG_ERROR("Failed to get instance when GetValue, The instance is nullptr."); + return E_INNER_ERROR; + } + context->defValue = instance->Get(context->key, context->defValue); return OK; }; auto output = [context](napi_env env, napi_value &result) { @@ -237,13 +258,17 @@ napi_value PreferencesProxy::SetValue(napi_env env, napi_callback_info info) PRE_CHECK_RETURN_VOID_SET(argc == 2, std::make_shared("2 or 3")); PRE_CHECK_RETURN_VOID(ParseKey(env, argv[0], context) == OK); PRE_CHECK_RETURN_VOID(ParseDefValue(env, argv[1], context) == OK); - napi_unwrap(env, self, &context->boundObj); - PRE_CHECK_RETURN_VOID_SET(context->boundObj != nullptr, + std::tie(context->boundObj, context->instance_) = GetSelfInstance(env, self); + PRE_CHECK_RETURN_VOID_SET(context->boundObj != nullptr && context->instance_.lock() != nullptr, std::make_shared("Failed to unwrap when setting value.")); }; auto exec = [context]() -> int { - PreferencesProxy *obj = reinterpret_cast(context->boundObj); - return obj->value_->Put(context->key, context->defValue); + auto instance = context->instance_.lock(); + if (instance == nullptr) { + LOG_ERROR("Failed to get instance when GetValue, The instance is nullptr."); + return E_INNER_ERROR; + } + return instance->Put(context->key, context->defValue); }; auto output = [context](napi_env env, napi_value &result) { napi_status status = napi_get_undefined(env, &result); @@ -264,13 +289,17 @@ napi_value PreferencesProxy::Delete(napi_env env, napi_callback_info info) auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) { PRE_CHECK_RETURN_VOID_SET(argc == 1, std::make_shared("1 or 2")); PRE_CHECK_RETURN_VOID(ParseKey(env, argv[0], context) == OK); - napi_unwrap(env, self, &context->boundObj); - PRE_CHECK_RETURN_VOID_SET(context->boundObj != nullptr, + std::tie(context->boundObj, context->instance_) = GetSelfInstance(env, self); + PRE_CHECK_RETURN_VOID_SET(context->boundObj != nullptr && context->instance_.lock() != nullptr, std::make_shared("Failed to unwrap when deleting value.")); }; auto exec = [context]() -> int { - PreferencesProxy *obj = reinterpret_cast(context->boundObj); - return obj->value_->Delete(context->key); + auto instance = context->instance_.lock(); + if (instance == nullptr) { + LOG_ERROR("Failed to get instance when GetValue, The instance is nullptr."); + return E_INNER_ERROR; + } + return instance->Delete(context->key); }; auto output = [context](napi_env env, napi_value &result) { napi_status status = napi_get_undefined(env, &result); @@ -291,13 +320,17 @@ napi_value PreferencesProxy::HasKey(napi_env env, napi_callback_info info) auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) { PRE_CHECK_RETURN_VOID_SET(argc == 1, std::make_shared("1 or 2")); PRE_CHECK_RETURN_VOID(ParseKey(env, argv[0], context) == OK); - napi_unwrap(env, self, &context->boundObj); - PRE_CHECK_RETURN_VOID_SET(context->boundObj != nullptr, + std::tie(context->boundObj, context->instance_) = GetSelfInstance(env, self); + PRE_CHECK_RETURN_VOID_SET(context->boundObj != nullptr && context->instance_.lock() != nullptr, std::make_shared("Failed to unwrap when having key.")); }; auto exec = [context]() -> int { - PreferencesProxy *obj = reinterpret_cast(context->boundObj); - context->hasKey = obj->value_->HasKey(context->key); + auto instance = context->instance_.lock(); + if (instance == nullptr) { + LOG_ERROR("Failed to get instance when GetValue, The instance is nullptr."); + return E_INNER_ERROR; + } + context->hasKey = instance->HasKey(context->key); return OK; }; auto output = [context](napi_env env, napi_value &result) { @@ -318,13 +351,17 @@ napi_value PreferencesProxy::Flush(napi_env env, napi_callback_info info) auto context = std::make_shared(); auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) { PRE_CHECK_RETURN_VOID_SET(argc == 0, std::make_shared("0 or 1")); - napi_unwrap(env, self, &context->boundObj); - PRE_CHECK_RETURN_VOID_SET(context->boundObj != nullptr, + std::tie(context->boundObj, context->instance_) = GetSelfInstance(env, self); + PRE_CHECK_RETURN_VOID_SET(context->boundObj != nullptr && context->instance_.lock() != nullptr, std::make_shared("Failed to unwrap when flushing.")); }; auto exec = [context]() -> int { - PreferencesProxy *obj = reinterpret_cast(context->boundObj); - return obj->value_->FlushSync(); + auto instance = context->instance_.lock(); + if (instance == nullptr) { + LOG_ERROR("Failed to get instance when GetValue, The instance is nullptr."); + return E_INNER_ERROR; + } + return instance->FlushSync(); }; auto output = [context](napi_env env, napi_value &result) { napi_status status = napi_get_undefined(env, &result); @@ -344,13 +381,17 @@ napi_value PreferencesProxy::Clear(napi_env env, napi_callback_info info) auto context = std::make_shared(); auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) { PRE_CHECK_RETURN_VOID_SET(argc == 0, std::make_shared("0 or 1")); - napi_unwrap(env, self, &context->boundObj); - PRE_CHECK_RETURN_VOID_SET(context->boundObj != nullptr, + std::tie(context->boundObj, context->instance_) = GetSelfInstance(env, self); + PRE_CHECK_RETURN_VOID_SET(context->boundObj != nullptr && context->instance_.lock() != nullptr, std::make_shared("Failed to unwrap unwrap when clearing.")); }; auto exec = [context]() -> int { - PreferencesProxy *obj = reinterpret_cast(context->boundObj); - return obj->value_->Clear(); + auto instance = context->instance_.lock(); + if (instance == nullptr) { + LOG_ERROR("Failed to get instance when GetValue, The instance is nullptr."); + return E_INNER_ERROR; + } + return instance->Clear(); }; auto output = [context](napi_env env, napi_value &result) { napi_status status = napi_get_undefined(env, &result); @@ -392,8 +433,9 @@ napi_value PreferencesProxy::RegisterObserver(napi_env env, napi_callback_info i NAPI_CALL(env, napi_typeof(env, args[1], &type)); PRE_NAPI_ASSERT(env, type == napi_function, std::make_shared("The callback must be function.")); - PreferencesProxy *obj = nullptr; - NAPI_CALL(env, napi_unwrap(env, thiz, reinterpret_cast(&obj))); + auto [obj, instance] = GetSelfInstance(env, thiz); + PRE_NAPI_ASSERT(env, obj != nullptr && instance.lock() != nullptr, + std::make_shared("Failed to unwrap when register callback")); int errCode = obj->RegisteredObserver(args[1], ConvertToRegisterMode(registerMode)); PRE_NAPI_ASSERT(env, errCode == OK, std::make_shared(errCode)); @@ -433,8 +475,9 @@ napi_value PreferencesProxy::UnRegisterObserver(napi_env env, napi_callback_info std::make_shared("The callback must be function.")); } - PreferencesProxy *obj = nullptr; - NAPI_CALL(env, napi_unwrap(env, thiz, reinterpret_cast(&obj))); + auto [obj, instance] = GetSelfInstance(env, thiz); + PRE_NAPI_ASSERT(env, obj != nullptr && instance.lock() != nullptr, + std::make_shared("Failed to unwrap when register callback")); int errCode; if (type == napi_function) { errCode = obj->UnRegisteredObserver(args[1], ConvertToRegisterMode(registerMode)); @@ -475,7 +518,12 @@ int PreferencesProxy::RegisteredObserver(napi_value callback, RegisterMode mode) auto &observers = (mode == RegisterMode::LOCAL_CHANGE) ? localObservers_ : multiProcessObservers_; if (!HasRegisteredObserver(callback, mode)) { auto observer = std::make_shared(uvQueue_, callback); - int errCode = value_->RegisterObserver(observer, mode); + auto instance = GetInstance(); + if (instance == nullptr) { + LOG_ERROR("The observer subscribed failed."); + return E_INNER_ERROR; + } + int errCode = instance->RegisterObserver(observer, mode); if (errCode != E_OK) { return errCode; } @@ -489,10 +537,15 @@ int PreferencesProxy::UnRegisteredObserver(napi_value callback, RegisterMode mod { std::lock_guard lck(listMutex_); auto &observers = (mode == RegisterMode::LOCAL_CHANGE) ? localObservers_ : multiProcessObservers_; + auto instance = GetInstance(); + if (instance == nullptr) { + LOG_ERROR("The observer unsubscribed failed."); + return E_INNER_ERROR; + } auto it = observers.begin(); while (it != observers.end()) { if (JSUtils::Equals(env_, callback, (*it)->GetCallback())) { - int errCode = value_->UnRegisterObserver(*it, mode); + int errCode = instance->UnRegisterObserver(*it, mode); if (errCode != E_OK) { return errCode; } @@ -515,8 +568,13 @@ int PreferencesProxy::UnRegisteredAllObservers(RegisterMode mode, const std::vec auto &observers = (mode == RegisterMode::LOCAL_CHANGE) ? localObservers_ : multiProcessObservers_; bool hasFailed = false; int errCode = E_OK; + auto instance = GetInstance(); + if (instance == nullptr) { + LOG_ERROR("All observer unsubscribed failed."); + return E_INNER_ERROR; + } for (auto &observer : observers) { - errCode = value_->UnRegisterObserver(observer, mode); + errCode = instance->UnRegisterObserver(observer, mode); if (errCode != E_OK) { hasFailed = true; LOG_ERROR("The observer unsubscribed has failed, errCode %{public}d.", errCode); @@ -547,8 +605,9 @@ napi_value PreferencesProxy::RegisterDataObserver(napi_env env, size_t argc, nap NAPI_CALL(env, napi_typeof(env, argv[funcIndex], &type)); PRE_NAPI_ASSERT(env, type == napi_function, std::make_shared("The callback must be function.")); - PreferencesProxy *obj = nullptr; - NAPI_CALL(env, napi_unwrap(env, self, reinterpret_cast(&obj))); + auto [obj, instance] = GetSelfInstance(env, self); + PRE_NAPI_ASSERT(env, obj != nullptr && instance.lock() != nullptr, + std::make_shared("Failed to unwrap when register callback")); errCode = obj->RegisteredDataObserver(keys, argv[funcIndex]); PRE_NAPI_ASSERT(env, errCode == OK, std::make_shared(errCode)); return nullptr; @@ -558,9 +617,14 @@ int PreferencesProxy::RegisteredDataObserver(const std::vector &key { std::lock_guard lck(listMutex_); auto &observers = dataObservers_; + auto instance = GetInstance(); + if (instance == nullptr) { + LOG_ERROR("The dataChange observer subscribed failed."); + return E_INNER_ERROR; + } if (!HasRegisteredObserver(callback, RegisterMode::DATA_CHANGE)) { auto observer = std::make_shared(uvQueue_, callback); - int errCode = value_->RegisterDataObserver(observer, keys); + int errCode = instance->RegisterDataObserver(observer, keys); if (errCode != E_OK) { LOG_ERROR("Registered dataObserver failed:%{public}d", errCode); return errCode; @@ -589,8 +653,9 @@ napi_value PreferencesProxy::UnRegisterDataObserver(napi_env env, size_t argc, n PRE_NAPI_ASSERT(env, type == napi_function || type == napi_undefined || type == napi_null, std::make_shared("The callback must be function.")); } - PreferencesProxy *obj = nullptr; - NAPI_CALL(env, napi_unwrap(env, self, reinterpret_cast(&obj))); + auto [obj, instance] = GetSelfInstance(env, self); + PRE_NAPI_ASSERT(env, obj != nullptr && instance.lock() != nullptr, + std::make_shared("Failed to unwrap when unregister callback")); if (type == napi_function) { errCode = obj->UnRegisteredDataObserver(keys, argv[funcIndex]); } else { @@ -605,10 +670,15 @@ int PreferencesProxy::UnRegisteredDataObserver(const std::vector &k std::lock_guard lck(listMutex_); auto &observers = dataObservers_; bool isUnRegisterAll = (callback == nullptr); + auto instance = GetInstance(); + if (instance == nullptr) { + LOG_ERROR("The dataChange observer unsubscribed failed."); + return E_INNER_ERROR; + } auto it = observers.begin(); while (it != observers.end()) { if (isUnRegisterAll || JSUtils::Equals(env_, callback, (*it)->GetCallback())) { - int errCode = value_->UnRegisterDataObserver(*it, keys); + int errCode = instance->UnRegisterDataObserver(*it, keys); if (errCode != E_OK && errCode != E_OBSERVER_RESERVE) { return errCode; } else if (errCode == E_OK) { @@ -628,4 +698,4 @@ int PreferencesProxy::UnRegisteredDataObserver(const std::vector &k return E_OK; } } // namespace PreferencesJsKit -} // namespace OHOS +} // namespace OHOS \ No newline at end of file diff --git a/preferences/frameworks/native/platform/include/preferences_db_adapter.h b/preferences/frameworks/native/platform/include/preferences_db_adapter.h index dc7a50dbf98a4981b86f1550ce473570ef4b5908..d00f6a772572fd5309a776c615ecfac1a17335a4 100644 --- a/preferences/frameworks/native/platform/include/preferences_db_adapter.h +++ b/preferences/frameworks/native/platform/include/preferences_db_adapter.h @@ -171,6 +171,7 @@ private: #define GRD_INVALID_ARGS (-3000) #define GRD_FAILED_FILE_OPERATION (-5000) #define GRD_INNER_ERR (-8000) +#define GRD_NO_DATA (-11000) #define GRD_FAILED_MEMORY_ALLOCATE (-13000) #define GRD_FAILED_MEMORY_RELEASE (-14000) #define GRD_UNDEFINED_TABLE (-23000) diff --git a/preferences/frameworks/native/platform/src/preferences_db_adapter.cpp b/preferences/frameworks/native/platform/src/preferences_db_adapter.cpp index d732f97aaeaa7eacbcfae54cf911e6f6cf1a171f..985f4f654fc8e6535378133e4371631cec7c4c6b 100644 --- a/preferences/frameworks/native/platform/src/preferences_db_adapter.cpp +++ b/preferences/frameworks/native/platform/src/preferences_db_adapter.cpp @@ -75,7 +75,8 @@ const std::map GRDErrnoMap = { { GRD_INVALID_ARGS, E_INVALID_ARGS }, { GRD_FAILED_MEMORY_ALLOCATE, E_OUT_OF_MEMORY }, { GRD_FAILED_MEMORY_RELEASE, E_OUT_OF_MEMORY }, - { GRD_PERMISSION_DENIED, PERMISSION_DENIED } + { GRD_PERMISSION_DENIED, PERMISSION_DENIED }, + { GRD_NO_DATA, E_NO_DATA } }; int TransferGrdErrno(int err) @@ -164,7 +165,6 @@ int PreferencesDb::CloseDb() if (errCode != E_OK) { LOG_ERROR("close db failed, errcode=%{public}d, file: %{public}s", errCode, ExtractFileName(dbPath_).c_str()); - PreferencesDfxManager::ReportDbFault(GetReportParam("close db failed", errCode)); return TransferGrdErrno(errCode); } LOG_INFO("db has been closed."); @@ -185,7 +185,6 @@ int PreferencesDb::CreateCollection() TABLE_MODE, 0); if (errCode != GRD_OK) { LOG_ERROR("rd create table failed:%{public}d", errCode); - PreferencesDfxManager::ReportDbFault(GetReportParam("create table failed", errCode)); } return TransferGrdErrno(errCode); } @@ -206,7 +205,6 @@ int PreferencesDb::OpenDb(bool isNeedRebuild) std::string errMsg = isNeedRebuild ? "open db failed with open_create | open_check" : "open db failed with open_create"; LOG_ERROR("%{public}s, errCode: %{public}d, isRebuild:%{public}d", errMsg.c_str(), errCode, isNeedRebuild); - PreferencesDfxManager::ReportDbFault(GetReportParam(errMsg, errCode)); } return errCode; } @@ -221,7 +219,6 @@ int PreferencesDb::RepairDb() if (errCode != GRD_OK) { std::string errMsg = "db repair failed"; LOG_ERROR("repair db failed, errCode: %{public}d", errCode); - PreferencesDfxManager::ReportDbFault(GetReportParam(errMsg, errCode)); } return errCode; } @@ -273,12 +270,20 @@ int PreferencesDb::Init(const std::string &dbPath, const std::string &bundleName dbPath_ = dbPath + ".db"; bundleName_ = bundleName; int errCode = OpenDb(false); - if (errCode == GRD_DATA_CORRUPTED || errCode == GRD_FAILED_FILE_OPERATION || errCode == GRD_INNER_ERR) { + if (errCode == GRD_DATA_CORRUPTED) { + PreferencesDfxManager::ReportDbFault(GetReportParam("db corrupted", errCode)); + } + if (errCode == GRD_DATA_CORRUPTED || errCode == GRD_INNER_ERR) { int innerErr = TryRepairAndRebuild(errCode); if (innerErr != GRD_OK) { // log inside return TransferGrdErrno(innerErr); } + if (errCode == GRD_DATA_CORRUPTED) { + ReportParam param = GetReportParam("db repair success", GRD_OK); + param.errnoCode = 0; + PreferencesDfxManager::ReportDbFault(param); + } } else if (errCode != GRD_OK) { LOG_ERROR("db open failed, errCode: %{public}d", errCode); return TransferGrdErrno(errCode); @@ -323,7 +328,6 @@ int PreferencesDb::Put(const std::vector &key, const std::vector &key) return TransferGrdErrno(ret); } else { LOG_ERROR("rd delete failed:%{public}d", ret); - PreferencesDfxManager::ReportDbFault(GetReportParam("rd delete failed", ret)); return TransferGrdErrno(ret); } } @@ -414,13 +417,6 @@ int PreferencesDb::Get(const std::vector &key, std::vector &va int PreferencesDb::GetAllInner(std::list, std::vector>> &data, GRD_ResultSet *resultSet) { - if (PreferenceDbAdapter::GetApiInstance().NextApi == nullptr || - PreferenceDbAdapter::GetApiInstance().GetItemSizeApi == nullptr || - PreferenceDbAdapter::GetApiInstance().FreeResultSetApi == nullptr || - PreferenceDbAdapter::GetApiInstance().GetItemApi == nullptr) { - LOG_ERROR("api load failed: NextApi or GetItemSizeApi or FreeResultSetApi or GetItemApi"); - return E_ERROR; - } int ret = E_OK; while (TransferGrdErrno(PreferenceDbAdapter::GetApiInstance().NextApi(resultSet)) == E_OK) { std::pair, std::vector> dataItem; @@ -429,7 +425,6 @@ int PreferencesDb::GetAllInner(std::list, std::ve ret = PreferenceDbAdapter::GetApiInstance().GetItemSizeApi(resultSet, &keySize, &valueSize); if (ret != GRD_OK) { LOG_ERROR("ger reulstSet kv size failed %{public}d", ret); - PreferenceDbAdapter::GetApiInstance().FreeResultSetApi(resultSet); return TransferGrdErrno(ret); } dataItem.first.resize(keySize); @@ -438,7 +433,6 @@ int PreferencesDb::GetAllInner(std::list, std::ve dataItem.second.data()); if (ret != E_OK) { LOG_ERROR("ger reulstSet failed %{public}d", ret); - PreferenceDbAdapter::GetApiInstance().FreeResultSetApi(resultSet); return TransferGrdErrno(ret); } data.emplace_back(std::move(dataItem)); @@ -446,13 +440,22 @@ int PreferencesDb::GetAllInner(std::list, std::ve return TransferGrdErrno(ret); } +static inline bool IsApiValid() +{ + auto& apiInstance = PreferenceDbAdapter::GetApiInstance(); + return (apiInstance.DbKvFilterApi != nullptr && apiInstance.NextApi != nullptr && + apiInstance.GetItemSizeApi != nullptr && apiInstance.GetItemApi != nullptr && + apiInstance.FreeResultSetApi != nullptr); +} + int PreferencesDb::GetAll(std::list, std::vector>> &data) { if (db_ == nullptr) { LOG_ERROR("GetAll failed, db has been closed."); return E_ALREADY_CLOSED; - } else if (PreferenceDbAdapter::GetApiInstance().DbKvFilterApi == nullptr) { - LOG_ERROR("api load failed: DbKvFilterApi"); + } + if (!IsApiValid()) { + LOG_ERROR("api load failed when get all"); return E_ERROR; } @@ -462,28 +465,25 @@ int PreferencesDb::GetAll(std::list, std::vector< int retryTimes = CREATE_COLLECTION_RETRY_TIMES; int ret = E_OK; + do { ret = PreferenceDbAdapter::GetApiInstance().DbKvFilterApi(db_, TABLENAME, ¶m, &resultSet); if (ret == GRD_UNDEFINED_TABLE) { LOG_INFO("CreateCollection called when GetAll, file: %{public}s", ExtractFileName(dbPath_).c_str()); (void)CreateCollection(); + } else if (ret == GRD_OK) { + int innerErr = GetAllInner(data, resultSet); // log inside when failed + PreferenceDbAdapter::GetApiInstance().FreeResultSetApi(resultSet); + return innerErr; } else { - if (ret == GRD_OK) { - break; - } else { - LOG_ERROR("rd kv filter failed:%{public}d", ret); - return TransferGrdErrno(ret); - } + LOG_ERROR("rd kv filter failed:%{public}d", ret); + return TransferGrdErrno(ret); } retryTimes--; } while (retryTimes > 0); - if (retryTimes == 0) { - LOG_ERROR("rd get over retry times, errcode: :%{public}d", ret); - return TransferGrdErrno(ret); - } - - return GetAllInner(data, resultSet); + LOG_ERROR("rd get over retry times, errcode: :%{public}d", ret); + return TransferGrdErrno(ret); } int PreferencesDb::DropCollection() @@ -499,7 +499,6 @@ int PreferencesDb::DropCollection() int errCode = PreferenceDbAdapter::GetApiInstance().DbDropCollectionApi(db_, TABLENAME, 0); if (errCode != E_OK) { LOG_ERROR("rd drop collection failed:%{public}d", errCode); - PreferencesDfxManager::ReportDbFault(GetReportParam("rd drop collection failed", errCode)); } return TransferGrdErrno(errCode); } diff --git a/preferences/frameworks/native/platform/src/preferences_dfx_adapter.cpp b/preferences/frameworks/native/platform/src/preferences_dfx_adapter.cpp index 7b8883ebee21b07e7e77ca53cfda39565646565b..be84ddf25e9c2c1989c5940c9bc6899589ee50b3 100644 --- a/preferences/frameworks/native/platform/src/preferences_dfx_adapter.cpp +++ b/preferences/frameworks/native/platform/src/preferences_dfx_adapter.cpp @@ -73,10 +73,14 @@ void PreferencesDfxManager::ReportDbFault(const ReportParam &reportParam) std::thread thread([reportParam]() { std::string nowTime = GetCurrentTime(); std::string moudleName = GetModuleName(); + if (moudleName.empty()) { + moudleName = reportParam.storeName; + } + std::string bundleName = reportParam.bundleName.empty() ? moudleName : reportParam.bundleName; HiSysEventParam params[] = { { .name = "BUNDLE_NAME", .t = HISYSEVENT_STRING, - .v = { .s = const_cast(reportParam.bundleName.c_str()) }, + .v = { .s = const_cast(bundleName.c_str()) }, .arraySize = 0 }, { .name = "MODULE_NAME", .t = HISYSEVENT_STRING, diff --git a/preferences/frameworks/native/src/preferences_enhance_impl.cpp b/preferences/frameworks/native/src/preferences_enhance_impl.cpp index d510e5519f7fc01a37a47ab431e49b1a3dab9924..9121a5b4a2cff9a50da6b984770eadc48ac82b01 100644 --- a/preferences/frameworks/native/src/preferences_enhance_impl.cpp +++ b/preferences/frameworks/native/src/preferences_enhance_impl.cpp @@ -50,7 +50,11 @@ int PreferencesEnhanceImpl::Init() std::unique_lock writeLock(dbMutex_); db_ = std::make_shared(); cachedDataVersion_ = 0; - return db_->Init(options_.filePath, options_.bundleName); + int errCode = db_->Init(options_.filePath, options_.bundleName); + if (errCode != E_OK) { + db_ = nullptr; + } + return errCode; } PreferencesValue PreferencesEnhanceImpl::Get(const std::string &key, const PreferencesValue &defValue) @@ -268,7 +272,7 @@ std::map PreferencesEnhanceImpl::GetAll() void PreferencesEnhanceImpl::NotifyPreferencesObserver(std::shared_ptr pref, const std::string &key, const PreferencesValue &value) { - std::shared_lock readLock(pref->mapSharedMutex_); + std::shared_lock readLock(pref->obseverMetux_); LOG_DEBUG("notify observer size:%{public}zu", pref->dataObserversMap_.size()); for (const auto &[weakPrt, keys] : pref->dataObserversMap_) { auto itKey = keys.find(key); diff --git a/preferences/frameworks/native/src/preferences_helper.cpp b/preferences/frameworks/native/src/preferences_helper.cpp index c59c60b846a9c8fd30aead7fab12eda5b1c36bec..1aa8a1b8535c88d716dd7c9e7667fef6ea5b2b21 100644 --- a/preferences/frameworks/native/src/preferences_helper.cpp +++ b/preferences/frameworks/native/src/preferences_helper.cpp @@ -156,6 +156,13 @@ 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/frameworks/native/src/preferences_impl.cpp b/preferences/frameworks/native/src/preferences_impl.cpp index 2230f36dcadaa601eb42634cb8748050d5972ec8..3d5de80346b784d8f28b1f84996e3f63544a37d9 100644 --- a/preferences/frameworks/native/src/preferences_impl.cpp +++ b/preferences/frameworks/native/src/preferences_impl.cpp @@ -527,18 +527,16 @@ std::pair PreferencesImpl::GetValue(const std::string &ke } AwaitLoadFile(); - std::lock_guard lock(mutex_); auto iter = valuesCache_.Find(key); if (iter.first) { return std::make_pair(E_OK, iter.second); } - return std::make_pair(E_ERROR, defValue); + return std::make_pair(E_NO_DATA, defValue); } - + std::pair> PreferencesImpl::GetAllData() { AwaitLoadFile(); - std::lock_guard lock(mutex_); return std::make_pair(E_OK, valuesCache_.Clone()); } diff --git a/preferences/frameworks/native/src/preferences_xml_utils.cpp b/preferences/frameworks/native/src/preferences_xml_utils.cpp index 0ff478cc4237dcad61e7da6385742bc3b90fac03..587fd928e0aaad4668175d87c9f7460838b9d248 100644 --- a/preferences/frameworks/native/src/preferences_xml_utils.cpp +++ b/preferences/frameworks/native/src/preferences_xml_utils.cpp @@ -29,6 +29,8 @@ namespace OHOS { namespace NativePreferences { +constexpr int REQUIRED_KEY_NOT_AVAILABLE = 126; +constexpr int REQUIRED_KEY_REVOKED = 128; static bool ParseNodeElement(const xmlNode *node, Element &element); static bool ParsePrimitiveNodeElement(const xmlNode *node, Element &element); static bool ParseStringNodeElement(const xmlNode *node, Element &element); @@ -55,17 +57,51 @@ static void RemoveBackupFile(const std::string &fileName) } } -static bool RenameFromBackupFile(const std::string &fileName) +static xmlDoc *ReadFile(const std::string &fileName, int &errCode) +{ + xmlDoc *doc = xmlReadFile(fileName.c_str(), "UTF-8", XML_PARSE_NOBLANKS | XML_PARSE_HUGE); + errCode = errno; + return doc; +} + +static void ReportXmlFileIsBroken(const std::string &fileName, const std::string &bundleName, + const std::string &operationMsg, int errCode) +{ + ReportParam reportParam = { bundleName, NORMAL_DB, ExtractFileName(fileName), E_ERROR, errCode, operationMsg }; + PreferencesDfxManager::ReportDbFault(reportParam); + ReportParam succreportParam = reportParam; + succreportParam.errCode = E_OK; + succreportParam.errnoCode = 0; + succreportParam.appendix = "operation: restore success"; + PreferencesDfxManager::ReportDbFault(succreportParam); +} + +static bool RenameFromBackupFile(const std::string &fileName, const std::string &bundleName, bool &isReportCorrupt) { std::string backupFileName = MakeFilePath(fileName, STR_BACKUP); if (!IsFileExist(backupFileName)) { LOG_DEBUG("the backup file does not exist."); return false; } + xmlResetLastError(); + int errCode = 0; + auto bakDoc = std::shared_ptr(ReadFile(backupFileName, errCode), + [](xmlDoc *bakDoc) { xmlFreeDoc(bakDoc); }); + if (bakDoc == nullptr) { + xmlErrorPtr xmlErr = xmlGetLastError(); + std::string errMessage = (xmlErr != nullptr) ? xmlErr->message : "null"; + LOG_ERROR("restore XML file: %{public}s failed, errno is %{public}d, error is %{public}s.", + ExtractFileName(fileName).c_str(), errCode, errMessage.c_str()); + std::remove(backupFileName.c_str()); + isReportCorrupt = true; + return false; + } if (std::rename(backupFileName.c_str(), fileName.c_str())) { LOG_ERROR("failed to restore backup errno %{public}d.", errno); return false; } + isReportCorrupt = false; + LOG_INFO("restore XML file %{public}s successfully.", ExtractFileName(fileName).c_str()); return true; } @@ -84,40 +120,43 @@ static bool RenameToBackupFile(const std::string &fileName) return RenameFile(fileName, STR_BACKUP); } -static bool RenameToBrokenFile(const std::string &fileName, const ReportParam &reportParam) +static bool RenameToBrokenFile(const std::string &fileName) { - PreferencesDfxManager::ReportDbFault(reportParam); return RenameFile(fileName, STR_BROKEN); } -static xmlDoc *ReadFile(const std::string &fileName) -{ - return xmlReadFile(fileName.c_str(), "UTF-8", XML_PARSE_NOBLANKS | XML_PARSE_HUGE); -} - static xmlDoc *XmlReadFile(const std::string &fileName, const std::string &bundleName, const std::string &dataGroupId) { xmlDoc *doc = nullptr; + bool isReport = false; PreferencesFileLock fileLock(MakeFilePath(fileName, STR_LOCK), dataGroupId); + int errCode = 0; if (IsFileExist(fileName)) { - doc = ReadFile(fileName); + doc = ReadFile(fileName, errCode); if (doc != nullptr) { return doc; } xmlErrorPtr xmlErr = xmlGetLastError(); std::string errMessage = (xmlErr != nullptr) ? xmlErr->message : "null"; - LOG_ERROR("failed to read XML format file: %{public}s, error is %{public}s.", - ExtractFileName(fileName).c_str(), errMessage.c_str()); - ReportParam reportParam = { bundleName, NORMAL_DB, - ExtractFileName(fileName), E_ERROR, errno, "operation: failed to read XML format file." }; - if (!RenameToBrokenFile(fileName, reportParam)) { + LOG_ERROR("failed to read XML format file: %{public}s, errno is %{public}d, error is %{public}s.", + ExtractFileName(fileName).c_str(), errCode, errMessage.c_str()); + if (errCode == REQUIRED_KEY_NOT_AVAILABLE || errCode == REQUIRED_KEY_REVOKED) { + return nullptr; + } + if (!RenameToBrokenFile(fileName)) { return doc; } + isReport = true; } - if (RenameFromBackupFile(fileName)) { - return ReadFile(fileName); + + if (RenameFromBackupFile(fileName, bundleName, isReport)) { + doc = ReadFile(fileName, errCode); } - return nullptr; + if (isReport) { + const std::string operationMsg = "operation: failed to read XML format file."; + ReportXmlFileIsBroken(fileName, bundleName, operationMsg, errCode); + } + return doc; } /* static */ @@ -278,31 +317,39 @@ bool ParseArrayNodeElement(const xmlNode *node, Element &element) return success; } -static bool SaveFormatFileEnc(const std::string &fileName, xmlDoc *doc) +static std::pair SaveFormatFileEnc(const std::string &fileName, xmlDoc *doc) { - return xmlSaveFormatFileEnc(fileName.c_str(), doc, "UTF-8", 1) > 0; + return {xmlSaveFormatFileEnc(fileName.c_str(), doc, "UTF-8", 1) > 0, errno}; } bool XmlSaveFormatFileEnc( const std::string &fileName, const std::string &bundleName, const std::string &dataGroupId, xmlDoc *doc) { PreferencesFileLock fileLock(MakeFilePath(fileName, STR_LOCK), dataGroupId); - + LOG_INFO("save xml file:%{public}s.", ExtractFileName(fileName).c_str()); if (IsFileExist(fileName) && !RenameToBackupFile(fileName)) { return false; } - if (!SaveFormatFileEnc(fileName, doc)) { + bool isReport = false; + auto [ret, errCode] = SaveFormatFileEnc(fileName, doc); + if (!ret) { xmlErrorPtr xmlErr = xmlGetLastError(); std::string errMessage = (xmlErr != nullptr) ? xmlErr->message : "null"; - LOG_ERROR("failed to save XML format file: %{public}s, error is %{public}s.", - ExtractFileName(fileName).c_str(), errMessage.c_str()); + LOG_ERROR("failed to save XML format file: %{public}s, errno is %{public}d, error is %{public}s.", + ExtractFileName(fileName).c_str(), errCode, errMessage.c_str()); + if (errCode == REQUIRED_KEY_NOT_AVAILABLE || errCode == REQUIRED_KEY_REVOKED) { + return false; + } if (IsFileExist(fileName)) { - ReportParam reportParam = { bundleName, NORMAL_DB, - ExtractFileName(fileName), E_ERROR, errno, "operation: failed to save XML format file." }; - RenameToBrokenFile(fileName, reportParam); + RenameToBrokenFile(fileName); + isReport = true; + } + RenameFromBackupFile(fileName, bundleName, isReport); + if (isReport) { + const std::string operationMsg = "operation: failed to save XML format file."; + ReportXmlFileIsBroken(fileName, bundleName, operationMsg, errCode); } - RenameFromBackupFile(fileName); return false; } diff --git a/preferences/frameworks/ndk/include/oh_preferences_impl.h b/preferences/frameworks/ndk/include/oh_preferences_impl.h index fdc818ea150319a8fca3589bc475f10cccd892b1..645e3616760200a1d2500dada404936118f0287d 100644 --- a/preferences/frameworks/ndk/include/oh_preferences_impl.h +++ b/preferences/frameworks/ndk/include/oh_preferences_impl.h @@ -21,28 +21,31 @@ #include "oh_preferences.h" #include "preferences_observer.h" #include "preferences.h" +#include "log_print.h" -#ifdef __cplusplus -extern "C" { -#endif +enum PreferencesNdkStructId : std::int64_t { + PREFERENCES_OH_OPTION_CID = 1002931, + PREFERENCES_OH_PREFERENCES_CID, + PREFERENCES_OH_VALUE_CID, + PREFERENCES_OH_PAIR_CID +}; class NDKPreferencesObserver : public OHOS::NativePreferences::PreferencesObserver { public: - NDKPreferencesObserver(const OH_PreferencesDataObserver *observer, void *context); + NDKPreferencesObserver(OH_PreferencesDataObserver observer, void *context); ~NDKPreferencesObserver() noexcept override = default; void OnChange(const std::string &key) override; void OnChange(const std::map &records) override; - bool operator==(const OH_PreferencesDataObserver *other); + bool ObserverCompare(OH_PreferencesDataObserver other); -private: - const OH_PreferencesDataObserver *dataObserver_; + OH_PreferencesDataObserver dataObserver_; void *context_; }; struct OH_Preferences { - int id; + int64_t cid; }; class OH_PreferencesImpl : public OH_Preferences { @@ -58,8 +61,9 @@ public: } int RegisterDataObserver( - const OH_PreferencesDataObserver *observer, void *context, const std::vector &keys = {}); - int UnRegisterDataObserver(const OH_PreferencesDataObserver *observer, const std::vector &keys = {}); + OH_PreferencesDataObserver observer, void *context, const std::vector &keys = {}); + int UnregisterDataObserver(OH_PreferencesDataObserver observer, void *context, + const std::vector &keys = {}); void SetPreferencesStoreFilePath(const std::string &filePath); std::string GetPreferencesStoreFilePath(); @@ -69,16 +73,26 @@ private: std::shared_mutex mutex_; std::string filePath_ = ""; std::shared_mutex obsMutex_; - std::vector> dataObservers_; + std::vector, void *>> dataObservers_; }; struct OH_PreferencesOption { - std::string filePath; - std::string bundleName; - std::string dataGroupId; + int64_t cid; + std::string fileName = ""; + std::string bundleName = ""; + std::string dataGroupId = ""; + std::shared_mutex opMutex_; + int SetFileName(const std::string &str); + void SetBundleName(const std::string &str); + void SetDataGroupId(const std::string &str); + std::string GetFileName(); + std::string GetBundleName(); + std::string GetDataGroupId(); +}; + +class NDKPreferencesUtils { +public: + static bool PreferencesStructValidCheck(int64_t cid, int64_t structCid); }; -#ifdef __cplusplus -} -#endif #endif // PREFERENCES_STORE_IMPL_H \ No newline at end of file diff --git a/preferences/frameworks/ndk/include/oh_preferences_value_impl.h b/preferences/frameworks/ndk/include/oh_preferences_value_impl.h index 619472f4a109b99204d837b6a7876b07fd2a8909..27e9bc0a1ed399bbb51f0dff552e25ffd0c88cc3 100644 --- a/preferences/frameworks/ndk/include/oh_preferences_value_impl.h +++ b/preferences/frameworks/ndk/include/oh_preferences_value_impl.h @@ -17,29 +17,23 @@ #define OH_PREFERENCES_VALUE_IMPL_H #include "oh_preferences_value.h" +#include "oh_preferences_impl.h" #include "preferences.h" -#ifdef __cplusplus -extern "C" { -#endif - struct OH_PreferencesValue { - int id; + int64_t cid; }; struct OH_PreferencesPair { + int64_t cid; const char *key; const OH_PreferencesValue *value; + uint32_t maxIndex; }; class OH_PreferencesValueImpl : public OH_PreferencesValue { public: OHOS::NativePreferences::PreferencesValue value_; - Preference_ValueType type_; }; - -#ifdef __cplusplus -} -#endif #endif // OH_PREFERENCES_VALUE_IMPL_H diff --git a/preferences/frameworks/ndk/src/convertor_error_code.cpp b/preferences/frameworks/ndk/src/convertor_error_code.cpp index 6720af30e13cf9bf8b3bc6124f5a4ebebf12b67d..435bd8754e75423e101385da09c9d3ea328efac2 100644 --- a/preferences/frameworks/ndk/src/convertor_error_code.cpp +++ b/preferences/frameworks/ndk/src/convertor_error_code.cpp @@ -27,10 +27,15 @@ struct NdkErrCode { const std::map ERROR_CODE_MAP = { { OHOS::NativePreferences::E_OK, OH_Preferences_ErrCode::PREFERENCES_OK }, { OHOS::NativePreferences::E_INVALID_ARGS, OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM }, + { OHOS::NativePreferences::E_KEY_EMPTY, OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM }, + { OHOS::NativePreferences::E_KEY_EXCEED_MAX_LENGTH, OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM }, + { OHOS::NativePreferences::E_VALUE_EXCEED_MAX_LENGTH, OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM }, { OHOS::NativePreferences::E_NOT_SUPPORTED, OH_Preferences_ErrCode::PREFERENCES_ERROR_NOT_SUPPORTED }, { OHOS::NativePreferences::E_DELETE_FILE_FAIL, OH_Preferences_ErrCode::PREFERENCES_ERROR_DELETE_FILE }, { OHOS::NativePreferences::E_GET_DATAOBSMGRCLIENT_FAIL, - OH_Preferences_ErrCode::PREFERENCES_ERROR_GET_DATAOBSMGRCLIENT } + OH_Preferences_ErrCode::PREFERENCES_ERROR_GET_DATAOBSMGRCLIENT }, + { OHOS::NativePreferences::E_NO_DATA, OH_PREFERENCES_ERR_CODE_H::PREFERENCES_ERROR_KEY_NOT_FOUND }, + { OHOS::NativePreferences::E_OBSERVER_RESERVE, OH_Preferences_ErrCode::PREFERENCES_OK } }; int ConvertorErrorCode::NativeErrToNdk(int nativeCode) diff --git a/preferences/frameworks/ndk/src/oh_preferences.cpp b/preferences/frameworks/ndk/src/oh_preferences.cpp index 4dd749bcee03f8b21de080fc97f7ccab1605bdf5..180fa4abce2895852cd06e004d4a89066423569a 100644 --- a/preferences/frameworks/ndk/src/oh_preferences.cpp +++ b/preferences/frameworks/ndk/src/oh_preferences.cpp @@ -15,56 +15,128 @@ #include "oh_preferences.h" +#include "application_context.h" #include "convertor_error_code.h" #include "log_print.h" - #include "oh_preferences_err_code.h" #include "oh_preferences_impl.h" #include "oh_preferences_value_impl.h" #include "oh_preferences_value.h" #include "preferences_file_operation.h" #include "preferences_helper.h" +#include "securec.h" using namespace OHOS::PreferencesNdk; +using namespace OHOS::AbilityRuntime; OH_PreferencesImpl::OH_PreferencesImpl (std::shared_ptr preferences) : preferences_(preferences) { } -OH_Preferences *OH_Preferences_Open(OH_PreferencesOption *options, int *errCode) +bool NDKPreferencesUtils::PreferencesStructValidCheck(int64_t originCid, int64_t targetCid) +{ + if (originCid != targetCid) { + LOG_ERROR("cid check failed, ori cid: %{public}ld, target cid: %{public}ld", static_cast(originCid), + static_cast(targetCid)); + return false; + } + return true; +} + +std::pair GetPreferencesDir(OH_PreferencesOption *options) { - if (options == nullptr || options->filePath.empty()) { - LOG_ERROR("open store config error, options is null: %{public}d, filePath is null: %{public}d", - (options == nullptr), options->filePath.empty()); + auto context = OHOS::AbilityRuntime::Context::GetApplicationContext(); + if (context == nullptr) { + LOG_ERROR("get application context go wrong"); + return { OH_Preferences_ErrCode::PREFERENCES_ERROR_STORAGE, "" }; + } + if (options->GetDataGroupId().empty()) { + return { OH_Preferences_ErrCode::PREFERENCES_OK, context->GetPreferencesDir() }; + } + std::string stagePreferencesDir; + int err = context->GetSystemPreferencesDir(options->GetDataGroupId(), false, stagePreferencesDir); + if (err != 0) { + LOG_ERROR("get system preferences dir failed, err: %{public}d", err); + return { OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM, stagePreferencesDir }; + } + return { OH_Preferences_ErrCode::PREFERENCES_OK, stagePreferencesDir }; +} + +OH_Preferences *OH_Preferences_Open(OH_PreferencesOption *option, int *errCode) +{ + int err = OH_Preferences_ErrCode::PREFERENCES_OK; + if (option == nullptr || option->fileName.empty() || + !NDKPreferencesUtils::PreferencesStructValidCheck( + option->cid, PreferencesNdkStructId::PREFERENCES_OH_OPTION_CID) || + errCode == nullptr) { + LOG_ERROR("open preference cfg error, option is null: %{public}d, fileName is null: %{public}d, " + "errCode is null: %{public}d, err:%{public}d", + (option == nullptr), (option == nullptr) ? 1 : option->fileName.empty(), (errCode == nullptr), + OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM); + if (errCode != nullptr) { + *errCode = OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM; + } return nullptr; } - OHOS::NativePreferences::Options nativeOptions(std::string(options->filePath), std::string(options->bundleName), - std::string(options->dataGroupId), true); + auto dirRes = GetPreferencesDir(option); + if (dirRes.first != OH_Preferences_ErrCode::PREFERENCES_OK) { + *errCode = dirRes.first; + return nullptr; + } + std::string filePath = dirRes.second + "/" + option->GetFileName(); - std::shared_ptr store = - OHOS::NativePreferences::PreferencesHelper::GetPreferences(nativeOptions, *errCode); - *errCode = ConvertorErrorCode::NativeErrToNdk(*errCode); + OHOS::NativePreferences::Options nativeOptions(filePath, option->GetBundleName(), + option->GetDataGroupId(), true); - if (store == nullptr) { - LOG_ERROR("Get Preferences Store failed %{public}s", - OHOS::NativePreferences::ExtractFileName(nativeOptions.filePath).c_str()); + std::shared_ptr innerPreferences= + OHOS::NativePreferences::PreferencesHelper::GetPreferences(nativeOptions, err); + err = ConvertorErrorCode::NativeErrToNdk(err); + *errCode = err; + if (innerPreferences== nullptr || err != OH_Preferences_ErrCode::PREFERENCES_OK) { + LOG_ERROR("Get native Preferences failed: %{public}s, errcode: %{public}d", + OHOS::NativePreferences::ExtractFileName(nativeOptions.filePath).c_str(), err); return nullptr; } - OH_PreferencesImpl *spStore = new(std::nothrow) OH_PreferencesImpl(store); - spStore->SetPreferencesStoreFilePath(std::string(options->filePath)); + OH_PreferencesImpl *preferenceImpl = new (std::nothrow) OH_PreferencesImpl(innerPreferences); + if (preferenceImpl == nullptr) { + LOG_ERROR("new impl object failed"); + *errCode = OH_Preferences_ErrCode::PREFERENCES_ERROR_MALLOC; + return nullptr; + } + preferenceImpl->SetPreferencesStoreFilePath(filePath); + preferenceImpl->cid = PreferencesNdkStructId::PREFERENCES_OH_PREFERENCES_CID; + return static_cast(preferenceImpl); +} - return spStore; +static OH_PreferencesImpl *GetPreferencesImpl(OH_Preferences *preference) +{ + if (preference == nullptr || + !NDKPreferencesUtils::PreferencesStructValidCheck( + preference->cid, PreferencesNdkStructId::PREFERENCES_OH_PREFERENCES_CID)) { + LOG_ERROR("preference invalid, is null: %{public}d", preference == nullptr); + return nullptr; + } + return static_cast(preference); } -static OH_PreferencesImpl *GetPreferencesImpl(OH_Preferences *store) +static std::shared_ptr GetNativePreferencesFromOH(OH_Preferences *preference) { - if (store == nullptr) { - LOG_ERROR("store invalid, wichi is null"); + auto preferencesImpl = GetPreferencesImpl(preference); + if (preferencesImpl == nullptr || + !NDKPreferencesUtils::PreferencesStructValidCheck( + preference->cid, PreferencesNdkStructId::PREFERENCES_OH_PREFERENCES_CID)) { + LOG_ERROR("preferences is null: %{public}d when get native preferences from ohPreferences", + (preferencesImpl == nullptr)); + return nullptr; + } + std::shared_ptr innerPreferences= preferencesImpl->GetNativePreferences(); + if (innerPreferences== nullptr) { + LOG_ERROR("preference not open yet"); return nullptr; } - return static_cast(store); + return innerPreferences; } void OH_PreferencesImpl::SetPreferencesStoreFilePath(const std::string &filePath) @@ -86,18 +158,18 @@ int OH_Preferences_Close(OH_Preferences *preference) LOG_ERROR("preferences close failed, preferences is null"); return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM; } - - std::shared_ptr nativePreferences = preferencesImpl->GetNativePreferences(); - if (nativePreferences == nullptr) { + std::shared_ptr innerPreferences= preferencesImpl->GetNativePreferences(); + if (innerPreferences== nullptr) { LOG_ERROR("preference not open yet"); return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM; } - nativePreferences->FlushSync(); + + innerPreferences->FlushSync(); int errCode = OHOS::NativePreferences::PreferencesHelper::RemovePreferencesFromCache( preferencesImpl->GetPreferencesStoreFilePath()); if (errCode != OHOS::NativePreferences::E_OK) { - LOG_ERROR("preference close store failed: %{public}d", errCode); + LOG_ERROR("preference close failed: %{public}d", errCode); return ConvertorErrorCode::NativeErrToNdk(errCode); } delete preferencesImpl; @@ -106,24 +178,27 @@ int OH_Preferences_Close(OH_Preferences *preference) int OH_Preferences_GetInt(OH_Preferences *preference, const char *key, int *value) { - auto preferencesImpl = GetPreferencesImpl(preference); - if (preferencesImpl == nullptr || key == nullptr) { - LOG_ERROR("get int failed, preference is null: %{public}d, key is null: %{public}d", - (preferencesImpl == nullptr), (key == nullptr)); + std::shared_ptr innerPreferences= GetNativePreferencesFromOH(preference); + if (innerPreferences== nullptr || key == nullptr || value == nullptr) { + LOG_ERROR("get int failed, preference not open yet: %{public}d, key is null: %{public}d, " + "value is null: %{public}d, err: %{public}d", (innerPreferences== nullptr), (key == nullptr), + (value == nullptr), OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM); return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM; } - std::shared_ptr nativePreferences = preferencesImpl->GetNativePreferences(); - if (nativePreferences == nullptr) { - LOG_ERROR("preference not open yet"); - return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM; + auto res = innerPreferences->GetValue(key, OHOS::NativePreferences::PreferencesValue()); + if (res.first != OHOS::NativePreferences::E_OK) { + LOG_ERROR("Get Int failed, %{public}d", res.first); + return ConvertorErrorCode::NativeErrToNdk(res.first); } - auto res = nativePreferences->GetValue(key, OHOS::NativePreferences::PreferencesValue()); if (res.second.IsInt()) { *value = (int)(res.second); } else { LOG_ERROR("Get Int failed, value's type is not int"); + if (res.first == OHOS::NativePreferences::E_OK) { + return OH_Preferences_ErrCode::PREFERENCES_ERROR_KEY_NOT_FOUND; + } } return ConvertorErrorCode::NativeErrToNdk(res.first); @@ -132,35 +207,52 @@ int OH_Preferences_GetInt(OH_Preferences *preference, const char *key, int *valu int OH_Preferences_GetString(OH_Preferences *preference, const char *key, char **value, uint32_t *valueLen) { - auto preferencesImpl = GetPreferencesImpl(preference); - if (preferencesImpl == nullptr || key == nullptr) { - LOG_ERROR("get string failed, preference is null: %{public}d, key is null: %{public}d", - (preferencesImpl == nullptr), (key == nullptr)); + std::shared_ptr innerPreferences= GetNativePreferencesFromOH(preference); + if (innerPreferences== nullptr || key == nullptr || value == nullptr || valueLen == nullptr) { + LOG_ERROR("get str failed, preference not open yet: %{public}d, key is null: %{public}d, " + "value is null: %{public}d, valueLen is null: %{public}d, err: %{public}d", + (innerPreferences== nullptr), (key == nullptr), (value == nullptr), (valueLen == nullptr), + OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM); return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM; } - std::shared_ptr nativePreferences = preferencesImpl->GetNativePreferences(); - if (nativePreferences == nullptr) { - LOG_ERROR("preference not open yet"); - return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM; + auto res = innerPreferences->GetValue(key, OHOS::NativePreferences::PreferencesValue()); + if (res.first != OHOS::NativePreferences::E_OK) { + LOG_ERROR("Get string failed, %{public}d", res.first); + return ConvertorErrorCode::NativeErrToNdk(res.first); } - auto res = nativePreferences->GetValue(key, OHOS::NativePreferences::PreferencesValue()); if (res.second.IsString()) { std::string str = (std::string)(res.second); - void *ptr = malloc(str.size() + 1); // free by caller + size_t strLen = str.size(); + if (strLen >= SIZE_MAX) { + LOG_ERROR(" string length overlimit: %{public}zu", strLen); + return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM; + } + void *ptr = malloc(strLen + 1); // free by caller if (ptr == nullptr) { LOG_ERROR("malloc failed when get string, errno: %{public}d", errno); return OH_Preferences_ErrCode::PREFERENCES_ERROR_MALLOC; } *value = (char *)ptr; - for (size_t i = 0; i < str.size() + 1; i++) { - (*value)[i] = (char)str[i]; + int sysErr = memset_s(*value, (strLen + 1), 0, (strLen + 1)); + if (sysErr != EOK) { + LOG_ERROR("memset failed when get string, errCode: %{public}d", sysErr); + } + if (strLen > 0) { + sysErr = memcpy_s(*value, strLen, str.c_str(), strLen); + if (sysErr != EOK) { + LOG_ERROR("memcpy failed when get string, errCode: %{public}d", sysErr); + free(ptr); + return OH_Preferences_ErrCode::PREFERENCES_ERROR_MALLOC; + } } - (*value)[str.size()] = '\0'; - *valueLen = str.size() + 1; + *valueLen = strLen + 1; } else { - LOG_ERROR("Get string failed, value's type is not string"); + LOG_ERROR("Get string failed, value's type is not string, err: %{public}d", res.first); + if (res.first == OHOS::NativePreferences::E_OK) { + return OH_Preferences_ErrCode::PREFERENCES_ERROR_KEY_NOT_FOUND; + } } return ConvertorErrorCode::NativeErrToNdk(res.first); @@ -177,23 +269,27 @@ void OH_Preferences_FreeString(char *string) int OH_Preferences_GetBool(OH_Preferences *preference, const char *key, bool *value) { - auto preferencesImpl = GetPreferencesImpl(preference); - if (preferencesImpl == nullptr || key == nullptr) { - LOG_ERROR("get bool failed, preference is null: %{public}d, key is null: %{public}d", - (preferencesImpl == nullptr), (key == nullptr)); + std::shared_ptr innerPreferences= GetNativePreferencesFromOH(preference); + if (innerPreferences== nullptr || key == nullptr || value == nullptr) { + LOG_ERROR("get bool failed, preference not open yet: %{public}d, key is null: %{public}d, " + "value is null: %{public}d, err: %{public}d", (innerPreferences== nullptr), (key == nullptr), + (value == nullptr), OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM); return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM; } - std::shared_ptr nativePreferences = preferencesImpl->GetNativePreferences(); - if (nativePreferences == nullptr) { - LOG_ERROR("preference not open yet"); - return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM; + + auto res = innerPreferences->GetValue(key, OHOS::NativePreferences::PreferencesValue()); + if (res.first != OHOS::NativePreferences::E_OK) { + LOG_ERROR("Get bool failed, %{public}d", res.first); + return ConvertorErrorCode::NativeErrToNdk(res.first); } - auto res = nativePreferences->GetValue(key, OHOS::NativePreferences::PreferencesValue()); if (res.second.IsBool()) { *value = (bool)(res.second); } else { - LOG_ERROR("Get bool failed, value's type is not bool"); + LOG_ERROR("Get bool failed, value's type is not bool, err: %{public}d", res.first); + if (res.first == OHOS::NativePreferences::E_OK) { + return OH_Preferences_ErrCode::PREFERENCES_ERROR_KEY_NOT_FOUND; + } } return ConvertorErrorCode::NativeErrToNdk(res.first); @@ -201,176 +297,161 @@ int OH_Preferences_GetBool(OH_Preferences *preference, const char *key, bool *va int OH_Preferences_SetInt(OH_Preferences *preference, const char *key, int value) { - auto preferencesImpl = GetPreferencesImpl(preference); - if (preferencesImpl == nullptr || key == nullptr) { - LOG_ERROR("set int failed, preference is null: %{public}d, key is null: %{public}d", - (preferencesImpl == nullptr), (key == nullptr)); + std::shared_ptr innerPreferences= GetNativePreferencesFromOH(preference); + if (innerPreferences== nullptr || key == nullptr) { + LOG_ERROR("set int failed, preference not open yet: %{public}d, key is null: %{public}d, err: %{public}d", + (innerPreferences== nullptr), (key == nullptr), OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM); return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM; } - std::shared_ptr nativePreferences = preferencesImpl->GetNativePreferences(); - if (nativePreferences == nullptr) { - LOG_ERROR("preference not open yet"); - return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM; - } - int errCode = nativePreferences->PutInt(key, value); + + int errCode = innerPreferences->PutInt(key, value); if (errCode != OHOS::NativePreferences::E_OK) { - LOG_ERROR("preference put int failed"); + LOG_ERROR("preference put int failed, err: %{public}d", errCode); } return ConvertorErrorCode::NativeErrToNdk(errCode); } int OH_Preferences_SetBool(OH_Preferences *preference, const char *key, bool value) { - auto preferencesImpl = GetPreferencesImpl(preference); - if (preferencesImpl == nullptr || key == nullptr) { - LOG_ERROR("set bool failed, preference is null: %{public}d, key is null: %{public}d", - (preferencesImpl == nullptr), (key == nullptr)); + std::shared_ptr innerPreferences= GetNativePreferencesFromOH(preference); + if (innerPreferences== nullptr || key == nullptr) { + LOG_ERROR("set bool failed, preference not open yet: %{public}d, key is null: %{public}d, err: %{public}d", + (innerPreferences== nullptr), (key == nullptr), OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM); return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM; } - std::shared_ptr nativePreferences = preferencesImpl->GetNativePreferences(); - if (nativePreferences == nullptr) { - LOG_ERROR("preference not open yet"); - return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM; - } - int errCode = nativePreferences->PutBool(key, value); + int errCode = innerPreferences->PutBool(key, value); if (errCode != OHOS::NativePreferences::E_OK) { - LOG_ERROR("preference put bool failed"); + LOG_ERROR("preference put bool failed, err: %{public}d", errCode); } return ConvertorErrorCode::NativeErrToNdk(errCode); } int OH_Preferences_SetString(OH_Preferences *preference, const char *key, const char *value) { - auto preferencesImpl = GetPreferencesImpl(preference); - if (preferencesImpl == nullptr || key == nullptr) { - LOG_ERROR("set string failed, preference is null: %{public}d, key is null: %{public}d", - (preferencesImpl == nullptr), (key == nullptr)); + std::shared_ptr innerPreferences= GetNativePreferencesFromOH(preference); + if (innerPreferences== nullptr || key == nullptr || value == nullptr) { + LOG_ERROR("set str failed, preference not open yet: %{public}d, key is null: %{public}d, " + "value is null: %{public}d, err: %{public}d", (innerPreferences== nullptr), (key == nullptr), + (value == nullptr), OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM); return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM; } - std::shared_ptr nativePreferences = preferencesImpl->GetNativePreferences(); - if (nativePreferences == nullptr) { - LOG_ERROR("preference not open yet"); - return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM; - } - int errCode = nativePreferences->PutString(key, value); + int errCode = innerPreferences->PutString(key, value); if (errCode != OHOS::NativePreferences::E_OK) { - LOG_ERROR("preference put string failed"); + LOG_ERROR("preference put string failed, err: %{public}d", errCode); } return ConvertorErrorCode::NativeErrToNdk(errCode); } int OH_Preferences_Delete(OH_Preferences *preference, const char *key) { - auto preferencesImpl = GetPreferencesImpl(preference); - if (preferencesImpl == nullptr || key == nullptr) { - LOG_ERROR("delete failed, preference is null: %{public}d, key is null: %{public}d", - (preferencesImpl == nullptr), (key == nullptr)); + std::shared_ptr innerPreferences= GetNativePreferencesFromOH(preference); + if (innerPreferences== nullptr || key == nullptr) { + LOG_ERROR("delete failed, preference not open yet: %{public}d, key is null: %{public}d, err: %{public}d", + (innerPreferences== nullptr), (key == nullptr), OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM); return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM; } - std::shared_ptr nativePreferences = preferencesImpl->GetNativePreferences(); - if (nativePreferences == nullptr) { - LOG_ERROR("preference not open yet"); - return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM; - } - int errCode = nativePreferences->Delete(key); + int errCode = innerPreferences->Delete(key); if (errCode != OHOS::NativePreferences::E_OK) { - LOG_ERROR("preference delete value failed"); + LOG_ERROR("preference delete value failed, err: %{public}d", errCode); } return ConvertorErrorCode::NativeErrToNdk(errCode); } int OH_Preferences_RegisterDataObserver(OH_Preferences *preference, void *context, - const OH_PreferencesDataObserver *observer, const char *keys[], uint32_t keyCount) + OH_PreferencesDataObserver observer, const char *keys[], uint32_t keyCount) { auto preferencesImpl = GetPreferencesImpl(preference); - if (preferencesImpl == nullptr || observer == nullptr) { - LOG_ERROR("register failed, invalid agrs, preference is null ? %{public}d, observer is null ? %{public}d", - (preferencesImpl == nullptr), (observer == nullptr)); + if (preferencesImpl == nullptr || observer == nullptr || keys == nullptr) { + LOG_ERROR("register failed, sp is null ? %{public}d, obs is null ? %{public}d, " + "keys is null: %{public}d, err: %{public}d", (preferencesImpl == nullptr), (observer == nullptr), + (keys == nullptr), OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM); return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM; } - if (keyCount == 0) { - return preferencesImpl->RegisterDataObserver(observer, context); - } + std::vector keysVec; for (uint32_t i = 0; i < keyCount; i++) { keysVec.push_back(keys[i]); } - return preferencesImpl->RegisterDataObserver(observer, context, keysVec); + return ConvertorErrorCode::NativeErrToNdk(preferencesImpl->RegisterDataObserver(observer, context, keysVec)); } int OH_Preferences_UnregisterDataObserver(OH_Preferences *preference, void *context, - const OH_PreferencesDataObserver *observer, const char *keys[], uint32_t keyCount) + OH_PreferencesDataObserver observer, const char *keys[], uint32_t keyCount) { auto preferencesImpl = GetPreferencesImpl(preference); - if (preferencesImpl == nullptr || observer == nullptr) { - LOG_ERROR("unregister failed, invalid agrs, preference is null ? %{public}d, observer is null ? %{public}d", - (preferencesImpl == nullptr), (observer == nullptr)); + if (preferencesImpl == nullptr || observer == nullptr || keys == nullptr) { + LOG_ERROR("unregister failed, sp is null ? %{public}d, obs is null ? %{public}d, " + "keys is null: %{public}d, err: %{public}d", (preferencesImpl == nullptr), (observer == nullptr), + (keys == nullptr), OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM); return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM; } - if (keyCount == 0) { - return preferencesImpl->UnRegisterDataObserver(observer); - } std::vector keysVec; for (uint32_t i = 0; i < keyCount; i++) { keysVec.push_back(keys[i]); } - return preferencesImpl->UnRegisterDataObserver(observer, keysVec); + return ConvertorErrorCode::NativeErrToNdk(preferencesImpl->UnregisterDataObserver(observer, context, keysVec)); } int OH_PreferencesImpl::RegisterDataObserver( - const OH_PreferencesDataObserver *observer, void *context, const std::vector &keys) + OH_PreferencesDataObserver observer, void *context, const std::vector &keys) { std::unique_lock writeLock(obsMutex_); auto ndkObserver = std::make_shared(observer, context); int errCode = preferences_->RegisterDataObserver(ndkObserver, keys); if (errCode != OHOS::NativePreferences::E_OK) { - LOG_ERROR("register failed"); + LOG_ERROR("register failed, err: %{public}d", errCode); } else { - dataObservers_.emplace_back(std::move(ndkObserver)); + dataObservers_.emplace_back(std::make_pair(std::move(ndkObserver), context)); } return ConvertorErrorCode::NativeErrToNdk(errCode); } -NDKPreferencesObserver::NDKPreferencesObserver(const OH_PreferencesDataObserver *observer, void *context) +NDKPreferencesObserver::NDKPreferencesObserver(OH_PreferencesDataObserver observer, void *context) : dataObserver_(observer), context_(context) {} +inline void FreePairValue(OH_PreferencesPair *pairs, size_t count) +{ + for (size_t i = 0; i < count; i++) { + delete pairs[i].value; + } +} + void NDKPreferencesObserver::OnChange(const std::map &records) { + if (dataObserver_ == nullptr) { + LOG_ERROR("failed to trigger change, data observer is null"); + return; + } auto count = records.size(); if (count == 0) { return; } - OH_PreferencesPair *pairs = new OH_PreferencesPair[count]; + OH_PreferencesPair *pairs = new (std::nothrow) OH_PreferencesPair[count]; if (pairs == nullptr) { - LOG_ERROR("malloc pairs failed when on change, count: %{public}u, errno:%{public}d", count, errno); + LOG_ERROR("malloc pairs failed when on change, count: %{public}d, errno:%{public}d", static_cast(count), + errno); return; } int i = 0; for (const auto &[key, value] : records) { - OH_PreferencesValueImpl *valueImpl = new OH_PreferencesValueImpl(); - if (value.IsInt()) { - valueImpl->type_ = Preference_ValueType::TYPE_INT; - valueImpl->value_ = value; - } else if (value.IsBool()) { - valueImpl->type_ = Preference_ValueType::TYPE_BOOL; - valueImpl->value_ = value; - } else if (value.IsString()) { - valueImpl->type_ = Preference_ValueType::TYPE_STRING; - valueImpl->value_ = value; - } else { - valueImpl->type_ = Preference_ValueType::TYPE_NULL; + OH_PreferencesValueImpl *valueImpl = new (std::nothrow) OH_PreferencesValueImpl(); + if (valueImpl == nullptr) { + LOG_ERROR("new value object failed"); + FreePairValue(pairs, i); + delete []pairs; } - pairs[i++] = OH_PreferencesPair { key.c_str(), valueImpl }; - } - (*dataObserver_)(context_, pairs, count); - for (size_t i = 0; i < count; i++) { - delete pairs[i].value; + valueImpl->cid = PreferencesNdkStructId::PREFERENCES_OH_VALUE_CID; + valueImpl->value_ = value; + pairs[i++] = OH_PreferencesPair { PreferencesNdkStructId::PREFERENCES_OH_PAIR_CID, key.c_str(), + static_cast(valueImpl), count}; } + (dataObserver_)(context_, pairs, count); + FreePairValue(pairs, count); delete []pairs; } @@ -378,28 +459,32 @@ void NDKPreferencesObserver::OnChange(const std::string &key) { } -int OH_PreferencesImpl::UnRegisterDataObserver(const OH_PreferencesDataObserver *observer, +int OH_PreferencesImpl::UnregisterDataObserver(OH_PreferencesDataObserver observer, void *context, const std::vector &keys) { std::unique_lock writeLock(obsMutex_); for (size_t i = 0; i < dataObservers_.size(); i++) { - if (!(*dataObservers_[i] == observer)) { - i++; + if (!dataObservers_[i].first->ObserverCompare(observer) || dataObservers_[i].second != context) { continue; } - int errCode = preferences_->UnRegisterDataObserver(dataObservers_[i], keys); + + int errCode = preferences_->UnRegisterDataObserver(dataObservers_[i].first, keys); if (errCode != OHOS::NativePreferences::E_OK) { - LOG_ERROR("un register observer failed"); + LOG_ERROR("un register observer failed, err: %{public}d", errCode); return ConvertorErrorCode::NativeErrToNdk(errCode); } + if (keys.empty()) { + dataObservers_[i] = { nullptr, nullptr }; + dataObservers_.erase(dataObservers_.begin() + i); + } } return OH_Preferences_ErrCode::PREFERENCES_OK; } -bool NDKPreferencesObserver::operator==(const OH_PreferencesDataObserver *other) +bool NDKPreferencesObserver::ObserverCompare(OH_PreferencesDataObserver other) { if (other == nullptr) { return false; } - return &other == &dataObserver_; + return other == dataObserver_; } diff --git a/preferences/frameworks/ndk/src/oh_preferences_option.cpp b/preferences/frameworks/ndk/src/oh_preferences_option.cpp index 999ed730313009e5fbb7b1e7f59adb2b57086643..e25e68ea55b9e6fbb12cd2e4cd3257b87ac7be81 100644 --- a/preferences/frameworks/ndk/src/oh_preferences_option.cpp +++ b/preferences/frameworks/ndk/src/oh_preferences_option.cpp @@ -21,31 +21,105 @@ using namespace OHOS::PreferencesNdk; +int OH_PreferencesOption::SetFileName(const std::string &str) +{ + std::unique_lock writeLock(opMutex_); + if (str.empty()) { + LOG_ERROR("Set file path failed, str is empty"); + return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM; + } + fileName = str; + return OH_Preferences_ErrCode::PREFERENCES_OK; +} + +void OH_PreferencesOption::SetBundleName(const std::string &str) +{ + std::unique_lock writeLock(opMutex_); + bundleName = str; +} + +void OH_PreferencesOption::SetDataGroupId(const std::string &str) +{ + std::unique_lock writeLock(opMutex_); + dataGroupId = str; +} + +std::string OH_PreferencesOption::GetFileName() +{ + return fileName; +} + +std::string OH_PreferencesOption::GetBundleName() +{ + return bundleName; +} + +std::string OH_PreferencesOption::GetDataGroupId() +{ + return dataGroupId; +} + OH_PreferencesOption* OH_PreferencesOption_Create(void) { - return new (std::nothrow) OH_PreferencesOption(); + OH_PreferencesOption* option = new (std::nothrow) OH_PreferencesOption(); + if (option == nullptr) { + LOG_ERROR("new option object failed"); + return nullptr; + } + option->cid = PreferencesNdkStructId::PREFERENCES_OH_OPTION_CID; + return option; } -int OH_PreferencesOption_SetFilePath(OH_PreferencesOption *option, const char *filePath) +int OH_PreferencesOption_SetFileName(OH_PreferencesOption *option, const char *fileName) { - option->filePath = std::string(filePath); - return OH_Preferences_ErrCode::PREFERENCES_OK; + if (option == nullptr || fileName == nullptr || + !NDKPreferencesUtils::PreferencesStructValidCheck( + option->cid, PreferencesNdkStructId::PREFERENCES_OH_OPTION_CID)) { + LOG_ERROR("set option's file path failed, option is null: %{public}d, fileName is null: %{public}d, " + "err: %{public}d", (option == nullptr), (fileName == nullptr), + OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM); + return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM; + } + return option->SetFileName(std::string(fileName)); } int OH_PreferencesOption_SetBundleName(OH_PreferencesOption *option, const char *bundleName) { - option->bundleName = std::string(bundleName); + if (option == nullptr || bundleName == nullptr || + !NDKPreferencesUtils::PreferencesStructValidCheck( + option->cid, PreferencesNdkStructId::PREFERENCES_OH_OPTION_CID)) { + LOG_ERROR("set option's bundleName failed, option is null: %{public}d, " + "bundleName is null: %{public}d, errCode: %{public}d", (option == nullptr), + (bundleName == nullptr), OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM); + return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM; + } + option->SetBundleName(std::string(bundleName)); return OH_Preferences_ErrCode::PREFERENCES_OK; } int OH_PreferencesOption_SetDataGroupId(OH_PreferencesOption *option, const char *dataGroupId) { - option->dataGroupId = std::string(dataGroupId); + if (option == nullptr || dataGroupId == nullptr || + !NDKPreferencesUtils::PreferencesStructValidCheck( + option->cid, PreferencesNdkStructId::PREFERENCES_OH_OPTION_CID)) { + LOG_ERROR("set option's dataGroupId failed, option is null: %{public}d, " + "dataGroupId is null: %{public}d, errCode: %{public}d", (option == nullptr), + (dataGroupId == nullptr), OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM); + return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM; + } + option->SetDataGroupId(std::string(dataGroupId)); return OH_Preferences_ErrCode::PREFERENCES_OK; } int OH_PreferencesOption_Destroy(OH_PreferencesOption* option) { + if (option == nullptr || + !NDKPreferencesUtils::PreferencesStructValidCheck( + option->cid, PreferencesNdkStructId::PREFERENCES_OH_OPTION_CID)) { + LOG_ERROR("destroy option failed, option is null: %{public}d, errCode: %{public}d", + (option == nullptr), OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM); + return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM; + } delete option; return OH_Preferences_ErrCode::PREFERENCES_OK; } diff --git a/preferences/frameworks/ndk/src/oh_preferences_value.cpp b/preferences/frameworks/ndk/src/oh_preferences_value.cpp index 44bcdaa049b0ecdd339786dba3fd728ea5b1c97c..509c9567955d4c06694695dec46f1e35ba5973ee 100644 --- a/preferences/frameworks/ndk/src/oh_preferences_value.cpp +++ b/preferences/frameworks/ndk/src/oh_preferences_value.cpp @@ -18,32 +18,32 @@ #include "oh_preferences_err_code.h" #include "oh_preferences_impl.h" #include "oh_preferences_value_impl.h" +#include "securec.h" using namespace OHOS::PreferencesNdk; static OH_PreferencesValueImpl *GetSelf(const OH_PreferencesValue *value) { - if (value == nullptr) { - LOG_ERROR("preferences_value invalid, which is null"); + if (value == nullptr || + !NDKPreferencesUtils::PreferencesStructValidCheck( + value->cid, PreferencesNdkStructId::PREFERENCES_OH_VALUE_CID)) { + LOG_ERROR("preferences_value invalid, value is null: %{public}d", (value == nullptr)); return nullptr; } OH_PreferencesValue *prefValue = const_cast(value); - OH_PreferencesValueImpl *self = static_cast(prefValue); - if (self->value_.IsInt()) { - self->type_ = Preference_ValueType::TYPE_INT; - } else if (self->value_.IsBool()) { - self->type_ = Preference_ValueType::TYPE_BOOL; - } else if (self->value_.IsString()) { - self->type_ = Preference_ValueType::TYPE_STRING; - } else { - return nullptr; - } - return self; + return static_cast(prefValue); } const char *OH_PreferencesPair_GetKey(const OH_PreferencesPair *pairs, uint32_t index) { - if (pairs == nullptr) { + if (pairs == nullptr || index >= pairs[0].maxIndex) { + LOG_ERROR("failed to get key from pair, pairs is null or index over limit"); + return nullptr; + } + + if (!NDKPreferencesUtils::PreferencesStructValidCheck( + pairs[index].cid, PreferencesNdkStructId::PREFERENCES_OH_PAIR_CID)) { + LOG_ERROR("cid error when get key from pair, cid: %{public}ld", static_cast(pairs[index].cid)); return nullptr; } return pairs[index].key; @@ -51,7 +51,14 @@ const char *OH_PreferencesPair_GetKey(const OH_PreferencesPair *pairs, uint32_t const OH_PreferencesValue *OH_PreferencesPair_GetPreferencesValue(const OH_PreferencesPair *pairs, uint32_t index) { - if (pairs == nullptr) { + if (pairs == nullptr || index >= pairs[0].maxIndex) { + LOG_ERROR("failed to get value from pair, pairs is null or index over limit"); + return nullptr; + } + + if (!NDKPreferencesUtils::PreferencesStructValidCheck( + pairs[index].cid, PreferencesNdkStructId::PREFERENCES_OH_PAIR_CID)) { + LOG_ERROR("cid error when get value from pair, cid: %{public}ld", static_cast(pairs[index].cid)); return nullptr; } return pairs[index].value; @@ -62,63 +69,90 @@ Preference_ValueType OH_PreferencesValue_GetValueType(const OH_PreferencesValue auto self = GetSelf(object); if (self == nullptr) { LOG_ERROR("Preferences GetValueType failed, object is null"); - return Preference_ValueType::TYPE_NULL; + return Preference_ValueType::PREFERENCE_TYPE_NULL; } - return self->type_; + if (self->value_.IsInt()) { + return Preference_ValueType::PREFERENCE_TYPE_INT; + } else if (self->value_.IsBool()) { + return Preference_ValueType::PREFERENCE_TYPE_BOOL; + } else if (self->value_.IsString()) { + return Preference_ValueType::PREFERENCE_TYPE_STRING; + } + return Preference_ValueType::PREFERENCE_TYPE_NULL; } int OH_PreferencesValue_GetInt(const OH_PreferencesValue *object, int *value) { auto self = GetSelf(object); - if (self == nullptr) { - LOG_ERROR("Preferences GetInt failed, object is null"); + if (self == nullptr || value == nullptr) { + LOG_ERROR("Preferences GetInt failed, object is null: %{public}d, value is null: %{public}d, err: %{public}d", + (self == nullptr), (value == nullptr), OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM); return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM; } - if (self->type_ == Preference_ValueType::TYPE_INT) { - *value = std::get(self->value_.value_); + if (self->value_.IsInt()) { + *value = (int)(self->value_); return OH_Preferences_ErrCode::PREFERENCES_OK; } - LOG_ERROR("Preferences GetInt failed, type: %{public}d", self->type_); - return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM; + LOG_ERROR("Preferences GetInt failed, type error, err: %{public}d", + OH_Preferences_ErrCode::PREFERENCES_ERROR_KEY_NOT_FOUND); + return OH_Preferences_ErrCode::PREFERENCES_ERROR_KEY_NOT_FOUND; } int OH_PreferencesValue_GetBool(const OH_PreferencesValue *object, bool *value) { auto self = GetSelf(object); - if (self == nullptr) { - LOG_ERROR("Preferences GetBool failed, object is null"); + if (self == nullptr || value == nullptr) { + LOG_ERROR("Preferences GetBool failed, object is null: %{public}d, value is null: %{public}d, err: %{public}d", + (self == nullptr), (self == nullptr), OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM); return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM; } - if (self->type_ == Preference_ValueType::TYPE_BOOL) { - *value = std::get(self->value_.value_); + if (self->value_.IsBool()) { + *value = (bool)(self->value_); return OH_Preferences_ErrCode::PREFERENCES_OK; } - LOG_ERROR("Preferences GetBool failed, type: %{public}d", self->type_); - return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM; + LOG_ERROR("Preferences GetBool failed, type error, err: %{public}d", + OH_Preferences_ErrCode::PREFERENCES_ERROR_KEY_NOT_FOUND); + return OH_Preferences_ErrCode::PREFERENCES_ERROR_KEY_NOT_FOUND; } int OH_PreferencesValue_GetString(const OH_PreferencesValue *object, char **value, uint32_t *valueLen) { auto self = GetSelf(object); - if (self == nullptr) { - LOG_ERROR("Preferences GetString failed, object is null"); + if (self == nullptr || value == nullptr || valueLen == nullptr) { + LOG_ERROR("Preferences GetString failed, object is null: %{public}d, value is null: %{public}d, " + "valueLen is null: %{public}d, err: %{public}d", (self == nullptr), (value == nullptr), + (valueLen == nullptr), OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM); return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM; } - if (self->type_ == Preference_ValueType::TYPE_STRING) { + if (self->value_.IsString()) { std::string str = (std::string)(self->value_); - void *ptr = malloc(str.size() + 1); // free by caller + size_t strLen = str.size(); + if (strLen >= SIZE_MAX) { + LOG_ERROR("string length overlimit: %{public}zu", strLen); + return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM; + } + void *ptr = malloc(strLen + 1); // free by caller if (ptr == nullptr) { LOG_ERROR("malloc failed when value get string, errno: %{public}d", errno); return OH_Preferences_ErrCode::PREFERENCES_ERROR_MALLOC; } *value = (char *)ptr; - for (size_t i = 0; i < str.size() + 1; i++) { - (*value)[i] = (char)str[i]; + int sysErr = memset_s(*value, (strLen + 1), 0, (strLen + 1)); + if (sysErr != EOK) { + LOG_ERROR("memset failed when get string, errCode: %{public}d", sysErr); + } + if (strLen > 0) { + sysErr = memcpy_s(*value, strLen, str.c_str(), strLen); + if (sysErr != EOK) { + LOG_ERROR("memcpy failed when value get string, errCode: %{public}d", sysErr); + free(ptr); + return OH_Preferences_ErrCode::PREFERENCES_ERROR_MALLOC; + } } - (*value)[str.size()] = '\0'; - *valueLen = str.size() + 1; + *valueLen = strLen + 1; return OH_Preferences_ErrCode::PREFERENCES_OK; } - LOG_ERROR("Preferences GetString failed, type: %{public}d", self->type_); - return OH_Preferences_ErrCode::PREFERENCES_ERROR_INVALID_PARAM; + LOG_ERROR("Preferences GetString failed, type error, err: %{public}d", + OH_Preferences_ErrCode::PREFERENCES_ERROR_KEY_NOT_FOUND); + return OH_Preferences_ErrCode::PREFERENCES_ERROR_KEY_NOT_FOUND; } diff --git a/preferences/interfaces/inner_api/include/preferences_errno.h b/preferences/interfaces/inner_api/include/preferences_errno.h index 245bb79e8378f85eb4d13948ab6fb0e46211bd3e..1ea6ca2d7718a6b7362d3f2351a0af6e1d61acef 100644 --- a/preferences/interfaces/inner_api/include/preferences_errno.h +++ b/preferences/interfaces/inner_api/include/preferences_errno.h @@ -154,6 +154,10 @@ constexpr int E_OBSERVER_RESERVE = (E_BASE + 20); */ constexpr int E_ALREADY_CLOSED = (E_BASE + 21); +/** +* @brief The error code is used to indicate that database has been closed. +*/ +constexpr int E_NO_DATA = (E_BASE + 22); } // namespace NativePreferences } // namespace OHOS #endif // PREFERENCES_ERRNO_H diff --git a/preferences/interfaces/ndk/BUILD.gn b/preferences/interfaces/ndk/BUILD.gn index 776788d8aa293b7fc5a38756c0908fa33bde1109..02473bbd824a4385599f9fe9e6caf879bee095d0 100644 --- a/preferences/interfaces/ndk/BUILD.gn +++ b/preferences/interfaces/ndk/BUILD.gn @@ -36,7 +36,7 @@ if (is_ohos) { "${preferences_ndk_path}/src/oh_preferences_option.cpp", "${preferences_ndk_path}/src/oh_preferences_value.cpp", ] - ohos_shared_library("ohpreferences") { + ohos_shared_library("libohpreferences") { branch_protector_ret = "pac_ret" sanitize = { cfi = true @@ -57,39 +57,15 @@ if (is_ohos) { configs = [ ":ndk_preferences_config" ] external_deps = [ - "bounds_checking_function:libsec_shared", + "ability_runtime:app_context", "c_utils:utils", "hilog:libhilog", ] public_configs = [ ":ndk_preferences_public_config" ] relative_install_dir = "ndk" part_name = "preferences" + output_name = "ohpreferences" subsystem_name = "distributeddatamgr" output_extension = "so" } - - ohos_static_library("ohpreferences_static") { - branch_protector_ret = "pac_ret" - sanitize = { - boundary_sanitize = true - ubsan = true - cfi = true - cfi_cross_dso = true - debug = false - } - deps = - [ "${preferences_base_path}/interfaces/inner_api:native_preferences" ] - sources = base_sources - - configs = [ ":ndk_preferences_config" ] - - external_deps = [ - "bounds_checking_function:libsec_shared", - "c_utils:utils", - "hilog:libhilog", - ] - public_configs = [ ":ndk_preferences_public_config" ] - part_name = "preferences" - subsystem_name = "distributeddatamgr" - } } diff --git a/preferences/interfaces/ndk/include/oh_preferences.h b/preferences/interfaces/ndk/include/oh_preferences.h index ea2d66ac8cd9c9600ffd03eea085fe2a9c700e08..c3a56fd957325706b955d94fa3568c5d8a7d1824 100644 --- a/preferences/interfaces/ndk/include/oh_preferences.h +++ b/preferences/interfaces/ndk/include/oh_preferences.h @@ -39,7 +39,8 @@ #ifndef OH_PREFERENCES_H #define OH_PREFERENCES_H -#include +#include +#include #include "oh_preferences_value.h" #include "oh_preferences_option.h" @@ -110,7 +111,7 @@ int OH_Preferences_Close(OH_Preferences *preference); * {@link PREFERENCES_ERROR_INVALID_PARAM} indicates invalid args are passed in. * {@link PREFERENCES_ERROR_STORAGE} indicates an storage error. * {@link PREFERENCES_ERROR_MALLOC} indicates an malloc memory error. - * {@link PREFERENCES_ERROR_KEY_NOT_FOUND} indicates key is not exist. + * {@link PREFERENCES_ERROR_KEY_NOT_FOUND} indicates the key does not exist. * @see OH_Preferences. * @since 13 */ @@ -127,7 +128,7 @@ int OH_Preferences_GetInt(OH_Preferences *preference, const char *key, int *valu * {@link PREFERENCES_ERROR_INVALID_PARAM} indicates invalid args are passed in. * {@link PREFERENCES_ERROR_STORAGE} indicates an storage error. * {@link PREFERENCES_ERROR_MALLOC} indicates an malloc memory error. - * {@link PREFERENCES_ERROR_KEY_NOT_FOUND} indicates key is not exist. + * {@link PREFERENCES_ERROR_KEY_NOT_FOUND} indicates the key does not exist. * @see OH_Preferences. * @since 13 */ @@ -146,7 +147,7 @@ int OH_Preferences_GetBool(OH_Preferences *preference, const char *key, bool *va * {@link PREFERENCES_ERROR_INVALID_PARAM} indicates invalid args are passed in. * {@link PREFERENCES_ERROR_STORAGE} indicates an storage error. * {@link PREFERENCES_ERROR_MALLOC} indicates an malloc memory error. - * {@link PREFERENCES_ERROR_KEY_NOT_FOUND} indicates key is not exist. + * {@link PREFERENCES_ERROR_KEY_NOT_FOUND} indicates the key does not exist. * @see OH_Preferences. * @since 13 */ @@ -229,7 +230,7 @@ int OH_Preferences_Delete(OH_Preferences *preference, const char *key); * * @param preference Pointer to the target {@Link OH_Preferences} instance. * @param context Pointer to the context of the data observer. - * @param observer Pointer to the {@Link OH_PreferencesDataObserver} to register. + * @param observer the {@Link OH_PreferencesDataObserver} to register. * @param keys Pointer to the keys to observe. * @param keyCount Number of keys to observe. * @return Returns the status code of the execution. @@ -242,14 +243,14 @@ int OH_Preferences_Delete(OH_Preferences *preference, const char *key); * @since 13 */ int OH_Preferences_RegisterDataObserver(OH_Preferences *preference, void *context, - const OH_PreferencesDataObserver *observer, const char *keys[], uint32_t keyCount); + OH_PreferencesDataObserver observer, const char *keys[], uint32_t keyCount); /** * @brief Unregisters a data observer for a Preferences object. * * @param preference Pointer to the target {@Link OH_Preferences} instance. * @param context Pointer to the context of the data observer. - * @param observer Pointer to the {@Link OH_PreferencesDataObserver} to unregister. + * @param observer the {@Link OH_PreferencesDataObserver} to unregister. * @param keys Pointer to the keys observed. If this parameter is null, this API unregisters the listening for all keys. * @param keyCount Number of the keys. * @return Returns the status code of the execution. @@ -261,7 +262,7 @@ int OH_Preferences_RegisterDataObserver(OH_Preferences *preference, void *contex * @since 13 */ int OH_Preferences_UnregisterDataObserver(OH_Preferences *preference, void *context, - const OH_PreferencesDataObserver *observer, const char *keys[], uint32_t keyCount); + OH_PreferencesDataObserver observer, const char *keys[], uint32_t keyCount); #ifdef __cplusplus }; diff --git a/preferences/interfaces/ndk/include/oh_preferences_option.h b/preferences/interfaces/ndk/include/oh_preferences_option.h index 4b2d1d953d4c57bc0c3979a8ed6980aa5ee4dc9e..a8a25af9f55287456e3595803981a3c727390acf 100644 --- a/preferences/interfaces/ndk/include/oh_preferences_option.h +++ b/preferences/interfaces/ndk/include/oh_preferences_option.h @@ -39,7 +39,7 @@ #ifndef OH_PREFERENCES_OPTION_H #define OH_PREFERENCES_OPTION_H -#include +#include #ifdef __cplusplus extern "C" { @@ -66,14 +66,14 @@ OH_PreferencesOption *OH_PreferencesOption_Create(void); * @brief Sets the file path in an {@Link OH_PreferencesOption} instance. * * @param option Pointer to the target {@Link OH_PreferencesOption} instance. - * @param filePath Pointer to the file path to set. + * @param fileName Pointer to the file name to set. * @return Returns the status code of the execution. * {@link PREFERENCES_OK} success. * {@link PREFERENCES_ERROR_INVALID_PARAM} indicates invalid args are passed in. * @see OH_PreferencesOption. * @since 13 */ -int OH_PreferencesOption_SetFilePath(OH_PreferencesOption *option, const char *filePath); +int OH_PreferencesOption_SetFileName(OH_PreferencesOption *option, const char *fileName); /** * @brief Sets the bundle name in an {@Link OH_PreferencesOption} instance. diff --git a/preferences/interfaces/ndk/include/oh_preferences_value.h b/preferences/interfaces/ndk/include/oh_preferences_value.h index 5fd358f32346d13f6772961d6e747bd231edea4a..945e28fc62980fe1de55cd342a2f1eb33e3d2bb7 100644 --- a/preferences/interfaces/ndk/include/oh_preferences_value.h +++ b/preferences/interfaces/ndk/include/oh_preferences_value.h @@ -39,7 +39,8 @@ #ifndef OH_PREFERENCES_VALUE_H #define OH_PREFERENCES_VALUE_H -#include +#include +#include #ifdef __cplusplus extern "C" { @@ -54,23 +55,23 @@ typedef enum Preference_ValueType { /** * @brief Null. */ - TYPE_NULL = 0, + PREFERENCE_TYPE_NULL = 0, /** * @brief Int. */ - TYPE_INT, + PREFERENCE_TYPE_INT, /** * @brief boolean. */ - TYPE_BOOL, + PREFERENCE_TYPE_BOOL, /** * @brief String. */ - TYPE_STRING, + PREFERENCE_TYPE_STRING, /** * @brief end butt. */ - TYPE_BUTT + PREFERENCE_TYPE_BUTT } Preference_ValueType; /** @@ -116,7 +117,7 @@ const OH_PreferencesValue *OH_PreferencesPair_GetPreferencesValue(const OH_Prefe * * @param object Pointer to the target {@Link OH_PreferencesValue} instance. * @return Returns the value type obtained. - * {@link TYPE_NULL} indicates invalid args are passed in. + * {@link PREFERENCE_TYPE_NULL} indicates invalid args are passed in. * @see OH_PreferencesValue. * @since 13 */ diff --git a/preferences/preferences.gni b/preferences/preferences.gni index 3183a48812288a73bcd4d9b5a147fca06d6238d7..fd6114df1bf1b8ecad81447f5f7c65431612f140 100644 --- a/preferences/preferences.gni +++ b/preferences/preferences.gni @@ -22,3 +22,5 @@ preferences_native_path = "${preferences_base_path}/frameworks/native" preferences_innerapi_path = "${preferences_base_path}/interfaces/inner_api" preferences_ndk_path = "${preferences_base_path}/frameworks/ndk" + +preferences_interfaces_path = "${preferences_base_path}/interfaces" diff --git a/preferences/test/native/unittest/preferences_helper_test.cpp b/preferences/test/native/unittest/preferences_helper_test.cpp index 5f8ec60328ddd02880551ab31ba8cc88006bb2e5..4c68e22afc8a82a10e714b68e4d5ac68bf84bec7 100644 --- a/preferences/test/native/unittest/preferences_helper_test.cpp +++ b/preferences/test/native/unittest/preferences_helper_test.cpp @@ -134,4 +134,32 @@ HWTEST_F(PreferencesHelperTest, NativePreferencesHelperTest_004, TestSize.Level1 pref = PreferencesHelper::RemovePreferencesFromCache(""); EXPECT_EQ(pref, E_EMPTY_FILE_PATH); } + +/** + * @tc.name: NativePreferencesHelperTest_005 + * @tc.desc: error testcase of GetRealPath + * @tc.type: FUNC + */ +HWTEST_F(PreferencesHelperTest, NativePreferencesHelperTest_005, TestSize.Level1) +{ + Options option = Options("test300", "com.hmos.uttest", ""); + int errCode = E_OK; + std::shared_ptr preferences = PreferencesHelper::GetPreferences(option, errCode); + 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/preferences/test/native/unittest/preferences_xml_utils_test.cpp b/preferences/test/native/unittest/preferences_xml_utils_test.cpp index 7def6040f6f27248c9ece20ba3e59eeec1a0d2f6..987690ba816a871f90e775762d50df5799ad0b3f 100644 --- a/preferences/test/native/unittest/preferences_xml_utils_test.cpp +++ b/preferences/test/native/unittest/preferences_xml_utils_test.cpp @@ -421,4 +421,49 @@ HWTEST_F(PreferencesXmlUtilsTest, RenameToBrokenFileTest_001, TestSize.Level1) int ret = PreferencesHelper::DeletePreferences(fileName); EXPECT_EQ(ret, E_OK); } + +/** +* @tc.name: ReadSettingXmlTest_004 +* @tc.desc: RenameToBrokenFile testcase of PreferencesXmlUtils +* @tc.type: FUNC +*/ +HWTEST_F(PreferencesXmlUtilsTest, ReadSettingXmlTest_004, TestSize.Level1) +{ + std::string fileName = "/data/test/test01"; + // construct an unreadable file + std::ofstream oss(fileName); + oss << "corrupted"; + + std::ofstream ossBak(MakeFilePath(fileName, STR_BACKUP)); + ossBak << "corruptedBak"; + + std::vector settings; + bool res = PreferencesXmlUtils::ReadSettingXml(fileName, "", "", settings); + EXPECT_EQ(res, false); + + int ret = PreferencesHelper::DeletePreferences(fileName); + EXPECT_EQ(ret, E_OK); +} + +/** +* @tc.name: WriteSettingXmlWhenFileIsNotExistTest_001 +* @tc.desc: RenameToBrokenFile testcase of PreferencesXmlUtils +* @tc.type: FUNC +*/ +HWTEST_F(PreferencesXmlUtilsTest, WriteSettingXmlWhenFileIsNotExistTest_001, TestSize.Level1) +{ + std::string fileName = "/data/test/test01"; + std::vector settings; + Element elem; + elem.key_ = "stringKey"; + elem.tag_ = "string"; + elem.value_ = ""; + + settings.push_back(elem); + bool result = PreferencesXmlUtils::WriteSettingXml("/data/test/preferences/test01", "", "", settings); + EXPECT_EQ(result, false); + + result = PreferencesXmlUtils::WriteSettingXml(fileName, "", "", settings); + EXPECT_EQ(result, true); +} } diff --git a/preferences/test/ndk/BUILD.gn b/preferences/test/ndk/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..f3cecbf9eca75d9402e4f5b19220b483aaabeef0 --- /dev/null +++ b/preferences/test/ndk/BUILD.gn @@ -0,0 +1,90 @@ +# Copyright (c) 2021 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. +import("//build/test.gni") +import("//foundation/distributeddatamgr/preferences/preferences.gni") + +module_output_path = "preferences/ndk_preferences" + +############################################################################### + +config("module_private_config") { + visibility = [ ":*" ] + include_dirs = [ + "${preferences_base_path}/frameworks/ndk/include", + "${preferences_base_path}/frameworks/common/include", + "${preferences_native_path}/include", + "${preferences_native_path}/platform/include/", + "${preferences_interfaces_path}/inner_api/include/", + "${preferences_interfaces_path}/ndk/include/", + "${preferences_base_path}/test/ndk/mock", + "${preferences_native_path}/mock/ability_runtime/dataobs_manager/include", + "${preferences_native_path}/mock/ability_base/zuri/include", + ] +} + +ohos_unittest("NDKPreferencesTest") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } + module_out_path = module_output_path + + sources = [ + "${preferences_native_path}/mock/ability_base/zuri/src/uri.cpp", + "${preferences_native_path}/mock/ability_runtime/dataobs_manager/src/data_ability_observer_stub.cpp", + "${preferences_native_path}/mock/ability_runtime/dataobs_manager/src/dataobs_mgr_client.cpp", + "${preferences_native_path}/platform/src/preferences_db_adapter.cpp", + "${preferences_native_path}/platform/src/preferences_dfx_adapter.cpp", + "${preferences_native_path}/platform/src/preferences_file_lock.cpp", + "${preferences_native_path}/platform/src/preferences_thread.cpp", + "${preferences_native_path}/src/base64_helper.cpp", + "${preferences_native_path}/src/preferences_base.cpp", + "${preferences_native_path}/src/preferences_enhance_impl.cpp", + "${preferences_native_path}/src/preferences_helper.cpp", + "${preferences_native_path}/src/preferences_impl.cpp", + "${preferences_native_path}/src/preferences_observer.cpp", + "${preferences_native_path}/src/preferences_utils.cpp", + "${preferences_native_path}/src/preferences_value.cpp", + "${preferences_native_path}/src/preferences_value_parcel.cpp", + "${preferences_native_path}/src/preferences_xml_utils.cpp", + "${preferences_ndk_path}/src/convertor_error_code.cpp", + "${preferences_ndk_path}/src/oh_preferences.cpp", + "${preferences_ndk_path}/src/oh_preferences_option.cpp", + "${preferences_ndk_path}/src/oh_preferences_value.cpp", + "mock/application_context.cpp", + "unittest/preferences_ndk_test.cpp", + "unittest/preferences_ndk_value_test.cpp", + "unittest/preferences_test_utils.cpp", + ] + + configs = [ ":module_private_config" ] + external_deps = [ + "access_token:libaccesstoken_sdk", + "c_utils:utils", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + "ipc:ipc_core", + "libxml2:libxml2", + ] +} + +############################################################################### +group("unittest") { + testonly = true + + deps = [ ":NDKPreferencesTest" ] +} +############################################################################### diff --git a/preferences/test/ndk/mock/application_context.cpp b/preferences/test/ndk/mock/application_context.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ab7a010f59fbd38440c1681133c53d298c7f3877 --- /dev/null +++ b/preferences/test/ndk/mock/application_context.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2021-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 "application_context.h" +#include + +namespace OHOS { +namespace AbilityRuntime { + +std::shared_ptr Context::applicationContext_ = nullptr; + +std::shared_ptr Context::GetApplicationContext() +{ + printf("mock Context success.\n"); + applicationContext_ = std::make_shared(); + return applicationContext_; +} + +std::string ApplicationContext::GetPreferencesDir() +{ + return std::string("/data/test"); +} + +int32_t ApplicationContext::GetSystemPreferencesDir(const std::string &groupId, bool checkExist, + std::string &preferencesDir) +{ + preferencesDir = "/data/test"; + return 0; +} + +} // namespace AbilityRuntime +} // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/customutdinstaller_fuzzer/customutdinstaller_fuzzer.cpp b/preferences/test/ndk/mock/application_context.h similarity index 34% rename from datamgr_service/services/distributeddataservice/service/test/fuzztest/customutdinstaller_fuzzer/customutdinstaller_fuzzer.cpp rename to preferences/test/ndk/mock/application_context.h index 36670b42e800a5e2271154971fb033149fd618e6..052039d8db1a1ce589b98db9dbfa498187d8de01 100644 --- a/datamgr_service/services/distributeddataservice/service/test/fuzztest/customutdinstaller_fuzzer/customutdinstaller_fuzzer.cpp +++ b/preferences/test/ndk/mock/application_context.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-2022 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 @@ -12,46 +12,33 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#ifndef OHOS_ABILITY_RUNTIME_APPLICATION_CONTEXT_H +#define OHOS_ABILITY_RUNTIME_APPLICATION_CONTEXT_H -#include "customutdinstaller_fuzzer.h" -#include -#include - -#include "ipc_skeleton.h" -#include "custom_utd_installer.h" -#include "message_parcel.h" -#include "securec.h" - -using namespace OHOS::UDMF; +#include namespace OHOS { - -bool InstallUtdFuzz(const uint8_t* data, size_t size) -{ - int32_t user = static_cast(*data); - std::string bundleName(reinterpret_cast(data), size); - CustomUtdInstaller::GetInstance().InstallUtd(bundleName, user); - return true; -} - -bool UninstallUtdFuzz(const uint8_t* data, size_t size) -{ - int32_t user = static_cast(*data); - std::string bundleName(reinterpret_cast(data), size); - CustomUtdInstaller::GetInstance().UninstallUtd(bundleName, user); - return true; -} -} - -/* Fuzzer entry point */ -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) -{ - if (data == nullptr) { - return 0; - } - - OHOS::InstallUtdFuzz(data, size); - OHOS::UninstallUtdFuzz(data, size); - - return 0; -} \ No newline at end of file +namespace AbilityRuntime { +class ApplicationContext; +// mock Context from ablity +class Context : public std::enable_shared_from_this { +public: + Context() = default; + virtual ~Context() = default; + static std::shared_ptr GetApplicationContext(); + virtual std::string GetPreferencesDir() = 0; + virtual int32_t GetSystemPreferencesDir(const std::string &groupId, bool checkExist, + std::string &preferencesDir) = 0; + static std::shared_ptr applicationContext_; +}; + +class ApplicationContext : public Context { +public: + ApplicationContext() = default; + ~ApplicationContext() override = default; + std::string GetPreferencesDir() override; + int32_t GetSystemPreferencesDir(const std::string &groupId, bool checkExist, std::string &preferencesDir) override; +}; +} // namespace AbilityRuntime +} // namespace OHOS +#endif // OHOS_ABILITY_RUNTIME_APPLICATION_CONTEXT_H diff --git a/preferences/test/ndk/unittest/preferences_ndk_test.cpp b/preferences/test/ndk/unittest/preferences_ndk_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dc42af4e0c0b650de1dbd56ebf73bac0480bb0cf --- /dev/null +++ b/preferences/test/ndk/unittest/preferences_ndk_test.cpp @@ -0,0 +1,769 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "log_print.h" +#include "preferences_test_utils.h" +#include "oh_preferences_impl.h" +#include "oh_preferences.h" +#include "oh_preferences_err_code.h" +#include "oh_preferences_value.h" +#include "oh_preferences_option.h" +#include "preferences_helper.h" + +using namespace testing::ext; +using namespace testing; +using namespace OHOS::PreferencesNdk; +using namespace OHOS::NativePreferences; +namespace { +class PreferencesNdkTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void PreferencesNdkTest::SetUpTestCase(void) +{ + NdkTestUtils::CreateDirectoryRecursively("/data/test/"); +} +void PreferencesNdkTest::TearDownTestCase(void) {} + +void PreferencesNdkTest::SetUp(void) +{ + NdkTestUtils::CreateDirectoryRecursively("/data/test/"); +} + +void PreferencesNdkTest::TearDown(void) {} + +enum class PrefDataType { UNASSIGNED, INT, STRING, BOOL }; + +const uint32_t INVALID_INDEX = 100; + +static OH_PreferencesOption *GetCommonOption() +{ + OH_PreferencesOption *option = OH_PreferencesOption_Create(); + EXPECT_EQ(OH_PreferencesOption_SetFileName(option, "testdb"), PREFERENCES_OK); + EXPECT_EQ(OH_PreferencesOption_SetBundleName(option, "com.uttest"), PREFERENCES_OK); + EXPECT_EQ(OH_PreferencesOption_SetDataGroupId(option, "123"), PREFERENCES_OK); + return option; +} + +std::map g_intDataMap = { + {"ndktest_int_key_1", -2147483648}, + {"ndktest_int_key_2", -1}, + {"ndktest_int_key_3", 0}, + {"ndktest_int_key_4", 1}, + {"ndktest_int_key_5", 2147483647} +}; + +std::map g_stringDataMap = { + {"ndktest_string_key_1", "2679b2c70120214984b3aec34fc849dc996f40e3cdb60f3b3eaf8abe2559439a"}, + {"ndktest_string_key_2", "+88780079687688"}, + {"ndktest_string_key_3", "/data/storage/el2/base/files/Thumbnail_1717209543267.jpg"}, + {"ndktest_string_key_4", "A NEW PHONE"}, + {"ndktest_string_key_5", "https://upfile-drcn.platform.hicloud.com/"} +}; + +std::map g_boolDataMap = { + {"ndktest_bool_key_1", true}, + {"ndktest_bool_key_2", false}, + {"ndktest_bool_key_3", false}, + {"ndktest_bool_key_4", true}, + {"ndktest_bool_key_5", true} +}; + +int g_changeNum = 0; +void DataChangeObserverCallback(void *context, const OH_PreferencesPair *pairs, uint32_t count) +{ + for (uint32_t i = 0; i < count; i++) { + const OH_PreferencesValue *pValue = OH_PreferencesPair_GetPreferencesValue(pairs, i); + Preference_ValueType type = OH_PreferencesValue_GetValueType(pValue); + const char *pKey = OH_PreferencesPair_GetKey(pairs, i); + EXPECT_NE(pKey, nullptr); + if (type == Preference_ValueType::PREFERENCE_TYPE_INT) { + int intV = 0; + OH_PreferencesValue_GetInt(pValue, &intV); + } else if (type == Preference_ValueType::PREFERENCE_TYPE_BOOL) { + bool boolV = false; + OH_PreferencesValue_GetBool(pValue, &boolV); + } else if (type == Preference_ValueType::PREFERENCE_TYPE_STRING) { + char *stringV = nullptr; + uint32_t len = 0; + OH_PreferencesValue_GetString(pValue, &stringV, &len); + OH_Preferences_FreeString(stringV); + } + g_changeNum++; + } +} + +int PreferencesFlush(OH_Preferences *preference) +{ + OH_PreferencesImpl *pref = static_cast(preference); + std::shared_ptr nativePreferences = pref->GetNativePreferences(); + return nativePreferences->FlushSync(); +} + +void SetAllValuesWithCheck(OH_Preferences *pref) +{ + for (auto &[key, value] : g_intDataMap) { + EXPECT_EQ(OH_Preferences_SetInt(pref, key.c_str(), value), PREFERENCES_OK); + EXPECT_EQ(PreferencesFlush(pref), OHOS::NativePreferences::E_OK); + int res = 0; + EXPECT_EQ(OH_Preferences_GetInt(pref, key.c_str(), &res), PREFERENCES_OK); + EXPECT_EQ(res, value); + } + for (auto &[key, value] : g_stringDataMap) { + EXPECT_EQ(OH_Preferences_SetString(pref, key.c_str(), value.c_str()), PREFERENCES_OK); + EXPECT_EQ(PreferencesFlush(pref), OHOS::NativePreferences::E_OK); + char *res = nullptr; + uint32_t len = 0; + EXPECT_EQ(OH_Preferences_GetString(pref, key.c_str(), &res, &len), PREFERENCES_OK); + EXPECT_EQ(strcmp(res, value.c_str()), 0); + OH_Preferences_FreeString(res); + } + for (auto &[key, value] : g_boolDataMap) { + EXPECT_EQ(OH_Preferences_SetBool(pref, key.c_str(), value), PREFERENCES_OK); + EXPECT_EQ(PreferencesFlush(pref), OHOS::NativePreferences::E_OK); + bool res; + EXPECT_EQ(OH_Preferences_GetBool(pref, key.c_str(), &res), PREFERENCES_OK); + EXPECT_EQ(res, value); + } +} + +void CheckTargetTypeValues(OH_Preferences *pref, bool exist, PrefDataType pdt) +{ + if (pdt == PrefDataType::INT) { + for (auto &[key, value] : g_intDataMap) { + int res; + if (exist) { + EXPECT_EQ(OH_Preferences_GetInt(pref, key.c_str(), &res), PREFERENCES_OK); + EXPECT_EQ(res, value); + } else { + EXPECT_EQ(OH_Preferences_GetInt(pref, key.c_str(), &res), PREFERENCES_ERROR_KEY_NOT_FOUND); + } + } + } else if (pdt == PrefDataType::STRING) { + for (auto &[key, value] : g_stringDataMap) { + char *res = nullptr; + uint32_t len = 0; + if (exist) { + EXPECT_EQ(OH_Preferences_GetString(pref, key.c_str(), &res, &len), PREFERENCES_OK); + EXPECT_EQ(strcmp(res, value.c_str()), 0); + } else { + EXPECT_EQ(OH_Preferences_GetString(pref, key.c_str(), &res, &len), PREFERENCES_ERROR_KEY_NOT_FOUND); + } + OH_Preferences_FreeString(res); + } + } else if (pdt == PrefDataType::BOOL) { + for (auto &[key, value] : g_boolDataMap) { + bool res; + if (exist) { + EXPECT_EQ(OH_Preferences_GetBool(pref, key.c_str(), &res), PREFERENCES_OK); + EXPECT_EQ(res, value); + } else { + EXPECT_EQ(OH_Preferences_GetBool(pref, key.c_str(), &res), PREFERENCES_ERROR_KEY_NOT_FOUND); + } + } + } +} + +/** + * @tc.name: NDKPreferencesGetTest_001 + * @tc.desc: 测试先put int类型的kv,再get相同的key,值相同 + * @tc.type: FUNC + * @tc.require: NA + * @tc.author: Song Yixiu + */ +HWTEST_F(PreferencesNdkTest, NDKPreferencesGetTest_001, TestSize.Level1) +{ + int errCode = PREFERENCES_OK; + OH_PreferencesOption *option = GetCommonOption(); + OH_Preferences *pref = OH_Preferences_Open(option, &errCode); + (void)OH_PreferencesOption_Destroy(option); + ASSERT_EQ(errCode, PREFERENCES_OK); + + SetAllValuesWithCheck(pref); + + const char *key = "test_key_int"; + EXPECT_EQ(OH_Preferences_SetInt(pref, key, 12), PREFERENCES_OK); + int ret; + EXPECT_EQ(OH_Preferences_GetInt(pref, key, &ret), PREFERENCES_OK); + EXPECT_EQ(ret, 12); + + EXPECT_EQ(OH_Preferences_Close(pref), PREFERENCES_OK); + EXPECT_EQ(OHOS::NativePreferences::PreferencesHelper::DeletePreferences("/data/test/testdb"), + OHOS::NativePreferences::E_OK); +} + +/** + * @tc.name: NDKPreferencesGetTest_002 + * @tc.desc: 测试先put string类型的kv,再get相同的key,值相同 + * @tc.type: FUNC + * @tc.require: NA + * @tc.author: Song Yixiu + */ +HWTEST_F(PreferencesNdkTest, NDKPreferencesGetTest_002, TestSize.Level1) +{ + int errCode = PREFERENCES_OK; + OH_PreferencesOption *option = GetCommonOption(); + OH_Preferences *pref = OH_Preferences_Open(option, &errCode); + (void)OH_PreferencesOption_Destroy(option); + ASSERT_EQ(errCode, PREFERENCES_OK); + + SetAllValuesWithCheck(pref); + + const char *key = "test_key_string"; + const char *value = "test_value"; + EXPECT_EQ(OH_Preferences_SetString(pref, key, value), PREFERENCES_OK); + char *ret = nullptr; + uint32_t len = 0; + EXPECT_EQ(OH_Preferences_GetString(pref, key, &ret, &len), PREFERENCES_OK); + EXPECT_EQ(strcmp(ret, value), 0); + OH_Preferences_FreeString(ret); + + EXPECT_EQ(OH_Preferences_Close(pref), PREFERENCES_OK); + EXPECT_EQ(OHOS::NativePreferences::PreferencesHelper::DeletePreferences("/data/test/testdb"), + OHOS::NativePreferences::E_OK); +} + +/** + * @tc.name: NDKPreferencesGetTest_003 + * @tc.desc: 测试先put bool类型的kv,再get相同的key,值相同 + * @tc.type: FUNC + * @tc.require: NA + * @tc.author: Song Yixiu + */ +HWTEST_F(PreferencesNdkTest, NDKPreferencesGetTest_003, TestSize.Level1) +{ + int errCode = PREFERENCES_OK; + OH_PreferencesOption *option = GetCommonOption(); + OH_Preferences *pref = OH_Preferences_Open(option, &errCode); + (void)OH_PreferencesOption_Destroy(option); + ASSERT_EQ(errCode, PREFERENCES_OK); + + SetAllValuesWithCheck(pref); + + const char *key = "test_key_bool"; + bool value = true; + EXPECT_EQ(OH_Preferences_SetBool(pref, key, value), PREFERENCES_OK); + bool ret; + EXPECT_EQ(OH_Preferences_GetBool(pref, key, &ret), PREFERENCES_OK); + EXPECT_EQ(ret, value); + + EXPECT_EQ(OH_Preferences_Close(pref), PREFERENCES_OK); + EXPECT_EQ(OHOS::NativePreferences::PreferencesHelper::DeletePreferences("/data/test/testdb"), + OHOS::NativePreferences::E_OK); +} + +/** + * @tc.name: NDKPreferencesGetTest_004 + * @tc.desc: 测试get不存在的kv + * @tc.type: FUNC + * @tc.require: NA + * @tc.author: Song Yixiu + */ +HWTEST_F(PreferencesNdkTest, NDKPreferencesGetTest_004, TestSize.Level1) +{ + int errCode = PREFERENCES_OK; + OH_PreferencesOption *option = GetCommonOption(); + OH_Preferences *pref = OH_Preferences_Open(option, &errCode); + (void)OH_PreferencesOption_Destroy(option); + ASSERT_EQ(errCode, PREFERENCES_OK); + + CheckTargetTypeValues(pref, false, PrefDataType::INT); + CheckTargetTypeValues(pref, false, PrefDataType::STRING); + CheckTargetTypeValues(pref, false, PrefDataType::BOOL); + + EXPECT_EQ(OH_Preferences_Close(pref), PREFERENCES_OK); + EXPECT_EQ(OHOS::NativePreferences::PreferencesHelper::DeletePreferences("/data/test/testdb"), + OHOS::NativePreferences::E_OK); +} + +/** + * @tc.name: NDKPreferencesPutTest_001 + * @tc.desc: 测试先get不存在的kv,再put进kv,然后get + * @tc.type: FUNC + * @tc.require: NA + * @tc.author: Song Yixiu + */ +HWTEST_F(PreferencesNdkTest, NDKPreferencesPutTest_001, TestSize.Level1) +{ + int errCode = PREFERENCES_OK; + OH_PreferencesOption *option = GetCommonOption(); + OH_Preferences *pref = OH_Preferences_Open(option, &errCode); + (void)OH_PreferencesOption_Destroy(option); + ASSERT_EQ(errCode, PREFERENCES_OK); + + CheckTargetTypeValues(pref, false, PrefDataType::INT); + CheckTargetTypeValues(pref, false, PrefDataType::STRING); + CheckTargetTypeValues(pref, false, PrefDataType::BOOL); + + SetAllValuesWithCheck(pref); + + CheckTargetTypeValues(pref, true, PrefDataType::INT); + CheckTargetTypeValues(pref, true, PrefDataType::STRING); + CheckTargetTypeValues(pref, true, PrefDataType::BOOL); + + EXPECT_EQ(OH_Preferences_Close(pref), PREFERENCES_OK); + EXPECT_EQ(OHOS::NativePreferences::PreferencesHelper::DeletePreferences("/data/test/testdb"), + OHOS::NativePreferences::E_OK); +} + +/** + * @tc.name: NDKPreferencesUpdateTest_001 + * @tc.desc: 测试先put int类型的kv,然后get,然后再put新的值进行更新,再get + * @tc.type: FUNC + * @tc.require: NA + * @tc.author: Song Yixiu + */ +HWTEST_F(PreferencesNdkTest, NDKPreferencesUpdateTest_001, TestSize.Level1) +{ + int errCode = PREFERENCES_OK; + OH_PreferencesOption *option = GetCommonOption(); + OH_Preferences *pref = OH_Preferences_Open(option, &errCode); + (void)OH_PreferencesOption_Destroy(option); + ASSERT_EQ(errCode, PREFERENCES_OK); + + SetAllValuesWithCheck(pref); + + const char *key = "ndktest_int_key_1"; + int newValue = 10; + EXPECT_EQ(OH_Preferences_SetInt(pref, key, newValue), PREFERENCES_OK); + int ret; + EXPECT_EQ(OH_Preferences_GetInt(pref, key, &ret), PREFERENCES_OK); + EXPECT_EQ(ret, newValue); + + EXPECT_EQ(OH_Preferences_Close(pref), PREFERENCES_OK); + EXPECT_EQ(OHOS::NativePreferences::PreferencesHelper::DeletePreferences("/data/test/testdb"), + OHOS::NativePreferences::E_OK); +} + +/** + * @tc.name: NDKPreferencesUpdateTest_002 + * @tc.desc: 测试先put string类型的kv,然后get,然后再put新的值进行更新,再get + * @tc.type: FUNC + * @tc.require: NA + * @tc.author: Song Yixiu + */ +HWTEST_F(PreferencesNdkTest, NDKPreferencesUpdateTest_002, TestSize.Level1) +{ + int errCode = PREFERENCES_OK; + OH_PreferencesOption *option = GetCommonOption(); + OH_Preferences *pref = OH_Preferences_Open(option, &errCode); + (void)OH_PreferencesOption_Destroy(option); + ASSERT_EQ(errCode, PREFERENCES_OK); + + SetAllValuesWithCheck(pref); + + const char *key = "ndktest_string_key_1"; + const char *newValue = "adlkj1#$&sdioj9i0i841a61aa4gh44o98()!@@.,.{:/',}"; + EXPECT_EQ(OH_Preferences_SetString(pref, key, newValue), PREFERENCES_OK); + char *ret = nullptr; + uint32_t len = 0; + EXPECT_EQ(OH_Preferences_GetString(pref, key, &ret, &len), PREFERENCES_OK); + EXPECT_EQ(strcmp(ret, newValue), 0); + OH_Preferences_FreeString(ret); + + EXPECT_EQ(OH_Preferences_Close(pref), PREFERENCES_OK); + EXPECT_EQ(OHOS::NativePreferences::PreferencesHelper::DeletePreferences("/data/test/testdb"), + OHOS::NativePreferences::E_OK); +} + +/** + * @tc.name: NDKPreferencesUpdateTest_003 + * @tc.desc: 测试先put bool类型的kv,然后get,然后再put新的值进行更新,再get + * @tc.type: FUNC + * @tc.require: NA + * @tc.author: Song Yixiu + */ +HWTEST_F(PreferencesNdkTest, NDKPreferencesUpdateTest_003, TestSize.Level1) +{ + int errCode = PREFERENCES_OK; + OH_PreferencesOption *option = GetCommonOption(); + OH_Preferences *pref = OH_Preferences_Open(option, &errCode); + (void)OH_PreferencesOption_Destroy(option); + ASSERT_EQ(errCode, PREFERENCES_OK); + + SetAllValuesWithCheck(pref); + + const char *key = "ndktest_bool_key_1"; + bool newValue = false; + EXPECT_EQ(OH_Preferences_SetBool(pref, key, newValue), PREFERENCES_OK); + bool ret; + EXPECT_EQ(OH_Preferences_GetBool(pref, key, &ret), PREFERENCES_OK); + EXPECT_EQ(ret, newValue); + + EXPECT_EQ(OH_Preferences_Close(pref), PREFERENCES_OK); + EXPECT_EQ(OHOS::NativePreferences::PreferencesHelper::DeletePreferences("/data/test/testdb"), + OHOS::NativePreferences::E_OK); +} + +/** + * @tc.name: NDKPreferencesDeleteTest_001 + * @tc.desc: test Delete exist key + * @tc.type: FUNC + * @tc.require: NA + * @tc.author: Liu Xiaolong + */ +HWTEST_F(PreferencesNdkTest, NDKPreferencesDeleteTest_001, TestSize.Level1) +{ + int errCode = PREFERENCES_OK; + OH_PreferencesOption *option = GetCommonOption(); + OH_Preferences *pref = OH_Preferences_Open(option, &errCode); + (void)OH_PreferencesOption_Destroy(option); + ASSERT_EQ(errCode, PREFERENCES_OK); + + SetAllValuesWithCheck(pref); + + for (auto &[key, value] : g_stringDataMap) { + EXPECT_EQ(OH_Preferences_Delete(pref, key.c_str()), PREFERENCES_OK); + } + + CheckTargetTypeValues(pref, true, PrefDataType::INT); + CheckTargetTypeValues(pref, false, PrefDataType::STRING); + CheckTargetTypeValues(pref, true, PrefDataType::BOOL); + + EXPECT_EQ(OH_Preferences_Close(pref), PREFERENCES_OK); + EXPECT_EQ(OHOS::NativePreferences::PreferencesHelper::DeletePreferences("/data/test/testdb"), + OHOS::NativePreferences::E_OK); +} + +/** + * @tc.name: NDKPreferencesDeleteTest_002 + * @tc.desc: test Delete non-exist key + * @tc.type: FUNC + * @tc.require: NA + * @tc.author: Liu Xiaolong + */ +HWTEST_F(PreferencesNdkTest, NDKPreferencesDeleteTest_002, TestSize.Level1) +{ + int errCode = PREFERENCES_OK; + OH_PreferencesOption *option = GetCommonOption(); + OH_Preferences *pref = OH_Preferences_Open(option, &errCode); + (void)OH_PreferencesOption_Destroy(option); + ASSERT_EQ(errCode, PREFERENCES_OK); + + CheckTargetTypeValues(pref, false, PrefDataType::INT); + + for (auto &[key, value] : g_intDataMap) { + EXPECT_EQ(OH_Preferences_Delete(pref, key.c_str()), PREFERENCES_OK); + } + + EXPECT_EQ(OH_Preferences_Close(pref), PREFERENCES_OK); + EXPECT_EQ(OHOS::NativePreferences::PreferencesHelper::DeletePreferences("/data/test/testdb"), + OHOS::NativePreferences::E_OK); +} + +static void RegisterObsInFunc(OH_Preferences *pref) +{ + const char *keys[] = {"ndktest_int_key_1", "ndktest_string_key_1", "ndktest_bool_key_1"}; + + int ret = OH_Preferences_RegisterDataObserver(pref, nullptr, DataChangeObserverCallback, keys, 3); + ASSERT_EQ(ret, PREFERENCES_OK); +} + +static void UnRegisterObsInFunc(OH_Preferences *pref) +{ + const char *keys[] = {"ndktest_int_key_1", "ndktest_string_key_1", "ndktest_bool_key_1"}; + + int ret = OH_Preferences_UnregisterDataObserver(pref, nullptr, DataChangeObserverCallback, keys, 3); + ASSERT_EQ(ret, PREFERENCES_OK); +} + +/** + * @tc.name: NDKPreferencesObserverTest_001 + * @tc.desc: test Observer + * @tc.type: FUNC + * @tc.require: NA + * @tc.author: Liu Xiaolong + */ +HWTEST_F(PreferencesNdkTest, NDKPreferencesObserverTest_001, TestSize.Level1) +{ + int errCode = PREFERENCES_OK; + OH_PreferencesOption *option = GetCommonOption(); + OH_Preferences *pref = OH_Preferences_Open(option, &errCode); + (void)OH_PreferencesOption_Destroy(option); + ASSERT_EQ(errCode, PREFERENCES_OK); + + RegisterObsInFunc(pref); + + SetAllValuesWithCheck(pref); + + for (auto &[key, value] : g_intDataMap) { + EXPECT_EQ(OH_Preferences_Delete(pref, key.c_str()), PREFERENCES_OK); + EXPECT_EQ(PreferencesFlush(pref), OHOS::NativePreferences::E_OK); + } + + for (auto &[key, value] : g_stringDataMap) { + const char *newValue = "update_string_value_109uokadnf894u5"; + EXPECT_EQ(OH_Preferences_SetString(pref, key.c_str(), newValue), PREFERENCES_OK); + EXPECT_EQ(PreferencesFlush(pref), OHOS::NativePreferences::E_OK); + } + + std::this_thread::sleep_for(std::chrono::milliseconds(2000)); + + EXPECT_EQ(g_changeNum, 5); + + UnRegisterObsInFunc(pref); + + EXPECT_EQ(OH_Preferences_Close(pref), PREFERENCES_OK); + EXPECT_EQ(OHOS::NativePreferences::PreferencesHelper::DeletePreferences("/data/test/testdb"), + OHOS::NativePreferences::E_OK); +} + +/** + * @tc.name: NDKPreferencesObserverTest_002 + * @tc.desc: test Observer + * @tc.type: FUNC + * @tc.require: NA + * @tc.author: bluhuang + */ +HWTEST_F(PreferencesNdkTest, NDKPreferencesObserverTest_002, TestSize.Level1) +{ + // cannot get callback when unregister + int errCode = PREFERENCES_OK; + OH_PreferencesOption *option = GetCommonOption(); + OH_Preferences *pref = OH_Preferences_Open(option, &errCode); + (void)OH_PreferencesOption_Destroy(option); + ASSERT_EQ(errCode, PREFERENCES_OK); + + const char *keys[] = {"ndktest_int_key_1", "ndktest_string_key_1", "ndktest_bool_key_1"}; + g_changeNum = 0; + int ret = OH_Preferences_RegisterDataObserver(pref, nullptr, DataChangeObserverCallback, keys, 3); + ASSERT_EQ(ret, PREFERENCES_OK); + const char *empty[] = {}; + EXPECT_EQ(OH_Preferences_UnregisterDataObserver(pref, nullptr, DataChangeObserverCallback, empty, 0), + PREFERENCES_OK); + + SetAllValuesWithCheck(pref); + std::this_thread::sleep_for(std::chrono::milliseconds(2000)); + EXPECT_EQ(g_changeNum, 0); + EXPECT_EQ(OH_Preferences_Close(pref), PREFERENCES_OK); + + EXPECT_EQ(OHOS::NativePreferences::PreferencesHelper::DeletePreferences("/data/test/testdb"), + OHOS::NativePreferences::E_OK); +} + +/** + * @tc.name: NDKPreferencesObserverTest_003 + * @tc.desc: test Observer + * @tc.type: FUNC + * @tc.require: NA + * @tc.author: bluhuang + */ +HWTEST_F(PreferencesNdkTest, NDKPreferencesObserverTest_003, TestSize.Level1) +{ + int errCode = PREFERENCES_OK; + OH_PreferencesOption *option = GetCommonOption(); + OH_Preferences *pref = OH_Preferences_Open(option, &errCode); + (void)OH_PreferencesOption_Destroy(option); + ASSERT_EQ(errCode, PREFERENCES_OK); + + const char *keys[] = {"ndktest_int_key_1", "ndktest_string_key_1", "ndktest_bool_key_1"}; + g_changeNum = 0; + ASSERT_EQ(OH_Preferences_RegisterDataObserver(nullptr, nullptr, DataChangeObserverCallback, keys, 3), + PREFERENCES_ERROR_INVALID_PARAM); + ASSERT_EQ(OH_Preferences_RegisterDataObserver(pref, nullptr, nullptr, keys, 3), PREFERENCES_ERROR_INVALID_PARAM); + ASSERT_EQ(OH_Preferences_RegisterDataObserver(pref, nullptr, DataChangeObserverCallback, nullptr, 3), + PREFERENCES_ERROR_INVALID_PARAM); + EXPECT_EQ(OH_Preferences_UnregisterDataObserver(nullptr, nullptr, DataChangeObserverCallback, keys, 0), + PREFERENCES_ERROR_INVALID_PARAM); + EXPECT_EQ(OH_Preferences_UnregisterDataObserver(pref, nullptr, nullptr, keys, 0), + PREFERENCES_ERROR_INVALID_PARAM); + EXPECT_EQ(OH_Preferences_UnregisterDataObserver(pref, nullptr, DataChangeObserverCallback, nullptr, 0), + PREFERENCES_ERROR_INVALID_PARAM); +} + +/** + * @tc.name: NDKPreferencesObserverTest_004 + * @tc.desc: test Observer + * @tc.type: FUNC + * @tc.require: NA + * @tc.author: bluhuang + */ +HWTEST_F(PreferencesNdkTest, NDKPreferencesObserverTest_004, TestSize.Level1) +{ + int errCode = PREFERENCES_OK; + OH_PreferencesOption *option = GetCommonOption(); + OH_Preferences *pref = OH_Preferences_Open(option, &errCode); + (void)OH_PreferencesOption_Destroy(option); + ASSERT_EQ(errCode, PREFERENCES_OK); + + const char *keys1[] = {"ndktest_int_key_1", "ndktest_string_key_1", "ndktest_bool_key_1"}; + g_changeNum = 0; + double obj = 1.1; + void *context1 = &obj; + ASSERT_EQ(OH_Preferences_RegisterDataObserver(pref, (void*) context1, DataChangeObserverCallback, keys1, 3), + PREFERENCES_OK); + + const char *keys2[] = {"ndktest_int_key_5"}; + double obj2 = 2.2; + void *context2 = &obj2; + ASSERT_EQ(OH_Preferences_RegisterDataObserver(pref, (void*) context2, DataChangeObserverCallback, keys2, 1), + PREFERENCES_OK); + SetAllValuesWithCheck(pref); + + std::this_thread::sleep_for(std::chrono::milliseconds(2000)); + + EXPECT_EQ(g_changeNum, 4); + + EXPECT_EQ(OH_Preferences_UnregisterDataObserver(pref, nullptr, DataChangeObserverCallback, keys1, 3), + PREFERENCES_OK); + EXPECT_EQ(OH_Preferences_UnregisterDataObserver(pref, nullptr, DataChangeObserverCallback, keys2, 1), + PREFERENCES_OK); + EXPECT_EQ(OH_Preferences_Close(pref), PREFERENCES_OK); + + EXPECT_EQ(OHOS::NativePreferences::PreferencesHelper::DeletePreferences("/data/test/testdb"), + OHOS::NativePreferences::E_OK); +} + +/** + * @tc.name: NDKPreferencesObserverTest_005 + * @tc.desc: test Observer + * @tc.type: FUNC + * @tc.require: NA + * @tc.author: bluhuang + */ +HWTEST_F(PreferencesNdkTest, NDKPreferencesObserverTest_005, TestSize.Level1) +{ + // cancel part of all registerd key + int errCode = PREFERENCES_OK; + OH_PreferencesOption *option = GetCommonOption(); + OH_Preferences *pref = OH_Preferences_Open(option, &errCode); + (void)OH_PreferencesOption_Destroy(option); + ASSERT_EQ(errCode, PREFERENCES_OK); + + const char *keys[] = {"ndktest_int_key_1", "ndktest_string_key_1", "ndktest_bool_key_1"}; + g_changeNum = 0; + ASSERT_EQ(OH_Preferences_RegisterDataObserver(pref, nullptr, DataChangeObserverCallback, keys, 3), + PREFERENCES_OK); + const char *cancel[] = {"ndktest_bool_key_1"}; + EXPECT_EQ(OH_Preferences_UnregisterDataObserver(pref, nullptr, DataChangeObserverCallback, cancel, 1), + PREFERENCES_OK); + + SetAllValuesWithCheck(pref); + + std::this_thread::sleep_for(std::chrono::milliseconds(2000)); + EXPECT_EQ(g_changeNum, 2); + + EXPECT_EQ(OH_Preferences_Close(pref), PREFERENCES_OK); + EXPECT_EQ(OHOS::NativePreferences::PreferencesHelper::DeletePreferences("/data/test/testdb"), + OHOS::NativePreferences::E_OK); +} + +void NullTestCallback(void *context, const OH_PreferencesPair *pairs, uint32_t count) +{ + for (uint32_t i = 0; i < count; i++) { + EXPECT_EQ(OH_PreferencesPair_GetPreferencesValue(nullptr, INVALID_INDEX), nullptr); + EXPECT_EQ(OH_PreferencesPair_GetPreferencesValue(pairs, INVALID_INDEX), nullptr); + + EXPECT_EQ(OH_PreferencesValue_GetValueType(nullptr), Preference_ValueType::PREFERENCE_TYPE_NULL); + + EXPECT_EQ(OH_PreferencesPair_GetKey(nullptr, INVALID_INDEX), nullptr); + EXPECT_EQ(OH_PreferencesPair_GetKey(pairs, INVALID_INDEX), nullptr); + + const OH_PreferencesValue *pValue = OH_PreferencesPair_GetPreferencesValue(pairs, i); + Preference_ValueType type = OH_PreferencesValue_GetValueType(pValue); + const char *pKey = OH_PreferencesPair_GetKey(pairs, i); + EXPECT_NE(pKey, nullptr); + if (type == Preference_ValueType::PREFERENCE_TYPE_INT) { + EXPECT_EQ(OH_PreferencesValue_GetInt(nullptr, nullptr), PREFERENCES_ERROR_INVALID_PARAM); + EXPECT_EQ(OH_PreferencesValue_GetInt(pValue, nullptr), PREFERENCES_ERROR_INVALID_PARAM); + + bool boolV = false; + EXPECT_EQ(OH_PreferencesValue_GetBool(pValue, &boolV), PREFERENCES_ERROR_KEY_NOT_FOUND); + } else if (type == Preference_ValueType::PREFERENCE_TYPE_BOOL) { + EXPECT_EQ(OH_PreferencesValue_GetBool(nullptr, nullptr), PREFERENCES_ERROR_INVALID_PARAM); + EXPECT_EQ(OH_PreferencesValue_GetBool(pValue, nullptr), PREFERENCES_ERROR_INVALID_PARAM); + + char *stringV = nullptr; + uint32_t len = 0; + EXPECT_EQ(OH_PreferencesValue_GetString(pValue, &stringV, &len), PREFERENCES_ERROR_KEY_NOT_FOUND); + } else if (type == Preference_ValueType::PREFERENCE_TYPE_STRING) { + char *stringV = nullptr; + EXPECT_EQ(OH_PreferencesValue_GetString(nullptr, nullptr, nullptr), PREFERENCES_ERROR_INVALID_PARAM); + EXPECT_EQ(OH_PreferencesValue_GetString(pValue, nullptr, nullptr), PREFERENCES_ERROR_INVALID_PARAM); + EXPECT_EQ(OH_PreferencesValue_GetString(pValue, &stringV, nullptr), PREFERENCES_ERROR_INVALID_PARAM); + + int intV = 0; + EXPECT_EQ(OH_PreferencesValue_GetInt(pValue, &intV), PREFERENCES_ERROR_KEY_NOT_FOUND); + } + } +} + +/** + * @tc.name: NDKPreferencesNullInputTest_001 + * @tc.desc: test NULL Input + * @tc.type: FUNC + * @tc.require: NA + * @tc.author: Liu Xiaolong + */ +HWTEST_F(PreferencesNdkTest, NDKPreferencesNullInputTest_001, TestSize.Level1) +{ + int errCode = PREFERENCES_OK; + OH_PreferencesOption *option = OH_PreferencesOption_Create(); + + EXPECT_EQ(OH_PreferencesOption_SetFileName(nullptr, nullptr), PREFERENCES_ERROR_INVALID_PARAM); + EXPECT_EQ(OH_PreferencesOption_SetFileName(option, nullptr), PREFERENCES_ERROR_INVALID_PARAM); + EXPECT_EQ(OH_PreferencesOption_SetFileName(option, ""), PREFERENCES_ERROR_INVALID_PARAM); + + EXPECT_EQ(OH_PreferencesOption_SetBundleName(nullptr, nullptr), PREFERENCES_ERROR_INVALID_PARAM); + EXPECT_EQ(OH_PreferencesOption_SetBundleName(option, nullptr), PREFERENCES_ERROR_INVALID_PARAM); + + EXPECT_EQ(OH_PreferencesOption_SetDataGroupId(nullptr, nullptr), PREFERENCES_ERROR_INVALID_PARAM); + EXPECT_EQ(OH_PreferencesOption_SetDataGroupId(option, nullptr), PREFERENCES_ERROR_INVALID_PARAM); + + EXPECT_EQ(OH_PreferencesOption_Destroy(nullptr), PREFERENCES_ERROR_INVALID_PARAM); + + EXPECT_EQ(OH_PreferencesOption_SetFileName(option, "testdb"), PREFERENCES_OK); + EXPECT_EQ(OH_PreferencesOption_SetBundleName(option, "com.uttest"), PREFERENCES_OK); + EXPECT_EQ(OH_PreferencesOption_SetDataGroupId(option, "123"), PREFERENCES_OK); + OH_Preferences *pref = OH_Preferences_Open(option, &errCode); + (void)OH_PreferencesOption_Destroy(option); + ASSERT_EQ(errCode, PREFERENCES_OK); + + const char *keys[] = {"ndktest_int_key_1", "ndktest_string_key_1", "ndktest_bool_key_1"}; + ASSERT_EQ(OH_Preferences_RegisterDataObserver(pref, nullptr, NullTestCallback, keys, 3), PREFERENCES_OK); + + SetAllValuesWithCheck(pref); + + std::this_thread::sleep_for(std::chrono::milliseconds(2000)); + + EXPECT_EQ(OH_Preferences_UnregisterDataObserver(pref, nullptr, NullTestCallback, keys, 3), PREFERENCES_OK); + EXPECT_EQ(OH_Preferences_Close(pref), PREFERENCES_OK); + + EXPECT_EQ(OH_Preferences_Close(nullptr), PREFERENCES_ERROR_INVALID_PARAM); + + EXPECT_EQ(OHOS::NativePreferences::PreferencesHelper::DeletePreferences("/data/test/testdb"), + OHOS::NativePreferences::E_OK); +} +} diff --git a/preferences/test/ndk/unittest/preferences_ndk_value_test.cpp b/preferences/test/ndk/unittest/preferences_ndk_value_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3f4c2eb8df48a0d99ef877d084ee8de07dbb579d --- /dev/null +++ b/preferences/test/ndk/unittest/preferences_ndk_value_test.cpp @@ -0,0 +1,364 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "log_print.h" +#include "preferences_test_utils.h" +#include "oh_preferences_impl.h" +#include "oh_preferences.h" +#include "oh_preferences_err_code.h" +#include "oh_preferences_value.h" +#include "oh_preferences_option.h" +#include "preferences_helper.h" + +using namespace testing::ext; + +using namespace OHOS::PreferencesNdk; +using namespace OHOS::NativePreferences; +namespace { +class PreferencesNdkValueTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void PreferencesNdkValueTest::SetUpTestCase(void) +{ + NdkTestUtils::CreateDirectoryRecursively("/data/test/"); +} +void PreferencesNdkValueTest::TearDownTestCase(void) {} + +void PreferencesNdkValueTest::SetUp(void) +{ + NdkTestUtils::CreateDirectoryRecursively("/data/test/"); +} + +void PreferencesNdkValueTest::TearDown(void) {} + +enum class PrefDataType { UNASSIGNED, INT, STRING, BOOL }; + +static OH_PreferencesOption *GetCommonOption() +{ + OH_PreferencesOption *option = OH_PreferencesOption_Create(); + EXPECT_EQ(OH_PreferencesOption_SetFileName(option, "valueTestDbb"), PREFERENCES_OK); + EXPECT_EQ(OH_PreferencesOption_SetBundleName(option, "com.uttest"), PREFERENCES_OK); + EXPECT_EQ(OH_PreferencesOption_SetDataGroupId(option, "123"), PREFERENCES_OK); + return option; +} + +int PreferencesFlush(OH_Preferences *store) +{ + if (store == nullptr) { + printf("preferences flush failed, store is null\n"); + return PREFERENCES_ERROR_BASE; + } + OH_PreferencesImpl *pref = static_cast(store); + std::shared_ptr nativePreferences = pref->GetNativePreferences(); + return nativePreferences->FlushSync(); +} + +/** + * @tc.name: NDKPreferencesTest_001 + * @tc.desc: test pref is nullptr + * @tc.type: FUNC + * @tc.require: NA + * @tc.author: Lirui + */ +HWTEST_F(PreferencesNdkValueTest, NDKPreferencesTest_001, TestSize.Level1) +{ + int errCode = PREFERENCES_OK; + std::string intKey = "ndktest_int_key"; + int value = 0; + int res = 0; + errCode = OH_Preferences_SetInt(nullptr, intKey.c_str(), 123); + EXPECT_EQ(errCode, PREFERENCES_ERROR_INVALID_PARAM); + + errCode = OH_Preferences_GetInt(nullptr, intKey.c_str(), &value); + EXPECT_EQ(errCode, PREFERENCES_ERROR_INVALID_PARAM); + + OH_PreferencesOption *option = GetCommonOption(); + OH_Preferences *pref = OH_Preferences_Open(option, &errCode); + (void)OH_PreferencesOption_Destroy(option); + ASSERT_EQ(errCode, PREFERENCES_OK); + + errCode = OH_Preferences_SetInt(pref, "", value); + EXPECT_EQ(errCode, PREFERENCES_ERROR_INVALID_PARAM); + errCode = OH_Preferences_GetInt(pref, "", &res); + EXPECT_EQ(errCode, PREFERENCES_ERROR_INVALID_PARAM); + + errCode = OH_Preferences_SetInt(pref, nullptr, value); + EXPECT_EQ(errCode, PREFERENCES_ERROR_INVALID_PARAM); + errCode = OH_Preferences_GetInt(pref, nullptr, &res); + EXPECT_EQ(errCode, PREFERENCES_ERROR_INVALID_PARAM); + EXPECT_EQ(res, value); + + EXPECT_EQ(OH_Preferences_Close(pref), PREFERENCES_OK); + EXPECT_EQ(OHOS::NativePreferences::PreferencesHelper::DeletePreferences("/data/test/valueTestDb"), + OHOS::NativePreferences::E_OK); +} + +/** + * @tc.name: NDKPreferencesTest_002 + * @tc.desc: test pref is nullptr + * @tc.type: FUNC + * @tc.require: NA + * @tc.author: Lirui + */ +HWTEST_F(PreferencesNdkValueTest, NDKPreferencesTest_002, TestSize.Level1) +{ + int errCode = PREFERENCES_OK; + std::string stringKey = "ndktest_int_key"; + uint32_t len = 0; + char *res = nullptr; + char *resValue = nullptr; + errCode = OH_Preferences_SetString(nullptr, stringKey.c_str(), "test"); + EXPECT_EQ(errCode, PREFERENCES_ERROR_INVALID_PARAM); + + errCode = OH_Preferences_GetString(nullptr, stringKey.c_str(), &res, &len); + EXPECT_EQ(errCode, PREFERENCES_ERROR_INVALID_PARAM); + + OH_PreferencesOption *option = GetCommonOption(); + OH_Preferences *pref = OH_Preferences_Open(option, &errCode); + + ASSERT_EQ(errCode, PREFERENCES_OK); + + errCode = OH_Preferences_SetString(pref, "", "test"); + EXPECT_EQ(errCode, PREFERENCES_ERROR_INVALID_PARAM); + errCode = OH_Preferences_GetString(pref, "", &res, &len); + EXPECT_EQ(errCode, PREFERENCES_ERROR_INVALID_PARAM); + + errCode = OH_Preferences_SetString(pref, nullptr, "test"); + EXPECT_EQ(errCode, PREFERENCES_ERROR_INVALID_PARAM); + errCode = OH_Preferences_GetString(pref, nullptr, &res, &len); + EXPECT_EQ(errCode, PREFERENCES_ERROR_INVALID_PARAM); + + errCode = OH_Preferences_SetString(pref, stringKey.c_str(), "123 test"); + ASSERT_EQ(errCode, PREFERENCES_OK); + errCode = OH_Preferences_GetString(pref, stringKey.c_str(), &resValue, &len); + ASSERT_EQ(errCode, PREFERENCES_OK); + EXPECT_EQ(strcmp(resValue, "123 test"), 0); + EXPECT_EQ(PreferencesFlush(pref), PREFERENCES_OK); + OH_Preferences_FreeString(resValue); + + EXPECT_EQ(OH_Preferences_Close(pref), PREFERENCES_OK); + pref = OH_Preferences_Open(option, &errCode); + errCode = OH_Preferences_GetString(pref, stringKey.c_str(), &resValue, &len); + ASSERT_EQ(errCode, PREFERENCES_OK); + EXPECT_EQ(strcmp(resValue, "123 test"), 0); + (void)OH_PreferencesOption_Destroy(option); + EXPECT_EQ(OHOS::NativePreferences::PreferencesHelper::DeletePreferences("/data/test/valueTestDb"), + OHOS::NativePreferences::E_OK); +} + +/** + * @tc.name: NDKPreferencesTest_003 + * @tc.desc: test pref is nullptr + * @tc.type: FUNC + * @tc.require: NA + * @tc.author: Lirui + */ +HWTEST_F(PreferencesNdkValueTest, NDKPreferencesTest_003, TestSize.Level1) +{ + int errCode = PREFERENCES_OK; + std::string boolKey = "ndktest_int_key"; + bool boolValue = false; + errCode = OH_Preferences_SetBool(nullptr, boolKey.c_str(), true); + EXPECT_EQ(errCode, PREFERENCES_ERROR_INVALID_PARAM); + + errCode = OH_Preferences_GetBool(nullptr, boolKey.c_str(), &boolValue); + EXPECT_EQ(errCode, PREFERENCES_ERROR_INVALID_PARAM); + + OH_PreferencesOption *option = GetCommonOption(); + OH_Preferences *pref = OH_Preferences_Open(option, &errCode); + (void)OH_PreferencesOption_Destroy(option); + ASSERT_EQ(errCode, PREFERENCES_OK); + + errCode = OH_Preferences_SetBool(pref, "", false); + EXPECT_EQ(errCode, PREFERENCES_ERROR_INVALID_PARAM); + errCode = OH_Preferences_GetBool(pref, "", &boolValue); + EXPECT_EQ(errCode, PREFERENCES_ERROR_INVALID_PARAM); + + errCode = OH_Preferences_SetBool(pref, nullptr, false); + EXPECT_EQ(errCode, PREFERENCES_ERROR_INVALID_PARAM); + errCode = OH_Preferences_GetBool(pref, nullptr, &boolValue); + EXPECT_EQ(errCode, PREFERENCES_ERROR_INVALID_PARAM); + + errCode = OH_Preferences_SetBool(pref, " ", true); + EXPECT_EQ(errCode, PREFERENCES_OK); + errCode = OH_Preferences_GetBool(pref, " ", &boolValue); + EXPECT_EQ(errCode, PREFERENCES_OK); + ASSERT_EQ(boolValue, true); + + EXPECT_EQ(OH_Preferences_Close(pref), PREFERENCES_OK); + EXPECT_EQ(OHOS::NativePreferences::PreferencesHelper::DeletePreferences("/data/test/valueTestDb"), + OHOS::NativePreferences::E_OK); +} + +/** + * @tc.name: NDKPreferencesTest_004 + * @tc.desc: test pref is nullptr + * @tc.type: FUNC + * @tc.require: NA + * @tc.author: Lirui + */ +HWTEST_F(PreferencesNdkValueTest, NDKPreferencesTest_004, TestSize.Level1) +{ + int errCode = PREFERENCES_OK; + std::string boolKey = "ndktest_int_key"; + errCode = OH_Preferences_Delete(nullptr, boolKey.c_str()); + EXPECT_EQ(errCode, PREFERENCES_ERROR_INVALID_PARAM); + + OH_PreferencesOption *option = GetCommonOption(); + OH_Preferences *pref = OH_Preferences_Open(option, &errCode); + ASSERT_EQ(errCode, PREFERENCES_OK); + + errCode = OH_Preferences_Delete(pref, ""); + EXPECT_EQ(errCode, PREFERENCES_ERROR_INVALID_PARAM); + errCode = OH_Preferences_Delete(pref, nullptr); + EXPECT_EQ(errCode, PREFERENCES_ERROR_INVALID_PARAM); + + EXPECT_EQ(OH_Preferences_Close(pref), PREFERENCES_OK); + + errCode = OH_Preferences_SetBool(pref, boolKey.c_str(), false); + EXPECT_EQ(errCode, PREFERENCES_ERROR_INVALID_PARAM); + bool res; + errCode = OH_Preferences_GetBool(pref, boolKey.c_str(), &res); + EXPECT_EQ(errCode, PREFERENCES_ERROR_INVALID_PARAM); + EXPECT_EQ(res, false); + (void)OH_PreferencesOption_Destroy(option); + + EXPECT_EQ(OHOS::NativePreferences::PreferencesHelper::DeletePreferences("/data/test/valueTestDb"), + OHOS::NativePreferences::E_OK); +} + +/** + * @tc.name: NDKPreferencesTest_005 + * @tc.desc: test key and value + * @tc.type: FUNC + * @tc.require: NA + * @tc.author: Lirui + */ +HWTEST_F(PreferencesNdkValueTest, NDKPreferencesTest_005, TestSize.Level1) +{ + int errCode = PREFERENCES_OK; + std::string boolKey = "ndktest_int_key"; + errCode = OH_Preferences_Delete(nullptr, boolKey.c_str()); + EXPECT_EQ(errCode, PREFERENCES_ERROR_INVALID_PARAM); + + OH_PreferencesOption *option = GetCommonOption(); + OH_Preferences *pref = OH_Preferences_Open(option, &errCode); + ASSERT_EQ(errCode, PREFERENCES_OK); + (void)OH_PreferencesOption_Destroy(option); + + std::string stringKey(1024, 'a'); + errCode = OH_Preferences_SetString(pref, stringKey.c_str(), "test"); + EXPECT_EQ(errCode, PREFERENCES_OK); + errCode = OH_Preferences_SetString(pref, stringKey.append("a").c_str(), "test"); + EXPECT_EQ(errCode, PREFERENCES_ERROR_INVALID_PARAM); + std::string stringValue(16 * 1024 * 1024, 'a'); + errCode = OH_Preferences_SetString(pref, "test", stringValue.c_str()); + EXPECT_EQ(errCode, PREFERENCES_OK); + errCode = OH_Preferences_SetString(pref, "test", stringValue.append("a").c_str()); + EXPECT_EQ(errCode, PREFERENCES_ERROR_INVALID_PARAM); + + EXPECT_EQ(OH_Preferences_Close(pref), PREFERENCES_OK); + EXPECT_EQ(OHOS::NativePreferences::PreferencesHelper::DeletePreferences("/data/test/valueTestDb"), + OHOS::NativePreferences::E_OK); +} + +/** + * @tc.name: NDKPreferencesTestEmptyValueTest001 + * @tc.desc: test key and value + * @tc.type: FUNC + * @tc.require: NA + * @tc.author: Lirui + */ +HWTEST_F(PreferencesNdkValueTest, NDKPreferencesTestEmptyValueTest001, TestSize.Level1) +{ + int errCode = PREFERENCES_OK; + OH_PreferencesOption *option = GetCommonOption(); + OH_Preferences *pref = OH_Preferences_Open(option, &errCode); + ASSERT_EQ(errCode, PREFERENCES_OK); + (void)OH_PreferencesOption_Destroy(option); + + uint32_t len = 0; + char *valueGet = nullptr; + EXPECT_EQ(OH_Preferences_SetString(pref, "abc", ""), PREFERENCES_OK); + errCode = OH_Preferences_GetString(pref, "abc", &valueGet, &len); + ASSERT_EQ(errCode, PREFERENCES_OK); + EXPECT_EQ(strcmp(valueGet, ""), 0); + EXPECT_EQ(len, 1); + EXPECT_EQ(OH_Preferences_Close(pref), PREFERENCES_OK); + EXPECT_EQ(OHOS::NativePreferences::PreferencesHelper::DeletePreferences("/data/test/valueTestDb"), + OHOS::NativePreferences::E_OK); +} + +/** + * @tc.name: NDKPreferencesTestEmptyValueTest001 + * @tc.desc: test key and value + * @tc.type: FUNC + * @tc.require: NA + * @tc.author: bluhuang + */ +HWTEST_F(PreferencesNdkValueTest, NDKPreferencesTestTypeTest001, TestSize.Level1) +{ + int errCode = PREFERENCES_OK; + OH_PreferencesOption *option = GetCommonOption(); + OH_Preferences *pref = OH_Preferences_Open(option, &errCode); + ASSERT_EQ(errCode, PREFERENCES_OK); + (void)OH_PreferencesOption_Destroy(option); + + std::string key = "testKey"; + uint32_t len = 0; + char *strValue = nullptr; + bool boolValue = false; + int intValue = -1; + EXPECT_EQ(OH_Preferences_SetInt(pref, key.c_str(), 123), PREFERENCES_OK); + EXPECT_EQ(OH_Preferences_GetString(pref, key.c_str(), &strValue, &len), PREFERENCES_ERROR_KEY_NOT_FOUND); + EXPECT_EQ(OH_Preferences_GetBool(pref, key.c_str(), &boolValue), PREFERENCES_ERROR_KEY_NOT_FOUND); + EXPECT_EQ(OH_Preferences_GetInt(pref, key.c_str(), &intValue), PREFERENCES_OK); + + EXPECT_EQ(OH_Preferences_SetBool(pref, key.c_str(), true), PREFERENCES_OK); + EXPECT_EQ(OH_Preferences_GetInt(pref, key.c_str(), &intValue), PREFERENCES_ERROR_KEY_NOT_FOUND); + EXPECT_EQ(OH_Preferences_GetString(pref, key.c_str(), &strValue, &len), PREFERENCES_ERROR_KEY_NOT_FOUND); + EXPECT_EQ(OH_Preferences_GetBool(pref, key.c_str(), &boolValue), PREFERENCES_OK); + + EXPECT_EQ(OH_Preferences_SetString(pref, key.c_str(), ""), PREFERENCES_OK); + EXPECT_EQ(OH_Preferences_GetBool(pref, key.c_str(), &boolValue), PREFERENCES_ERROR_KEY_NOT_FOUND); + EXPECT_EQ(OH_Preferences_GetInt(pref, key.c_str(), &intValue), PREFERENCES_ERROR_KEY_NOT_FOUND); + EXPECT_EQ(OH_Preferences_GetString(pref, key.c_str(), &strValue, &len), PREFERENCES_OK); + + EXPECT_EQ(OH_Preferences_Close(pref), PREFERENCES_OK); + EXPECT_EQ(OHOS::NativePreferences::PreferencesHelper::DeletePreferences("/data/test/valueTestDb"), + OHOS::NativePreferences::E_OK); +} +} diff --git a/preferences/test/ndk/unittest/preferences_test_utils.cpp b/preferences/test/ndk/unittest/preferences_test_utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1c6bf3468a0bd5b19f4ba19b830a69a2892a9e9f --- /dev/null +++ b/preferences/test/ndk/unittest/preferences_test_utils.cpp @@ -0,0 +1,65 @@ +/* + * 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 "preferences_test_utils.h" +#include "oh_preferences.h" +#include "convertor_error_code.h" +#include "log_print.h" +#include "oh_preferences_err_code.h" +#include "oh_preferences_impl.h" +#include "oh_preferences_value_impl.h" +#include "oh_preferences_value.h" +#include "preferences_file_operation.h" +#include "preferences_helper.h" + +namespace OHOS { +namespace PreferencesNdk { + +void NdkTestUtils::CreateDirectoryRecursively(const std::string &path) +{ + std::string::size_type pos = path.find_last_of('/'); + if (pos == std::string::npos || path.front() != '/') { + printf("path can not be relative path.\n"); + } + std::string dir = path.substr(0, pos); + + std::string tempDirectory = dir; + std::vector directories; + + pos = tempDirectory.find('/'); + while (pos != std::string::npos) { + std::string directory = tempDirectory.substr(0, pos); + if (!directory.empty()) { + directories.push_back(directory); + } + tempDirectory = tempDirectory.substr(pos + 1); + pos = tempDirectory.find('/'); + } + directories.push_back(tempDirectory); + + std::string databaseDirectory; + for (const std::string& directory : directories) { + databaseDirectory = databaseDirectory + "/" + directory; + if (OHOS::NativePreferences::Access(databaseDirectory.c_str()) != F_OK) { + if (OHOS::NativePreferences::Mkdir(databaseDirectory)) { + printf("failed to mkdir, errno %d, %s \n", errno, databaseDirectory.c_str()); + return; + } + } + } +} + +} // End of namespace PreferencesNdk +} // End of namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/customutdinstaller_fuzzer/customutdinstaller_fuzzer.h b/preferences/test/ndk/unittest/preferences_test_utils.h similarity index 62% rename from datamgr_service/services/distributeddataservice/service/test/fuzztest/customutdinstaller_fuzzer/customutdinstaller_fuzzer.h rename to preferences/test/ndk/unittest/preferences_test_utils.h index da098deb1ff316284700c1371e63a2f89eefe608..46e8de62578db9c543e32210cd5b310bf983d588 100644 --- a/datamgr_service/services/distributeddataservice/service/test/fuzztest/customutdinstaller_fuzzer/customutdinstaller_fuzzer.h +++ b/preferences/test/ndk/unittest/preferences_test_utils.h @@ -13,9 +13,20 @@ * limitations under the License. */ -#ifndef CUSTOM_UTD_INSTALLER_FUZZER_H -#define CUSTOM_UTD_INSTALLER_FUZZER_H +#ifndef PREFERENCES_TEST_UTILS_H +#define PREFERENCES_TEST_UTILS_H -#define FUZZ_PROJECT_NAME "customutdinstaller_fuzzer" +#include -#endif // CUSTOM_UTD_INSTALLER_FUZZER_H \ No newline at end of file +#include "oh_preferences.h" + +namespace OHOS { +namespace PreferencesNdk { + +class NdkTestUtils { +public: + static void CreateDirectoryRecursively(const std::string &path); +}; +} // End of namespace PreferencesNdk +} // End of namespace OHOS +#endif // End of #ifndef PREFERENCES_TEST_UTILS_H \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/cloud_data/BUILD.gn b/relational_store/frameworks/js/napi/cloud_data/BUILD.gn index 163d59a9202a724f1f563ba29a9ff80085eccc67..b9ffc946da2a48976bb806adc5344cff93d6aebc 100644 --- a/relational_store/frameworks/js/napi/cloud_data/BUILD.gn +++ b/relational_store/frameworks/js/napi/cloud_data/BUILD.gn @@ -34,6 +34,7 @@ ohos_shared_library("clouddata") { "${cloud_data_native_path}/src/cloud_manager.cpp", "${cloud_data_native_path}/src/cloud_service_proxy.cpp", "${cloud_data_native_path}/src/cloud_types_util.cpp", + "${relational_store_napi_path}/common/src/js_df_manager.cpp", "${relational_store_napi_path}/common/src/js_utils.cpp", ] diff --git a/relational_store/frameworks/js/napi/cloud_data/src/js_config.cpp b/relational_store/frameworks/js/napi/cloud_data/src/js_config.cpp index c9b8174f4761cf12a0ca6a757ac52c7487d942b2..31a5fe07f4801883df87ef4c317e7bb2b95e7377 100644 --- a/relational_store/frameworks/js/napi/cloud_data/src/js_config.cpp +++ b/relational_store/frameworks/js/napi/cloud_data/src/js_config.cpp @@ -26,6 +26,7 @@ #include "js_strategy_context.h" #include "logger.h" #include "napi_queue.h" +#include "js_df_manager.h" using namespace OHOS::Rdb; using namespace OHOS::CloudData; @@ -434,6 +435,10 @@ napi_value JsConfig::New(napi_env env, napi_callback_info info) } auto finalize = [](napi_env env, void *data, void *hint) { + auto tid = JSDFManager::GetInstance().GetFreedTid(data); + if (tid != 0) { + LOG_ERROR("(T:%{public}d) freed! data:0x%016" PRIXPTR, tid, uintptr_t(data) & LOWER_24_BITS_MASK); + } LOG_DEBUG("cloudConfig finalize."); auto *config = reinterpret_cast(data); ASSERT_VOID(config != nullptr, "finalize null!"); @@ -447,6 +452,7 @@ napi_value JsConfig::New(napi_env env, napi_callback_info info) finalize(env, cloudConfig, nullptr); return nullptr; } + JSDFManager::GetInstance().AddNewInfo(cloudConfig); return self; } @@ -470,18 +476,12 @@ napi_value JsConfig::QueryLastSyncInfo(napi_env env, napi_callback_info info) status = JSUtils::Convert2Value(env, argv[1], ctxt->bundleName); ASSERT_BUSINESS_ERR( ctxt, status == JSUtils::OK, Status::INVALID_ARGUMENT, "The type of bundleName must be string."); - - // 3 means param exist - if (argc >= 3) { - napi_valuetype valueType = napi_undefined; + // 2 is the index of argument storeId + if (argc > 2 && !JSUtils::IsNull(ctxt->env, argv[2])) { // 2 is the index of argument storeId - napi_typeof(env, argv[2], &valueType); - if (valueType == napi_string) { - // 2 is the index of argument storeId - status = JSUtils::Convert2Value(env, argv[2], ctxt->storeId); - ASSERT_BUSINESS_ERR( - ctxt, status == JSUtils::OK, Status::INVALID_ARGUMENT, "The type of storeId must be string."); - } + status = JSUtils::Convert2Value(env, argv[2], ctxt->storeId); + ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK, Status::INVALID_ARGUMENT, + "The type of storeId must be string."); } }); diff --git a/relational_store/frameworks/js/napi/cloud_extension/cloud_extension_stub.js b/relational_store/frameworks/js/napi/cloud_extension/cloud_extension_stub.js index 6293c4769b3d5008feb999ac0ae92f100e6e7bc1..eef8a03ea9c1b68775572f4a8b0f44dd2108cd45 100644 --- a/relational_store/frameworks/js/napi/cloud_extension/cloud_extension_stub.js +++ b/relational_store/frameworks/js/napi/cloud_extension/cloud_extension_stub.js @@ -21,7 +21,7 @@ const INVALID_STATE = -1; const INVALID_STR = ''; const MAX_SIZE = 4 * 1024 * 1024 * 1024 - 1; -export var cloudExtension; +export let cloudExtension; (function (a) { let f; (function (f) { @@ -484,7 +484,7 @@ export var cloudExtension; } else if (t1 instanceof Uint8Array) { u.writeInt(f.BLOB); - var l3 = []; + let l3 = []; for (let f2 = 0; f2 < t1.length; f2++) { l3.push(t1[f2]); } diff --git a/relational_store/interfaces/inner_api/rdb/mock/include/rdb_helper.h b/relational_store/frameworks/js/napi/common/include/js_df_manager.h similarity index 47% rename from relational_store/interfaces/inner_api/rdb/mock/include/rdb_helper.h rename to relational_store/frameworks/js/napi/common/include/js_df_manager.h index 2183de99fc99dd26dc953b86662113abf6e3f0ff..e30fc60b57697564519575c4de9acddcb5ad7e4c 100644 --- a/relational_store/interfaces/inner_api/rdb/mock/include/rdb_helper.h +++ b/relational_store/frameworks/js/napi/common/include/js_df_manager.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * 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 @@ -13,27 +13,23 @@ * limitations under the License. */ -#ifndef NATIVE_RDB_RDB_HELPER_H -#define NATIVE_RDB_RDB_HELPER_H - -#include +#ifndef OHOS_DISTRIBUTED_DATA_RELATIONAL_STORE_FRAMEWORKS_JS_NAPI_COMMON_JSUAF_MANAGER_H +#define OHOS_DISTRIBUTED_DATA_RELATIONAL_STORE_FRAMEWORKS_JS_NAPI_COMMON_JSUAF_MANAGER_H +#include +#include #include -#include - -#include "rdb_open_callback.h" -#include "rdb_store.h" -#include "rdb_store_config.h" - -namespace OHOS { -namespace NativeRdb { -class RdbHelper final { +namespace OHOS::AppDataMgrJsKit { +class JSDFManager { public: - static std::shared_ptr GetRdbStore( - const RdbStoreConfig &config, int version, RdbOpenCallback &openCallback, int &errCode); - static int DeleteRdbStore(const std::string &path); - static int DeleteRdbStore(const RdbStoreConfig &config); - static void ClearCache(); + static JSDFManager &GetInstance(); + void AddNewInfo(void *data); + int32_t GetFreedTid(void *data); + +private: + std::map instances_; + std::mutex mapMutex; }; -} // namespace NativeRdb -} // namespace OHOS -#endif +} + +constexpr auto LOWER_24_BITS_MASK = (1u << 24) - 1; +#endif // OHOS_DISTRIBUTED_DATA_RELATIONAL_STORE_FRAMEWORKS_JS_NAPI_COMMON_JSUAF_MANAGER_H diff --git a/relational_store/frameworks/js/napi/common/src/js_df_manager.cpp b/relational_store/frameworks/js/napi/common/src/js_df_manager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5638415bf462506964a97031a1ff9f9327e4c665 --- /dev/null +++ b/relational_store/frameworks/js/napi/common/src/js_df_manager.cpp @@ -0,0 +1,56 @@ +/* + * 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 "js_df_manager.h" + +namespace OHOS::AppDataMgrJsKit { +JSDFManager &JSDFManager::GetInstance() +{ + static JSDFManager instance; + return instance; +} + +void JSDFManager::AddNewInfo(void *data) +{ + std::lock_guard lockGuard(mapMutex); + instances_[data] = 0; +} + +int32_t JSDFManager::GetFreedTid(void *data) +{ + std::lock_guard lockGuard(mapMutex); + int32_t freedTid = 0; + auto it = instances_.find(data); + if (it != instances_.end()) { + auto tid = it->second; + if (tid != 0) { + freedTid = tid; + } else { +#if defined(CROSS_PLATFORM) + tid = 0; +#else + // tid = gettid(); + tid = random(); +#endif + instances_[data] = tid; + } + } + return freedTid; +} +} \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/dataability/BUILD.gn b/relational_store/frameworks/js/napi/dataability/BUILD.gn index 7d79cc09cc1ce6735852fa37655fe99138cf614b..4dc0670f0d37ad15b74e47b832976ce9ae4dcfd1 100644 --- a/relational_store/frameworks/js/napi/dataability/BUILD.gn +++ b/relational_store/frameworks/js/napi/dataability/BUILD.gn @@ -31,6 +31,7 @@ ohos_shared_library("dataability") { sources = [ "${relational_store_js_common_path}/src/js_utils.cpp", + "${relational_store_napi_path}/common/src/js_df_manager.cpp", "src/entry_point.cpp", "src/napi_data_ability_predicates.cpp", "src/napi_predicates_utils.cpp", diff --git a/relational_store/frameworks/js/napi/dataability/src/napi_data_ability_predicates.cpp b/relational_store/frameworks/js/napi/dataability/src/napi_data_ability_predicates.cpp index 93d528a0129fc52d63d46919b829b4f6fb22b7f8..3a91edd52a6880fc7b57ee1a49635be600ce4453 100644 --- a/relational_store/frameworks/js/napi/dataability/src/napi_data_ability_predicates.cpp +++ b/relational_store/frameworks/js/napi/dataability/src/napi_data_ability_predicates.cpp @@ -19,6 +19,7 @@ #include "logger.h" #include "napi_async_proxy.h" #include "napi_predicates_utils.h" +#include "js_df_manager.h" using namespace OHOS::Rdb; using namespace OHOS::NativeRdb; @@ -104,6 +105,7 @@ napi_value DataAbilityPredicatesProxy::New(napi_env env, napi_callback_info info delete proxy; return nullptr; } + JSDFManager::GetInstance().AddNewInfo(proxy); return thiz; } @@ -161,7 +163,12 @@ std::shared_ptr DataAbilityPredicatesProxy::Ge void DataAbilityPredicatesProxy::Destructor(napi_env env, void *nativeObject, void *) { + auto tid = JSDFManager::GetInstance().GetFreedTid(nativeObject); + if (tid != 0) { + LOG_ERROR("(T:%{public}d) freed! data:0x%016" PRIXPTR, tid, uintptr_t(nativeObject) & LOWER_24_BITS_MASK); + } DataAbilityPredicatesProxy *proxy = static_cast(nativeObject); + proxy->predicates_ = std::move(nullptr); delete proxy; } diff --git a/relational_store/frameworks/js/napi/rdb/BUILD.gn b/relational_store/frameworks/js/napi/rdb/BUILD.gn index 146a40616b193facf245d2a80ac8b18fb2b6bed8..db0236f0d29626692aab1857f44ab36d4cc607b3 100644 --- a/relational_store/frameworks/js/napi/rdb/BUILD.gn +++ b/relational_store/frameworks/js/napi/rdb/BUILD.gn @@ -23,6 +23,7 @@ ohos_copy("relational_store_declaration") { ohos_shared_library("napi_rdb") { sources = [ + "../common/src/js_df_manager.cpp", "../common/src/js_utils.cpp", "src/napi_async_call.cpp", "src/napi_rdb_const_properties.cpp", @@ -52,10 +53,16 @@ ohos_shared_library("napi_rdb") { ] if (is_mac) { buildos = "mac" - defines = [ "MAC_PLATFORM" ] + defines = [ + "MAC_PLATFORM", + "CROSS_PLATFORM", + ] } else { buildos = "windows" - defines = [ "WINDOWS_PLATFORM" ] + defines = [ + "WINDOWS_PLATFORM", + "CROSS_PLATFORM", + ] } sources += [ "${relational_store_js_common_path}/mock/src/js_ability.cpp" ] deps = [ @@ -123,10 +130,16 @@ ohos_shared_library("rdb") { ] if (is_mac) { buildos = "mac" - defines = [ "MAC_PLATFORM" ] + defines = [ + "MAC_PLATFORM", + "CROSS_PLATFORM", + ] } else { buildos = "windows" - defines = [ "WINDOWS_PLATFORM" ] + defines = [ + "WINDOWS_PLATFORM", + "CROSS_PLATFORM", + ] } deps = [ diff --git a/relational_store/frameworks/js/napi/rdb/src/napi_rdb_predicates.cpp b/relational_store/frameworks/js/napi/rdb/src/napi_rdb_predicates.cpp index 609e8cc94668b97a74b4f6edee6fddd34b2f02b2..6ad5b674f219922efbf554ab753d0e73a6d16593 100644 --- a/relational_store/frameworks/js/napi/rdb/src/napi_rdb_predicates.cpp +++ b/relational_store/frameworks/js/napi/rdb/src/napi_rdb_predicates.cpp @@ -19,6 +19,7 @@ #include "logger.h" #include "napi_rdb_error.h" #include "napi_rdb_trace.h" +#include "js_df_manager.h" using namespace OHOS::Rdb; using namespace OHOS::NativeRdb; @@ -141,6 +142,7 @@ napi_value RdbPredicatesProxy::InnerNew(napi_env env, napi_callback_info info, i delete proxy; return nullptr; } + JSDFManager::GetInstance().AddNewInfo(proxy); return thiz; } @@ -186,7 +188,12 @@ napi_value RdbPredicatesProxy::NewInstance(napi_env env, std::shared_ptr(nativeObject); + proxy->predicates_ = std::move(nullptr); delete proxy; } diff --git a/relational_store/frameworks/js/napi/rdb/src/napi_rdb_store.cpp b/relational_store/frameworks/js/napi/rdb/src/napi_rdb_store.cpp index 3595c3f371565cd2cf6faf13d29995353b77af56..0a20b3fe6b69cc8ef41b2ddd9a3a8e8489727ddf 100644 --- a/relational_store/frameworks/js/napi/rdb/src/napi_rdb_store.cpp +++ b/relational_store/frameworks/js/napi/rdb/src/napi_rdb_store.cpp @@ -27,6 +27,7 @@ #include "napi_rdb_trace.h" #include "napi_result_set.h" #include "rdb_errno.h" +#include "js_df_manager.h" #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) #include "rdb_utils.h" @@ -152,7 +153,12 @@ napi_value RdbStoreProxy::InnerInitialize(napi_env env, napi_callback_info info, napi_value self = nullptr; NAPI_CALL(env, napi_get_cb_info(env, info, NULL, NULL, &self, nullptr)); auto finalize = [](napi_env env, void *data, void *hint) { + auto tid = JSDFManager::GetInstance().GetFreedTid(data); + if (tid != 0) { + LOG_ERROR("(T:%{public}d) freed! data:0x%016" PRIXPTR, tid, uintptr_t(data) & LOWER_24_BITS_MASK); + } RdbStoreProxy *proxy = reinterpret_cast(data); + proxy->rdbStore_ = std::move(nullptr); delete proxy; }; auto *proxy = new (std::nothrow) RdbStoreProxy(); @@ -166,6 +172,7 @@ napi_value RdbStoreProxy::InnerInitialize(napi_env env, napi_callback_info info, delete proxy; return nullptr; } + JSDFManager::GetInstance().AddNewInfo(proxy); return self; } @@ -700,7 +707,11 @@ napi_value RdbStoreProxy::Query(napi_env env, napi_callback_info info) auto exec = [context]() { RdbStoreProxy *obj = reinterpret_cast(context->boundObj); CHECK_RETURN_ERR(obj != nullptr && obj->rdbStore_ != nullptr); +#if defined(WINDOWS_PLATFORM) || defined(MAC_PLATFORM) || defined(ANDROID_PLATFORM) || defined(IOS_PLATFORM) + context->resultSet = obj->rdbStore_->QueryByStep(*(context->rdbPredicates), context->columns); +#else context->resultSet = obj->rdbStore_->Query(*(context->rdbPredicates), context->columns); +#endif LOG_DEBUG("RdbStoreProxy::Query result is nullptr ? %{public}d.", (context->resultSet == nullptr)); return (context->resultSet != nullptr) ? OK : ERR; }; diff --git a/relational_store/frameworks/js/napi/rdb/src/napi_result_set.cpp b/relational_store/frameworks/js/napi/rdb/src/napi_result_set.cpp index 1f12bd438e1d3581d831b9fa5b2a049b441f49b2..3ecf55c107bb11bf488b14c8356bded780d7fdd6 100644 --- a/relational_store/frameworks/js/napi/rdb/src/napi_result_set.cpp +++ b/relational_store/frameworks/js/napi/rdb/src/napi_result_set.cpp @@ -22,6 +22,7 @@ #include "napi_rdb_error.h" #include "napi_rdb_trace.h" #include "rdb_errno.h" +#include "js_df_manager.h" #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) #include "abs_shared_result_set.h" @@ -178,7 +179,12 @@ napi_value ResultSetProxy::InnerInitialize(napi_env env, napi_callback_info info } proxy->apiversion = version; auto finalize = [](napi_env env, void *data, void *hint) { + auto tid = JSDFManager::GetInstance().GetFreedTid(data); + if (tid != 0) { + LOG_ERROR("(T:%{public}d) freed! data:0x%016" PRIXPTR, tid, uintptr_t(data) & LOWER_24_BITS_MASK); + } ResultSetProxy *proxy = reinterpret_cast(data); + proxy->SetInstance(nullptr); delete proxy; }; napi_status status = napi_wrap(env, self, proxy, finalize, nullptr, nullptr); @@ -187,6 +193,7 @@ napi_value ResultSetProxy::InnerInitialize(napi_env env, napi_callback_info info finalize(env, proxy, nullptr); return nullptr; } + JSDFManager::GetInstance().AddNewInfo(proxy); return self; } diff --git a/relational_store/frameworks/js/napi/relationalstore/BUILD.gn b/relational_store/frameworks/js/napi/relationalstore/BUILD.gn index 60d56eb45ee7ee410484c90c73db6abd1ff29b3c..53b602514696544a989aa5296ac389c84cdf758e 100644 --- a/relational_store/frameworks/js/napi/relationalstore/BUILD.gn +++ b/relational_store/frameworks/js/napi/relationalstore/BUILD.gn @@ -22,6 +22,7 @@ ohos_copy("relational_store_declaration") { } sources = [ + "../common/src/js_df_manager.cpp", "../common/src/js_scope.cpp", "../common/src/js_sendable_utils.cpp", "../common/src/js_utils.cpp", @@ -36,6 +37,7 @@ sources = [ "src/napi_rdb_store.cpp", "src/napi_rdb_store_helper.cpp", "src/napi_result_set.cpp", + "src/napi_transaction.cpp", "src/napi_uv_queue.cpp", ] @@ -100,6 +102,7 @@ if (is_ohos) { buildos = "windows" defines = [ "WINDOWS_PLATFORM", + "CROSS_PLATFORM", "API_EXPORT=__declspec(dllimport)", ] @@ -136,7 +139,10 @@ if (is_ohos) { ] buildos = "mac" - defines = [ "MAC_PLATFORM" ] + defines = [ + "MAC_PLATFORM", + "CROSS_PLATFORM", + ] sources += [ "${relational_store_js_common_path}/mock/src/js_ability.cpp" ] @@ -212,7 +218,10 @@ if (is_ohos) { "-stdlib=libc++", ] - defines = [ "IOS_PLATFORM" ] + defines = [ + "IOS_PLATFORM", + "CROSS_PLATFORM", + ] sources += [ "${relational_store_js_common_path}/mock/src/js_ability.cpp" ] diff --git a/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_context.h b/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_context.h index 2a89fe25caa2c62371afa0c80d593e9f02eb917e..844150a2a884b98d8211ac978ac6af003e4d95cd 100644 --- a/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_context.h +++ b/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_context.h @@ -18,12 +18,20 @@ #include "napi_async_call.h" #include "napi_rdb_predicates.h" +#include "transaction.h" +#include "values_buckets.h" namespace OHOS { namespace RelationalStoreJsKit { class ResultSetProxy; using namespace OHOS::NativeRdb; struct RdbStoreContextBase : public ContextBase { + std::shared_ptr StealRdbStore() + { + auto rdb = std::move(rdbStore); + rdbStore = nullptr; + return rdb; + } std::shared_ptr rdbStore = nullptr; }; @@ -37,6 +45,7 @@ struct RdbStoreContext : public RdbStoreContextBase { std::vector columns; ValuesBucket valuesBucket; std::vector valuesBuckets; + ValuesBuckets sharedValuesBuckets; std::map numberMaps; std::vector bindArgs; int64_t int64Output; @@ -73,6 +82,11 @@ struct RdbStoreContext : public RdbStoreContextBase { { } }; + +struct CreateTransactionContext : public RdbStoreContextBase { + int32_t transactionType = 0; + std::shared_ptr transaction; +}; } // namespace RelationalStoreJsKit } // namespace OHOS #endif // NAPI_RDB_CONTEXT_H \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_js_utils.h b/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_js_utils.h index b578cca131cb61ddcaa7626341a76b3a30f6dd00..4ecc0ab49ae5a2398347bbbff8764cad5de24ccb 100644 --- a/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_js_utils.h +++ b/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_js_utils.h @@ -27,6 +27,8 @@ #include "result_set.h" #include "value_object.h" #include "values_bucket.h" +#include "values_buckets.h" + namespace OHOS::AppDataMgrJsKit { namespace JSUtils { using Asset = OHOS::NativeRdb::AssetValue; @@ -41,7 +43,12 @@ using RdbStoreConfig = NativeRdb::RdbStoreConfig; using BigInt = OHOS::NativeRdb::BigInteger; using SqlExecInfo = DistributedRdb::SqlObserver::SqlExecutionInfo; using ValuesBucket = OHOS::NativeRdb::ValuesBucket; +using ValuesBuckets = OHOS::NativeRdb::ValuesBuckets; using HAMode = NativeRdb::HAMode; +using HmacAlgo = NativeRdb::HmacAlgo; +using KdfAlgo = NativeRdb::KdfAlgo; +using EncryptAlgo = NativeRdb::EncryptAlgo; +using CryptoParam = NativeRdb::RdbStoreConfig::CryptoParam; struct RdbConfig { bool isEncrypt = false; bool isSearchable = false; @@ -56,6 +63,7 @@ struct RdbConfig { std::string path; std::vector pluginLibs = {}; int32_t haMode = HAMode::SINGLE; + CryptoParam cryptoParam; }; struct ContextParam { @@ -79,6 +87,9 @@ int32_t Convert2Value(napi_env env, napi_value jsValue, DistributedRdb::Distribu template<> int32_t Convert2Value(napi_env env, napi_value jsValue, ValueObject &valueObject); +template<> +int32_t Convert2Value(napi_env env, napi_value jsValue, CryptoParam &cryptoParam); + template<> int32_t Convert2Value(napi_env env, napi_value jsValue, RdbConfig &rdbConfig); @@ -125,6 +136,7 @@ bool HasDuplicateAssets(const ValueObject &value); bool HasDuplicateAssets(const std::vector &values); bool HasDuplicateAssets(const ValuesBucket &value); bool HasDuplicateAssets(const std::vector &values); +bool HasDuplicateAssets(const ValuesBuckets &values); }; // namespace JSUtils } // namespace OHOS::AppDataMgrJsKit #endif // RDB_JSKIT_NAPI_RDB_JS_UTILS_H \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_store.h b/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_store.h index 6f867da256167db0d32f1d33fd82713f042c6055..23f74e460c36709bfc84b292cf873619e87e9f88 100644 --- a/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_store.h +++ b/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_store.h @@ -61,7 +61,6 @@ private: static napi_value Detach(napi_env env, napi_callback_info info); static napi_value GetPath(napi_env env, napi_callback_info info); static napi_value IsMemoryRdb(napi_env env, napi_callback_info info); - static napi_value IsHoldingConnection(napi_env env, napi_callback_info info); static napi_value IsReadOnly(napi_env env, napi_callback_info info); static napi_value BeginTransaction(napi_env env, napi_callback_info info); static napi_value BeginTrans(napi_env env, napi_callback_info info); @@ -70,7 +69,6 @@ private: static napi_value Commit(napi_env env, napi_callback_info info); static napi_value QueryByStep(napi_env env, napi_callback_info info); static napi_value IsInTransaction(napi_env env, napi_callback_info info); - static napi_value IsOpen(napi_env env, napi_callback_info info); static napi_value GetVersion(napi_env env, napi_callback_info info); static napi_value GetRebuilt(napi_env env, napi_callback_info info); static napi_value SetVersion(napi_env env, napi_callback_info info); @@ -86,6 +84,7 @@ private: static napi_value Notify(napi_env env, napi_callback_info info); static napi_value QuerySharingResource(napi_env env, napi_callback_info info); static napi_value Close(napi_env env, napi_callback_info info); + static napi_value CreateTransaction(napi_env env, napi_callback_info info); static Descriptor GetDescriptors(); static void AddSyncFunctions(std::vector &properties); static napi_value ModifyLockStatus(napi_env env, napi_callback_info info, bool isLock); diff --git a/relational_store/frameworks/js/napi/relationalstore/include/napi_transaction.h b/relational_store/frameworks/js/napi/relationalstore/include/napi_transaction.h new file mode 100644 index 0000000000000000000000000000000000000000..13226b782b9278d06e84b8207d71dd122b6b081e --- /dev/null +++ b/relational_store/frameworks/js/napi/relationalstore/include/napi_transaction.h @@ -0,0 +1,52 @@ +/* + * 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. + */ + +#ifndef RDB_JSKIT_NAPI_TRANSACTION_H +#define RDB_JSKIT_NAPI_TRANSACTION_H + +#include + +#include "js_proxy.h" +#include "napi/native_api.h" +#include "napi/native_common.h" +#include "napi/native_node_api.h" +#include "transaction.h" + +namespace OHOS { +namespace RelationalStoreJsKit { +class TransactionProxy final : public JSProxy::JSProxy { +public: + TransactionProxy() = default; + ~TransactionProxy(); + TransactionProxy(std::shared_ptr transaction); + static void Init(napi_env env, napi_value exports); + static napi_value NewInstance(napi_env env, std::shared_ptr transaction); + +private: + static napi_value Initialize(napi_env env, napi_callback_info info); + static napi_value Commit(napi_env env, napi_callback_info info); + static napi_value Rollback(napi_env env, napi_callback_info info); + static napi_value Delete(napi_env env, napi_callback_info info); + static napi_value Update(napi_env env, napi_callback_info info); + static napi_value Insert(napi_env env, napi_callback_info info); + static napi_value BatchInsert(napi_env env, napi_callback_info info); + static napi_value Query(napi_env env, napi_callback_info info); + static napi_value QuerySql(napi_env env, napi_callback_info info); + static napi_value Execute(napi_env env, napi_callback_info info); + static void AddSyncFunctions(std::vector &properties); +}; +} // namespace RelationalStoreJsKit +} // namespace OHOS +#endif // RDB_JSKIT_NAPI_TRANSACTION_H diff --git a/relational_store/frameworks/js/napi/relationalstore/mock/include/napi_rdb_store.h b/relational_store/frameworks/js/napi/relationalstore/mock/include/napi_rdb_store.h index 7784564e2bf77db29a5f4870fbcf44f3aa341bfb..2b178af9b9866fd202774133944c731b515cb0b8 100644 --- a/relational_store/frameworks/js/napi/relationalstore/mock/include/napi_rdb_store.h +++ b/relational_store/frameworks/js/napi/relationalstore/mock/include/napi_rdb_store.h @@ -74,6 +74,7 @@ private: static napi_value SetVersion(napi_env env, napi_callback_info info); static napi_value Restore(napi_env env, napi_callback_info info); static napi_value Close(napi_env env, napi_callback_info info); + static napi_value CreateTransaction(napi_env env, napi_callback_info info); int32_t dbType = NativeRdb::DB_SQLITE; std::mutex mutex_; diff --git a/relational_store/frameworks/js/napi/relationalstore/src/entry_point.cpp b/relational_store/frameworks/js/napi/relationalstore/src/entry_point.cpp index f47662bfa0a06af171de38ac4b11c7c6fcf992c3..713b0da8279fd19f9df5107a22d2733a79eb8076 100644 --- a/relational_store/frameworks/js/napi/relationalstore/src/entry_point.cpp +++ b/relational_store/frameworks/js/napi/relationalstore/src/entry_point.cpp @@ -18,6 +18,7 @@ #include "napi_rdb_store_helper.h" #include "napi_rdb_const_properties.h" #include "napi_result_set.h" +#include "napi_transaction.h" #include "napi/native_api.h" using namespace OHOS::RelationalStoreJsKit; @@ -32,6 +33,7 @@ static napi_value Init(napi_env env, napi_value exports) RdbStoreProxy::Init(env, exports); RdbPredicatesProxy::Init(env, exports); ResultSetProxy::Init(env, exports); + TransactionProxy::Init(env, exports); InitConstProperties(env, exports); return exports; } diff --git a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_const_properties.cpp b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_const_properties.cpp index 7786a504c257ce535fde30505a5817fde31cda04..4e6f768be6391237fa8c79175b486f7637357d53 100644 --- a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_const_properties.cpp +++ b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_const_properties.cpp @@ -211,6 +211,53 @@ static napi_value ExportHAMode(napi_env env) return haMode; } +static napi_value ExportEncryptionAlgo(napi_env env) +{ + napi_value encryptionAlgo = nullptr; + napi_create_object(env, &encryptionAlgo); + + SET_NAPI_PROPERTY(encryptionAlgo, "AES_256_GCM", int32_t(NativeRdb::EncryptAlgo::AES_256_GCM)); + SET_NAPI_PROPERTY(encryptionAlgo, "AES_256_CBC", int32_t(NativeRdb::EncryptAlgo::AES_256_CBC)); + napi_object_freeze(env, encryptionAlgo); + return encryptionAlgo; +} + +static napi_value ExportHmacAlgo(napi_env env) +{ + napi_value hmacAlgo = nullptr; + napi_create_object(env, &hmacAlgo); + + SET_NAPI_PROPERTY(hmacAlgo, "SHA1", int32_t(NativeRdb::HmacAlgo::SHA1)); + SET_NAPI_PROPERTY(hmacAlgo, "SHA256", int32_t(NativeRdb::HmacAlgo::SHA256)); + SET_NAPI_PROPERTY(hmacAlgo, "SHA512", int32_t(NativeRdb::HmacAlgo::SHA512)); + napi_object_freeze(env, hmacAlgo); + return hmacAlgo; +} + +static napi_value ExportKdfAlgo(napi_env env) +{ + napi_value kdfAlgo = nullptr; + napi_create_object(env, &kdfAlgo); + + SET_NAPI_PROPERTY(kdfAlgo, "KDF_SHA1", int32_t(NativeRdb::KdfAlgo::KDF_SHA1)); + SET_NAPI_PROPERTY(kdfAlgo, "KDF_SHA256", int32_t(NativeRdb::KdfAlgo::KDF_SHA256)); + SET_NAPI_PROPERTY(kdfAlgo, "KDF_SHA512", int32_t(NativeRdb::KdfAlgo::KDF_SHA512)); + napi_object_freeze(env, kdfAlgo); + return kdfAlgo; +} + +static napi_value ExportTransactionType(napi_env env) +{ + napi_value transactionType = nullptr; + napi_create_object(env, &transactionType); + + SET_NAPI_PROPERTY(transactionType, "DEFERRED", int32_t(NativeRdb::Transaction::DEFERRED)); + SET_NAPI_PROPERTY(transactionType, "IMMEDIATE", int32_t(NativeRdb::Transaction::IMMEDIATE)); + SET_NAPI_PROPERTY(transactionType, "EXCLUSIVE", int32_t(NativeRdb::Transaction::EXCLUSIVE)); + napi_object_freeze(env, transactionType); + return transactionType; +} + napi_status InitConstProperties(napi_env env, napi_value exports) { const napi_property_descriptor properties[] = { @@ -229,6 +276,10 @@ napi_status InitConstProperties(napi_env env, napi_value exports) DECLARE_NAPI_PROPERTY("Field", ExportField(env)), DECLARE_NAPI_PROPERTY("RebuildType", ExportRebuiltType(env)), DECLARE_NAPI_PROPERTY("HAMode", ExportHAMode(env)), + DECLARE_NAPI_PROPERTY("EncryptionAlgo", ExportEncryptionAlgo(env)), + DECLARE_NAPI_PROPERTY("HmacAlgo", ExportHmacAlgo(env)), + DECLARE_NAPI_PROPERTY("KdfAlgo", ExportKdfAlgo(env)), + DECLARE_NAPI_PROPERTY("TransactionType", ExportTransactionType(env)), }; size_t count = sizeof(properties) / sizeof(properties[0]); diff --git a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_js_utils.cpp b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_js_utils.cpp index 6cfd5a857b5f38954da007ae87559a5b6f05ec56..9b83fee9f5225eccdbb864ce7bd5c9ea46cc0b42 100644 --- a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_js_utils.cpp +++ b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_js_utils.cpp @@ -133,15 +133,12 @@ napi_value Convert2JSValue(napi_env env, const Asset &value) template<> napi_value Convert2JSValue(napi_env env, const RowEntity &rowEntity) { - std::vector descriptors; + napi_value object = nullptr; + NAPI_CALL_RETURN_ERR(napi_create_object(env, &object), object); auto &values = rowEntity.Get(); for (auto const &[key, value] : values) { - descriptors.emplace_back(DECLARE_JS_PROPERTY(env, key.c_str(), value)); + NAPI_CALL_RETURN_ERR(SetNamedProperty(env, object, key.c_str(), value), object); } - - napi_value object = nullptr; - NAPI_CALL_RETURN_ERR( - napi_create_object_with_properties(env, &object, descriptors.size(), descriptors.data()), object); return object; } @@ -317,6 +314,28 @@ int32_t GetLevel(SecurityLevel level, SecurityLevel &out) } } +template<> +int32_t Convert2Value(napi_env env, napi_value input, CryptoParam &cryptoParam) +{ + napi_valuetype type = napi_undefined; + napi_status status = napi_typeof(env, input, &type); + if (status != napi_ok || type != napi_object) { + LOG_DEBUG("napi_typeof failed status = %{public}d type = %{public}d", status, type); + return napi_invalid_arg; + } + + NAPI_CALL_RETURN_ERR(GetNamedProperty(env, input, "encryptionKey", cryptoParam.encryptKey_), napi_invalid_arg); + NAPI_CALL_RETURN_ERR(GetNamedProperty(env, input, "iterationCount", cryptoParam.iterNum, true), napi_invalid_arg); + NAPI_CALL_RETURN_ERR( + GetNamedProperty(env, input, "encryptionAlgo", cryptoParam.encryptAlgo, true), napi_invalid_arg); + NAPI_CALL_RETURN_ERR(GetNamedProperty(env, input, "hmacAlgo", cryptoParam.hmacAlgo, true), napi_invalid_arg); + NAPI_CALL_RETURN_ERR(GetNamedProperty(env, input, "kdfAlgo", cryptoParam.kdfAlgo, true), napi_invalid_arg); + NAPI_CALL_RETURN_ERR( + GetNamedProperty(env, input, "cryptoPageSize", cryptoParam.cryptoPageSize, true), napi_invalid_arg); + + return napi_ok; +} + template<> int32_t Convert2Value(napi_env env, napi_value jsValue, RdbConfig &rdbConfig) { @@ -358,6 +377,9 @@ int32_t Convert2Value(napi_env env, napi_value jsValue, RdbConfig &rdbConfig) status = GetNamedProperty(env, jsValue, "haMode", rdbConfig.haMode, true); ASSERT(OK == status, "get haMode failed.", napi_invalid_arg); + + status = GetNamedProperty(env, jsValue, "cryptoParam", rdbConfig.cryptoParam, true); + ASSERT(OK == status, "get cryptoParam failed.", napi_invalid_arg); return napi_ok; } @@ -479,6 +501,8 @@ RdbStoreConfig GetRdbStoreConfig(const RdbConfig &rdbConfig, const ContextParam rdbStoreConfig.SetArea(param.area); rdbStoreConfig.SetPluginLibs(rdbConfig.pluginLibs); rdbStoreConfig.SetHaMode(rdbConfig.haMode); + + rdbStoreConfig.SetCryptoParam(rdbConfig.cryptoParam); return rdbStoreConfig; } @@ -529,5 +553,16 @@ bool HasDuplicateAssets(const std::vector &values) } return false; } + +bool HasDuplicateAssets(const ValuesBuckets &values) +{ + const auto &[fields, vals] = values.GetFieldsAndValues(); + for (const auto &valueObject : *vals) { + if (HasDuplicateAssets(valueObject)) { + return true; + } + } + return false; +} }; // namespace JSUtils } // namespace OHOS::AppDataMgrJsKit \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_predicates.cpp b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_predicates.cpp index 724e1296518c6737a13730e62f50557e76db89c7..1c239ee168ab6bd71464c12923a382cd1e4f846b 100644 --- a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_predicates.cpp +++ b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_predicates.cpp @@ -19,6 +19,7 @@ #include "logger.h" #include "napi_rdb_error.h" #include "napi_rdb_trace.h" +#include "js_df_manager.h" using namespace OHOS::Rdb; using namespace OHOS::NativeRdb; @@ -114,6 +115,7 @@ napi_value RdbPredicatesProxy::New(napi_env env, napi_callback_info info) delete proxy; return nullptr; } + JSDFManager::GetInstance().AddNewInfo(proxy); return thiz; } @@ -157,7 +159,13 @@ napi_value RdbPredicatesProxy::NewInstance(napi_env env, std::shared_ptr(nativeObject); + + proxy->SetInstance(nullptr); delete proxy; } 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 62c151f2e2b2446a15592307b1531d99e3697a79..53880dac4a4ada2014dba671c4c8723aecccf3b8 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 @@ -31,9 +31,11 @@ #include "napi_rdb_js_utils.h" #include "napi_rdb_trace.h" #include "napi_result_set.h" +#include "napi_transaction.h" #include "rdb_errno.h" #include "rdb_sql_statistic.h" #include "securec.h" +#include "js_df_manager.h" #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) #include "rdb_utils.h" @@ -164,6 +166,7 @@ Descriptor RdbStoreProxy::GetDescriptors() DECLARE_NAPI_FUNCTION("close", Close), DECLARE_NAPI_FUNCTION("attach", Attach), DECLARE_NAPI_FUNCTION("detach", Detach), + DECLARE_NAPI_FUNCTION("createTransaction", CreateTransaction), #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) DECLARE_NAPI_FUNCTION("remoteQuery", RemoteQuery), DECLARE_NAPI_FUNCTION("setDistributedTables", SetDistributedTables), @@ -210,12 +213,17 @@ napi_value RdbStoreProxy::Initialize(napi_env env, napi_callback_info info) napi_value self = nullptr; NAPI_CALL(env, napi_get_cb_info(env, info, NULL, NULL, &self, nullptr)); auto finalize = [](napi_env env, void *data, void *hint) { + auto tid = JSDFManager::GetInstance().GetFreedTid(data); + if (tid != 0) { + LOG_ERROR("(T:%{public}d) freed! data:0x%016" PRIXPTR, tid, uintptr_t(data) & LOWER_24_BITS_MASK); + } if (data != hint) { LOG_ERROR("RdbStoreProxy memory corrupted! data:0x%016" PRIXPTR "hint:0x%016" PRIXPTR, uintptr_t(data), uintptr_t(hint)); return; } RdbStoreProxy *proxy = reinterpret_cast(data); + proxy->SetInstance(nullptr); delete proxy; }; auto *proxy = new (std::nothrow) RdbStoreProxy(); @@ -228,6 +236,7 @@ napi_value RdbStoreProxy::Initialize(napi_env env, napi_callback_info info) finalize(env, proxy, proxy); return nullptr; } + JSDFManager::GetInstance().AddNewInfo(proxy); return self; } @@ -268,7 +277,7 @@ RdbStoreProxy *GetNativeInstance(napi_env env, napi_value self) RdbStoreProxy *proxy = nullptr; napi_status status = napi_unwrap(env, self, reinterpret_cast(&proxy)); if (proxy == nullptr) { - LOG_ERROR("RdbStoreProxy::GetNativePredicates native instance is nullptr! code:%{public}d!", status); + LOG_ERROR("RdbStoreProxy native instance is nullptr! code:%{public}d!", status); return nullptr; } return proxy; @@ -441,20 +450,6 @@ int ParseColumns(const napi_env env, const napi_value arg, std::shared_ptr context) -{ - context->aliasName = JSUtils::Convert2String(env, arg); - CHECK_RETURN_SET(!context->aliasName.empty(), std::make_shared("aliasName", "not empty")); - return OK; -} - -int ParsePath(const napi_env env, const napi_value arg, std::shared_ptr context) -{ - context->pathName = JSUtils::Convert2String(env, arg); - CHECK_RETURN_SET(!context->pathName.empty(), std::make_shared("pathName", "not empty")); - return OK; -} - int ParseBindArgs(const napi_env env, const napi_value arg, std::shared_ptr context) { context->bindArgs.clear(); @@ -599,7 +594,7 @@ int ParseValuesBuckets(const napi_env env, const napi_value arg, std::shared_ptr CHECK_RETURN_SET(status == napi_ok, std::make_shared("napi_get_element failed.")); CHECK_RETURN_ERR(ParseValuesBucket(env, obj, context) == OK); - context->valuesBuckets.push_back(std::move(context->valuesBucket)); + context->sharedValuesBuckets.Put(context->valuesBucket); context->valuesBucket.Clear(); } return OK; @@ -647,6 +642,19 @@ napi_value RdbStoreProxy::Insert(napi_env env, napi_callback_info info) return ASYNC_CALL(env, context); } +int ParseTransactionType( + const napi_env &env, size_t argc, napi_value *argv, std::shared_ptr context) +{ + context->transactionType = Transaction::DEFERRED; + if (argc > 0 && !JSUtils::IsNull(env, argv[0])) { + auto status = JSUtils::Convert2ValueExt(env, argv[0], context->transactionType); + bool checked = status == napi_ok && context->transactionType >= Transaction::DEFERRED && + context->transactionType <= Transaction::EXCLUSIVE; + CHECK_RETURN_SET(checked, std::make_shared("type", "a TransactionType")); + } + return OK; +} + napi_value RdbStoreProxy::BatchInsert(napi_env env, napi_callback_info info) { auto context = std::make_shared(); @@ -655,13 +663,15 @@ napi_value RdbStoreProxy::BatchInsert(napi_env env, napi_callback_info info) CHECK_RETURN(OK == ParserThis(env, self, context)); CHECK_RETURN(OK == ParseTableName(env, argv[0], context)); CHECK_RETURN(OK == ParseValuesBuckets(env, argv[1], context)); - CHECK_RETURN_SET_E(!HasDuplicateAssets(context->valuesBuckets), std::make_shared("Duplicate assets " - "are not allowed")); + CHECK_RETURN_SET_E(!HasDuplicateAssets(context->sharedValuesBuckets), + std::make_shared("Duplicate assets are not allowed")); }; auto exec = [context]() -> int { CHECK_RETURN_ERR(context->rdbStore != nullptr); auto rdbStore = std::move(context->rdbStore); - return rdbStore->BatchInsert(context->int64Output, context->tableName, context->valuesBuckets); + auto [ret, output] = rdbStore->BatchInsert(context->tableName, context->sharedValuesBuckets); + context->int64Output = output; + return ret; }; auto output = [context](napi_env env, napi_value &result) { napi_status status = napi_create_int64(env, context->int64Output, &result); @@ -762,7 +772,11 @@ napi_value RdbStoreProxy::Query(napi_env env, napi_callback_info info) }; auto exec = [context]() -> int { CHECK_RETURN_ERR(context->rdbStore != nullptr && context->rdbPredicates != nullptr); +#if defined(WINDOWS_PLATFORM) || defined(MAC_PLATFORM) || defined(ANDROID_PLATFORM) || defined(IOS_PLATFORM) + context->resultSet = context->rdbStore->QueryByStep(*(context->rdbPredicates), context->columns); +#else context->resultSet = context->rdbStore->Query(*(context->rdbPredicates), context->columns); +#endif context->rdbStore = nullptr; return (context->resultSet != nullptr) ? E_OK : E_ERROR; }; @@ -1080,18 +1094,6 @@ napi_value RdbStoreProxy::IsReadOnly(napi_env env, napi_callback_info info) return JSUtils::Convert2JSValue(env, out); } -napi_value RdbStoreProxy::IsMemoryRdb(napi_env env, napi_callback_info info) -{ - napi_value thisObj = nullptr; - napi_get_cb_info(env, info, nullptr, nullptr, &thisObj, nullptr); - RdbStoreProxy *rdbStoreProxy = GetNativeInstance(env, thisObj); - RDB_NAPI_ASSERT(env, rdbStoreProxy != nullptr && rdbStoreProxy->GetInstance() != nullptr, - std::make_shared("RdbStore", "valid")); - bool out = rdbStoreProxy->GetInstance()->IsMemoryRdb(); - LOG_DEBUG("RdbStoreProxy::IsMemoryRdb out is : %{public}d", out); - return JSUtils::Convert2JSValue(env, out); -} - napi_value RdbStoreProxy::GetPath(napi_env env, napi_callback_info info) { napi_value thisObj = nullptr; @@ -1255,32 +1257,6 @@ napi_value RdbStoreProxy::QueryByStep(napi_env env, napi_callback_info info) return ASYNC_CALL(env, context); } -napi_value RdbStoreProxy::IsInTransaction(napi_env env, napi_callback_info info) -{ - napi_value thisObj = nullptr; - napi_get_cb_info(env, info, nullptr, nullptr, &thisObj, nullptr); - RdbStoreProxy *rdbStoreProxy = GetNativeInstance(env, thisObj); - RDB_NAPI_ASSERT(env, rdbStoreProxy != nullptr, std::make_shared("RdbStore", "valid")); - RDB_NAPI_ASSERT( - env, rdbStoreProxy->GetInstance() != nullptr, std::make_shared(NativeRdb::E_ALREADY_CLOSED)); - bool out = rdbStoreProxy->GetInstance()->IsInTransaction(); - LOG_DEBUG("RdbStoreProxy::IsInTransaction out is : %{public}d", out); - return JSUtils::Convert2JSValue(env, out); -} - -napi_value RdbStoreProxy::IsOpen(napi_env env, napi_callback_info info) -{ - napi_value thisObj = nullptr; - napi_get_cb_info(env, info, nullptr, nullptr, &thisObj, nullptr); - RdbStoreProxy *rdbStoreProxy = GetNativeInstance(env, thisObj); - RDB_NAPI_ASSERT(env, rdbStoreProxy != nullptr, std::make_shared("RdbStore", "valid")); - RDB_NAPI_ASSERT( - env, rdbStoreProxy->GetInstance() != nullptr, std::make_shared(NativeRdb::E_ALREADY_CLOSED)); - bool out = rdbStoreProxy->GetInstance()->IsOpen(); - LOG_DEBUG("RdbStoreProxy::IsOpen out is : %{public}d", out); - return JSUtils::Convert2JSValue(env, out); -} - napi_value RdbStoreProxy::GetVersion(napi_env env, napi_callback_info info) { napi_value thisObj = nullptr; @@ -1578,7 +1554,7 @@ napi_value RdbStoreProxy::GetModifyTime(napi_env env, napi_callback_info info) napi_value RdbStoreProxy::CleanDirtyData(napi_env env, napi_callback_info info) { - LOG_DEBUG("RdbStoreProxy::Clean start."); + LOG_INFO("RdbStoreProxy::Clean start."); auto context = std::make_shared(); auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) { CHECK_RETURN_SET_E(argc >= 1, std::make_shared("1 - 3")); @@ -2195,5 +2171,32 @@ napi_value RdbStoreProxy::Close(napi_env env, napi_callback_info info) CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK); return ASYNC_CALL(env, context); } + +napi_value RdbStoreProxy::CreateTransaction(napi_env env, napi_callback_info info) +{ + auto context = std::make_shared(); + auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) { + CHECK_RETURN(OK == ParserThis(env, self, context)); + CHECK_RETURN(OK == ParseTransactionType(env, argc, argv, context)); + }; + auto exec = [context]() -> int { + CHECK_RETURN_ERR(context->rdbStore != nullptr); + int32_t code = E_ERROR; + std::tie(code, context->transaction) = context->StealRdbStore()->CreateTransaction(context->transactionType); + if (code != E_OK) { + context->transaction = nullptr; + return code; + } + return context->transaction != nullptr ? OK : E_ERROR; + }; + auto output = [context](napi_env env, napi_value &result) { + result = TransactionProxy::NewInstance(env, context->transaction); + CHECK_RETURN_SET_E(result != nullptr, std::make_shared(E_ERROR)); + }; + context->SetAction(env, info, input, exec, output); + + CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK); + return ASYNC_CALL(env, context); +} } // namespace RelationalStoreJsKit } // namespace OHOS diff --git a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_store_helper.cpp b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_store_helper.cpp index a5f1f78bcc5de72a61c0a5481327b12ec80f4e28..cd4fea766ad7f392ddd51ca9aa4b73a3ad0bc1d0 100644 --- a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_store_helper.cpp +++ b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_store_helper.cpp @@ -67,6 +67,8 @@ napi_value GetRdbStore(napi_env env, napi_callback_info info) errCode = Convert2Value(env, argv[1], context->config); CHECK_RETURN_SET_E(OK == errCode, std::make_shared("Illegal StoreConfig or name.")); + CHECK_RETURN_SET_E(context->config.cryptoParam.IsValid(), std::make_shared("Illegal CryptoParam.")); + auto [code, err] = GetRealPath(env, argv[0], context->config, context->param); CHECK_RETURN_SET_E(OK == code, err); }; diff --git a/relational_store/frameworks/js/napi/relationalstore/src/napi_result_set.cpp b/relational_store/frameworks/js/napi/relationalstore/src/napi_result_set.cpp index 9cbb6f1add31285455e4e44ac8513b86cd322231..ff24ca2b24a28677d1c826c3cde185e5ab5d3148 100644 --- a/relational_store/frameworks/js/napi/relationalstore/src/napi_result_set.cpp +++ b/relational_store/frameworks/js/napi/relationalstore/src/napi_result_set.cpp @@ -23,6 +23,7 @@ #include "napi_rdb_js_utils.h" #include "napi_rdb_sendable_utils.h" #include "napi_rdb_trace.h" +#include "js_df_manager.h" #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) #include "rdb_result_set_bridge.h" #include "string_ex.h" @@ -86,12 +87,17 @@ napi_value ResultSetProxy::Initialize(napi_env env, napi_callback_info info) return nullptr; } auto finalize = [](napi_env env, void *data, void *hint) { + auto tid = JSDFManager::GetInstance().GetFreedTid(data); + if (tid != 0) { + LOG_ERROR("(T:%{public}d) freed! data:0x%016" PRIXPTR, tid, uintptr_t(data) & LOWER_24_BITS_MASK); + } if (data != hint) { LOG_ERROR("RdbStoreProxy memory corrupted! data:0x%016" PRIXPTR "hint:0x%016" PRIXPTR, uintptr_t(data), uintptr_t(hint)); return; } ResultSetProxy *proxy = reinterpret_cast(data); + proxy->SetInstance(nullptr); delete proxy; }; napi_status status = napi_wrap(env, self, proxy, finalize, proxy, nullptr); @@ -100,6 +106,7 @@ napi_value ResultSetProxy::Initialize(napi_env env, napi_callback_info info) finalize(env, proxy, proxy); return nullptr; } + JSDFManager::GetInstance().AddNewInfo(proxy); return self; } diff --git a/relational_store/frameworks/js/napi/relationalstore/src/napi_transaction.cpp b/relational_store/frameworks/js/napi/relationalstore/src/napi_transaction.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f4b6f4e7b5c4749592063d56c9249d235994fac6 --- /dev/null +++ b/relational_store/frameworks/js/napi/relationalstore/src/napi_transaction.cpp @@ -0,0 +1,676 @@ +/* + * 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 "TransactionProxy" +#include "napi_transaction.h" + +#include "js_df_manager.h" +#include "js_utils.h" +#include "napi_async_call.h" +#include "napi_rdb_error.h" +#include "napi_rdb_js_utils.h" +#include "napi_rdb_predicates.h" +#include "napi_result_set.h" +#include "rdb_common.h" +#include "rdb_errno.h" +using namespace OHOS::Rdb; +using namespace OHOS::NativeRdb; +using namespace OHOS::AppDataMgrJsKit; +namespace OHOS::RelationalStoreJsKit { +#define ASSERT_RETURN_SET_ERROR(assertion, paramError) \ + CHECK_RETURN_CORE(assertion, SetError(paramError), ERR) + +struct TransactionContext : public ContextBase { + void GetInstance(napi_value self) + { + auto status = napi_unwrap(env_, self, reinterpret_cast(&boundObj)); + if (status != napi_ok || boundObj == nullptr) { + LOG_ERROR("TransactionProxy native instance is nullptr! code:%{public}d!", status); + return; + } + transaction_ = reinterpret_cast(boundObj)->GetInstance(); + } + std::shared_ptr StealTransaction() + { + auto trans = std::move(transaction_); + transaction_ = nullptr; + return trans; + } + int32_t ParseRdbPredicatesProxy(napi_env env, napi_value arg, std::shared_ptr &predicates); + int32_t ParseSendableValuesBucket(napi_env env, napi_value arg, ValuesBucket &valuesBucket); + int32_t ParseValuesBucket(napi_env env, napi_value arg, ValuesBucket &valuesBucket); + int32_t ParseValuesBuckets(napi_env env, napi_value arg, std::vector &valuesBuckets); + int32_t ParseConflictResolution(napi_env env, napi_value arg, NativeRdb::ConflictResolution &conflictResolution); + std::shared_ptr transaction_ = nullptr; + static constexpr int32_t KEY_INDEX = 0; + static constexpr int32_t VALUE_INDEX = 1; +}; + +int32_t TransactionContext::ParseRdbPredicatesProxy( + napi_env env, napi_value arg, std::shared_ptr &predicates) +{ + RdbPredicatesProxy *predicatesProxy = nullptr; + auto status = napi_unwrap(env, arg, reinterpret_cast(&predicatesProxy)); + ASSERT_RETURN_SET_ERROR(status == napi_ok && predicatesProxy != nullptr, + std::make_shared("predicates", "an RdbPredicates.")); + predicates = predicatesProxy->GetInstance(); + ASSERT_RETURN_SET_ERROR(predicates != nullptr, std::make_shared("predicates", "an RdbPredicates.")); + return OK; +} + +int32_t TransactionContext::ParseSendableValuesBucket( + const napi_env env, const napi_value map, ValuesBucket &valuesBucket) +{ + uint32_t length = 0; + napi_status status = napi_map_get_size(env, map, &length); + auto error = std::make_shared("ValuesBucket is invalid."); + ASSERT_RETURN_SET_ERROR(status == napi_ok && length > 0, error); + napi_value entries = nullptr; + status = napi_map_get_entries(env, map, &entries); + ASSERT_RETURN_SET_ERROR(status == napi_ok, std::make_shared("napi_map_get_entries failed.")); + for (uint32_t i = 0; i < length; ++i) { + napi_value iter = nullptr; + status = napi_map_iterator_get_next(env, entries, &iter); + ASSERT_RETURN_SET_ERROR(status == napi_ok, std::make_shared("napi_map_iterator_get_next failed.")); + napi_value values = nullptr; + status = napi_get_named_property(env, iter, "value", &values); + ASSERT_RETURN_SET_ERROR( + status == napi_ok, std::make_shared("napi_get_named_property value failed.")); + napi_value key = nullptr; + status = napi_get_element(env, values, KEY_INDEX, &key); + ASSERT_RETURN_SET_ERROR(status == napi_ok, std::make_shared("napi_get_element key failed.")); + std::string keyStr = JSUtils::Convert2String(env, key); + napi_value value = nullptr; + status = napi_get_element(env, values, VALUE_INDEX, &value); + ASSERT_RETURN_SET_ERROR(status == napi_ok, std::make_shared("napi_get_element value failed.")); + ValueObject valueObject; + int32_t ret = JSUtils::Convert2Value(env, value, valueObject.value); + if (ret == napi_ok) { + valuesBucket.values_.insert_or_assign(std::move(keyStr), std::move(valueObject)); + } else if (ret != napi_generic_failure) { + ASSERT_RETURN_SET_ERROR(false, std::make_shared("The value type of " + keyStr, "invalid.")); + } + } + return OK; +} + +int32_t TransactionContext::ParseValuesBucket(napi_env env, napi_value arg, ValuesBucket &valuesBucket) +{ + bool isMap = false; + napi_status status = napi_is_map(env, arg, &isMap); + ASSERT_RETURN_SET_ERROR( + status == napi_ok, std::make_shared("call napi_is_map failed" + std::to_string(status))); + if (isMap) { + return ParseSendableValuesBucket(env, arg, valuesBucket); + } + napi_value keys = nullptr; + napi_get_all_property_names(env, arg, napi_key_own_only, + static_cast(napi_key_enumerable | napi_key_skip_symbols), napi_key_numbers_to_strings, &keys); + uint32_t arrLen = 0; + status = napi_get_array_length(env, keys, &arrLen); + ASSERT_RETURN_SET_ERROR(status == napi_ok && arrLen > 0, std::make_shared("ValuesBucket is invalid")); + + for (size_t i = 0; i < arrLen; ++i) { + napi_value key = nullptr; + status = napi_get_element(env, keys, i, &key); + ASSERT_RETURN_SET_ERROR(status == napi_ok, std::make_shared("ValuesBucket is invalid.")); + std::string keyStr = JSUtils::Convert2String(env, key); + napi_value value = nullptr; + napi_get_property(env, arg, key, &value); + ValueObject valueObject; + int32_t ret = JSUtils::Convert2Value(env, value, valueObject.value); + if (ret == napi_ok) { + valuesBucket.values_.insert_or_assign(std::move(keyStr), std::move(valueObject)); + } else if (ret != napi_generic_failure) { + ASSERT_RETURN_SET_ERROR(false, std::make_shared("The value type of " + keyStr, "invalid.")); + } + } + return OK; +} + +int32_t TransactionContext::ParseValuesBuckets(napi_env env, napi_value arg, std::vector &valuesBuckets) +{ + bool isArray = false; + auto status = napi_is_array(env, arg, &isArray); + ASSERT_RETURN_SET_ERROR(status == napi_ok && isArray, std::make_shared("ValuesBucket is invalid.")); + + uint32_t arrLen = 0; + status = napi_get_array_length(env, arg, &arrLen); + ASSERT_RETURN_SET_ERROR(status == napi_ok && arrLen > 0, std::make_shared("ValuesBucket is invalid.")); + + for (uint32_t i = 0; i < arrLen; ++i) { + napi_value obj = nullptr; + status = napi_get_element(env, arg, i, &obj); + ASSERT_RETURN_SET_ERROR(status == napi_ok, std::make_shared("napi_get_element failed.")); + ValuesBucket valuesBucket; + ASSERT_RETURN_SET_ERROR( + ParseValuesBucket(env, obj, valuesBucket) == OK, std::make_shared("ValuesBucket is invalid.")); + valuesBuckets.push_back(std::move(valuesBucket)); + } + return OK; +} + +int32_t TransactionContext::ParseConflictResolution( + const napi_env env, const napi_value arg, NativeRdb::ConflictResolution &conflictResolution) +{ + int32_t input = 0; + auto status = napi_get_value_int32(env, arg, &input); + int min = static_cast(NativeRdb::ConflictResolution::ON_CONFLICT_NONE); + int max = static_cast(NativeRdb::ConflictResolution::ON_CONFLICT_REPLACE); + bool checked = status == napi_ok && (input >= min) && (input <= max); + ASSERT_RETURN_SET_ERROR(checked, std::make_shared("conflictResolution", "a ConflictResolution.")); + conflictResolution = static_cast(input); + return OK; +} + +napi_value TransactionProxy::NewInstance(napi_env env, std::shared_ptr transaction) +{ + napi_value cons = JSUtils::GetClass(env, "ohos.data.relationalStore", "Transaction"); + if (cons == nullptr) { + LOG_ERROR("Constructor of Transaction is nullptr!"); + return nullptr; + } + napi_value instance = nullptr; + auto status = napi_new_instance(env, cons, 0, nullptr, &instance); + if (status != napi_ok) { + LOG_ERROR("NewInstance napi_new_instance failed! code:%{public}d!", status); + return nullptr; + } + + TransactionProxy *proxy = nullptr; + status = napi_unwrap(env, instance, reinterpret_cast(&proxy)); + if (proxy == nullptr) { + LOG_ERROR("NewInstance native instance is nullptr! code:%{public}d!", status); + return instance; + } + proxy->SetInstance(std::move(transaction)); + return instance; +} + +void TransactionProxy::Init(napi_env env, napi_value exports) +{ + auto lambda = []() -> std::vector { + std::vector properties = { + DECLARE_NAPI_FUNCTION("rollback", Rollback), + DECLARE_NAPI_FUNCTION("commit", Commit), + DECLARE_NAPI_FUNCTION_WITH_DATA("delete", Delete, ASYNC), + DECLARE_NAPI_FUNCTION_WITH_DATA("update", Update, ASYNC), + DECLARE_NAPI_FUNCTION_WITH_DATA("insert", Insert, ASYNC), + DECLARE_NAPI_FUNCTION_WITH_DATA("batchInsert", BatchInsert, ASYNC), + DECLARE_NAPI_FUNCTION_WITH_DATA("query", Query, ASYNC), + DECLARE_NAPI_FUNCTION_WITH_DATA("querySql", QuerySql, ASYNC), + DECLARE_NAPI_FUNCTION_WITH_DATA("execute", Execute, ASYNC), + }; + AddSyncFunctions(properties); + return properties; + }; + auto jsCtor = JSUtils::DefineClass(env, "ohos.data.relationalStore", "Transaction", lambda, Initialize); + NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, exports, "Transaction", jsCtor)); + + LOG_DEBUG("TransactionProxy::Init end."); +} + +void TransactionProxy::AddSyncFunctions(std::vector &properties) +{ + properties.push_back(DECLARE_NAPI_FUNCTION_WITH_DATA("deleteSync", Delete, SYNC)); + properties.push_back(DECLARE_NAPI_FUNCTION_WITH_DATA("updateSync", Update, SYNC)); + properties.push_back(DECLARE_NAPI_FUNCTION_WITH_DATA("insertSync", Insert, SYNC)); + properties.push_back(DECLARE_NAPI_FUNCTION_WITH_DATA("batchInsertSync", BatchInsert, SYNC)); + properties.push_back(DECLARE_NAPI_FUNCTION_WITH_DATA("querySync", Query, SYNC)); + properties.push_back(DECLARE_NAPI_FUNCTION_WITH_DATA("querySqlSync", QuerySql, SYNC)); + properties.push_back(DECLARE_NAPI_FUNCTION_WITH_DATA("executeSync", Execute, SYNC)); +} + +TransactionProxy::~TransactionProxy() +{ +} + +TransactionProxy::TransactionProxy(std::shared_ptr transaction) +{ + if (GetInstance() == transaction) { + return; + } + SetInstance(std::move(transaction)); +} + +napi_value TransactionProxy::Initialize(napi_env env, napi_callback_info info) +{ + napi_value self = nullptr; + NAPI_CALL(env, napi_get_cb_info(env, info, nullptr, nullptr, &self, nullptr)); + auto *proxy = new (std::nothrow) TransactionProxy(); + if (proxy == nullptr) { + LOG_ERROR("no memory, new TransactionProxy failed!"); + return nullptr; + } + auto finalize = [](napi_env env, void *data, void *hint) { + auto tid = JSDFManager::GetInstance().GetFreedTid(data); + if (tid != 0) { + LOG_ERROR("(T:%{public}d) freed! data:0x%016" PRIXPTR, tid, uintptr_t(data) & LOWER_24_BITS_MASK); + } + if (data != hint) { + LOG_ERROR("memory corrupted! data:0x%016" PRIXPTR "hint:0x%016" PRIXPTR, uintptr_t(data), + uintptr_t(hint)); + return; + } + TransactionProxy *proxy = reinterpret_cast(data); + proxy->SetInstance(nullptr); + delete proxy; + }; + napi_status status = napi_wrap(env, self, proxy, finalize, proxy, nullptr); + if (status != napi_ok) { + LOG_ERROR("napi_wrap failed! code:%{public}d!", status); + finalize(env, proxy, proxy); + return nullptr; + } + JSDFManager::GetInstance().AddNewInfo(proxy); + return self; +} + +struct CommitContext : public TransactionContext { + int32_t Parse(napi_env env, size_t argc, napi_value *argv, napi_value self) + { + GetInstance(self); + ASSERT_RETURN_SET_ERROR( + transaction_ != nullptr, std::make_shared("transaction", "a transaction.")); + return OK; + } +}; +/* + * [JS API Prototype] + * [Promise] + * commit(): Promise; + */ +napi_value TransactionProxy::Commit(napi_env env, napi_callback_info info) +{ + auto context = std::make_shared(); + auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) { + context->Parse(env, argc, argv, self); + }; + auto exec = [context]() -> int { + CHECK_RETURN_ERR(context->transaction_ != nullptr); + return context->StealTransaction()->Commit(); + }; + auto output = [context](napi_env env, napi_value &result) { + napi_status status = napi_get_undefined(env, &result); + CHECK_RETURN_SET_E(status == napi_ok, std::make_shared(E_ERROR)); + }; + context->SetAction(env, info, input, exec, output); + + CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK); + return ASYNC_CALL(env, context); +} + +struct RollbackContext : public TransactionContext { + int32_t Parse(napi_env env, size_t argc, napi_value *argv, napi_value self) + { + GetInstance(self); + ASSERT_RETURN_SET_ERROR( + transaction_ != nullptr, std::make_shared("transaction", "a transaction.")); + return OK; + } +}; + +/* + * [JS API Prototype] + * [Promise] + * rollback(): Promise; + */ +napi_value TransactionProxy::Rollback(napi_env env, napi_callback_info info) +{ + auto context = std::make_shared(); + auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) { + context->Parse(env, argc, argv, self); + }; + auto exec = [context]() -> int { + CHECK_RETURN_ERR(context->transaction_ != nullptr); + return context->StealTransaction()->Rollback(); + }; + auto output = [context](napi_env env, napi_value &result) { + napi_status status = napi_get_undefined(env, &result); + CHECK_RETURN_SET_E(status == napi_ok, std::make_shared(E_ERROR)); + }; + context->SetAction(env, info, input, exec, output); + + CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK); + return ASYNC_CALL(env, context); +} + +struct DeleteContext : public TransactionContext { + int32_t Parse(napi_env env, size_t argc, napi_value *argv, napi_value self) + { + ASSERT_RETURN_SET_ERROR(argc == 1, std::make_shared("1")); + GetInstance(self); + ASSERT_RETURN_SET_ERROR( + transaction_ != nullptr, std::make_shared("transaction", "a transaction.")); + CHECK_RETURN_ERR(ParseRdbPredicatesProxy(env, argv[0], rdbPredicates) == OK); + return OK; + } + std::shared_ptr rdbPredicates = nullptr; + + int64_t deleteRows = -1; +}; + +/* + * [JS API Prototype] + * [Promise] + * delete(predicates: RdbPredicates): Promise; + */ +napi_value TransactionProxy::Delete(napi_env env, napi_callback_info info) +{ + auto context = std::make_shared(); + auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) { + context->Parse(env, argc, argv, self); + }; + auto exec = [context]() -> int { + CHECK_RETURN_ERR(context->transaction_ != nullptr && context->rdbPredicates != nullptr); + auto [code, deleteRows] = context->StealTransaction()->Delete(*(context->rdbPredicates)); + context->deleteRows = deleteRows; + return code; + }; + auto output = [context](napi_env env, napi_value &result) { + napi_status status = napi_create_int64(env, context->deleteRows, &result); + CHECK_RETURN_SET_E(status == napi_ok, std::make_shared(E_ERROR)); + }; + context->SetAction(env, info, input, exec, output); + + CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK); + return ASYNC_CALL(env, context); +} + +struct UpdateContext : public TransactionContext { + int32_t Parse(napi_env env, size_t argc, napi_value *argv, napi_value self) + { + ASSERT_RETURN_SET_ERROR(argc == 2 || argc == 3, std::make_shared("2 to 3")); + GetInstance(self); + ASSERT_RETURN_SET_ERROR( + transaction_ != nullptr, std::make_shared("transaction", "a transaction.")); + CHECK_RETURN_ERR(ParseValuesBucket(env, argv[0], valuesBucket) == OK); + CHECK_RETURN_ERR(ParseRdbPredicatesProxy(env, argv[1], rdbPredicates) == OK); + // 'argv[2]' is an optional parameter + if (argc > 2 && !JSUtils::IsNull(env, argv[2])) { + // 'argv[2]' represents a ConflictResolution parameter + CHECK_RETURN_ERR(ParseConflictResolution(env, argv[2], conflictResolution)); + } + return OK; + } + ValuesBucket valuesBucket; + std::shared_ptr rdbPredicates = nullptr; + NativeRdb::ConflictResolution conflictResolution = ConflictResolution::ON_CONFLICT_NONE; + + int64_t updateRows = -1; +}; + +/* + * [JS API Prototype] + * [Promise] + * update(values: ValuesBucket, predicates: RdbPredicates, conflict?: ConflictResolution): Promise; + */ +napi_value TransactionProxy::Update(napi_env env, napi_callback_info info) +{ + auto context = std::make_shared(); + auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) { + context->Parse(env, argc, argv, self); + }; + auto exec = [context]() -> int { + CHECK_RETURN_ERR(context->transaction_ != nullptr && context->rdbPredicates != nullptr); + auto [code, updateRows] = context->StealTransaction()->Update( + context->valuesBucket, *context->rdbPredicates, context->conflictResolution); + context->updateRows = updateRows; + return code; + }; + auto output = [context](napi_env env, napi_value &result) { + napi_status status = napi_create_int64(env, context->updateRows, &result); + CHECK_RETURN_SET_E(status == napi_ok, std::make_shared(E_ERROR)); + }; + context->SetAction(env, info, input, exec, output); + + CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK); + return ASYNC_CALL(env, context); +} + +struct InsertContext : public TransactionContext { + int32_t Parse(napi_env env, size_t argc, napi_value *argv, napi_value self) + { + ASSERT_RETURN_SET_ERROR(argc == 2 || argc == 3, std::make_shared("2 to 3")); + GetInstance(self); + ASSERT_RETURN_SET_ERROR( + transaction_ != nullptr, std::make_shared("transaction", "a transaction.")); + CHECK_RETURN_ERR(JSUtils::Convert2Value(env, argv[0], tableName) == OK); + CHECK_RETURN_ERR(ParseValuesBucket(env, argv[1], valuesBucket) == OK); + // 'argv[2]' is an optional parameter + if (argc > 2 && !JSUtils::IsNull(env, argv[2])) { + // 'argv[2]' represents a ConflictResolution parameter + CHECK_RETURN_ERR(ParseConflictResolution(env, argv[2], conflictResolution)); + } + return OK; + } + std::string tableName; + ValuesBucket valuesBucket; + NativeRdb::ConflictResolution conflictResolution = ConflictResolution::ON_CONFLICT_NONE; + + int64_t insertRows = -1; +}; + +/* + * [JS API Prototype] + * [Promise] + * insert(table: string, values: ValuesBucket, conflict?: ConflictResolution): Promise; + */ +napi_value TransactionProxy::Insert(napi_env env, napi_callback_info info) +{ + auto context = std::make_shared(); + auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) { + context->Parse(env, argc, argv, self); + }; + auto exec = [context]() -> int { + CHECK_RETURN_ERR(context->transaction_ != nullptr); + auto [code, insertRows] = context->StealTransaction()->Insert( + context->tableName, context->valuesBucket, context->conflictResolution); + context->insertRows = insertRows; + return code; + }; + auto output = [context](napi_env env, napi_value &result) { + napi_status status = napi_create_int64(env, context->insertRows, &result); + CHECK_RETURN_SET_E(status == napi_ok, std::make_shared(E_ERROR)); + }; + context->SetAction(env, info, input, exec, output); + + CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK); + return ASYNC_CALL(env, context); +} + +struct BatchInsertContext : public TransactionContext { + int32_t Parse(napi_env env, size_t argc, napi_value *argv, napi_value self) + { + ASSERT_RETURN_SET_ERROR(argc == 2, std::make_shared("2")); + GetInstance(self); + ASSERT_RETURN_SET_ERROR( + transaction_ != nullptr, std::make_shared("transaction", "a transaction.")); + ASSERT_RETURN_SET_ERROR( + JSUtils::Convert2Value(env, argv[0], tableName) == OK, std::make_shared("table", "a string.")); + CHECK_RETURN_ERR(ParseValuesBuckets(env, argv[1], valuesBuckets) == OK); + return OK; + } + std::string tableName; + std::vector valuesBuckets; + + int64_t insertRows = -1; +}; + +/* + * [JS API Prototype] + * [Promise] + * batchInsert(table: string, values: Array): Promise; + */ +napi_value TransactionProxy::BatchInsert(napi_env env, napi_callback_info info) +{ + auto context = std::make_shared(); + auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) { + context->Parse(env, argc, argv, self); + }; + auto exec = [context]() -> int { + CHECK_RETURN_ERR(context->transaction_ != nullptr); + auto [code, insertRows] = context->StealTransaction()->BatchInsert(context->tableName, context->valuesBuckets); + context->insertRows = insertRows; + return code; + }; + auto output = [context](napi_env env, napi_value &result) { + napi_status status = napi_create_int64(env, context->insertRows, &result); + CHECK_RETURN_SET_E(status == napi_ok, std::make_shared(E_ERROR)); + }; + context->SetAction(env, info, input, exec, output); + + CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK); + return ASYNC_CALL(env, context); +} + +struct QueryContext : public TransactionContext { + int32_t Parse(napi_env env, size_t argc, napi_value *argv, napi_value self) + { + ASSERT_RETURN_SET_ERROR(argc == 1 || argc == 2, std::make_shared("1 to 2")); + GetInstance(self); + ASSERT_RETURN_SET_ERROR( + transaction_ != nullptr, std::make_shared("transaction", "a transaction.")); + CHECK_RETURN_ERR(ParseRdbPredicatesProxy(env, argv[0], rdbPredicates) == OK); + if (argc > 1 && !JSUtils::IsNull(env, argv[1])) { + ASSERT_RETURN_SET_ERROR(JSUtils::Convert2Value(env, argv[1], columns) == OK, + std::make_shared("columns", "a Array.")); + } + return OK; + } + std::shared_ptr rdbPredicates = nullptr; + std::vector columns; + + std::shared_ptr resultSet; +}; + +/* + * [JS API Prototype] + * [Promise] + * query(predicates: RdbPredicates, columns?: Array): Promise; + */ +napi_value TransactionProxy::Query(napi_env env, napi_callback_info info) +{ + auto context = std::make_shared(); + auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) { + context->Parse(env, argc, argv, self); + }; + auto exec = [context]() -> int { + CHECK_RETURN_ERR(context->transaction_ != nullptr && context->rdbPredicates != nullptr); + context->resultSet = context->StealTransaction()->QueryByStep(*(context->rdbPredicates), context->columns); + return (context->resultSet != nullptr) ? E_OK : E_ALREADY_CLOSED; + }; + auto output = [context](napi_env env, napi_value &result) { + result = ResultSetProxy::NewInstance(env, context->resultSet); + CHECK_RETURN_SET_E(result != nullptr, std::make_shared(E_ERROR)); + }; + context->SetAction(env, info, input, exec, output); + + CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK); + return ASYNC_CALL(env, context); +} + +struct QuerySqlContext : public TransactionContext { + int32_t Parse(napi_env env, size_t argc, napi_value *argv, napi_value self) + { + ASSERT_RETURN_SET_ERROR(argc == 1 || argc == 2, std::make_shared("1 to 2")); + GetInstance(self); + ASSERT_RETURN_SET_ERROR( + transaction_ != nullptr, std::make_shared("transaction", "a transaction.")); + ASSERT_RETURN_SET_ERROR( + JSUtils::Convert2Value(env, argv[0], sql) == OK, std::make_shared("sql", "a string.")); + if (argc > 1 && !JSUtils::IsNull(env, argv[1])) { + ASSERT_RETURN_SET_ERROR(JSUtils::Convert2Value(env, argv[1], bindArgs) == OK, + std::make_shared("bindArgs", "a Array.")); + } + return OK; + } + std::string sql; + std::vector bindArgs; + + std::shared_ptr resultSet; +}; + +/* + * [JS API Prototype] + * [Promise] + * querySql(sql: string, bindArgs?: Array): Promise; + */ +napi_value TransactionProxy::QuerySql(napi_env env, napi_callback_info info) +{ + auto context = std::make_shared(); + auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) { + context->Parse(env, argc, argv, self); + }; + auto exec = [context]() -> int { + CHECK_RETURN_ERR(context->transaction_ != nullptr); + context->resultSet = context->StealTransaction()->QueryByStep(context->sql, context->bindArgs); + return (context->resultSet != nullptr) ? E_OK : E_ALREADY_CLOSED; + }; + auto output = [context](napi_env env, napi_value &result) { + result = ResultSetProxy::NewInstance(env, context->resultSet); + CHECK_RETURN_SET_E(result != nullptr, std::make_shared(E_ERROR)); + }; + context->SetAction(env, info, input, exec, output); + + CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK); + return ASYNC_CALL(env, context); +} + +struct ExecuteContext : public TransactionContext { + int32_t Parse(napi_env env, size_t argc, napi_value *argv, napi_value self) + { + ASSERT_RETURN_SET_ERROR(argc == 1 || argc == 2, std::make_shared("1 to 2")); + GetInstance(self); + ASSERT_RETURN_SET_ERROR(transaction_ != nullptr, std::make_shared("transaction", "a transaction.")); + CHECK_RETURN_ERR(JSUtils::Convert2Value(env, argv[0], sql) == OK); + if (argc > 1 && !JSUtils::IsNull(env, argv[1])) { + CHECK_RETURN_ERR(JSUtils::Convert2Value(env, argv[1], bindArgs) == OK); + } + return OK; + } + std::string sql; + std::vector bindArgs; + + ValueObject output; +}; + +/* + * [JS API Prototype] + * [Promise] + * execute(sql: string, args?: Array): Promise; + */ +napi_value TransactionProxy::Execute(napi_env env, napi_callback_info info) +{ + auto context = std::make_shared(); + auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) { + context->Parse(env, argc, argv, self); + }; + auto exec = [context]() -> int { + CHECK_RETURN_ERR(context->transaction_ != nullptr); + auto status = E_ERROR; + std::tie(status, context->output) = context->StealTransaction()->Execute(context->sql, context->bindArgs); + return status; + }; + auto output = [context](napi_env env, napi_value &result) { + result = JSUtils::Convert2JSValue(env, context->output); + CHECK_RETURN_SET_E(result != nullptr, std::make_shared(E_ERROR)); + }; + context->SetAction(env, info, input, exec, output); + + CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK); + return ASYNC_CALL(env, context); +} +} // namespace OHOS::RelationalStoreJsKit \ No newline at end of file diff --git a/relational_store/frameworks/native/dfx/include/rdb_fault_hiview_reporter.h b/relational_store/frameworks/native/dfx/include/rdb_fault_hiview_reporter.h index d8550d66a6ba0873c62de75c24ffb7d4d617eb79..e6582f8969c2dffc18e55cc4daae774d35493afa 100644 --- a/relational_store/frameworks/native/dfx/include/rdb_fault_hiview_reporter.h +++ b/relational_store/frameworks/native/dfx/include/rdb_fault_hiview_reporter.h @@ -50,7 +50,9 @@ public: static bool RegCollector(Connection::Collector collector); static void Report(const RdbCorruptedEvent &eventInfo); static void ReportFault(const RdbCorruptedEvent &eventInfo); - static void ReportRestore(const RdbCorruptedEvent &eventInfo); + static void ReportRestore(const RdbCorruptedEvent &eventInfo, bool repair = true); + static std::string Format(const std::map &debugs, const std::string &header); + static std::string FormatBrief(const std::map &debugs, const std::string &header); private: static void Update(RdbCorruptedEvent &eventInfo, const std::map &infos); @@ -59,7 +61,7 @@ private: static void CreateCorruptedFlag(const std::string &dbPath); static void DeleteCorruptedFlag(const std::string &dbPath); static std::string GetTimeWithMilliseconds(time_t sec, int64_t nsec); - + static std::string GetBundleName(const RdbCorruptedEvent &eventInfo); static Connection::Collector collector_; }; } // namespace OHOS::NativeRdb diff --git a/relational_store/frameworks/native/dfx/src/rdb_fault_hiview_reporter.cpp b/relational_store/frameworks/native/dfx/src/rdb_fault_hiview_reporter.cpp index 7f6e360d8cf39e8270dffc31a45227cf32187695..030d8441ddba967ae34411c953a9a47629e89e83 100644 --- a/relational_store/frameworks/native/dfx/src/rdb_fault_hiview_reporter.cpp +++ b/relational_store/frameworks/native/dfx/src/rdb_fault_hiview_reporter.cpp @@ -19,17 +19,24 @@ #include #include +#include #include #include +#include #include +#include #include "connection.h" #include "hisysevent_c.h" #include "logger.h" #include "rdb_errno.h" #include "sqlite_global_config.h" #include "sqlite_utils.h" +#include "ipc_skeleton.h" +#include "accesstoken_kit.h" + namespace OHOS::NativeRdb { using namespace OHOS::Rdb; +using namespace Security::AccessToken; static constexpr const char *EVENT_NAME = "DATABASE_CORRUPTED"; static constexpr const char *DISTRIBUTED_DATAMGR = "DISTDATAMGR"; static constexpr const char *DB_CORRUPTED_POSTFIX = ".corruptedflg"; @@ -42,30 +49,38 @@ Connection::Collector RdbFaultHiViewReporter::collector_ = nullptr; void RdbFaultHiViewReporter::ReportFault(const RdbCorruptedEvent &eventInfo) { if (IsReportCorruptedFault(eventInfo.path)) { - Report(eventInfo); + RdbCorruptedEvent eventInfoAppend = eventInfo; + eventInfoAppend.appendix += Format(eventInfoAppend.debugInfos, ""); + LOG_WARN("corrupted %{public}s errCode:0x%{public}x [%{public}s]", + SqliteUtils::Anonymous(eventInfoAppend.storeName).c_str(), + eventInfoAppend.errorCode, + eventInfoAppend.appendix.c_str()); + Report(eventInfoAppend); CreateCorruptedFlag(eventInfo.path); } } -void RdbFaultHiViewReporter::ReportRestore(const RdbCorruptedEvent &eventInfo) +void RdbFaultHiViewReporter::ReportRestore(const RdbCorruptedEvent &eventInfo, bool repair) { - Report(eventInfo); + if (IsReportCorruptedFault(eventInfo.path) && repair) { + return; + } + RdbCorruptedEvent eventInfoAppend = eventInfo; + eventInfoAppend.appendix += Format(eventInfoAppend.debugInfos, ""); + LOG_INFO("restored %{public}s errCode:0x%{public}x [%{public}s]", + SqliteUtils::Anonymous(eventInfo.storeName).c_str(), eventInfo.errorCode, eventInfoAppend.appendix.c_str()); + Report(eventInfoAppend); DeleteCorruptedFlag(eventInfo.path); } void RdbFaultHiViewReporter::Report(const RdbCorruptedEvent &eventInfo) { - std::string bundleName = eventInfo.bundleName; + std::string bundleName = GetBundleName(eventInfo); std::string moduleName = eventInfo.moduleName; std::string storeType = eventInfo.storeType; std::string storeName = eventInfo.storeName; uint32_t checkType = eventInfo.integrityCheck; std::string appendInfo = eventInfo.appendix; - for (auto &[name, debugInfo] : eventInfo.debugInfos) { - appendInfo += "\n" + name + " :" + GetFileStatInfo(debugInfo); - } - LOG_WARN("storeName: %{public}s, errorCode: %{public}d, appendInfo : %{public}s", - SqliteUtils::Anonymous(eventInfo.storeName).c_str(), eventInfo.errorCode, appendInfo.c_str()); std::string occurTime = GetTimeWithMilliseconds(eventInfo.errorOccurTime, 0); char *errorOccurTime = occurTime.data(); HiSysEventParam params[] = { @@ -89,14 +104,15 @@ std::string RdbFaultHiViewReporter::GetFileStatInfo(const DebugInfo &debugInfo) { std::stringstream oss; const uint32_t permission = 0777; - oss << " device: 0x" << std::hex << debugInfo.dev_ << " inode: 0x" << std::hex << debugInfo.inode_; + oss << " dev:0x" << std::hex << debugInfo.dev_ << " ino:0x" << std::hex << debugInfo.inode_; if (debugInfo.inode_ != debugInfo.oldInode_ && debugInfo.oldInode_ != 0) { oss << "<>0x" << std::hex << debugInfo.oldInode_; } - oss << " mode: 0" << std::oct << (debugInfo.mode_ & permission) << " size: " << std::dec << debugInfo.size_ - << " natime: " << GetTimeWithMilliseconds(debugInfo.atime_.sec_, debugInfo.atime_.nsec_) - << " smtime: " << GetTimeWithMilliseconds(debugInfo.mtime_.sec_, debugInfo.mtime_.nsec_) - << " sctime: " << GetTimeWithMilliseconds(debugInfo.ctime_.sec_, debugInfo.ctime_.nsec_); + oss << " mode:0" << std::oct << (debugInfo.mode_ & permission) << " size:" << std::dec << debugInfo.size_ + << " uid:" << std::dec << debugInfo.uid_ << " gid:" << std::dec << debugInfo.gid_ + << " atim:" << GetTimeWithMilliseconds(debugInfo.atime_.sec_, debugInfo.atime_.nsec_) + << " mtim:" << GetTimeWithMilliseconds(debugInfo.mtime_.sec_, debugInfo.mtime_.nsec_) + << " ctim:" << GetTimeWithMilliseconds(debugInfo.ctime_.sec_, debugInfo.ctime_.nsec_); return oss.str(); } @@ -206,4 +222,46 @@ void RdbFaultHiViewReporter::Update(RdbCorruptedEvent &eventInfo, const std::map } } } + +std::string RdbFaultHiViewReporter::GetBundleName(const RdbCorruptedEvent &eventInfo) +{ + if (!eventInfo.bundleName.empty()) { + return eventInfo.bundleName; + } + auto tokenId = IPCSkeleton::GetCallingTokenID(); + auto tokenType = AccessTokenKit::GetTokenTypeFlag(tokenId); + if ((tokenType == TOKEN_NATIVE) || (tokenType == TOKEN_SHELL)) { + NativeTokenInfo tokenInfo; + if (AccessTokenKit::GetNativeTokenInfo(tokenId, tokenInfo) == 0) { + return tokenInfo.processName; + } + } + return SqliteUtils::Anonymous(eventInfo.storeName); +} + +std::string RdbFaultHiViewReporter::Format(const std::map &debugs, const std::string &header) +{ + if (debugs.empty()) { + return ""; + } + std::string appendix = header; + for (auto &[name, debugInfo] : debugs) { + appendix += "\n" + name + " :" + GetFileStatInfo(debugInfo); + } + return appendix; +} + +std::string RdbFaultHiViewReporter::FormatBrief(const std::map &debugs, + const std::string &header) +{ + if (debugs.empty()) { + return ""; + } + std::stringstream oss; + oss << header << ":"; + for (auto &[name, debugInfo] : debugs) { + oss << "<" << name << ",0x" << std::hex << debugInfo.inode_ << "," << std::dec << debugInfo.size_ << ">"; + } + return oss.str(); +} } // namespace OHOS::NativeRdb \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb/include/connection.h b/relational_store/frameworks/native/rdb/include/connection.h index fa335803a1e3f350693da3629e9664c9009c7571..bf1678d8fbed59482c999d8bcd4c1e0aedc15faa 100644 --- a/relational_store/frameworks/native/rdb/include/connection.h +++ b/relational_store/frameworks/native/rdb/include/connection.h @@ -55,7 +55,7 @@ public: virtual int32_t GetDBType() const = 0; virtual bool IsWriter() const = 0; virtual int32_t ReSetKey(const RdbStoreConfig &config) = 0; - virtual int32_t TryCheckPoint() = 0; + virtual int32_t TryCheckPoint(bool timeout) = 0; virtual int32_t LimitWalSize() = 0; virtual int32_t ConfigLocale(const std::string &localeStr) = 0; virtual int32_t CleanDirtyData(const std::string &table, uint64_t cursor) = 0; diff --git a/relational_store/frameworks/native/rdb/include/connection_pool.h b/relational_store/frameworks/native/rdb/include/connection_pool.h index bef480ae320f77d58dcd638dd2781f60d46917df..6a0d444d86dce9ae22ac6192745343f7fd95dd7c 100644 --- a/relational_store/frameworks/native/rdb/include/connection_pool.h +++ b/relational_store/frameworks/native/rdb/include/connection_pool.h @@ -38,11 +38,11 @@ public: using SharedConn = std::shared_ptr; using SharedConns = std::vector; static constexpr std::chrono::milliseconds INVALID_TIME = std::chrono::milliseconds(0); - static std::shared_ptr Create(const RdbStoreConfig &storeConfig, int &errCode); + static std::shared_ptr Create(const RdbStoreConfig &config, int &errCode); ~ConnectionPool(); static std::pair> HandleDataCorruption (const RdbStoreConfig &storeConfig, int &errCode); - std::pair> CreateConnection(bool isReadOnly); + std::pair> CreateTransConn(bool limited = true); SharedConn AcquireConnection(bool isReadOnly); SharedConn Acquire(bool isReadOnly, std::chrono::milliseconds ms = INVALID_TIME); // this interface is only provided for resultSet @@ -64,26 +64,30 @@ public: private: struct ConnNode { + static constexpr uint32_t CHECK_POINT_INTERVAL = 5; // 5 min bool using_ = false; int32_t tid_ = 0; int32_t id_ = 0; std::chrono::steady_clock::time_point time_ = std::chrono::steady_clock::now(); + std::chrono::steady_clock::time_point failedTime_; std::shared_ptr connect_; explicit ConnNode(std::shared_ptr conn); std::shared_ptr GetConnect(); int64_t GetUsingTime() const; bool IsWriter() const; - int32_t Unused(); + int32_t Unused(bool inTrans); }; struct Container { using Creator = std::function>()>; static constexpr int32_t MAX_RIGHT = 0x4FFFFFFF; + static constexpr int32_t MIN_TRANS_ID = 10000; bool disable_ = true; int max_ = 0; int total_ = 0; int count_ = 0; + int trans_ = 0; int32_t left_ = 0; int32_t right_ = 0; std::chrono::seconds timeout_; @@ -97,13 +101,15 @@ private: int32_t ConfigLocale(const std::string &locale); std::shared_ptr Acquire(std::chrono::milliseconds milliS); std::list> AcquireAll(std::chrono::milliseconds milliS); + std::pair> Create(); void Disable(); void Enable(); int32_t Release(std::shared_ptr node); + int32_t Drop(std::shared_ptr node); int32_t Clear(); bool IsFull(); - int32_t Dump(const char *header); + int32_t Dump(const char *header, bool inTrans); private: int32_t ExtendNode(); @@ -113,8 +119,8 @@ private: explicit ConnectionPool(const RdbStoreConfig &storeConfig); std::pair> Init(bool isAttach = false, bool needWriter = false); int32_t GetMaxReaders(const RdbStoreConfig &config); - std::shared_ptr Convert2AutoConn(std::shared_ptr node); - void ReleaseNode(std::shared_ptr node); + std::shared_ptr Convert2AutoConn(std::shared_ptr node, bool isTrans = false); + void ReleaseNode(std::shared_ptr node, bool reuse = true); int RestoreByDbSqliteType(const std::string &newPath, const std::string &backupPath, SlaveStatus &slaveStatus); int RestoreMasterDb(const std::string &newPath, const std::string &backupPath); bool CheckIntegrity(const std::string &dbPath); @@ -122,6 +128,7 @@ private: static constexpr int LIMITATION = 1024; static constexpr uint32_t ITER_V1 = 5000; static constexpr uint32_t ITERS_COUNT = 2; + static constexpr uint32_t MAX_TRANS = 4; const RdbStoreConfig &config_; RdbStoreConfig attachConfig_; Container writers_; @@ -134,6 +141,7 @@ private: std::mutex transMutex_; bool transactionUsed_; std::atomic isInTransaction_ = false; + std::atomic transCount_ = 0; }; } // namespace NativeRdb diff --git a/relational_store/frameworks/native/rdb/include/rd_connection.h b/relational_store/frameworks/native/rdb/include/rd_connection.h index ec62e9d4c6a98fe3bcfa6c672a9e9c41014d53bf..26e1652366be62b0eca1d4881168e440815e6291 100644 --- a/relational_store/frameworks/native/rdb/include/rd_connection.h +++ b/relational_store/frameworks/native/rdb/include/rd_connection.h @@ -42,7 +42,7 @@ public: int32_t GetDBType() const override; bool IsWriter() const override; int32_t ReSetKey(const RdbStoreConfig& config) override; - int32_t TryCheckPoint() override; + int32_t TryCheckPoint(bool timeout) override; int32_t LimitWalSize() override; int32_t ConfigLocale(const std::string& localeStr) override; int32_t CleanDirtyData(const std::string& table, uint64_t cursor) override; diff --git a/relational_store/frameworks/native/rdb/include/rd_statement.h b/relational_store/frameworks/native/rdb/include/rd_statement.h index c570d5125baff0b6b6252c9aa40f1f25192d8186..e802c915c5b204567d87c98c5d72e20ec680283b 100644 --- a/relational_store/frameworks/native/rdb/include/rd_statement.h +++ b/relational_store/frameworks/native/rdb/include/rd_statement.h @@ -39,6 +39,7 @@ public: int32_t Step() override; int32_t Reset() override; int32_t Execute(const std::vector& args) override; + int32_t Execute(const std::vector>& args) override; std::pair ExecuteForValue(const std::vector& args) override; int32_t Changes() const override; int64_t LastInsertRowId() const override; @@ -55,6 +56,7 @@ public: private: friend class RdConnection; int Prepare(GRD_DB *db, const std::string &sql); + int32_t Bind(const std::vector>& args); int InnerBindBlobTypeArgs(const ValueObject &bindArg, uint32_t index) const; int IsValid(int index) const; 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 e5bf0043bf3f68f82c6864019319682b70307bd8..d031450910d12dcfe5769af527899d341928d632 100644 --- a/relational_store/frameworks/native/rdb/include/rdb_service_proxy.h +++ b/relational_store/frameworks/native/rdb/include/rdb_service_proxy.h @@ -41,7 +41,7 @@ public: int32_t InitNotifier(const RdbSyncerParam ¶m, sptr notifier) override; int32_t SetDistributedTables(const RdbSyncerParam ¶m, const std::vector &tables, - const std::vector &references, int32_t type = DISTRIBUTED_DEVICE) override; + const std::vector &references, bool isRebuild, int32_t type = DISTRIBUTED_DEVICE) override; int32_t Sync(const RdbSyncerParam& param, const Option& option, const PredicatesMemo& predicates, const AsyncDetail &async) override; diff --git a/relational_store/frameworks/native/rdb/include/rdb_store_impl.h b/relational_store/frameworks/native/rdb/include/rdb_store_impl.h index a0415cffcd7a6760e562ab06bb604c50a45a3246..338794a41cc7a03a3054d09c3e2c64b0008d2a43 100644 --- a/relational_store/frameworks/native/rdb/include/rdb_store_impl.h +++ b/relational_store/frameworks/native/rdb/include/rdb_store_impl.h @@ -44,8 +44,8 @@ namespace OHOS::NativeRdb { class DelayNotify; class RdbStoreLocalObserver { public: - explicit RdbStoreLocalObserver(DistributedRdb::RdbStoreObserver *observer) : observer_(observer) {}; - virtual ~RdbStoreLocalObserver() {}; + explicit RdbStoreLocalObserver(DistributedRdb::RdbStoreObserver *observer) : observer_(observer){}; + virtual ~RdbStoreLocalObserver(){}; void OnChange() { observer_->OnChange(); @@ -54,14 +54,15 @@ public: { return observer_; } + private: DistributedRdb::RdbStoreObserver *observer_ = nullptr; }; class RdbStoreLocalSharedObserver : public AAFwk::DataAbilityObserverStub { public: - explicit RdbStoreLocalSharedObserver(DistributedRdb::RdbStoreObserver *observer) : observer_(observer) {}; - virtual ~RdbStoreLocalSharedObserver() {}; + explicit RdbStoreLocalSharedObserver(DistributedRdb::RdbStoreObserver *observer) : observer_(observer){}; + virtual ~RdbStoreLocalSharedObserver(){}; void OnChange() override { observer_->OnChange(); @@ -70,6 +71,7 @@ public: { return observer_; } + private: DistributedRdb::RdbStoreObserver *observer_ = nullptr; }; @@ -79,45 +81,23 @@ public: RdbStoreImpl(const RdbStoreConfig &config); RdbStoreImpl(const RdbStoreConfig &config, int &errCode); ~RdbStoreImpl() override; - const RdbStoreConfig &GetConfig(); - int Insert(int64_t &outRowId, const std::string &table, const ValuesBucket &values) override; - int BatchInsert(int64_t& outInsertNum, const std::string& table, const std::vector& values) override; - int Replace(int64_t &outRowId, const std::string &table, const ValuesBucket &initialValues) override; - int InsertWithConflictResolution(int64_t &outRowId, const std::string &table, const ValuesBucket &values, - ConflictResolution conflictResolution) override; - int Update(int &changedRows, const std::string &table, const ValuesBucket &values, const std::string &whereClause, - const std::vector &whereArgs) override; - int Update(int &changedRows, const std::string &table, const ValuesBucket &values, const std::string &whereClause, - const std::vector &bindArgs) override; - int UpdateWithConflictResolution(int &changedRows, const std::string &table, const ValuesBucket &values, - const std::string &whereClause, const std::vector &whereArgs, - ConflictResolution conflictResolution) override; - int UpdateWithConflictResolution(int &changedRows, const std::string &table, const ValuesBucket &values, - const std::string &whereClause, const std::vector &bindArgs, - ConflictResolution conflictResolution) override; - int Delete(int &deletedRows, const std::string &table, const std::string &whereClause, - const std::vector &whereArgs) override; - int Delete(int &deletedRows, const std::string &table, const std::string &whereClause, - const std::vector &bindArgs) override; - std::shared_ptr Query(int &errCode, bool distinct, - const std::string &table, const std::vector &columns, - const std::string &whereClause, const std::vector &bindArgs, const std::string &groupBy, - const std::string &indexName, const std::string &orderBy, const int &limit, const int &offset) override; - std::shared_ptr QuerySql(const std::string &sql, - const std::vector &sqlArgs) override; - std::shared_ptr QuerySql(const std::string &sql, - const std::vector &bindArgs) override; - int ExecuteSql(const std::string& sql, const std::vector& bindArgs) override; - std::pair Execute(const std::string& sql, const std::vector& bindArgs, - int64_t trxId) override; - int ExecuteAndGetLong(int64_t &outValue, const std::string &sql, const std::vector &bindArgs) override; - int ExecuteAndGetString(std::string &outValue, const std::string &sql, - const std::vector &bindArgs) override; - int ExecuteForLastInsertedRowId(int64_t &outValue, const std::string &sql, - const std::vector &bindArgs) override; - int ExecuteForChangedRowCount(int64_t &outValue, const std::string &sql, - const std::vector &bindArgs) override; - int Backup(const std::string &databasePath, const std::vector &destEncryptKey) override; + std::pair Insert(const std::string &table, const Row &row, Resolution resolution) override; + std::pair BatchInsert(const std::string& table, const ValuesBuckets& values) override; + std::pair Update(const std::string &table, const Row &row, const std::string &where, const Values &args, + Resolution resolution) override; + int Delete(int &deletedRows, const std::string &table, const std::string &whereClause, const Values &args) override; + std::shared_ptr QuerySql(const std::string &sql, const Values &args) override; + std::shared_ptr QueryByStep(const std::string &sql, const Values &args) override; + std::shared_ptr RemoteQuery(const std::string &device, const AbsRdbPredicates &predicates, + const Fields &columns, int &errCode) override; + std::pair> QuerySharingResource(const AbsRdbPredicates &predicates, + const Fields &columns) override; + int ExecuteSql(const std::string &sql, const Values &args) override; + std::pair Execute(const std::string &sql, const Values &args, int64_t trxId) override; + int ExecuteAndGetLong(int64_t &outValue, const std::string &sql, const Values &args) override; + int ExecuteAndGetString(std::string &outValue, const std::string &sql, const Values &args) override; + int ExecuteForLastInsertedRowId(int64_t &outValue, const std::string &sql, const Values &args) override; + int ExecuteForChangedRowCount(int64_t &outValue, const std::string &sql, const Values &args) override; int GetVersion(int &version) override; int SetVersion(int version) override; int BeginTransaction() override; @@ -133,71 +113,49 @@ public: bool IsMemoryRdb() const override; bool IsHoldingConnection() override; bool IsSlaveDiffFromMaster() const override; - int ConfigLocale(const std::string &localeStr); + int Backup(const std::string &databasePath, const std::vector &encryptKey) override; int Restore(const std::string &backupPath, const std::vector &newKey) override; - std::string GetName(); - std::string GetFileType(); - std::shared_ptr QueryByStep(const std::string& sql, const std::vector& sqlArgs) override; - std::shared_ptr QueryByStep(const std::string &sql, const std::vector &args) override; - std::shared_ptr QueryByStep( - const AbsRdbPredicates &predicates, const std::vector &columns) override; - std::shared_ptr Query( - const AbsRdbPredicates &predicates, const std::vector &columns) override; - std::pair> QuerySharingResource( - const AbsRdbPredicates &predicates, const std::vector &columns) override; int Count(int64_t &outValue, const AbsRdbPredicates &predicates) override; - int Update(int &changedRows, const ValuesBucket &values, const AbsRdbPredicates &predicates) override; - int Delete(int &deletedRows, const AbsRdbPredicates &predicates) override; - - std::shared_ptr RemoteQuery(const std::string &device, const AbsRdbPredicates &predicates, - const std::vector &columns, int &errCode) override; - int SetDistributedTables(const std::vector &tables, int32_t type, const DistributedRdb::DistributedConfig &distributedConfig) override; - - std::string ObtainDistributedTableName(const std::string& device, const std::string& table, int &errCode) override; - + std::string ObtainDistributedTableName(const std::string &device, const std::string &table, int &errCode) override; int Sync(const SyncOption &option, const AbsRdbPredicates &predicate, const AsyncBrief &async) override; - int Sync(const SyncOption &option, const std::vector &tables, const AsyncDetail &async) override; - int Sync(const SyncOption &option, const AbsRdbPredicates &predicate, const AsyncDetail &async) override; - - int Subscribe(const SubscribeOption& option, RdbStoreObserver *observer) override; - - int UnSubscribe(const SubscribeOption& option, RdbStoreObserver *observer) override; - - int SubscribeObserver(const SubscribeOption& option, const std::shared_ptr &observer) override; - - int UnsubscribeObserver(const SubscribeOption& option, const std::shared_ptr &observer) override; - + int Subscribe(const SubscribeOption &option, RdbStoreObserver *observer) override; + int UnSubscribe(const SubscribeOption &option, RdbStoreObserver *observer) override; + int SubscribeObserver(const SubscribeOption &option, const std::shared_ptr &observer) override; + int UnsubscribeObserver(const SubscribeOption &option, const std::shared_ptr &observer) override; int RegisterAutoSyncCallback(std::shared_ptr observer) override; - int UnregisterAutoSyncCallback(std::shared_ptr observer) override; - int Notify(const std::string &event) override; - int SetSearchable(bool isSearchable) override; - - ModifyTime GetModifyTime(const std::string& table, const std::string& columnName, - std::vector& keys) override; - + ModifyTime GetModifyTime(const std::string &table, const std::string &columnName, + std::vector &keys) override; int GetRebuilt(RebuiltType &rebuilt) override; int CleanDirtyData(const std::string &table, uint64_t cursor) override; - std::pair Attach( - const RdbStoreConfig &config, const std::string &attachName, int32_t waitTime = 2) override; - std::pair Detach(const std::string &attachName, int32_t waitTime = 2) override; + std::pair Attach(const RdbStoreConfig &config, const std::string &attachName, + int32_t waitTime) override; + std::pair Detach(const std::string &attachName, int32_t waitTime) override; int ModifyLockStatus(const AbsRdbPredicates &predicates, bool isLock) override; int32_t GetDbType() const override; - std::pair LockCloudContainer() override; int32_t UnlockCloudContainer() override; int InterruptBackup() override; int32_t GetBackupStatus() const override; + std::pair> CreateTransaction(int32_t type) override; + + // not virtual functions / + const RdbStoreConfig &GetConfig(); + int ConfigLocale(const std::string &localeStr); + std::string GetName(); + std::string GetFileType(); int32_t ExchangeSlaverToMaster(); +protected: + std::string GetLogTableName(const std::string &tableName) override; + private: - using ExecuteSqls = std::vector>>>; using Stmt = std::shared_ptr; using RdbParam = DistributedRdb::RdbSyncerParam; @@ -210,44 +168,37 @@ private: const std::string &sql, const ValueObject &object, int sqlType); int CheckAttach(const std::string &sql); std::pair BeginExecuteSql(const std::string &sql); - ExecuteSqls GenerateSql(const std::string& table, const std::vector& buckets, int limit); int GetDataBasePath(const std::string &databasePath, std::string &backupFilePath); - void SetAssetStatus(const ValueObject &val, int32_t status); void DoCloudSync(const std::string &table); int InnerSync(const DistributedRdb::RdbService::Option &option, const DistributedRdb::PredicatesMemo &predicates, const AsyncDetail &async); - int InnerBackup(const std::string& databasePath, - const std::vector& destEncryptKey = std::vector()); - ModifyTime GetModifyTimeByRowId(const std::string& logTable, std::vector& keys); + int InnerBackup(const std::string &databasePath, + const std::vector &destEncryptKey = std::vector()); + ModifyTime GetModifyTimeByRowId(const std::string &logTable, std::vector &keys); Uri GetUri(const std::string &event); - int SubscribeLocal(const SubscribeOption& option, RdbStoreObserver *observer); - int SubscribeLocalShared(const SubscribeOption& option, RdbStoreObserver *observer); - int32_t SubscribeLocalDetail(const SubscribeOption& option, const std::shared_ptr &observer); - int SubscribeRemote(const SubscribeOption& option, RdbStoreObserver *observer); - int UnSubscribeLocal(const SubscribeOption& option, RdbStoreObserver *observer); - int UnSubscribeLocalAll(const SubscribeOption& option); - int UnSubscribeLocalShared(const SubscribeOption& option, RdbStoreObserver *observer); - int UnSubscribeLocalSharedAll(const SubscribeOption& option); - int32_t UnsubscribeLocalDetail(const SubscribeOption& option, const std::shared_ptr &observer); - int UnSubscribeRemote(const SubscribeOption& option, RdbStoreObserver *observer); + int SubscribeLocal(const SubscribeOption &option, RdbStoreObserver *observer); + int SubscribeLocalShared(const SubscribeOption &option, RdbStoreObserver *observer); + int32_t SubscribeLocalDetail(const SubscribeOption &option, const std::shared_ptr &observer); + int SubscribeRemote(const SubscribeOption &option, RdbStoreObserver *observer); + int UnSubscribeLocal(const SubscribeOption &option, RdbStoreObserver *observer); + int UnSubscribeLocalAll(const SubscribeOption &option); + int UnSubscribeLocalShared(const SubscribeOption &option, RdbStoreObserver *observer); + int UnSubscribeLocalSharedAll(const SubscribeOption &option); + int32_t UnsubscribeLocalDetail(const SubscribeOption &option, const std::shared_ptr &observer); + int UnSubscribeRemote(const SubscribeOption &option, RdbStoreObserver *observer); int RegisterDataChangeCallback(); void InitDelayNotifier(); - bool ColHasSpecificField(const std::vector &columns); - std::pair CreateWriteableStmt(const std::string &sql); - std::pair GetStatement(const std::string& sql, std::shared_ptr conn) const; - std::pair GetStatement(const std::string& sql, bool read = false) const; - int AttachInner(const std::string &attachName, - const std::string &dbPath, const std::vector &key, int32_t waitTime); + std::pair> CreateWritableConn(); + std::vector CreateBackupBindArgs(const std::string &databasePath, + const std::vector &destEncryptKey); + std::pair GetStatement(const std::string &sql, std::shared_ptr conn) const; + std::pair GetStatement(const std::string &sql, bool read = false) const; + int AttachInner(const RdbStoreConfig &config, const std::string &attachName, const std::string &dbPath, + const std::vector &key, int32_t waitTime); + int SetDefaultEncryptSql(const std::shared_ptr &statement, std::string sql, + const RdbStoreConfig &config); + int SetDefaultEncryptAlgo(const ConnectionPool::SharedConn &conn, const RdbStoreConfig &config); int GetHashKeyForLockRow(const AbsRdbPredicates &predicates, std::vector> &hashKeys); - int InsertWithConflictResolutionEntry(int64_t &outRowId, const std::string &table, const ValuesBucket &values, - ConflictResolution conflictResolution); - int UpdateWithConflictResolutionEntry(int &changedRows, const std::string &table, const ValuesBucket &values, - const std::string &whereClause, const std::vector &bindArgs, - ConflictResolution conflictResolution); - int BatchInsertEntry(int64_t& outInsertNum, const std::string& table, const std::vector& values); - int ExecuteSqlEntry(const std::string& sql, const std::vector& bindArgs); - std::pair ExecuteEntry(const std::string& sql, const std::vector& bindArgs, - int64_t trxId); int GetSlaveName(const std::string &dbName, std::string &backupFilePath); bool TryGetMasterSlaveBackupPath(const std::string &srcPath, std::string &destPath, bool isRestore = false); void NotifyDataChange(); @@ -257,7 +208,7 @@ private: static constexpr uint32_t EXPANSION = 2; static inline constexpr uint32_t INTERVAL = 10; static inline constexpr uint32_t RETRY_INTERVAL = 5; // s - static inline constexpr uint32_t MAX_RETRY_TIMES = 5; + static inline constexpr int32_t MAX_RETRY_TIMES = 5; static constexpr const char *ROW_ID = "ROWID"; bool isOpen_ = false; @@ -282,6 +233,7 @@ private: std::map>> localSharedObservers_; ConcurrentMap attachedInfo_; ConcurrentMap> trxConnMap_ = {}; + std::list> transactions_; }; } // namespace OHOS::NativeRdb #endif 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 36cb3d95cade011df5ad953dae0e79c2c663a756..ac06f7914aed16649c60bab3457632ea055c59ef 100644 --- a/relational_store/frameworks/native/rdb/include/rdb_store_manager.h +++ b/relational_store/frameworks/native/rdb/include/rdb_store_manager.h @@ -25,10 +25,10 @@ #include "lru_bucket.h" #include "rdb_open_callback.h" #include "rdb_store_config.h" -#include "rdb_store_impl.h" namespace OHOS { namespace NativeRdb { +class RdbStoreImpl; class RdbStoreManager { public: static RdbStoreManager &GetInstance(); @@ -50,6 +50,7 @@ private: int32_t GetParamFromService(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); static constexpr uint32_t BUCKET_MAX_SIZE = 4; static const bool regCollector_; diff --git a/relational_store/frameworks/native/rdb/include/sqlite_connection.h b/relational_store/frameworks/native/rdb/include/sqlite_connection.h index 638098feb454ff2ad874d91f028493dec192964a..a255521a67c789e695356067e7ec962b1728b043 100644 --- a/relational_store/frameworks/native/rdb/include/sqlite_connection.h +++ b/relational_store/frameworks/native/rdb/include/sqlite_connection.h @@ -28,7 +28,6 @@ #include "rdb_store_config.h" #include "sqlite3sym.h" #include "sqlite_statement.h" -#include "task_executor.h" #include "value_object.h" typedef struct ClientChangedData ClientChangedData; @@ -48,7 +47,7 @@ public: SqliteConnection(const RdbStoreConfig &config, bool isWriteConnection); ~SqliteConnection(); int32_t OnInitialize() override; - int TryCheckPoint() override; + int TryCheckPoint(bool timeout) override; int LimitWalSize() override; int ConfigLocale(const std::string &localeStr) override; int CleanDirtyData(const std::string &table, uint64_t cursor) override; @@ -85,9 +84,9 @@ private: int Configure(const RdbStoreConfig &config, std::string &dbPath); int SetPageSize(const RdbStoreConfig &config); int SetEncrypt(const RdbStoreConfig &config); - int SetEncryptKey(const std::vector &key, int32_t iter); + int SetEncryptKey(const std::vector &key, const RdbStoreConfig &config); int SetServiceKey(const RdbStoreConfig &config, int32_t errCode); - int SetEncryptAgo(int32_t iter); + int SetEncryptAgo(const RdbStoreConfig &config); int SetJournalMode(const RdbStoreConfig &config); int SetJournalSizeLimit(const RdbStoreConfig &config); int SetAutoCheckpoint(const RdbStoreConfig &config); @@ -113,10 +112,10 @@ 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 isWrite, bool checkSlaveExist = true); + int CreateSlaveConnection(const RdbStoreConfig &config, bool checkSlaveExist = true); int ExchangeSlaverToMaster(bool isRestore, SlaveStatus &status); - bool IsRepairable(); - std::pair ExchangeVerify(bool isRestore); + int IsRepairable(); + int ExchangeVerify(bool isRestore); static std::pair> InnerCreate(const RdbStoreConfig &config, bool isWrite); static constexpr SqliteConnection::Suffix FILE_SUFFIXES[] = { @@ -133,13 +132,15 @@ private: static constexpr int DEFAULT_BUSY_TIMEOUT_MS = 2000; 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 uint32_t NO_ITER = 0; + static constexpr uint32_t WAL_INDEX = 2; static const int32_t regCreator_; static const int32_t regRepairer_; static const int32_t regDeleter_; static const int32_t regCollector_; - std::atomic backupId_ = TaskExecutor::INVALID_TASK_ID; + std::atomic backupId_; sqlite3 *dbHandle_; bool isWriter_; bool isReadOnly_; diff --git a/relational_store/frameworks/native/rdb/include/sqlite_global_config.h b/relational_store/frameworks/native/rdb/include/sqlite_global_config.h index 8039a835f7346fe9486731730626377f6d6576f6..effef70e71696a02af1e092a1c7b9b18f29e6f91 100644 --- a/relational_store/frameworks/native/rdb/include/sqlite_global_config.h +++ b/relational_store/frameworks/native/rdb/include/sqlite_global_config.h @@ -29,8 +29,9 @@ public: static constexpr int SOFT_HEAP_LIMIT = 8 * 1024 * 1024; /* 8MB */ static constexpr int DB_PAGE_SIZE = 4096; /* default page size : 4k */ static constexpr int DB_JOURNAL_SIZE = 1024 * 1024; /* default file size : 1M */ - static constexpr uint32_t DB_WAL_SIZE_LIMIT_MIN = 20 * 1024 * 1024; /* default wal file maximum size : 20M */ - static constexpr uint32_t DB_WAL_SIZE_LIMIT_MAX = 1024 * 1024 * 1024; /* default wal file maximum size : 1G */ + static constexpr ssize_t DB_WAL_SIZE_LIMIT_MIN = 20 * 1024 * 1024; /* default wal file maximum size : 20M */ + static constexpr ssize_t DB_WAL_WARNING_SIZE = 256 * 1024 * 1024; /* default wal file maximum size : 256M */ + static constexpr ssize_t DB_WAL_SIZE_LIMIT_MAX = 512 * 1024 * 1024; /* default wal file maximum size : 512M */ static constexpr int WAL_AUTO_CHECKPOINT = 100; /* 100 pages */ static constexpr int APP_DEFAULT_UMASK = 0002; static constexpr int SQLITE_MAX_COLUMN = 2000; @@ -47,10 +48,20 @@ public: static constexpr char DEFAULE_SYNC_MODE[] = "FULL"; static constexpr char MEMORY_DB_PATH[] = ":memory:"; static constexpr char CODEC_HMAC_ALGO[] = "PRAGMA codec_hmac_algo=sha256"; + static constexpr char CODEC_HMAC_ALGO_PREFIX[] = "PRAGMA codec_hmac_algo='"; + static constexpr char CODEC_KDF_ALGO_PREFIX[] = "PRAGMA codec_kdf_algo='"; + static constexpr char CODEC_PAGE_SIZE_PREFIX[] = "PRAGMA codec_page_size="; static constexpr char CODEC_REKEY_HMAC_ALGO[] = "PRAGMA codec_rekey_hmac_algo=sha256"; static constexpr char CIPHER_DEFAULT_ALGO[] = "PRAGMA codec_cipher='aes-256-gcm'"; + static constexpr char CIPHER_ALGO_PREFIX[] = "PRAGMA codec_cipher='"; + static constexpr char ALGO_SUFFIX[] = "'"; static constexpr char CIPHER_KDF_ITER[] = "PRAGMA codec_kdf_iter="; static constexpr char CIPHER_DEFAULT_ATTACH_HMAC_ALGO[] = "PRAGMA cipher_default_attach_hmac_algo=sha256"; + static constexpr char CIPHER_DEFAULT_ATTACH_CIPHER_PREFIX[] = "PRAGMA cipher_default_attach_cipher='"; + static constexpr char CIPHER_DEFAULT_ATTACH_HMAC_ALGO_PREFIX[] = "PRAGMA cipher_default_attach_hmac_algo='"; + static constexpr char CIPHER_DEFAULT_ATTACH_KDF_ALGO_PREFIX[] = "PRAGMA cipher_default_attach_kdf_algo='"; + static constexpr char CIPHER_DEFAULT_ATTACH_PAGE_SIZE_PREFIX[] = "PRAGMA cipher_default_attach_page_size="; + static constexpr char CIPHER_DEFAULT_ATTACH_KDF_ITER_PREFIX[] = "PRAGMA cipher_default_attach_kdf_iter="; }; class SqliteGlobalConfig { diff --git a/relational_store/frameworks/native/rdb/include/sqlite_shared_result_set.h b/relational_store/frameworks/native/rdb/include/sqlite_shared_result_set.h index 6dc8ca05d190e3d322ed5fe7448a80aad506c310..c6109bb4cc2e00eb6d69500f15d361901365bd86 100644 --- a/relational_store/frameworks/native/rdb/include/sqlite_shared_result_set.h +++ b/relational_store/frameworks/native/rdb/include/sqlite_shared_result_set.h @@ -22,11 +22,11 @@ #include #include #include +#include #include "abs_shared_result_set.h" #include "connection.h" #include "shared_block.h" -#include "connection_pool.h" #include "statement.h" #include "value_object.h" @@ -34,8 +34,10 @@ namespace OHOS { namespace NativeRdb { class SqliteSharedResultSet : public AbsSharedResultSet { public: - SqliteSharedResultSet(std::shared_ptr pool, std::string path, - std::string sql, const std::vector &bindArgs); + using Values = std::vector; + using Conn = std::shared_ptr; + using Time = std::chrono::steady_clock::time_point; + SqliteSharedResultSet(Time start, Conn conn, std::string sql, const Values &args, const std::string &path); ~SqliteSharedResultSet() override; int Close() override; int32_t OnGo(int oldPosition, int newPosition) override; @@ -72,7 +74,6 @@ private: std::shared_ptr statement_; std::string qrySql_; std::vector bindArgs_; - std::vector columnNames_; std::mutex mutex_; }; } // namespace NativeRdb diff --git a/relational_store/frameworks/native/rdb/include/sqlite_sql_builder.h b/relational_store/frameworks/native/rdb/include/sqlite_sql_builder.h index 537a08427ae7a887d6bb1e0118d7df5c043a05a9..104e6b87e676430207ba3b79183411620c9f2fde 100644 --- a/relational_store/frameworks/native/rdb/include/sqlite_sql_builder.h +++ b/relational_store/frameworks/native/rdb/include/sqlite_sql_builder.h @@ -26,7 +26,8 @@ namespace OHOS { namespace NativeRdb { class SqliteSqlBuilder { public: - using ExecuteSqls = std::vector>>>; + using RefValue = std::reference_wrapper; + using BatchRefSqls = std::vector>>>; SqliteSqlBuilder(); ~SqliteSqlBuilder(); static std::string BuildUpdateString(const ValuesBucket &values, const std::string &tableName, @@ -48,16 +49,20 @@ public: const AbsRdbPredicates &predicates, const std::vector &columns, const std::string &logTable); static std::string GetSqlArgs(size_t size); - static ExecuteSqls MakeExecuteSqls( - const std::string &sql, std::vector &&args, int fieldSize, int limit); + static BatchRefSqls GenerateSqls(const std::string &table, const ValuesBuckets &buckets, int limit); + static void UpdateAssetStatus(const ValueObject &value, int32_t status); private: + static BatchRefSqls MakeExecuteSqls(const std::string &sql, const std::vector &args, int fieldSize, + int limit); static void AppendClause(std::string &builder, const std::string &name, const std::string &clause, const std::string &table = ""); static void AppendColumns( std::string &builder, const std::vector &columns, const std::string &table = ""); static constexpr const char *SHARING_RESOURCE = "sharing_resource"; - + static constexpr uint32_t EXPANSION = 2; + static ValueObject nullObject_; + static std::reference_wrapper nullRef_; static std::string HandleTable(const std::string &tableName); }; } // namespace NativeRdb diff --git a/relational_store/frameworks/native/rdb/include/sqlite_statement.h b/relational_store/frameworks/native/rdb/include/sqlite_statement.h index 835ddbc539adcc0d6a9028f603cf6fa25d34953c..92d2f8b7823a7ec157a4d267058c80eedd834ff1 100644 --- a/relational_store/frameworks/native/rdb/include/sqlite_statement.h +++ b/relational_store/frameworks/native/rdb/include/sqlite_statement.h @@ -44,6 +44,7 @@ public: int Reset() override; int Finalize() override; int Execute(const std::vector &args) override; + int32_t Execute(const std::vector> &args) override; std::pair ExecuteForValue(const std::vector &args) override; int Changes() const override; int64_t LastInsertRowId() const override; @@ -82,12 +83,13 @@ private: int Prepare(sqlite3 *dbHandle, const std::string &sql); int BindArgs(const std::vector &bindArgs); + int BindArgs(const std::vector> &bindArgs); int IsValid(int index) const; int InnerStep(); int InnerFinalize(); ValueObject GetValueFromBlob(int32_t index, int32_t type) const; void ReadFile2Buffer(); - void PrintInfoForDbError(int errorCode); + void PrintInfoForDbError(int errCode, const std::string &sql); static constexpr uint32_t BUFFER_LEN = 16; @@ -104,9 +106,9 @@ private: std::shared_ptr conn_; std::string sql_; mutable std::vector types_; - std::shared_ptr slave_; + std::shared_ptr slave_; const RdbStoreConfig *config_ = nullptr; }; } // namespace NativeRdb } // namespace OHOS -#endif \ No newline at end of file +#endif diff --git a/relational_store/frameworks/native/rdb/include/sqlite_utils.h b/relational_store/frameworks/native/rdb/include/sqlite_utils.h index 069e775725dfea38ffa257dfd46e58d241a789c2..e8b1563f2d99d489965516b026dbddd509585735 100644 --- a/relational_store/frameworks/native/rdb/include/sqlite_utils.h +++ b/relational_store/frameworks/native/rdb/include/sqlite_utils.h @@ -55,11 +55,14 @@ public: static bool RenameFile(const std::string &srcFile, const std::string &destFile); static bool CopyFile(const std::string &srcFile, const std::string &destFile); static std::string Anonymous(const std::string &srcFile); - static int GetFileSize(const std::string &fileName); + 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 const char *HmacAlgoDescription(int32_t hmacAlgo); + static const char *KdfAlgoDescription(int32_t kdfAlgo); + static const char *EncryptAlgoDescription(int32_t encryptAlgo); private: struct SqlType { diff --git a/relational_store/frameworks/native/rdb/include/statement.h b/relational_store/frameworks/native/rdb/include/statement.h index 400bcff86611dcc33f62e005544349a27ca15bed..d5d25653616bcbd463b9375c3eacd8886708fa58 100644 --- a/relational_store/frameworks/native/rdb/include/statement.h +++ b/relational_store/frameworks/native/rdb/include/statement.h @@ -39,6 +39,7 @@ public: virtual int32_t Reset() = 0; virtual int32_t Finalize() = 0; virtual int32_t Execute(const std::vector &args = {}) = 0; + virtual int32_t Execute(const std::vector> &args) = 0; virtual std::pair ExecuteForValue(const std::vector &args = {}) = 0; virtual int32_t Changes() const = 0; diff --git a/relational_store/frameworks/native/rdb/include/step_result_set.h b/relational_store/frameworks/native/rdb/include/step_result_set.h index e2a580c51351ddfb09a4dc5d4b7a782ba0a890cc..3db6ebde8b8c1fb2bbb64033a766a9c94db580e7 100644 --- a/relational_store/frameworks/native/rdb/include/step_result_set.h +++ b/relational_store/frameworks/native/rdb/include/step_result_set.h @@ -30,8 +30,10 @@ namespace OHOS { namespace NativeRdb { class StepResultSet : public AbsResultSet { public: - StepResultSet(std::shared_ptr pool, const std::string &sql, - const std::vector &selectionArgs); + using Values = std::vector; + using Conn = std::shared_ptr; + using Time = std::chrono::steady_clock::time_point; + StepResultSet(Time start, Conn conn, const std::string &sql, const Values &args, bool safe = false); ~StepResultSet() override; int GetColumnType(int columnIndex, ColumnType &columnType) override; int GoToRow(int position) override; @@ -59,12 +61,11 @@ private: static const int EMPTY_ROW_COUNT = 0; bool isSupportCountRow_ = true; - std::shared_ptr sqliteStatement_; + std::shared_ptr statement_; std::shared_ptr conn_; std::string sql_; std::vector args_; - mutable std::shared_mutex mutex_; }; } // namespace NativeRdb } // namespace OHOS diff --git a/relational_store/frameworks/native/rdb/include/trans_db.h b/relational_store/frameworks/native/rdb/include/trans_db.h new file mode 100644 index 0000000000000000000000000000000000000000..de0de5764c8eddfd8a8faafbb838669e874ac9fb --- /dev/null +++ b/relational_store/frameworks/native/rdb/include/trans_db.h @@ -0,0 +1,48 @@ +/* + * 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. + */ + +#ifndef NATIVE_RDB_TRANS_DB_H +#define NATIVE_RDB_TRANS_DB_H +#include + +#include "connection.h" +#include "rdb_store.h" +#include "statement.h" +namespace OHOS::NativeRdb { +class TransDB : public RdbStore { +public: + TransDB(std::shared_ptr conn, const std::string &name); + std::pair Insert(const std::string &table, const Row &row, Resolution resolution) override; + std::pair BatchInsert(const std::string &table, const RefRows &rows) override; + std::pair Update(const std::string &table, const Row &row, const std::string &where, const Values &args, + Resolution resolution) override; + int Delete(int &deletedRows, const std::string &table, const std::string &whereClause, const Values &args) override; + std::shared_ptr QuerySql(const std::string &sql, const Values &args) override; + std::shared_ptr QueryByStep(const std::string &sql, const Values &args) override; + std::pair Execute(const std::string &sql, const Values &args, int64_t trxId) override; + int GetVersion(int &version) override; + int SetVersion(int version) override; + int Sync(const SyncOption &option, const std::vector &tables, const AsyncDetail &async) override; + +private: + std::pair> GetStatement(const std::string &sql) const; + + int32_t maxArgs_ = 0; + int64_t vSchema_ = 0; + std::weak_ptr conn_; + std::string name_; +}; +} // namespace OHOS::NativeRdb +#endif // NATIVE_RDB_TRANS_DB_H \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb/include/transaction_impl.h b/relational_store/frameworks/native/rdb/include/transaction_impl.h new file mode 100644 index 0000000000000000000000000000000000000000..5a4d689314b8f82a382761226c571fd3c8651a8d --- /dev/null +++ b/relational_store/frameworks/native/rdb/include/transaction_impl.h @@ -0,0 +1,68 @@ +/* + * 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. + */ +#ifndef NATIVE_RDB_TRANSACTION_IMPL_H +#define NATIVE_RDB_TRANSACTION_IMPL_H + +#include +#include +#include + +#include "connection.h" +#include "transaction.h" + +namespace OHOS::NativeRdb { +class RdbStore; +class TransactionImpl : public Transaction { +public: + TransactionImpl(std::shared_ptr connection, const std::string &name); + ~TransactionImpl() override; + + int32_t Commit() override; + int32_t Rollback() override; + int32_t Close() override; + + std::pair Insert(const std::string &table, const Row &row, Resolution resolution) override; + std::pair BatchInsert(const std::string &table, const Rows &rows) override; + std::pair BatchInsert(const std::string &table, const RefRows &rows) override; + std::pair Update(const Row &row, const AbsRdbPredicates &predicates, + Resolution resolution) override; + std::pair Delete(const AbsRdbPredicates &predicates) override; + std::shared_ptr QueryByStep(const std::string &sql, const Values &args) override; + std::shared_ptr QueryByStep(const AbsRdbPredicates &predicates, const Fields &columns) override; + std::pair Execute(const std::string &sql, const Values &args) override; + + static std::pair> Create( + int32_t type, std::shared_ptr connection, const std::string &name); + +private: + static std::string GetBeginSql(int32_t type); + int32_t Begin(int32_t type); + int32_t CloseInner(); + std::shared_ptr GetStore(); + void AddResultSet(std::weak_ptr resultSet); + + std::string name_; + std::recursive_mutex mutex_; + std::shared_ptr store_; + std::shared_ptr connection_; + std::vector> resultSets_; + + static const int32_t regCreator_; + static constexpr char COMMIT_SQL[] = "COMMIT;"; + static constexpr char ROLLBACK_SQL[] = "ROLLBACK;"; + static constexpr const char *BEGIN_SQLS[] = { "BEGIN DEFERRED;", "BEGIN IMMEDIATE;", "BEGIN EXCLUSIVE;" }; +}; +} +#endif diff --git a/relational_store/frameworks/native/rdb/mock/include/connection.h b/relational_store/frameworks/native/rdb/mock/include/connection.h deleted file mode 100644 index fa335803a1e3f350693da3629e9664c9009c7571..0000000000000000000000000000000000000000 --- a/relational_store/frameworks/native/rdb/mock/include/connection.h +++ /dev/null @@ -1,80 +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. - */ - -#ifndef OHOS_DISTRIBUTED_DATA_RELATIONAL_STORE_FRAMEWORKS_NATIVE_RDB_INCLUDE_CONNECTION_H -#define OHOS_DISTRIBUTED_DATA_RELATIONAL_STORE_FRAMEWORKS_NATIVE_RDB_INCLUDE_CONNECTION_H -#include -#include -#include -#include -#include -#include - -#include "rdb_common.h" -#include "rdb_types.h" -#include "statement.h" -namespace OHOS::NativeRdb { -class RdbStoreConfig; -class Statement; -class Connection { -public: - using Info = DistributedRdb::RdbDebugInfo; - using SConn = std::shared_ptr; - using Stmt = std::shared_ptr; - using Notifier = std::function &tables)>; - using Creator = std::pair (*)(const RdbStoreConfig &config, bool isWriter); - using Repairer = int32_t (*)(const RdbStoreConfig &config); - using Deleter = int32_t (*)(const RdbStoreConfig &config); - using Collector = std::map (*)(const RdbStoreConfig &config); - static std::pair Create(const RdbStoreConfig &config, bool isWriter); - static int32_t Repair(const RdbStoreConfig &config); - static int32_t Delete(const RdbStoreConfig &config); - static std::map Collect(const RdbStoreConfig &config); - static int32_t RegisterCreator(int32_t dbType, Creator creator); - static int32_t RegisterRepairer(int32_t dbType, Repairer repairer); - static int32_t RegisterDeleter(int32_t dbType, Deleter deleter); - static int32_t RegisterCollector(int32_t dbType, Collector collector); - - int32_t SetId(int32_t id); - int32_t GetId() const; - virtual ~Connection() = default; - virtual int32_t OnInitialize() = 0; - virtual std::pair CreateStatement(const std::string &sql, SConn conn) = 0; - virtual int32_t GetDBType() const = 0; - virtual bool IsWriter() const = 0; - virtual int32_t ReSetKey(const RdbStoreConfig &config) = 0; - virtual int32_t TryCheckPoint() = 0; - virtual int32_t LimitWalSize() = 0; - virtual int32_t ConfigLocale(const std::string &localeStr) = 0; - virtual int32_t CleanDirtyData(const std::string &table, uint64_t cursor) = 0; - virtual int32_t SubscribeTableChanges(const Notifier ¬ifier) = 0; - virtual int32_t GetMaxVariable() const = 0; - virtual int32_t GetJournalMode() = 0; - virtual int32_t ClearCache() = 0; - virtual int32_t Subscribe(const std::string &event, - const std::shared_ptr &observer) = 0; - virtual int32_t Unsubscribe(const std::string &event, - const std::shared_ptr &observer) = 0; - virtual int32_t Backup(const std::string &databasePath, const std::vector &destEncryptKey, - bool isAsync, SlaveStatus &slaveStatus) = 0; - virtual int32_t Restore(const std::string &databasePath, const std::vector &destEncryptKey, - SlaveStatus &slaveStatus) = 0; - virtual ExchangeStrategy GenerateExchangeStrategy(const SlaveStatus &status) = 0; - -private: - int32_t id_ = 0; -}; -} // namespace OHOS::NativeRdb -#endif // OHOS_DISTRIBUTED_DATA_RELATIONAL_STORE_FRAMEWORKS_NATIVE_RDB_INCLUDE_CONNECTION_H diff --git a/relational_store/frameworks/native/rdb/mock/include/connection_pool.h b/relational_store/frameworks/native/rdb/mock/include/connection_pool.h deleted file mode 100644 index bef480ae320f77d58dcd638dd2781f60d46917df..0000000000000000000000000000000000000000 --- a/relational_store/frameworks/native/rdb/mock/include/connection_pool.h +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (c) 2022 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 NATIVE_RDB_SQLITE_CONNECTION_POOL_H -#define NATIVE_RDB_SQLITE_CONNECTION_POOL_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "base_transaction.h" -#include "connection.h" -#include "rdb_common.h" -#include "rdb_store_config.h" -namespace OHOS { -namespace NativeRdb { -class ConnectionPool : public std::enable_shared_from_this { -public: - using SharedConn = std::shared_ptr; - using SharedConns = std::vector; - static constexpr std::chrono::milliseconds INVALID_TIME = std::chrono::milliseconds(0); - static std::shared_ptr Create(const RdbStoreConfig &storeConfig, int &errCode); - ~ConnectionPool(); - static std::pair> HandleDataCorruption - (const RdbStoreConfig &storeConfig, int &errCode); - std::pair> CreateConnection(bool isReadOnly); - SharedConn AcquireConnection(bool isReadOnly); - SharedConn Acquire(bool isReadOnly, std::chrono::milliseconds ms = INVALID_TIME); - // this interface is only provided for resultSet - SharedConn AcquireRef(bool isReadOnly, std::chrono::milliseconds ms = INVALID_TIME); - std::pair AcquireAll(int32_t time); - std::pair DisableWal(); - int32_t EnableWal(); - int RestartReaders(); - int ConfigLocale(const std::string &localeStr); - int ChangeDbFileForRestore(const std::string &newPath, const std::string &backupPath, - const std::vector &newKey, SlaveStatus &slaveStatus); - std::stack &GetTransactionStack(); - std::mutex &GetTransactionStackMutex(); - int AcquireTransaction(); - void ReleaseTransaction(); - void CloseAllConnections(); - bool IsInTransaction(); - void SetInTransaction(bool isInTransaction); - -private: - struct ConnNode { - bool using_ = false; - int32_t tid_ = 0; - int32_t id_ = 0; - std::chrono::steady_clock::time_point time_ = std::chrono::steady_clock::now(); - std::shared_ptr connect_; - - explicit ConnNode(std::shared_ptr conn); - std::shared_ptr GetConnect(); - int64_t GetUsingTime() const; - bool IsWriter() const; - int32_t Unused(); - }; - - struct Container { - using Creator = std::function>()>; - static constexpr int32_t MAX_RIGHT = 0x4FFFFFFF; - bool disable_ = true; - int max_ = 0; - int total_ = 0; - int count_ = 0; - int32_t left_ = 0; - int32_t right_ = 0; - std::chrono::seconds timeout_; - std::list> nodes_; - std::list> details_; - std::mutex mutex_; - std::condition_variable cond_; - Creator creator_ = nullptr; - std::pair> Initialize(Creator creator, int32_t max, int32_t timeout, - bool disable, bool acquire = false); - int32_t ConfigLocale(const std::string &locale); - std::shared_ptr Acquire(std::chrono::milliseconds milliS); - std::list> AcquireAll(std::chrono::milliseconds milliS); - - void Disable(); - void Enable(); - int32_t Release(std::shared_ptr node); - int32_t Clear(); - bool IsFull(); - int32_t Dump(const char *header); - - private: - int32_t ExtendNode(); - int32_t RelDetails(std::shared_ptr node); - }; - - explicit ConnectionPool(const RdbStoreConfig &storeConfig); - std::pair> Init(bool isAttach = false, bool needWriter = false); - int32_t GetMaxReaders(const RdbStoreConfig &config); - std::shared_ptr Convert2AutoConn(std::shared_ptr node); - void ReleaseNode(std::shared_ptr node); - int RestoreByDbSqliteType(const std::string &newPath, const std::string &backupPath, SlaveStatus &slaveStatus); - int RestoreMasterDb(const std::string &newPath, const std::string &backupPath); - bool CheckIntegrity(const std::string &dbPath); - - static constexpr int LIMITATION = 1024; - static constexpr uint32_t ITER_V1 = 5000; - static constexpr uint32_t ITERS_COUNT = 2; - const RdbStoreConfig &config_; - RdbStoreConfig attachConfig_; - Container writers_; - Container readers_; - int32_t maxReader_ = 0; - - std::stack transactionStack_; - std::mutex transactionStackMutex_; - std::condition_variable transCondition_; - std::mutex transMutex_; - bool transactionUsed_; - std::atomic isInTransaction_ = false; -}; - -} // namespace NativeRdb -} // namespace OHOS -#endif diff --git a/relational_store/frameworks/native/rdb/mock/include/rdb_store_impl.h b/relational_store/frameworks/native/rdb/mock/include/rdb_store_impl.h index 67056e277ce91ba68b7fe21d3d2756219f0478ed..c274dd6232b284bea81a93db5d4617cc13a27f66 100644 --- a/relational_store/frameworks/native/rdb/mock/include/rdb_store_impl.h +++ b/relational_store/frameworks/native/rdb/mock/include/rdb_store_impl.h @@ -36,38 +36,19 @@ public: RdbStoreImpl(const RdbStoreConfig &config); RdbStoreImpl(const RdbStoreConfig &config, int &errCode); ~RdbStoreImpl() override; - const RdbStoreConfig &GetConfig(); - int Insert(int64_t &outRowId, const std::string &table, const ValuesBucket &values) override; - int BatchInsert( - int64_t& outInsertNum, const std::string& table, const std::vector& values) override; - int Replace(int64_t &outRowId, const std::string &table, const ValuesBucket &initialValues) override; - int InsertWithConflictResolution(int64_t &outRowId, const std::string &table, const ValuesBucket &values, - ConflictResolution conflictResolution) override; - int Update(int &changedRows, const std::string &table, const ValuesBucket &values, - const std::string &whereClause, const std::vector &whereArgs) override; - int Update(int &changedRows, const std::string &table, const ValuesBucket &values, - const std::string &whereClause, const std::vector &bindArgs) override; - int UpdateWithConflictResolution(int &changedRows, const std::string &table, const ValuesBucket &values, - const std::string &whereClause, const std::vector &whereArgs, - ConflictResolution conflictResolution) override; - int UpdateWithConflictResolution(int &changedRows, const std::string &table, const ValuesBucket &values, - const std::string &whereClause, const std::vector &bindArgs, - ConflictResolution conflictResolution) override; - int Delete(int &deletedRows, const std::string &table, const std::string &whereClause, - const std::vector &whereArgs) override; - int Delete(int &deletedRows, const std::string &table, const std::string &whereClause, - const std::vector &bindArgs) override; - int ExecuteSql(const std::string& sql, const std::vector& bindArgs) override; - std::pair Execute(const std::string &sql, const std::vector &bindArgs, - int64_t trxId) override; - int ExecuteAndGetLong(int64_t &outValue, const std::string &sql, const std::vector &bindArgs) override; - int ExecuteAndGetString(std::string &outValue, const std::string &sql, - const std::vector &bindArgs) override; - int ExecuteForLastInsertedRowId(int64_t &outValue, const std::string &sql, - const std::vector &bindArgs) override; - int ExecuteForChangedRowCount(int64_t &outValue, const std::string &sql, - const std::vector &bindArgs) override; - int Backup(const std::string &databasePath, const std::vector &destEncryptKey) override; + std::pair Insert(const std::string &table, const Row &row, Resolution resolution) override; + std::pair BatchInsert(const std::string& table, const ValuesBuckets& values) override; + std::pair Update(const std::string &table, const Row &row, const std::string &where, const Values &args, + Resolution resolution) override; + int Delete(int &deletedRows, const std::string &table, const std::string &whereClause, const Values &args) override; + std::shared_ptr QuerySql(const std::string &sql, const Values &args) override; + std::shared_ptr QueryByStep(const std::string &sql, const Values &args) override; + int ExecuteSql(const std::string &sql, const Values &args) override; + std::pair Execute(const std::string &sql, const Values &args, int64_t trxId) override; + int ExecuteAndGetLong(int64_t &outValue, const std::string &sql, const Values &args) override; + int ExecuteAndGetString(std::string &outValue, const std::string &sql, const Values &args) override; + int ExecuteForLastInsertedRowId(int64_t &outValue, const std::string &sql, const Values &args) override; + int ExecuteForChangedRowCount(int64_t &outValue, const std::string &sql, const Values &args) override; int GetVersion(int &version) override; int SetVersion(int version) override; int BeginTransaction() override; @@ -83,31 +64,24 @@ public: bool IsMemoryRdb() const override; bool IsHoldingConnection() override; bool IsSlaveDiffFromMaster() const override; - int ConfigLocale(const std::string &localeStr); + int Backup(const std::string &databasePath, const std::vector &encryptKey) override; int Restore(const std::string &backupPath, const std::vector &newKey) override; - std::string GetName(); - std::string GetFileType(); - std::shared_ptr QueryByStep(const std::string &sql, - const std::vector &sqlArgs) override; - std::shared_ptr QueryByStep( - const std::string &sql, const std::vector &args) override; - std::shared_ptr QueryByStep( - const AbsRdbPredicates &predicates, const std::vector &columns) override; - std::shared_ptr Query( - const AbsRdbPredicates &predicates, const std::vector &columns) override; int Count(int64_t &outValue, const AbsRdbPredicates &predicates) override; - int Update(int &changedRows, const ValuesBucket &values, const AbsRdbPredicates &predicates) override; - int Delete(int &deletedRows, const AbsRdbPredicates &predicates) override; int GetRebuilt(RebuiltType &rebuilt) override; - std::pair Attach( - const RdbStoreConfig &config, const std::string &attachName, int32_t waitTime = 2) override; - std::pair Detach(const std::string &attachName, int32_t waitTime = 2) override; + std::pair Attach(const RdbStoreConfig &config, const std::string &attachName, + int32_t waitTime) override; + std::pair Detach(const std::string &attachName, int32_t waitTime) override; int InterruptBackup() override; int32_t GetBackupStatus() const override; + int32_t GetDbType() const override; + std::pair> CreateTransaction(int32_t type) override; + const RdbStoreConfig &GetConfig(); + int ConfigLocale(const std::string &localeStr); + std::string GetName(); + std::string GetFileType(); int32_t ExchangeSlaverToMaster(); private: - using ExecuteSqls = std::vector>>>; using Stmt = std::shared_ptr; using RdbParam = DistributedRdb::RdbSyncerParam; @@ -119,27 +93,20 @@ private: const std::string &sql, const ValueObject &object, int sqlType); int CheckAttach(const std::string &sql); std::pair BeginExecuteSql(const std::string &sql); - ExecuteSqls GenerateSql(const std::string& table, const std::vector& buckets, int limit); int GetDataBasePath(const std::string &databasePath, std::string &backupFilePath); - int ExecuteSqlInner(const std::string &sql, const std::vector &bindArgs); - void SetAssetStatus(const ValueObject &val, int32_t status); void DoCloudSync(const std::string &table); int InnerBackup(const std::string& databasePath, const std::vector& destEncryptKey = std::vector()); - std::pair CreateWriteableStmt(const std::string &sql); + std::pair> CreateWritableConn(); + std::vector CreateBackupBindArgs(const std::string &databasePath, + const std::vector &destEncryptKey); std::pair GetStatement(const std::string& sql, std::shared_ptr conn) const; std::pair GetStatement(const std::string& sql, bool read = false) const; - int AttachInner(const std::string &attachName, - const std::string &dbPath, const std::vector &key, int32_t waitTime); - int InsertWithConflictResolutionEntry(int64_t &outRowId, const std::string &table, const ValuesBucket &values, - ConflictResolution conflictResolution); - int UpdateWithConflictResolutionEntry(int &changedRows, const std::string &table, const ValuesBucket &values, - const std::string &whereClause, const std::vector &bindArgs, - ConflictResolution conflictResolution); - int BatchInsertEntry(int64_t& outInsertNum, const std::string& table, const std::vector& values); - int ExecuteSqlEntry(const std::string& sql, const std::vector& bindArgs); - std::pair ExecuteEntry(const std::string& sql, const std::vector& bindArgs, - int64_t trxId); + int AttachInner(const RdbStoreConfig &config, const std::string &attachName, const std::string &dbPath, + const std::vector &key, int32_t waitTime); + int SetDefaultEncryptSql(const std::shared_ptr &statement, std::string sql, + const RdbStoreConfig &config); + int SetDefaultEncryptAlgo(const ConnectionPool::SharedConn &conn, const RdbStoreConfig &config); int GetSlaveName(const std::string &dbName, std::string &backupFilePath); bool TryGetMasterSlaveBackupPath(const std::string &srcPath, std::string &destPath, bool isRestore = false); void NotifyDataChange(); @@ -149,14 +116,14 @@ private: static constexpr uint32_t EXPANSION = 2; static inline constexpr uint32_t INTERVAL = 10; static inline constexpr uint32_t RETRY_INTERVAL = 5; // s - static inline constexpr uint32_t MAX_RETRY_TIMES = 5; + static inline constexpr int32_t MAX_RETRY_TIMES = 5; static constexpr const char *ROW_ID = "ROWID"; bool isOpen_ = false; bool isReadOnly_ = false; bool isMemoryRdb_; - uint32_t rebuild_; - SlaveStatus slaveStatus_; + uint32_t rebuild_ = RebuiltType::NONE; + SlaveStatus slaveStatus_ = SlaveStatus::UNDEFINED; int64_t vSchema_ = 0; std::atomic newTrxId_ = 1; const RdbStoreConfig config_; @@ -170,6 +137,7 @@ private: std::set cloudTables_; ConcurrentMap attachedInfo_; ConcurrentMap> trxConnMap_ = {}; + std::list> transactions_; }; } // namespace OHOS::NativeRdb #endif diff --git a/relational_store/frameworks/native/rdb/mock/include/rdb_store_manager.h b/relational_store/frameworks/native/rdb/mock/include/rdb_store_manager.h deleted file mode 100644 index 36cb3d95cade011df5ad953dae0e79c2c663a756..0000000000000000000000000000000000000000 --- a/relational_store/frameworks/native/rdb/mock/include/rdb_store_manager.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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 NATIVE_RDB_STORE_MANAGER_H -#define NATIVE_RDB_STORE_MANAGER_H - -#include -#include -#include -#include -#include - -#include "lru_bucket.h" -#include "rdb_open_callback.h" -#include "rdb_store_config.h" -#include "rdb_store_impl.h" - -namespace OHOS { -namespace NativeRdb { -class RdbStoreManager { -public: - static RdbStoreManager &GetInstance(); - RdbStoreManager(); - virtual ~RdbStoreManager(); - std::shared_ptr GetRdbStore(const RdbStoreConfig &config, - int &errCode, int version, RdbOpenCallback &openCallback); - void Clear(); - bool Remove(const std::string &path); - bool Delete(const std::string &path); - int SetSecurityLabel(const RdbStoreConfig &config); - -private: - using Param = DistributedRdb::RdbSyncerParam; - using Info = DistributedRdb::RdbDebugInfo; - int ProcessOpenCallback(RdbStore &rdbStore, - const RdbStoreConfig &config, int version, RdbOpenCallback &openCallback); - bool IsConfigInvalidChanged(const std::string &path, const RdbStoreConfig &config); - int32_t GetParamFromService(DistributedRdb::RdbSyncerParam ¶m); - static Param GetSyncParam(const RdbStoreConfig &config); - static std::map Collector(const RdbStoreConfig &config); - - static constexpr uint32_t BUCKET_MAX_SIZE = 4; - static const bool regCollector_; - std::string bundleName_; - std::mutex mutex_; - std::map> storeCache_; - LRUBucket configCache_; -}; -} // namespace NativeRdb -} // namespace OHOS -#endif diff --git a/relational_store/frameworks/native/rdb/mock/include/sqlite_connection.h b/relational_store/frameworks/native/rdb/mock/include/sqlite_connection.h deleted file mode 100644 index 6ff8402251c60d5407211385670351ec39c00974..0000000000000000000000000000000000000000 --- a/relational_store/frameworks/native/rdb/mock/include/sqlite_connection.h +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright (c) 2022 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 NATIVE_RDB_SQLITE_CONNECTION_H -#define NATIVE_RDB_SQLITE_CONNECTION_H - -#include -#include -#include -#include -#include -#include - -#include "connection.h" -#include "rdb_local_db_observer.h" -#include "rdb_store_config.h" -#include "sqlite3sym.h" -#include "sqlite_statement.h" -#include "task_executor.h" -#include "value_object.h" - -typedef struct ClientChangedData ClientChangedData; -namespace OHOS { -namespace NativeRdb { -/** - * @brief Use DataChangeCallback replace std::function. - */ -using DataChangeCallback = std::function; - -class SqliteConnection : public Connection { -public: - static std::pair> Create(const RdbStoreConfig &config, bool isWrite); - static int32_t Delete(const RdbStoreConfig &config); - static int32_t Repair(const RdbStoreConfig &config); - static std::map Collect(const RdbStoreConfig &config); - SqliteConnection(const RdbStoreConfig &config, bool isWriteConnection); - ~SqliteConnection(); - int32_t OnInitialize() override; - int TryCheckPoint() override; - int LimitWalSize() override; - int ConfigLocale(const std::string &localeStr) override; - int CleanDirtyData(const std::string &table, uint64_t cursor) override; - int ReSetKey(const RdbStoreConfig &config) override; - int32_t GetJournalMode() override; - std::pair CreateStatement(const std::string &sql, SConn conn) override; - bool IsWriter() const override; - int SubscribeTableChanges(const Notifier ¬ifier) override; - int GetMaxVariable() const override; - int32_t GetDBType() const override; - int32_t ClearCache() override; - int32_t Subscribe(const std::string &event, - const std::shared_ptr &observer) override; - int32_t Unsubscribe(const std::string &event, - const std::shared_ptr &observer) override; - int32_t Backup(const std::string &databasePath, const std::vector &destEncryptKey, - bool isAsync, SlaveStatus &slaveStatus) override; - int32_t Restore(const std::string &databasePath, const std::vector &destEncryptKey, - SlaveStatus &slaveStatus) override; - ExchangeStrategy GenerateExchangeStrategy(const SlaveStatus &status) override; - -protected: - std::pair ExecuteForValue(const std::string &sql, - const std::vector &bindArgs = std::vector()); - int ExecuteSql(const std::string &sql, const std::vector &bindArgs = std::vector()); - -private: - struct Suffix { - const char *suffix_ = nullptr; - const char *debug_ = nullptr; - }; - - int InnerOpen(const RdbStoreConfig &config); - int Configure(const RdbStoreConfig &config, std::string &dbPath); - int SetPageSize(const RdbStoreConfig &config); - int SetEncrypt(const RdbStoreConfig &config); - int SetEncryptKey(const std::vector &key, int32_t iter); - int SetServiceKey(const RdbStoreConfig &config, int32_t errCode); - int SetEncryptAgo(int32_t iter); - int SetJournalMode(const RdbStoreConfig &config); - int SetJournalSizeLimit(const RdbStoreConfig &config); - int SetAutoCheckpoint(const RdbStoreConfig &config); - int SetWalFile(const RdbStoreConfig &config); - int SetWalSyncMode(const std::string &syncMode); - void LimitPermission(const std::string &dbPath) const; - - int SetPersistWal(); - int SetBusyTimeout(int timeout); - - int RegDefaultFunctions(sqlite3 *dbHandle); - static void MergeAssets(sqlite3_context *ctx, int argc, sqlite3_value **argv); - static void MergeAsset(sqlite3_context *ctx, int argc, sqlite3_value **argv); - static void CompAssets(std::map &oldAssets, - std::map &newAssets); - static void MergeAsset(ValueObject::Asset &oldAsset, ValueObject::Asset &newAsset); - - int SetCustomFunctions(const RdbStoreConfig &config); - int SetCustomScalarFunction(const std::string &functionName, int argc, ScalarFunction *function); - int32_t UnsubscribeLocalDetail(const std::string &event, - const std::shared_ptr &observer); - int32_t UnsubscribeLocalDetailAll(const std::string &event); - 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 isWrite, bool checkSlaveExist = true); - int ExchangeSlaverToMaster(bool isRestore, SlaveStatus &status); - bool IsRepairable(); - std::pair ExchangeVerify(bool isRestore); - static std::pair> InnerCreate(const RdbStoreConfig &config, - bool isWrite); - static constexpr SqliteConnection::Suffix FILE_SUFFIXES[] = { - {"", "DB"}, - {"-shm", "SHM"}, - {"-wal", "WAL"}, - {"-journal", "JOURNAL"}, - {"-slaveFailure", nullptr}, - {"-syncInterrupt", nullptr}, - {".corruptedflg", nullptr} - }; - static constexpr const char *MERGE_ASSETS_FUNC = "merge_assets"; - static constexpr const char *MERGE_ASSET_FUNC = "merge_asset"; - static constexpr int DEFAULT_BUSY_TIMEOUT_MS = 2000; - static constexpr int BACKUP_PAGES_PRE_STEP = 12800; // 1024 * 4 * 12800 == 50m - static constexpr int BACKUP_PRE_WAIT_TIME = 10; - static constexpr uint32_t NO_ITER = 0; - static const int32_t regCreator_; - static const int32_t regRepairer_; - static const int32_t regDeleter_; - static const int32_t regCollector_; - - std::atomic backupId_ = TaskExecutor::INVALID_TASK_ID; - sqlite3 *dbHandle_; - bool isWriter_; - bool isReadOnly_; - bool isConfigured_ = false; - bool hasClientObserver_ = false; - JournalMode mode_ = JournalMode::MODE_WAL; - int maxVariableNumber_; - std::mutex mutex_; - std::string filePath; - std::shared_ptr slaveConnection_; - std::map customScalarFunctions_; - std::map>> observers_; - const RdbStoreConfig config_; -}; -} // namespace NativeRdb -} // namespace OHOS -#endif diff --git a/relational_store/frameworks/native/rdb/mock/include/step_result_set.h b/relational_store/frameworks/native/rdb/mock/include/step_result_set.h deleted file mode 100644 index 31a57a231d0b59e33d3671ede91124f86d29102c..0000000000000000000000000000000000000000 --- a/relational_store/frameworks/native/rdb/mock/include/step_result_set.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2021 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 NATIVE_RDB_STEP_RESULT_SET_H -#define NATIVE_RDB_STEP_RESULT_SET_H - -#include -#include -#include -#include - -#include "abs_result_set.h" -#include "connection.h" -#include "connection_pool.h" -#include "statement.h" - -namespace OHOS { -namespace NativeRdb { -class StepResultSet : public AbsResultSet { -public: - StepResultSet(std::shared_ptr pool, const std::string& sql, - const std::vector& selectionArgs); - ~StepResultSet() override; - int GetColumnType(int columnIndex, ColumnType &columnType) override; - int GoToRow(int position) override; - int GoToNextRow() override; - int GetSize(int columnIndex, size_t &size) override; - int Get(int32_t col, ValueObject &value) override; - int Close() override; - int GetRowCount(int &count) override; - -protected: - std::pair> GetColumnNames() override; - -private: - template - int GetValue(int32_t col, T &value); - std::pair GetValueObject(int32_t col, size_t index); - std::shared_ptr GetStatement(); - int Reset(); - int PrepareStep(); - - // Max times of retrying step query - static const int STEP_QUERY_RETRY_MAX_TIMES = 50; - // Interval of retrying step query in millisecond - static const int STEP_QUERY_RETRY_INTERVAL = 1000; - static const int EMPTY_ROW_COUNT = 0; - - bool isSupportCountRow_ = true; - std::shared_ptr sqliteStatement_; - std::shared_ptr conn_; - - std::string sql_; - std::vector args_; - mutable std::shared_mutex mutex_; -}; -} // namespace NativeRdb -} // namespace OHOS -#endif diff --git a/relational_store/frameworks/native/rdb/mock/src/rdb_fault_hiview_reporter.cpp b/relational_store/frameworks/native/rdb/mock/src/rdb_fault_hiview_reporter.cpp index 701f3e63869ddba938dbe2dae5689ba6d7d32327..fc52d9c3eeeb14f2d04e4f6a4b467d68f3615a3d 100644 --- a/relational_store/frameworks/native/rdb/mock/src/rdb_fault_hiview_reporter.cpp +++ b/relational_store/frameworks/native/rdb/mock/src/rdb_fault_hiview_reporter.cpp @@ -22,7 +22,7 @@ void RdbFaultHiViewReporter::ReportFault(const RdbCorruptedEvent &eventInfo) (void)eventInfo; } -void RdbFaultHiViewReporter::ReportRestore(const RdbCorruptedEvent &eventInfo) +void RdbFaultHiViewReporter::ReportRestore(const RdbCorruptedEvent &eventInfo, bool repair) { (void)eventInfo; } @@ -76,4 +76,25 @@ void RdbFaultHiViewReporter::Update(RdbCorruptedEvent &eventInfo, const std::map (void)eventInfo; (void)infos; } + +std::string RdbFaultHiViewReporter::GetBundleName(const RdbCorruptedEvent &eventInfo) +{ + (void)eventInfo; + return ""; +} + +std::string RdbFaultHiViewReporter::Format(const std::map &debugs, const std::string &header) +{ + (void)debugs; + (void)header; + return ""; +} + +std::string RdbFaultHiViewReporter::FormatBrief(const std::map &debugs, + const std::string &header) +{ + (void)debugs; + (void)header; + return ""; +} } // namespace OHOS::NativeRdb \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb/src/abs_result_set.cpp b/relational_store/frameworks/native/rdb/src/abs_result_set.cpp index fcb3bc242cbc914c362322315ee2406b3a000f6c..71e22d2f45dc5532c3210e4a077ade1e2077fcd0 100644 --- a/relational_store/frameworks/native/rdb/src/abs_result_set.cpp +++ b/relational_store/frameworks/native/rdb/src/abs_result_set.cpp @@ -26,7 +26,6 @@ #include "result_set.h" #include "sqlite_utils.h" - namespace OHOS { namespace NativeRdb { using namespace OHOS::Rdb; @@ -74,7 +73,11 @@ void RowEntity::Clear(int32_t size) indexs_.resize(size); } -AbsResultSet::AbsResultSet() : rowPos_(INIT_POS), isClosed_(false), lastErr_(E_OK) +AbsResultSet::AbsResultSet() +{ +} + +AbsResultSet::AbsResultSet(bool safe) : globalMtx_(safe) { } diff --git a/relational_store/frameworks/native/rdb/src/big_integer.cpp b/relational_store/frameworks/native/rdb/src/big_integer.cpp index 89f388e4c392d67d890a5440bc9a4adfbb9f0a62..074efa2d144ad1c4130f2d3a37ff56f4bfb48e53 100644 --- a/relational_store/frameworks/native/rdb/src/big_integer.cpp +++ b/relational_store/frameworks/native/rdb/src/big_integer.cpp @@ -69,6 +69,11 @@ bool BigInteger::operator==(const BigInteger& other) return value_ == other.value_; } +bool BigInteger::operator<(const BigInteger &rhs) +{ + return sign_ != rhs.sign_ ? (sign_ > rhs.sign_) : (sign_ == 0 ? (value_ < rhs.value_) : (rhs.value_ < value_)); +} + int32_t BigInteger::Sign() const { return sign_; diff --git a/relational_store/frameworks/native/rdb/src/connection_pool.cpp b/relational_store/frameworks/native/rdb/src/connection_pool.cpp index 806062b47fc29a9a090d68dc640a6f56b4659f8a..05691362a4f11f55730402bbccebe9a0a9a7a0a2 100644 --- a/relational_store/frameworks/native/rdb/src/connection_pool.cpp +++ b/relational_store/frameworks/native/rdb/src/connection_pool.cpp @@ -23,10 +23,11 @@ #include #include -#include "logger.h" #include "connection.h" +#include "logger.h" #include "rdb_common.h" #include "rdb_errno.h" +#include "rdb_fault_hiview_reporter.h" #include "rdb_sql_statistic.h" #include "sqlite_global_config.h" #include "sqlite_utils.h" @@ -34,16 +35,18 @@ namespace OHOS { namespace NativeRdb { using namespace OHOS::Rdb; +using namespace std::chrono; using Conn = Connection; using ConnPool = ConnectionPool; using SharedConn = std::shared_ptr; using SharedConns = std::vector>; using SqlStatistic = DistributedRdb::SqlStatistic; +using Reportor = RdbFaultHiViewReporter; constexpr int32_t TRANSACTION_TIMEOUT(2); -std::shared_ptr ConnPool::Create(const RdbStoreConfig &storeConfig, int &errCode) +std::shared_ptr ConnPool::Create(const RdbStoreConfig &config, int &errCode) { - std::shared_ptr pool(new (std::nothrow) ConnPool(storeConfig)); + std::shared_ptr pool(new (std::nothrow) ConnPool(config)); if (pool == nullptr) { LOG_ERROR("ConnPool::Create new failed, pool is nullptr."); errCode = E_ERROR; @@ -55,13 +58,22 @@ std::shared_ptr ConnPool::Create(const RdbStoreConfig &storeConfig, in if (errCode != E_SQLITE_CORRUPT) { break; } - storeConfig.SetIter(ITER_V1); - } + config.SetIter(ITER_V1); + } + std::string dbPath; + (void)SqliteGlobalConfig::GetDbPath(config, dbPath); + LOG_INFO("code:%{public}d 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", + errCode, config.GetBundleName().c_str(), config.GetModuleName().c_str(), + SqliteUtils::Anonymous(dbPath).c_str(), config.GetDBType(), config.GetHaMode(), config.IsEncrypt(), + config.GetArea(), config.GetSecurityLevel(), config.GetRoleType(), config.IsReadOnly(), + Reportor::FormatBrief(Connection::Collect(config), SqliteUtils::Anonymous(config.GetName())).c_str()); return errCode == E_OK ? pool : nullptr; } -std::pair> ConnPool::HandleDataCorruption - (const RdbStoreConfig &storeConfig, int &errCode) +std::pair> ConnPool::HandleDataCorruption( + const RdbStoreConfig &storeConfig, int &errCode) { std::pair> result; auto &[rebuiltType, pool] = result; @@ -78,6 +90,8 @@ std::pair> ConnPool::HandleDataCorr LOG_WARN("failed, type %{public}d db %{public}s encrypt %{public}d error %{public}d, errno", static_cast(rebuiltType), SqliteUtils::Anonymous(storeConfig.GetName()).c_str(), storeConfig.IsEncrypt(), errCode, errno); + } else { + Reportor::ReportRestore(Reportor::Create(storeConfig, E_OK, "RestoreType:Rebuild"), false); } return result; @@ -145,7 +159,7 @@ int32_t ConnPool::GetMaxReaders(const RdbStoreConfig &config) } } -std::shared_ptr ConnPool::Convert2AutoConn(std::shared_ptr node) +std::shared_ptr ConnPool::Convert2AutoConn(std::shared_ptr node, bool isTrans) { if (node == nullptr) { return nullptr; @@ -155,12 +169,20 @@ std::shared_ptr ConnPool::Convert2AutoConn(std::shared_ptr if (conn == nullptr) { return nullptr; } - return std::shared_ptr(conn.get(), [pool = weak_from_this(), node](Connection *) { + if (isTrans) { + transCount_++; + } + + return std::shared_ptr(conn.get(), [pool = weak_from_this(), node, isTrans](auto *) mutable { auto realPool = pool.lock(); if (realPool == nullptr) { return; } - realPool->ReleaseNode(node); + if (isTrans) { + realPool->transCount_--; + } + realPool->ReleaseNode(node, !isTrans); + node = nullptr; }); } @@ -180,9 +202,13 @@ void ConnPool::SetInTransaction(bool isInTransaction) isInTransaction_.store(isInTransaction); } -std::pair> ConnPool::CreateConnection(bool isReadOnly) +std::pair> ConnPool::CreateTransConn(bool limited) { - return Connection::Create(config_, true); + if (transCount_ >= MAX_TRANS && limited) { + return { E_CON_OVER_LIMIT, nullptr }; + } + auto [errCode, node] = writers_.Create(); + return { errCode, Convert2AutoConn(node, true) }; } std::shared_ptr ConnPool::AcquireConnection(bool isReadOnly) @@ -237,7 +263,7 @@ std::shared_ptr ConnPool::Acquire(bool isReadOnly, std::chrono::millisecon auto node = container->Acquire(ms); if (node == nullptr) { const char *header = (isReadOnly && maxReader_ != 0) ? "readers_" : "writers_"; - container->Dump(header); + container->Dump(header, isInTransaction_); return nullptr; } return Convert2AutoConn(node); @@ -251,7 +277,7 @@ SharedConn ConnPool::AcquireRef(bool isReadOnly, std::chrono::milliseconds ms) } auto node = writers_.Acquire(ms); if (node == nullptr) { - writers_.Dump("writers_"); + writers_.Dump("writers_", isInTransaction_); return nullptr; } auto conn = node->connect_; @@ -265,28 +291,33 @@ SharedConn ConnPool::AcquireRef(bool isReadOnly, std::chrono::milliseconds ms) }); } -void ConnPool::ReleaseNode(std::shared_ptr node) +void ConnPool::ReleaseNode(std::shared_ptr node, bool reuse) { if (node == nullptr) { return; } - auto errCode = node->Unused(); - if (errCode == E_WAL_SIZE_OVER_LIMIT) { - readers_.Dump("WAL Over Limit"); + + auto inTrans = (isInTransaction_ || transCount_ > 0); + auto errCode = node->Unused(inTrans); + if (errCode == E_SQLITE_LOCKED || errCode == E_SQLITE_BUSY) { + writers_.Dump("WAL writers_", inTrans); + readers_.Dump("WAL readers_", inTrans); } - if (node->IsWriter()) { - writers_.Release(node); + + auto &container = node->IsWriter() ? writers_ : readers_; + if (reuse) { + container.Release(node); } else { - readers_.Release(node); + container.Drop(node); } } int ConnPool::AcquireTransaction() { std::unique_lock lock(transMutex_); - if (transCondition_.wait_for(lock, std::chrono::seconds(TRANSACTION_TIMEOUT), [this] { - return !transactionUsed_; - })) { + if (transCondition_.wait_for( + lock, std::chrono::seconds(TRANSACTION_TIMEOUT), + [this] { return !transactionUsed_; })) { transactionUsed_ = true; return E_OK; } @@ -307,10 +338,7 @@ int ConnPool::RestartReaders() { readers_.Clear(); auto [errCode, node] = readers_.Initialize( - [this]() { - return Connection::Create(config_, false); - }, - maxReader_, config_.GetReadTime(), maxReader_ == 0); + [this]() { return Connection::Create(config_, false); }, maxReader_, config_.GetReadTime(), maxReader_ == 0); return errCode; } @@ -338,7 +366,7 @@ int ConnPool::ChangeDbFileForRestore(const std::string &newPath, const std::stri } if (config_.GetDBType() == DB_VECTOR) { CloseAllConnections(); - auto [retVal, connection] = CreateConnection(false); + auto [retVal, connection] = CreateTransConn(); if (connection == nullptr) { LOG_ERROR("Get null connection."); @@ -358,32 +386,12 @@ int ConnPool::ChangeDbFileForRestore(const std::string &newPath, const std::stri int ConnPool::RestoreByDbSqliteType(const std::string &newPath, const std::string &backupPath, SlaveStatus &slaveStatus) { - int ret = E_OK; if (SqliteUtils::IsSlaveDbName(backupPath) && config_.GetHaMode() != HAMode::SINGLE) { auto connection = AcquireConnection(false); if (connection == nullptr) { return E_DATABASE_BUSY; } - ret = connection->Restore(backupPath, {}, slaveStatus); - if (ret == E_DB_NOT_EXIST || ret == E_SQLITE_CORRUPT) { - LOG_WARN("corrupt, rebuild:%{public}s", SqliteUtils::Anonymous(backupPath).c_str()); - CloseAllConnections(); - Connection::Delete(config_); - auto [errCode, node] = Init(); - if (errCode != E_OK) { - LOG_ERROR("init failed:%{public}d", errCode); - return errCode; - } - auto newConn = AcquireConnection(false); - if (newConn == nullptr) { - return E_DATABASE_BUSY; - } - ret = newConn->Restore(backupPath, {}, slaveStatus); - if (ret != E_OK) { - LOG_ERROR("restore failed:%{public}d, %{public}s", ret, SqliteUtils::Anonymous(backupPath).c_str()); - } - } - return ret; + return connection->Restore(backupPath, {}, slaveStatus); } return RestoreMasterDb(newPath, backupPath); @@ -448,25 +456,38 @@ ConnPool::ConnNode::ConnNode(std::shared_ptr conn) : connect_(std::move(co std::shared_ptr ConnPool::ConnNode::GetConnect() { tid_ = gettid(); - time_ = std::chrono::steady_clock::now(); + time_ = steady_clock::now(); return connect_; } int64_t ConnPool::ConnNode::GetUsingTime() const { - auto time = std::chrono::steady_clock::now() - time_; - return std::chrono::duration_cast(time).count(); + auto time = steady_clock::now() - time_; + return duration_cast(time).count(); } -int32_t ConnPool::ConnNode::Unused() +int32_t ConnPool::ConnNode::Unused(bool inTrans) { - int32_t errCode = E_OK; - tid_ = 0; - time_ = std::chrono::steady_clock::now(); - if (connect_ != nullptr) { - connect_->ClearCache(); - errCode = connect_->TryCheckPoint(); + time_ = steady_clock::now(); + if (connect_ == nullptr) { + return E_OK; + } + + connect_->ClearCache(); + if (!connect_->IsWriter()) { + tid_ = 0; + } + + if (inTrans) { + return E_OK; + } + auto timeout = time_ > (failedTime_ + minutes(CHECK_POINT_INTERVAL)) || time_ < failedTime_; + int32_t errCode = connect_->TryCheckPoint(timeout); + if (errCode == E_INNER_WARNING || errCode == E_NOT_SUPPORT) { + return E_OK; } + + failedTime_ = errCode != E_OK ? time_ : steady_clock::time_point(); return errCode; } @@ -478,8 +499,8 @@ bool ConnPool::ConnNode::IsWriter() const return false; } -std::pair> ConnPool::Container::Initialize(Creator creator, int32_t max, - int32_t timeout, bool disable, bool acquire) +std::pair> ConnPool::Container::Initialize( + Creator creator, int32_t max, int32_t timeout, bool disable, bool acquire) { std::shared_ptr connNode = nullptr; { @@ -543,8 +564,7 @@ std::shared_ptr ConnPool::Container::Acquire(std::chrono::mi }; if (cond_.wait_for(lock, interval, waiter)) { if (nodes_.empty()) { - LOG_ERROR( - "nodes is empty.count %{public}d max %{public}d total %{public}d left %{public}d right%{public}d", + LOG_ERROR("nodes is empty.count %{public}d max %{public}d total %{public}d left %{public}d right%{public}d", count_, max_, total_, left_, right_); count_ = 0; return nullptr; @@ -557,6 +577,28 @@ std::shared_ptr ConnPool::Container::Acquire(std::chrono::mi return nullptr; } +std::pair> ConnPool::Container::Create() +{ + if (creator_ == nullptr) { + return { E_NOT_SUPPORT, nullptr }; + } + + auto [errCode, conn] = creator_(); + if (conn == nullptr) { + return { errCode, nullptr }; + } + + auto node = std::make_shared(conn); + if (node == nullptr) { + return { E_ERROR, nullptr }; + } + node->id_ = MIN_TRANS_ID + trans_; + conn->SetId(node->id_); + details_.push_back(node); + trans_++; + return { E_OK, node }; +} + int32_t ConnPool::Container::ExtendNode() { if (creator_ == nullptr) { @@ -583,9 +625,7 @@ std::list> ConnPool::Container::AcquireAll(s auto interval = (milliS == INVALID_TIME) ? timeout_ : milliS; auto time = std::chrono::steady_clock::now() + interval; std::unique_lock lock(mutex_); - while (count < total_ && cond_.wait_until(lock, time, [this]() { - return count_ > 0; - })) { + while (count < total_ && cond_.wait_until(lock, time, [this]() { return count_ > 0; })) { nodes.merge(std::move(nodes_)); nodes_.clear(); count += count_; @@ -651,6 +691,16 @@ int32_t ConnPool::Container::Release(std::shared_ptr node) return E_OK; } +int32_t ConnectionPool::Container::Drop(std::shared_ptr node) +{ + { + std::unique_lock lock(mutex_); + RelDetails(node); + } + cond_.notify_one(); + return E_OK; +} + int32_t ConnectionPool::Container::RelDetails(std::shared_ptr node) { for (auto it = details_.begin(); it != details_.end();) { @@ -701,12 +751,12 @@ bool ConnPool::Container::IsFull() return total_ == count_; } -int32_t ConnPool::Container::Dump(const char *header) +int32_t ConnPool::Container::Dump(const char *header, bool inTrans) { std::string info; std::vector> details; - std::string title = " M_T_C[" + std::to_string(max_) + ","+ std::to_string(total_) +"," - + std::to_string(count_) + "]"; + std::string title = "B_M_T_C[" + std::to_string(inTrans) + "," + std::to_string(max_) + "," + + std::to_string(total_) + "," + std::to_string(count_) + "]"; { std::unique_lock lock(mutex_); details.reserve(details_.size()); diff --git a/relational_store/frameworks/native/rdb/src/raw_data_parser.cpp b/relational_store/frameworks/native/rdb/src/raw_data_parser.cpp index 44b0a361b4b1acccea9374a8514e75859e820eb6..15d31650bd62ec6d9e597c4b02b1faff1e4f0fb5 100644 --- a/relational_store/frameworks/native/rdb/src/raw_data_parser.cpp +++ b/relational_store/frameworks/native/rdb/src/raw_data_parser.cpp @@ -163,7 +163,7 @@ size_t RawDataParser::ParserRawData(const uint8_t* data, size_t length, BigInteg uint64_t count = Endian::LeToH(*(reinterpret_cast(alignData + used))); used += sizeof(uint64_t); - if (sizeof(uint64_t) * count > length - used) { + if (count > (length - used) / sizeof(uint64_t)) { return 0; } const uint64_t *temp = (reinterpret_cast(alignData + used)); @@ -201,7 +201,7 @@ size_t RawDataParser::ParserRawData(const uint8_t* data, size_t length, RawDataP uint32_t count = Endian::LeToH(*(reinterpret_cast(alignData + used))); used += sizeof(uint32_t); - if (sizeof(float) * count > length - used) { + if (count > (length - used) / sizeof(float)) { return 0; } auto values = reinterpret_cast(alignData + used); diff --git a/relational_store/frameworks/native/rdb/src/rd_connection.cpp b/relational_store/frameworks/native/rdb/src/rd_connection.cpp index 08994d7ad14272c71f167f13ccd07765975b1df3..779090e31d1c835b4ab73d20dd3afb05f74a497f 100644 --- a/relational_store/frameworks/native/rdb/src/rd_connection.cpp +++ b/relational_store/frameworks/native/rdb/src/rd_connection.cpp @@ -111,7 +111,7 @@ int RdConnection::InnerOpen(const RdbStoreConfig &config) } errCode = RdUtils::RdDbOpen(dbPath.c_str(), configStr_.c_str(), GRD_DB_OPEN_CREATE, &dbHandle_); if (errCode != E_OK) { - LOG_ERROR("Can not open rd db."); + LOG_ERROR("Can not open rd db %{public}d.", errCode); return errCode; } return errCode; @@ -155,7 +155,7 @@ int32_t RdConnection::ReSetKey(const RdbStoreConfig& config) return E_NOT_SUPPORT; } -int32_t RdConnection::TryCheckPoint() +int32_t RdConnection::TryCheckPoint(bool timeout) { return E_NOT_SUPPORT; } diff --git a/relational_store/frameworks/native/rdb/src/rd_statement.cpp b/relational_store/frameworks/native/rdb/src/rd_statement.cpp index f15baba6ed16a971e57f3e62c41df92726d8b7de..c6b0384cf712bacae21a7ef53a9bdf1177a13f5c 100644 --- a/relational_store/frameworks/native/rdb/src/rd_statement.cpp +++ b/relational_store/frameworks/native/rdb/src/rd_statement.cpp @@ -32,6 +32,7 @@ namespace OHOS { namespace NativeRdb { using namespace OHOS::Rdb; +using Reportor = RdbFaultHiViewReporter; RdStatement::RdStatement() { } @@ -116,7 +117,7 @@ int RdStatement::Prepare(GRD_DB *db, const std::string &newSql) (!EndWithNull(newSql, curIdx) && !TryEatSymbol(newSql, ';', curIdx))) { return E_INCORRECT_SQL; } - + readOnly_ = false; sql_ = newSql; return setPragmas_["user_version"](version); @@ -128,7 +129,7 @@ int RdStatement::Prepare(GRD_DB *db, const std::string &newSql) int ret = RdUtils::RdSqlPrepare(db, newSql.c_str(), newSql.length(), &tmpStmt, nullptr); if (ret != E_OK) { if (ret == E_SQLITE_CORRUPT && config_ != nullptr) { - RdbFaultHiViewReporter::ReportFault(RdbFaultHiViewReporter::Create(*config_, ret)); + Reportor::ReportFault(Reportor::Create(*config_, ret)); } if (tmpStmt != nullptr) { (void)RdUtils::RdSqlFinalize(tmpStmt); @@ -245,24 +246,33 @@ int32_t RdStatement::Prepare(const std::string& sql) } int32_t RdStatement::Bind(const std::vector& args) +{ + std::vector> refArgs; + for (auto &object : args) { + refArgs.emplace_back(std::ref(const_cast(object))); + } + return Bind(refArgs); +} + +int32_t RdStatement::Bind(const std::vector>& args) { uint32_t index = 1; int ret = E_OK; for (auto &arg : args) { - switch (arg.GetType()) { + switch (arg.get().GetType()) { case ValueObjectType::TYPE_NULL: { ret = RdUtils::RdSqlBindNull(stmtHandle_, index); break; } case ValueObjectType::TYPE_INT: { int64_t value = 0; - arg.GetLong(value); + arg.get().GetLong(value); ret = RdUtils::RdSqlBindInt64(stmtHandle_, index, value); break; } case ValueObjectType::TYPE_DOUBLE: { double doubleVal = 0; - arg.GetDouble(doubleVal); + arg.get().GetDouble(doubleVal); ret = RdUtils::RdSqlBindDouble(stmtHandle_, index, doubleVal); break; } @@ -296,7 +306,7 @@ int32_t RdStatement::Step() } int ret = RdUtils::RdSqlStep(stmtHandle_); if (ret == E_SQLITE_CORRUPT && config_ != nullptr) { - RdbFaultHiViewReporter::ReportFault(RdbFaultHiViewReporter::Create(*config_, ret)); + Reportor::ReportFault(Reportor::Create(*config_, ret)); } stepCnt_++; return ret; @@ -313,6 +323,15 @@ int32_t RdStatement::Reset() } int32_t RdStatement::Execute(const std::vector& args) +{ + std::vector> refArgs; + for (auto &object : args) { + refArgs.emplace_back(std::ref(const_cast(object))); + } + return Execute(refArgs); +} + +int32_t RdStatement::Execute(const std::vector>& args) { if (!readOnly_ && strcmp(sql_.c_str(), GlobalExpr::PRAGMA_VERSION) == 0) { // It has already set version in prepare procedure diff --git a/relational_store/frameworks/native/rdb/src/rdb_helper.cpp b/relational_store/frameworks/native/rdb/src/rdb_helper.cpp index 62170e410845e973a0d13a1e3106117c5994861e..55f34bef657459ae703c3f5f3fbb2763376fb0ce 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_helper.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_helper.cpp @@ -17,6 +17,7 @@ #include "logger.h" #include "rdb_errno.h" +#include "rdb_fault_hiview_reporter.h" #include "rdb_security_manager.h" #include "rdb_store_manager.h" #include "rdb_trace.h" @@ -30,6 +31,7 @@ namespace OHOS { namespace NativeRdb { using namespace OHOS::Rdb; +using Reportor = RdbFaultHiViewReporter; std::shared_ptr RdbHelper::GetRdbStore( const RdbStoreConfig &config, int version, RdbOpenCallback &openCallback, int &errCode) @@ -81,12 +83,13 @@ int RdbHelper::DeleteRdbStore(const std::string &dbFileName) 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)); - RdbStoreConfig config(dbFileName); config.SetDBType(DB_SQLITE); int errCodeSqlite = Connection::Delete(config); @@ -110,6 +113,7 @@ int RdbHelper::DeleteRdbStore(const RdbStoreConfig &config) LOG_ERROR("not exist, path %{public}s", SqliteUtils::Anonymous(dbFile).c_str()); return E_OK; // not not exist } + Reportor::ReportRestore(Reportor::Create(config, E_OK, "RestoreType:Restore")); RdbStoreManager::GetInstance().Delete(dbFile); Connection::Delete(config); RdbSecurityManager::GetInstance().DelAllKeyFiles(dbFile); 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 7cb1bf230b0ac23470f7c860d4f046e663f7bb96..17ce49cdb682531fd587207b30b79f1849906f84 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_service_proxy.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_service_proxy.cpp @@ -177,11 +177,12 @@ int32_t RdbServiceProxy::DoAsync(const RdbSyncerParam& param, const Option &opti } int32_t RdbServiceProxy::SetDistributedTables(const RdbSyncerParam& param, const std::vector &tables, - const std::vector &references, int32_t type) + const std::vector &references, bool isRebuild, int32_t type) { MessageParcel reply; int32_t status = IPC_SEND( - static_cast(RdbServiceCode::RDB_SERVICE_CMD_SET_DIST_TABLE), reply, param, tables, references, type); + static_cast(RdbServiceCode::RDB_SERVICE_CMD_SET_DIST_TABLE), reply, param, tables, references, + type, isRebuild); if (status != RDB_OK) { LOG_ERROR("status:%{public}d, bundleName:%{public}s, storeName:%{public}s, type:%{public}d", status, param.bundleName_.c_str(), SqliteUtils::Anonymous(param.storeName_).c_str(), type); diff --git a/relational_store/frameworks/native/rdb/src/rdb_store.cpp b/relational_store/frameworks/native/rdb/src/rdb_store.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d36c61ef0a4a3a4400d89243f7e9d1191aeb385d --- /dev/null +++ b/relational_store/frameworks/native/rdb/src/rdb_store.cpp @@ -0,0 +1,601 @@ +/* + * 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 "rdb_store.h" + +#include "sqlite_sql_builder.h" +#include "sqlite_utils.h" +#include "traits.h" +namespace OHOS::NativeRdb { +RdbStore::ModifyTime::ModifyTime(std::shared_ptr result, std::map, PRIKey> hashKeys, + bool isFromRowId) + : result_(std::move(result)), hash_(std::move(hashKeys)), isFromRowId_(isFromRowId) +{ + for (auto &[_, priKey] : hash_) { + if (priKey.index() != Traits::variant_index_of_v) { + break; + } + auto *val = Traits::get_if(&priKey); + if (val != nullptr && maxOriginKeySize_ <= val->length()) { + maxOriginKeySize_ = val->length() + 1; + } + } +} + +RdbStore::ModifyTime::operator std::map() +{ + if (result_ == nullptr) { + return {}; + } + int count = 0; + if (result_->GetRowCount(count) != E_OK || count <= 0) { + return {}; + } + std::map result; + for (int i = 0; i < count; i++) { + result_->GoToRow(i); + int64_t timeStamp = 0; + result_->GetLong(1, timeStamp); + PRIKey index = 0; + if (isFromRowId_) { + int64_t rowid = 0; + result_->GetLong(0, rowid); + index = rowid; + } else { + std::vector hashKey; + result_->GetBlob(0, hashKey); + index = hash_[hashKey]; + } + result[index] = Date(timeStamp); + } + return result; +} + +RdbStore::ModifyTime::operator std::shared_ptr() +{ + return result_; +} + +RdbStore::PRIKey RdbStore::ModifyTime::GetOriginKey(const std::vector &hash) +{ + auto it = hash_.find(hash); + return it != hash_.end() ? it->second : std::monostate(); +} + +size_t RdbStore::ModifyTime::GetMaxOriginKeySize() +{ + return maxOriginKeySize_; +} + +bool RdbStore::ModifyTime::NeedConvert() const +{ + return !hash_.empty(); +} + +static std::vector ToValues(const std::vector &args) +{ + std::vector newArgs; + std::for_each(args.begin(), args.end(), [&newArgs](const auto &it) { + newArgs.push_back(ValueObject(it)); + }); + return newArgs; +} + +static bool ColHasSpecificField(const std::vector &columns) +{ + for (const std::string &column : columns) { + if (column.find(SqliteUtils::REP) != std::string::npos) { + return true; + } + } + return false; +} + +std::pair RdbStore::Insert(const std::string &table, const Row &row, Resolution resolution) +{ + (void)table; + (void)row; + (void)resolution; + return { E_NOT_SUPPORT, -1 }; +} + +int RdbStore::Insert(int64_t &outRowId, const std::string &table, const Row &row) +{ + auto [errCode, rowid] = Insert(table, row, NO_ACTION); + if (errCode == E_OK) { + outRowId = rowid; + } + return errCode; +} + +int RdbStore::InsertWithConflictResolution(int64_t &outRowId, const std::string &table, const Row &row, + Resolution resolution) +{ + auto [errCode, rowid] = Insert(table, row, resolution); + if (errCode == E_OK) { + outRowId = rowid; + } + return errCode; +} + +int RdbStore::Replace(int64_t &outRowId, const std::string &table, const Row &row) +{ + auto [errCode, rowid] = Insert(table, row, Resolution::ON_CONFLICT_REPLACE); + if (errCode == E_OK) { + outRowId = rowid; + } + return errCode; +} + +int RdbStore::BatchInsert(int64_t &outInsertNum, const std::string &table, const Rows &rows) +{ + ValuesBuckets refRows; + for (auto &row : rows) { + refRows.Put(row); + } + auto [errCode, count] = BatchInsert(table, refRows); + if (errCode == E_OK) { + outInsertNum = count; + } + return errCode; +} + +std::pair RdbStore::BatchInsert(const std::string &table, const RefRows &rows) +{ + return { E_NOT_SUPPORT, -1 }; +} + +std::pair RdbStore::Update(const std::string &table, const Row &row, const std::string &where, + const Values &args, Resolution resolution) +{ + (void)table; + (void)row; + (void)where; + (void)args; + (void)resolution; + return { E_NOT_SUPPORT, 0 }; +} + +int RdbStore::Update(int &changedRows, const std::string &table, const Row &row, const std::string &whereClause, + const Values &args) +{ + auto [errCode, changes] = Update(table, row, whereClause, args, NO_ACTION); + if (errCode == E_OK) { + changedRows = changes; + } + return errCode; +} + +int RdbStore::Update(int &changedRows, const Row &row, const AbsRdbPredicates &predicates) +{ + return Update(changedRows, predicates.GetTableName(), row, predicates.GetWhereClause(), predicates.GetBindArgs()); +} + +int RdbStore::Update(int &changedRows, const std::string &table, const Row &row, const std::string &whereClause, + const Olds &args) +{ + return Update(changedRows, table, row, whereClause, ToValues(args)); +}; + +int RdbStore::UpdateWithConflictResolution(int &changedRows, const std::string &table, const Row &row, + const std::string &whereClause, const Olds &args, Resolution resolution) +{ + auto [errCode, changes] = Update(table, row, whereClause, ToValues(args), resolution); + if (errCode == E_OK) { + changedRows = changes; + } + return errCode; +} + +int RdbStore::UpdateWithConflictResolution(int &changedRows, const std::string &table, const Row &row, + const std::string &whereClause, const Values &args, Resolution resolution) +{ + auto [errCode, changes] = Update(table, row, whereClause, args, resolution); + if (errCode == E_OK) { + changedRows = changes; + } + return errCode; +} + +int RdbStore::Delete(int &deletedRows, const std::string &table, const std::string &whereClause, const Olds &args) +{ + return Delete(deletedRows, table, whereClause, ToValues(args)); +} + +int RdbStore::Delete(int &deletedRows, const AbsRdbPredicates &predicates) +{ + return Delete(deletedRows, predicates.GetTableName(), predicates.GetWhereClause(), predicates.GetBindArgs()); +} + +std::shared_ptr RdbStore::Query(int &errCode, bool distinct, const std::string &table, + const Fields &columns, const std::string &whereClause, const Values &args, const std::string &groupBy, + const std::string &indexName, const std::string &orderBy, const int &limit, const int &offset) +{ + std::string sql; + errCode = SqliteSqlBuilder::BuildQueryString(distinct, table, "", columns, whereClause, groupBy, indexName, + orderBy, limit, offset, sql); + if (errCode != E_OK) { + return nullptr; + } + return QuerySql(sql, args); +} + +std::shared_ptr RdbStore::Query(const AbsRdbPredicates &predicates, const Fields &columns) +{ + std::string sql; + std::pair queryStatus = { ColHasSpecificField(columns), predicates.HasSpecificField() }; + if (queryStatus.first || queryStatus.second) { + std::string table = predicates.GetTableName(); + std::string logTable = GetLogTableName(table); + sql = SqliteSqlBuilder::BuildCursorQueryString(predicates, columns, logTable, queryStatus); + } else { + sql = SqliteSqlBuilder::BuildQueryString(predicates, columns); + } + return QuerySql(sql, predicates.GetBindArgs()); +} + +std::shared_ptr RdbStore::QuerySql(const std::string &sql, const Olds &args) +{ + return QuerySql(sql, ToValues(args)); +} + +std::shared_ptr RdbStore::QueryByStep(const std::string &sql, const Olds &args) +{ + return QueryByStep(sql, ToValues(args)); +} + +std::shared_ptr RdbStore::QueryByStep(const AbsRdbPredicates &predicates, const RdbStore::Fields &columns) +{ + std::string sql; + if (predicates.HasSpecificField()) { + std::string table = predicates.GetTableName(); + std::string logTable = GetLogTableName(table); + sql = SqliteSqlBuilder::BuildLockRowQueryString(predicates, columns, logTable); + } else { + sql = SqliteSqlBuilder::BuildQueryString(predicates, columns); + } + return QueryByStep(sql, predicates.GetBindArgs()); +} + +std::shared_ptr RdbStore::RemoteQuery(const std::string &device, const AbsRdbPredicates &predicates, + const Fields &columns, int &errCode) +{ + (void)device; + (void)predicates; + (void)columns; + errCode = E_NOT_SUPPORT; + return nullptr; +} + +std::pair> RdbStore::QuerySharingResource(const AbsRdbPredicates &predicates, + const Fields &columns) +{ + (void)predicates; + (void)columns; + return { E_NOT_SUPPORT, nullptr }; +} + +int RdbStore::ExecuteSql(const std::string &sql, const Values &args) +{ + auto [errCode, value] = Execute(sql, args, 0); + return errCode; +} + +std::pair RdbStore::Execute(const std::string &sql, const Values &args, int64_t trxId) +{ + return { E_NOT_SUPPORT, ValueObject() }; +} + +int RdbStore::ExecuteAndGetLong(int64_t &outValue, const std::string &sql, const Values &args) +{ + auto [errCode, value] = Execute(sql, args); + if (errCode == E_OK) { + outValue = static_cast(value); + } + return errCode; +} + +int RdbStore::ExecuteAndGetString(std::string &outValue, const std::string &sql, const Values &args) +{ + auto [errCode, value] = Execute(sql, args); + if (errCode == E_OK) { + outValue = static_cast(value); + } + return errCode; +} + +int RdbStore::ExecuteForLastInsertedRowId(int64_t &outValue, const std::string &sql, const Values &args) +{ + (void)outValue; + (void)sql; + (void)args; + return E_NOT_SUPPORT; +} + +int RdbStore::ExecuteForChangedRowCount(int64_t &outValue, const std::string &sql, const Values &args) +{ + (void)outValue; + (void)sql; + (void)args; + return E_NOT_SUPPORT; +} + +int RdbStore::Backup(const std::string &databasePath, const std::vector &encryptKey) +{ + (void)databasePath; + (void)encryptKey; + return E_NOT_SUPPORT; +} + +int RdbStore::Attach(const std::string &alias, const std::string &pathName, const std::vector encryptKey) +{ + (void)alias; + (void)pathName; + (void)encryptKey; + return E_OK; +} + +int RdbStore::Count(int64_t &outValue, const AbsRdbPredicates &predicates) +{ + (void)outValue; + (void)predicates; + return E_NOT_SUPPORT; +} + +std::pair> RdbStore::CreateTransaction(int32_t type) +{ + (void)type; + return { E_NOT_SUPPORT, nullptr }; +} + +int RdbStore::BeginTransaction() +{ + return E_NOT_SUPPORT; +} + +std::pair RdbStore::BeginTrans() +{ + return { E_NOT_SUPPORT, 0 }; +} + +int RdbStore::RollBack() +{ + return E_NOT_SUPPORT; +} + +int RdbStore::RollBack(int64_t trxId) +{ + (void)trxId; + return E_NOT_SUPPORT; +} + +int RdbStore::Commit() +{ + return E_NOT_SUPPORT; +} + +int RdbStore::Commit(int64_t trxId) +{ + (void)trxId; + return E_NOT_SUPPORT; +} + +bool RdbStore::IsInTransaction() +{ + return true; +} + +std::string RdbStore::GetPath() +{ + return ""; +} + +bool RdbStore::IsHoldingConnection() +{ + return true; +} + +bool RdbStore::IsOpen() const +{ + return true; +} + +bool RdbStore::IsReadOnly() const +{ + return false; +} + +bool RdbStore::IsMemoryRdb() const +{ + return false; +} + +int RdbStore::Restore(const std::string &backupPath, const std::vector &newKey) +{ + (void)backupPath; + (void)newKey; + return E_NOT_SUPPORT; +} + +int RdbStore::SetDistributedTables(const std::vector &tables, int32_t type, + const DistributedRdb::DistributedConfig &distributedConfig) +{ + (void)tables; + (void)type; + (void)distributedConfig; + return E_NOT_SUPPORT; +} + +std::string RdbStore::ObtainDistributedTableName(const std::string &device, const std::string &table, int &errCode) +{ + errCode = E_NOT_SUPPORT; + return table + "_" + device; +} + +int RdbStore::Sync(const SyncOption &option, const AbsRdbPredicates &predicate, const AsyncBrief &async) +{ + (void)option; + (void)predicate; + (void)async; + return E_NOT_SUPPORT; +} + +int RdbStore::Sync(const SyncOption &option, const std::vector &tables, const AsyncDetail &async) +{ + (void)option; + (void)tables; + (void)async; + return E_NOT_SUPPORT; +} + +int RdbStore::Sync(const SyncOption &option, const AbsRdbPredicates &predicate, const AsyncDetail &async) +{ + (void)option; + (void)predicate; + (void)async; + return E_NOT_SUPPORT; +} + +int RdbStore::Subscribe(const SubscribeOption& option, RdbStoreObserver *observer) +{ + (void)option; + (void)observer; + return E_NOT_SUPPORT; +} + +int RdbStore::UnSubscribe(const SubscribeOption& option, RdbStoreObserver *observer) +{ + (void)option; + (void)observer; + return E_NOT_SUPPORT; +} + +int RdbStore::SubscribeObserver(const SubscribeOption& option, const std::shared_ptr &observer) +{ + (void)option; + (void)observer; + return E_NOT_SUPPORT; +} + +int RdbStore::UnsubscribeObserver(const SubscribeOption& option, const std::shared_ptr &observer) +{ + (void)option; + (void)observer; + return E_NOT_SUPPORT; +} + +int RdbStore::RegisterAutoSyncCallback(std::shared_ptr observer) +{ + (void)observer; + return E_NOT_SUPPORT; +} + +int RdbStore::UnregisterAutoSyncCallback(std::shared_ptr observer) +{ + (void)observer; + return E_NOT_SUPPORT; +} + +int RdbStore::Notify(const std::string &event) +{ + (void)event; + return E_NOT_SUPPORT; +} + +bool RdbStore::IsSlaveDiffFromMaster() const +{ + return false; +} + +int32_t RdbStore::GetDbType() const +{ + return DB_SQLITE; +} + +std::pair RdbStore::LockCloudContainer() +{ + return { E_OK, 0 }; +} + +int32_t RdbStore::UnlockCloudContainer() +{ + return E_OK; +} + +int RdbStore::InterruptBackup() +{ + return E_OK; +} + +int32_t RdbStore::GetBackupStatus() const +{ + return SlaveStatus::UNDEFINED; +} + +RdbStore::ModifyTime RdbStore::GetModifyTime(const std::string &table, const std::string &column, + std::vector &keys) +{ + (void)table; + (void)column; + (void)keys; + return {}; +} + +int RdbStore::CleanDirtyData(const std::string &table, uint64_t cursor) +{ + (void)table; + (void)cursor; + return E_NOT_SUPPORT; +} + +int RdbStore::GetRebuilt(RebuiltType &rebuilt) +{ + (void)rebuilt; + return E_NOT_SUPPORT; +} + +std::pair RdbStore::Attach(const RdbStoreConfig &config, const std::string &attachName, + int32_t waitTime) +{ + (void)config; + (void)attachName; + (void)waitTime; + return { E_NOT_SUPPORT, 0 }; +} + +std::pair RdbStore::Detach(const std::string &attachName, int32_t waitTime) +{ + (void)attachName; + (void)waitTime; + return { E_NOT_SUPPORT, 0 }; +} + +int RdbStore::ModifyLockStatus(const AbsRdbPredicates &predicates, bool isLock) +{ + (void)predicates; + (void)isLock; + return E_NOT_SUPPORT; +} + +int RdbStore::SetSearchable(bool isSearchable) +{ + (void)isSearchable; + return E_NOT_SUPPORT; +} + +std::string RdbStore::GetLogTableName(const std::string &tableName) +{ + return "naturalbase_rdb_aux_" + tableName + "_log"; +} +} \ 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 22db48a1dea32f62054a66e98bc6cfc47e8ed388..1b00b3f5fab95d60ac5735b77f7ca4eb517bc6d1 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_store_config.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_store_config.cpp @@ -26,13 +26,13 @@ using namespace OHOS::Rdb; RdbStoreConfig::RdbStoreConfig(const std::string &name, StorageMode storageMode, bool isReadOnly, const std::vector &encryptKey, const std::string &journalMode, const std::string &syncMode, const std::string &databaseFileType, SecurityLevel securityLevel, bool isCreateNecessary, bool autoCheck, - int journalSize, int pageSize, const std::string &encryptAlgo) + int journalSize, int pageSize) : readOnly_(isReadOnly), isCreateNecessary_(isCreateNecessary), autoCheck_(autoCheck), journalSize_(journalSize), pageSize_(pageSize), securityLevel_(securityLevel), storageMode_(storageMode), path_(name), - journalMode_(journalMode), syncMode_(syncMode), databaseFileType(databaseFileType), encryptAlgo_(encryptAlgo), - encryptKey_(encryptKey) + journalMode_(journalMode), syncMode_(syncMode), databaseFileType(databaseFileType) { name_ = StringUtils::ExtractFileName(name); + cryptoParam_.encryptKey_ = encryptKey; } RdbStoreConfig::~RdbStoreConfig() @@ -164,13 +164,13 @@ void RdbStoreConfig::SetPageSize(int pageSize) { this->pageSize_ = pageSize; } -const std::string RdbStoreConfig::GetEncryptAlgo() const +EncryptAlgo RdbStoreConfig::GetEncryptAlgo() const { - return encryptAlgo_; + return static_cast(cryptoParam_.encryptAlgo); } -void RdbStoreConfig::SetEncryptAlgo(const std::string &encryptAlgo) +void RdbStoreConfig::SetEncryptAlgo(EncryptAlgo encryptAlgo) { - this->encryptAlgo_ = encryptAlgo; + this->cryptoParam_.encryptAlgo = static_cast(encryptAlgo); } void RdbStoreConfig::SetReadOnly(bool readOnly) @@ -309,7 +309,7 @@ void RdbStoreConfig::SetEncryptStatus(const bool status) bool RdbStoreConfig::IsEncrypt() const { - return isEncrypt_ || !encryptKey_.empty(); + return isEncrypt_ || !cryptoParam_.encryptKey_.empty(); } bool RdbStoreConfig::IsCreateNecessary() const @@ -334,15 +334,16 @@ void RdbStoreConfig::SetReadConSize(int readConSize) void RdbStoreConfig::SetEncryptKey(const std::vector &encryptKey) { - encryptKey_ = encryptKey; + cryptoParam_.encryptKey_.assign(cryptoParam_.encryptKey_.size(), 0); + cryptoParam_.encryptKey_ = encryptKey; } void RdbStoreConfig::RestoreEncryptKey(const std::vector &encryptKey) const { RdbSecurityManager::GetInstance().RestoreKeyFile(GetPath(), encryptKey); - encryptKey_.assign(encryptKey_.size(), 0); + cryptoParam_.encryptKey_.assign(cryptoParam_.encryptKey_.size(), 0); newEncryptKey_.assign(newEncryptKey_.size(), 0); - encryptKey_ = encryptKey; + cryptoParam_.encryptKey_ = encryptKey; } void RdbStoreConfig::SetNewEncryptKey(const std::vector newEncryptKey) @@ -352,7 +353,7 @@ void RdbStoreConfig::SetNewEncryptKey(const std::vector newEncryptKey) std::vector RdbStoreConfig::GetEncryptKey() const { - return encryptKey_; + return cryptoParam_.encryptKey_; } void RdbStoreConfig::ChangeEncryptKey() const @@ -361,8 +362,8 @@ void RdbStoreConfig::ChangeEncryptKey() const if (newEncryptKey_.empty()) { return; } - encryptKey_.assign(encryptKey_.size(), 0); - encryptKey_.assign(newEncryptKey_.data(), newEncryptKey_.data() + newEncryptKey_.size()); + cryptoParam_.encryptKey_.assign(cryptoParam_.encryptKey_.size(), 0); + cryptoParam_.encryptKey_.assign(newEncryptKey_.data(), newEncryptKey_.data() + newEncryptKey_.size()); newEncryptKey_.assign(newEncryptKey_.size(), 0); newEncryptKey_.resize(0); } @@ -379,7 +380,7 @@ int32_t RdbStoreConfig::Initialize() const int32_t RdbStoreConfig::GenerateEncryptedKey() const { - if (!isEncrypt_) { + if (!isEncrypt_ || !cryptoParam_.encryptKey_.empty()) { return E_OK; } @@ -395,7 +396,7 @@ int32_t RdbStoreConfig::GenerateEncryptedKey() const } auto rdbPwd = RdbSecurityManager::GetInstance().GetRdbPassword(path_, KeyFileType::PUB_KEY_FILE); if (rdbPwd.IsValid()) { - encryptKey_ = std::vector(rdbPwd.GetData(), rdbPwd.GetData() + rdbPwd.GetSize()); + cryptoParam_.encryptKey_ = std::vector(rdbPwd.GetData(), rdbPwd.GetData() + rdbPwd.GetSize()); } rdbPwd.Clear(); if ((rdbPwd.isKeyExpired && autoRekey_) || @@ -406,7 +407,7 @@ int32_t RdbStoreConfig::GenerateEncryptedKey() const } rdbPwd.Clear(); } - if (encryptKey_.empty() && newEncryptKey_.empty()) { + if (cryptoParam_.encryptKey_.empty() && newEncryptKey_.empty()) { LOG_WARN("key is inValid, bundleName_:%{public}s", bundleName_.c_str()); } return E_OK; @@ -414,7 +415,7 @@ int32_t RdbStoreConfig::GenerateEncryptedKey() const void RdbStoreConfig::ClearEncryptKey() { - encryptKey_.assign(encryptKey_.size(), 0); + cryptoParam_.encryptKey_.assign(cryptoParam_.encryptKey_.size(), 0); newEncryptKey_.assign(newEncryptKey_.size(), 0); } @@ -566,12 +567,12 @@ std::vector RdbStoreConfig::GetPluginLibs() const int32_t RdbStoreConfig::GetIter() const { - return iter_; + return cryptoParam_.iterNum; } void RdbStoreConfig::SetIter(int32_t iter) const { - iter_ = iter; + cryptoParam_.iterNum = iter; } int32_t RdbStoreConfig::GetHaMode() const @@ -588,4 +589,51 @@ void RdbStoreConfig::EnableRekey(bool enable) { autoRekey_ = enable; } + +void RdbStoreConfig::SetCryptoParam(RdbStoreConfig::CryptoParam cryptoParam) +{ + cryptoParam_ = cryptoParam; +} + +RdbStoreConfig::CryptoParam RdbStoreConfig::GetCryptoParam() const +{ + return cryptoParam_; +} + +RdbStoreConfig::CryptoParam::CryptoParam() = default; + +RdbStoreConfig::CryptoParam::~CryptoParam() +{ + encryptKey_.assign(encryptKey_.size(), 0); +} + +bool RdbStoreConfig::CryptoParam::IsValid() const +{ + int32_t count = iterNum; + if (count < 0) { + return false; + } + + if (encryptAlgo != AES_256_CBC && encryptAlgo != AES_256_GCM) { + return false; + } + + if (hmacAlgo < SHA1 || hmacAlgo > SHA512) { + return false; + } + + if (kdfAlgo < KDF_SHA1 || kdfAlgo > KDF_SHA512) { + return false; + } + + int32_t pageSize = cryptoPageSize; + if (pageSize < DB_MIN_CRYPTO_PAGE_SIZE || pageSize > DB_MAX_CRYPTO_PAGE_SIZE) { + return false; + } + if (!((pageSize != 0) && ((pageSize & (pageSize - 1)) == 0))) { + return false; + } + return true; +} + } // 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 f4ea51fbeacacc770fd6ed74c7f6282766f56613..2d5d04080648d2afd1403bae1cd9d9ea78daa843 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_store_impl.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_store_impl.cpp @@ -15,8 +15,6 @@ #define LOG_TAG "RdbStoreImpl" #include "rdb_store_impl.h" -#include - #include #include #include @@ -25,11 +23,14 @@ #include #include #include +#include #include "cache_result_set.h" +#include "directory_ex.h" #include "logger.h" #include "rdb_common.h" #include "rdb_errno.h" +#include "rdb_fault_hiview_reporter.h" #include "rdb_radar_reporter.h" #include "rdb_security_manager.h" #include "rdb_sql_statistic.h" @@ -42,11 +43,10 @@ #include "sqlite_statement.h" #include "sqlite_utils.h" #include "step_result_set.h" +#include "values_buckets.h" #include "task_executor.h" #include "traits.h" - -#include "directory_ex.h" -#include "rdb_fault_hiview_reporter.h" +#include "transaction.h" #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) #include "delay_notify.h" #include "raw_data_parser.h" @@ -69,6 +69,7 @@ using namespace OHOS::Rdb; using namespace std::chrono; using SqlStatistic = DistributedRdb::SqlStatistic; using RdbNotifyConfig = DistributedRdb::RdbNotifyConfig; +using Reportor = RdbFaultHiViewReporter; #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) using RdbMgr = DistributedRdb::RdbManagerImpl; #endif @@ -76,6 +77,7 @@ using RdbMgr = DistributedRdb::RdbManagerImpl; static constexpr const char *BEGIN_TRANSACTION_SQL = "begin;"; static constexpr const char *COMMIT_TRANSACTION_SQL = "commit;"; static constexpr const char *ROLLBACK_TRANSACTION_SQL = "rollback;"; +constexpr int64_t TIME_OUT = 1500; void RdbStoreImpl::InitSyncerParam(const RdbStoreConfig &config, bool created) { @@ -126,7 +128,9 @@ void RdbStoreImpl::AfterOpen(const RdbParam ¶m, int32_t retry) SqliteUtils::Anonymous(param.storeName_).c_str()); auto pool = TaskExecutor::GetInstance().GetExecutor(); if (err == E_SERVICE_NOT_FOUND && pool != nullptr && retry++ < MAX_RETRY_TIMES) { - pool->Schedule(std::chrono::seconds(RETRY_INTERVAL), [param, retry]() { AfterOpen(param, retry); }); + pool->Schedule(std::chrono::seconds(RETRY_INTERVAL), [param, retry]() { + AfterOpen(param, retry); + }); } return; } @@ -137,77 +141,6 @@ void RdbStoreImpl::AfterOpen(const RdbParam ¶m, int32_t retry) } } -int32_t RdbStoreImpl::GetDbType() const -{ - return config_.GetDBType(); -} - -RdbStore::ModifyTime::ModifyTime(std::shared_ptr result, std::map, PRIKey> hashKeys, - bool isFromRowId) - : result_(std::move(result)), hash_(std::move(hashKeys)), isFromRowId_(isFromRowId) -{ - for (auto &[_, priKey] : hash_) { - if (priKey.index() != Traits::variant_index_of_v) { - break; - } - auto *val = Traits::get_if(&priKey); - if (val != nullptr && maxOriginKeySize_ <= val->length()) { - maxOriginKeySize_ = val->length() + 1; - } - } -} - -RdbStore::ModifyTime::operator std::map() -{ - if (result_ == nullptr) { - return {}; - } - int count = 0; - if (result_->GetRowCount(count) != E_OK || count <= 0) { - LOG_ERROR("get resultSet err."); - return {}; - } - std::map result; - for (int i = 0; i < count; i++) { - result_->GoToRow(i); - int64_t timeStamp = 0; - result_->GetLong(1, timeStamp); - PRIKey index = 0; - if (isFromRowId_) { - int64_t rowid = 0; - result_->GetLong(0, rowid); - index = rowid; - } else { - std::vector hashKey; - result_->GetBlob(0, hashKey); - index = hash_[hashKey]; - } - result[index] = Date(timeStamp); - } - return result; -} - -RdbStore::ModifyTime::operator std::shared_ptr() -{ - return result_; -} - -RdbStore::PRIKey RdbStore::ModifyTime::GetOriginKey(const std::vector &hash) -{ - auto it = hash_.find(hash); - return it != hash_.end() ? it->second : std::monostate(); -} - -size_t RdbStore::ModifyTime::GetMaxOriginKeySize() -{ - return maxOriginKeySize_; -} - -bool RdbStore::ModifyTime::NeedConvert() const -{ - return !hash_.empty(); -} - RdbStore::ModifyTime RdbStoreImpl::GetModifyTime(const std::string &table, const std::string &columnName, std::vector &keys) { @@ -273,643 +206,979 @@ RdbStore::ModifyTime RdbStoreImpl::GetModifyTimeByRowId(const std::string &logTa LOG_ERROR("get resultSet err."); return {}; } - return { resultSet, {}, true }; + return ModifyTime(resultSet, {}, true); } int RdbStoreImpl::CleanDirtyData(const std::string &table, uint64_t cursor) { if (isReadOnly_ || (config_.GetDBType() == DB_VECTOR)) { + LOG_ERROR("not support. table:%{public}s, isRead:%{public}d, dbType:%{public}d", + SqliteUtils::Anonymous(table).c_str(), isReadOnly_, config_.GetDBType()); return E_NOT_SUPPORT; } auto connection = connectionPool_->AcquireConnection(false); if (connection == nullptr) { + LOG_ERROR("db is busy. table:%{public}s", SqliteUtils::Anonymous(table).c_str()); return E_DATABASE_BUSY; } int errCode = connection->CleanDirtyData(table, cursor); return errCode; } -#endif -RdbStoreImpl::RdbStoreImpl(const RdbStoreConfig &config) - : isMemoryRdb_(config.IsMemoryRdb()), config_(config), name_(config.GetName()), - fileType_(config.GetDatabaseFileType()) +std::string RdbStoreImpl::GetLogTableName(const std::string &tableName) { - path_ = (config.GetRoleType() == VISITOR) ? config.GetVisitorDir() : config.GetPath(); - isReadOnly_ = config.IsReadOnly() || config.GetRoleType() == VISITOR; + return DistributedDB::RelationalStoreManager::GetDistributedLogTableName(tableName); } -RdbStoreImpl::RdbStoreImpl(const RdbStoreConfig &config, int &errCode) - : isMemoryRdb_(config.IsMemoryRdb()), config_(config), name_(config.GetName()), - fileType_(config.GetDatabaseFileType()) +std::pair> RdbStoreImpl::QuerySharingResource(const AbsRdbPredicates &predicates, + const Fields &columns) { - isReadOnly_ = config.IsReadOnly() || config.GetRoleType() == VISITOR; - path_ = (config.GetRoleType() == VISITOR) ? 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 !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) - RdbParam param; - param.bundleName_ = config_.GetBundleName(); - param.storeName_ = config_.GetName(); - auto [err, service] = RdbMgr::GetInstance().GetRdbService(param); - if (service != nullptr) { - service->Disable(param); - } -#endif - std::tie(rebuild_, connectionPool_) = ConnectionPool::HandleDataCorruption(config_, errCode); - created = true; -#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) - if (service != nullptr) { - service->Enable(param); - } -#endif + if (config_.GetDBType() == DB_VECTOR) { + return { E_NOT_SUPPORT, nullptr }; } - if (connectionPool_ == nullptr || errCode != E_OK) { - connectionPool_ = nullptr; - LOG_ERROR("Create connPool failed, err is %{public}d, path:%{public}s", errCode, - SqliteUtils::Anonymous(path_).c_str()); - return; + auto [errCode, service] = RdbMgr::GetInstance().GetRdbService(syncerParam_); + if (errCode != E_OK) { + return { errCode, nullptr }; } - InitSyncerParam(config_, created); - InnerOpen(); -} - -RdbStoreImpl::~RdbStoreImpl() -{ - connectionPool_ = nullptr; -} - -const RdbStoreConfig &RdbStoreImpl::GetConfig() -{ - return config_; + auto [status, resultSet] = + service->QuerySharingResource(syncerParam_, predicates.GetDistributedPredicates(), columns); + if (status != E_OK) { + return { status, nullptr }; + } + return { status, resultSet }; } -int RdbStoreImpl::Insert(int64_t &outRowId, const std::string &table, const ValuesBucket &values) +std::shared_ptr RdbStoreImpl::RemoteQuery(const std::string &device, const AbsRdbPredicates &predicates, + const Fields &columns, int &errCode) { - return InsertWithConflictResolutionEntry(outRowId, table, values, ConflictResolution::ON_CONFLICT_NONE); + DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); + if (config_.GetDBType() == DB_VECTOR) { + return nullptr; + } + std::vector selectionArgs = predicates.GetWhereArgs(); + std::string sql = SqliteSqlBuilder::BuildQueryString(predicates, columns); + auto [err, service] = RdbMgr::GetInstance().GetRdbService(syncerParam_); + if (err == E_NOT_SUPPORT) { + errCode = err; + return nullptr; + } + if (err != E_OK) { + LOG_ERROR("RdbStoreImpl::RemoteQuery get service failed"); + errCode = err; + return nullptr; + } + auto [status, resultSet] = service->RemoteQuery(syncerParam_, device, sql, selectionArgs); + errCode = status; + return resultSet; } -int RdbStoreImpl::BatchInsert(int64_t &outInsertNum, const std::string &table, const std::vector &values) +void RdbStoreImpl::NotifyDataChange() { - SqlStatistic sqlStatistic("", SqlStatistic::Step::STEP_TOTAL); - return BatchInsertEntry(outInsertNum, table, values); + int errCode = RegisterDataChangeCallback(); + if (errCode != E_OK) { + LOG_ERROR("RegisterDataChangeCallback is failed, err is %{public}d.", errCode); + } + DistributedRdb::RdbChangedData rdbChangedData; + if (delayNotifier_ != nullptr) { + delayNotifier_->UpdateNotify(rdbChangedData, true); + } } -int RdbStoreImpl::BatchInsertEntry(int64_t &outInsertNum, const std::string &table, - const std::vector &values) +int RdbStoreImpl::SetDistributedTables(const std::vector &tables, int32_t type, + const DistributedRdb::DistributedConfig &distributedConfig) { - if (isReadOnly_ || (config_.GetDBType() == DB_VECTOR)) { + DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); + if (config_.GetDBType() == DB_VECTOR || isReadOnly_) { return E_NOT_SUPPORT; } - if (values.empty()) { - outInsertNum = 0; + if (tables.empty()) { + LOG_WARN("The distributed tables to be set is empty."); return E_OK; } - auto connection = connectionPool_->AcquireConnection(false); - if (connection == nullptr) { - return E_DATABASE_BUSY; + auto [errCode, service] = RdbMgr::GetInstance().GetRdbService(syncerParam_); + if (errCode != E_OK) { + return errCode; } - auto executeSqlArgs = GenerateSql(table, values, connection->GetMaxVariable()); - if (executeSqlArgs.empty()) { - LOG_ERROR("empty, table=%{public}s, values:%{public}zu, max number:%{public}d.", table.c_str(), - values.size(), connection->GetMaxVariable()); - return E_INVALID_ARGS; + int32_t errorCode = service->SetDistributedTables(syncerParam_, tables, distributedConfig.references, + distributedConfig.isRebuild, type); + if (errorCode != E_OK) { + LOG_ERROR("Fail to set distributed tables, error=%{public}d", errorCode); + return errorCode; } -#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) - PauseDelayNotify pauseDelayNotify(delayNotifier_); -#endif - for (const auto &[sql, bindArgs] : executeSqlArgs) { - auto [errCode, statement] = GetStatement(sql, connection); - if (statement == nullptr) { - continue; + if (type != DistributedRdb::DISTRIBUTED_CLOUD) { + return E_OK; + } + auto conn = connectionPool_->AcquireConnection(false); + if (conn != nullptr) { + auto strategy = conn->GenerateExchangeStrategy(slaveStatus_); + if (strategy == ExchangeStrategy::BACKUP) { + (void)conn->Backup({}, {}, false, slaveStatus_); } - for (const auto &args : bindArgs) { - auto errCode = statement->Execute(args); - if (errCode != E_OK) { - outInsertNum = -1; - LOG_ERROR("BatchInsert failed, errCode : %{public}d, bindArgs : %{public}zu," - "table : %{public}s, sql : %{public}s", errCode, bindArgs.size(), table.c_str(), sql.c_str()); - return E_OK; - } + } + { + std::unique_lock lock(rwMutex_); + if (distributedConfig.autoSync) { + cloudTables_.insert(tables.begin(), tables.end()); + } else { + std::for_each(tables.begin(), tables.end(), [this](const auto &table) { cloudTables_.erase(table); }); + return E_OK; } } - connection = nullptr; - outInsertNum = static_cast(values.size()); - DoCloudSync(table); + auto isRebuilt = RebuiltType::NONE; + GetRebuilt(isRebuilt); + if (isRebuilt == RebuiltType::REBUILT) { + DoCloudSync(""); + } return E_OK; } -RdbStoreImpl::ExecuteSqls RdbStoreImpl::GenerateSql(const std::string& table, const std::vector& buckets, - int limit) +std::string RdbStoreImpl::ObtainDistributedTableName(const std::string &device, const std::string &table, int &errCode) { - std::vector> values; - std::map fields; - int32_t valuePosition = 0; - for (size_t row = 0; row < buckets.size(); row++) { - auto &vBucket = buckets[row]; - if (values.max_size() == 0) { - values.reserve(vBucket.values_.size() * EXPANSION); - } - for (auto &[key, value] : vBucket.values_) { - if (value.GetType() == ValueObject::TYPE_ASSET || value.GetType() == ValueObject::TYPE_ASSETS) { - SetAssetStatus(value, AssetValue::STATUS_INSERT); - } - int32_t col = 0; - auto it = fields.find(key); - if (it == fields.end()) { - values.emplace_back(std::vector(buckets.size())); - col = valuePosition; - fields.insert(std::make_pair(key, col)); - valuePosition++; - } else { - col = static_cast(it->second); - } - values[col][row] = value; - } + DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); + if (config_.GetDBType() == DB_VECTOR) { + return ""; } - - std::string sql = "INSERT OR REPLACE INTO " + table + " ("; - std::vector args(buckets.size() * values.size()); - int32_t col = 0; - for (auto &[key, pos] : fields) { - for (size_t row = 0; row < buckets.size(); ++row) { - args[col + static_cast(row * fields.size())] = std::move(values[pos][row]); - } - col++; - sql.append(key).append(","); + std::string uuid; + DeviceManagerAdaptor::RdbDeviceManagerAdaptor &deviceManager = + DeviceManagerAdaptor::RdbDeviceManagerAdaptor::GetInstance(syncerParam_.bundleName_); + errCode = deviceManager.GetEncryptedUuidByNetworkId(device, uuid); + if (errCode != E_OK) { + LOG_ERROR("GetUuid is failed."); + return ""; } - sql.pop_back(); - sql.append(") VALUES "); - return SqliteSqlBuilder::MakeExecuteSqls(sql, std::move(args), fields.size(), limit); + + auto translateCall = [uuid](const std::string &oriDevId, const DistributedDB::StoreInfo &info) { + return uuid; + }; + DistributedDB::RuntimeConfig::SetTranslateToDeviceIdCallback(translateCall); + + return DistributedDB::RelationalStoreManager::GetDistributedTableName(uuid, table); } -int RdbStoreImpl::Replace(int64_t &outRowId, const std::string &table, const ValuesBucket &values) +int RdbStoreImpl::Sync(const SyncOption &option, const AbsRdbPredicates &predicate, const AsyncBrief &callback) { - return InsertWithConflictResolutionEntry(outRowId, table, values, ConflictResolution::ON_CONFLICT_REPLACE); + if (config_.GetDBType() == DB_VECTOR) { + return E_NOT_SUPPORT; + } + return Sync(option, predicate, [callback](Details &&details) { + Briefs briefs; + for (auto &[key, value] : details) { + briefs.insert_or_assign(key, value.code); + } + if (callback != nullptr) { + callback(briefs); + } + }); } -int RdbStoreImpl::InsertWithConflictResolution(int64_t &outRowId, const std::string &table, - const ValuesBucket &values, ConflictResolution conflictResolution) +int RdbStoreImpl::Sync(const SyncOption &option, const std::vector &tables, const AsyncDetail &async) { - return InsertWithConflictResolutionEntry(outRowId, table, values, conflictResolution); + return Sync(option, AbsRdbPredicates(tables), async); } -int RdbStoreImpl::InsertWithConflictResolutionEntry(int64_t &outRowId, const std::string &table, - const ValuesBucket &values, ConflictResolution conflictResolution) +int RdbStoreImpl::Sync(const SyncOption &option, const AbsRdbPredicates &predicate, const AsyncDetail &async) { - SqlStatistic sqlStatistic("", SqlStatistic::Step::STEP_TOTAL); DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - if (isReadOnly_ || (config_.GetDBType() == DB_VECTOR)) { - return E_NOT_SUPPORT; + DistributedRdb::RdbService::Option rdbOption; + rdbOption.mode = option.mode; + rdbOption.isAsync = !option.isBlock; + RdbRadar ret(Scene::SCENE_SYNC, __FUNCTION__, config_.GetBundleName()); + ret = InnerSync(rdbOption, predicate.GetDistributedPredicates(), async); + return ret; +} + +int RdbStoreImpl::InnerSync(const DistributedRdb::RdbService::Option &option, + const DistributedRdb::PredicatesMemo &predicates, const RdbStore::AsyncDetail &async) +{ + auto [errCode, service] = RdbMgr::GetInstance().GetRdbService(syncerParam_); + if (errCode == E_NOT_SUPPORT) { + return errCode; } - if (table.empty()) { - return E_EMPTY_TABLE_NAME; + if (errCode != E_OK) { + LOG_ERROR("GetRdbService is failed, err is %{public}d, bundleName is %{public}s.", + errCode, syncerParam_.bundleName_.c_str()); + return errCode; } - - if (values.IsEmpty()) { - return E_EMPTY_VALUES_BUCKET; + errCode = service->Sync(syncerParam_, option, predicates, async); + if (errCode != E_OK) { + LOG_ERROR("Sync is failed, err is %{public}d.", errCode); + return errCode; } + return E_OK; +} - auto conflictClause = SqliteUtils::GetConflictClause(static_cast(conflictResolution)); - if (conflictClause == nullptr) { - return E_INVALID_CONFLICT_FLAG; +Uri RdbStoreImpl::GetUri(const std::string &event) +{ + std::string rdbUri; + if (config_.GetDataGroupId().empty()) { + rdbUri = SCHEME_RDB + config_.GetBundleName() + "/" + path_ + "/" + event; + } else { + rdbUri = SCHEME_RDB + config_.GetDataGroupId() + "/" + path_ + "/" + event; } + return Uri(rdbUri); +} - std::string sql; - sql.append("INSERT").append(conflictClause).append(" INTO ").append(table).append("("); - size_t bindArgsSize = values.values_.size(); - std::vector bindArgs; - bindArgs.reserve(bindArgsSize); - const char *split = ""; - for (const auto &[key, val] : values.values_) { - sql.append(split).append(key); - if (val.GetType() == ValueObject::TYPE_ASSETS && - conflictResolution == ConflictResolution::ON_CONFLICT_REPLACE) { - return E_INVALID_ARGS; - } - if (val.GetType() == ValueObject::TYPE_ASSET || val.GetType() == ValueObject::TYPE_ASSETS) { - SetAssetStatus(val, AssetValue::STATUS_INSERT); +int RdbStoreImpl::SubscribeLocal(const SubscribeOption& option, RdbStoreObserver *observer) +{ + std::lock_guard lock(mutex_); + localObservers_.try_emplace(option.event); + auto &list = localObservers_.find(option.event)->second; + for (auto it = list.begin(); it != list.end(); it++) { + if ((*it)->getObserver() == observer) { + LOG_ERROR("duplicate subscribe."); + return E_OK; } - - bindArgs.push_back(val); // columnValue - split = ","; - } - - sql.append(") VALUES ("); - if (bindArgsSize > 0) { - sql.append(SqliteSqlBuilder::GetSqlArgs(bindArgsSize)); } - sql.append(")"); - auto errCode = ExecuteForLastInsertedRowId(outRowId, sql, bindArgs); - if (errCode != E_OK) { - return errCode; - } - DoCloudSync(table); + localObservers_[option.event].push_back(std::make_shared(observer)); return E_OK; } -void RdbStoreImpl::SetAssetStatus(const ValueObject &val, int32_t status) +int RdbStoreImpl::SubscribeLocalShared(const SubscribeOption& option, RdbStoreObserver *observer) { - if (val.GetType() == ValueObject::TYPE_ASSET) { - auto *asset = Traits::get_if(&val.value); - if (asset != nullptr) { - asset->status = static_cast(status); + std::lock_guard lock(mutex_); + localSharedObservers_.try_emplace(option.event); + auto &list = localSharedObservers_.find(option.event)->second; + for (auto it = list.begin(); it != list.end(); it++) { + if ((*it)->getObserver() == observer) { + LOG_ERROR("duplicate subscribe."); + return E_OK; } } - if (val.GetType() == ValueObject::TYPE_ASSETS) { - auto *assets = Traits::get_if(&val.value); - if (assets != nullptr) { - for (auto &asset : *assets) { - asset.status = static_cast(status); - } - } + + auto client = OHOS::AAFwk::DataObsMgrClient::GetInstance(); + if (client == nullptr) { + LOG_ERROR("Failed to get DataObsMgrClient."); + return E_GET_DATAOBSMGRCLIENT_FAIL; + } + sptr localSharedObserver(new (std::nothrow) RdbStoreLocalSharedObserver(observer)); + int32_t err = client->RegisterObserver(GetUri(option.event), localSharedObserver); + if (err != 0) { + LOG_ERROR("Subscribe failed."); + return err; } + localSharedObservers_[option.event].push_back(std::move(localSharedObserver)); + return E_OK; } -int RdbStoreImpl::Update(int &changedRows, const std::string &table, const ValuesBucket &values, - const std::string &whereClause, const std::vector &whereArgs) +int32_t RdbStoreImpl::SubscribeLocalDetail(const SubscribeOption &option, + const std::shared_ptr &observer) { - std::vector bindArgs; - std::for_each( - whereArgs.begin(), whereArgs.end(), [&bindArgs](const auto &it) { bindArgs.push_back(ValueObject(it)); }); - return UpdateWithConflictResolution( - changedRows, table, values, whereClause, bindArgs, ConflictResolution::ON_CONFLICT_NONE); + auto connection = connectionPool_->AcquireConnection(false); + if (connection == nullptr) { + return E_DATABASE_BUSY; + } + int32_t errCode = connection->Subscribe(option.event, observer); + if (errCode != E_OK) { + LOG_ERROR("subscribe local detail observer failed. db name:%{public}s errCode:%{public}" PRId32, + SqliteUtils::Anonymous(config_.GetName()).c_str(), errCode); + } + return errCode; } -int RdbStoreImpl::Update(int &changedRows, const std::string &table, const ValuesBucket &values, - const std::string &whereClause, const std::vector &bindArgs) +int RdbStoreImpl::SubscribeRemote(const SubscribeOption& option, RdbStoreObserver *observer) { - return UpdateWithConflictResolution( - changedRows, table, values, whereClause, bindArgs, ConflictResolution::ON_CONFLICT_NONE); + auto [errCode, service] = RdbMgr::GetInstance().GetRdbService(syncerParam_); + if (errCode != E_OK) { + return errCode; + } + return service->Subscribe(syncerParam_, option, observer); } -int RdbStoreImpl::Update(int &changedRows, const ValuesBucket &values, const AbsRdbPredicates &predicates) +int RdbStoreImpl::Subscribe(const SubscribeOption &option, RdbStoreObserver *observer) { - return Update( - changedRows, predicates.GetTableName(), values, predicates.GetWhereClause(), predicates.GetBindArgs()); + if (config_.GetDBType() == DB_VECTOR) { + return E_NOT_SUPPORT; + } + if (option.mode == SubscribeMode::LOCAL) { + return SubscribeLocal(option, observer); + } + if (option.mode == SubscribeMode::LOCAL_SHARED) { + return SubscribeLocalShared(option, observer); + } + return SubscribeRemote(option, observer); } -int RdbStoreImpl::UpdateWithConflictResolution(int &changedRows, const std::string &table, const ValuesBucket &values, - const std::string &whereClause, const std::vector &whereArgs, ConflictResolution conflictResolution) +int RdbStoreImpl::UnSubscribeLocal(const SubscribeOption& option, RdbStoreObserver *observer) { - std::vector bindArgs; - std::for_each( - whereArgs.begin(), whereArgs.end(), [&bindArgs](const auto &it) { bindArgs.push_back(ValueObject(it)); }); - return UpdateWithConflictResolutionEntry( - changedRows, table, values, whereClause, bindArgs, conflictResolution); + std::lock_guard lock(mutex_); + auto obs = localObservers_.find(option.event); + if (obs == localObservers_.end()) { + return E_OK; + } + + auto &list = obs->second; + for (auto it = list.begin(); it != list.end(); it++) { + if ((*it)->getObserver() == observer) { + it = list.erase(it); + break; + } + } + + if (list.empty()) { + localObservers_.erase(option.event); + } + return E_OK; } -int RdbStoreImpl::UpdateWithConflictResolution(int &changedRows, const std::string &table, const ValuesBucket &values, - const std::string &whereClause, const std::vector &bindArgs, ConflictResolution conflictResolution) +int RdbStoreImpl::UnSubscribeLocalAll(const SubscribeOption& option) { - SqlStatistic sqlStatistic("", SqlStatistic::Step::STEP_TOTAL); - return UpdateWithConflictResolutionEntry(changedRows, table, values, whereClause, bindArgs, conflictResolution); + std::lock_guard lock(mutex_); + auto obs = localObservers_.find(option.event); + if (obs == localObservers_.end()) { + return E_OK; + } + + localObservers_.erase(option.event); + return E_OK; } -int RdbStoreImpl::UpdateWithConflictResolutionEntry(int &changedRows, const std::string &table, - const ValuesBucket &values, const std::string &whereClause, const std::vector &bindArgs, - ConflictResolution conflictResolution) +int RdbStoreImpl::UnSubscribeLocalShared(const SubscribeOption& option, RdbStoreObserver *observer) { - SqlStatistic sqlStatistic("", SqlStatistic::Step::STEP_TOTAL); - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - if (isReadOnly_ || (config_.GetDBType() == DB_VECTOR)) { - return E_NOT_SUPPORT; + std::lock_guard lock(mutex_); + auto obs = localSharedObservers_.find(option.event); + if (obs == localSharedObservers_.end()) { + return E_OK; } - if (table.empty()) { - return E_EMPTY_TABLE_NAME; + + auto client = OHOS::AAFwk::DataObsMgrClient::GetInstance(); + if (client == nullptr) { + LOG_ERROR("Failed to get DataObsMgrClient."); + return E_GET_DATAOBSMGRCLIENT_FAIL; } - if (values.IsEmpty()) { - return E_EMPTY_VALUES_BUCKET; + auto &list = obs->second; + for (auto it = list.begin(); it != list.end(); it++) { + if ((*it)->getObserver() == observer) { + int32_t err = client->UnregisterObserver(GetUri(option.event), *it); + if (err != 0) { + LOG_ERROR("UnSubscribeLocalShared failed."); + return err; + } + list.erase(it); + break; + } + } + if (list.empty()) { + localSharedObservers_.erase(option.event); } + return E_OK; +} - auto clause = SqliteUtils::GetConflictClause(static_cast(conflictResolution)); - if (clause == nullptr) { - return E_INVALID_CONFLICT_FLAG; +int RdbStoreImpl::UnSubscribeLocalSharedAll(const SubscribeOption& option) +{ + std::lock_guard lock(mutex_); + auto obs = localSharedObservers_.find(option.event); + if (obs == localSharedObservers_.end()) { + return E_OK; } - std::string sql; - sql.append("UPDATE").append(clause).append(" ").append(table).append(" SET "); - std::vector tmpBindArgs; - size_t tmpBindSize = values.values_.size() + bindArgs.size(); - tmpBindArgs.reserve(tmpBindSize); - const char *split = ""; - for (auto &[key, val] : values.values_) { - sql.append(split); - if (val.GetType() == ValueObject::TYPE_ASSETS) { - sql.append(key).append("=merge_assets(").append(key).append(", ?)"); // columnName - } else if (val.GetType() == ValueObject::TYPE_ASSET) { - sql.append(key).append("=merge_asset(").append(key).append(", ?)"); // columnName - } else { - sql.append(key).append("=?"); // columnName - } - tmpBindArgs.push_back(val); // columnValue - split = ","; + auto client = OHOS::AAFwk::DataObsMgrClient::GetInstance(); + if (client == nullptr) { + LOG_ERROR("Failed to get DataObsMgrClient."); + return E_GET_DATAOBSMGRCLIENT_FAIL; } - if (!whereClause.empty()) { - sql.append(" WHERE ").append(whereClause); + auto &list = obs->second; + auto it = list.begin(); + while (it != list.end()) { + int32_t err = client->UnregisterObserver(GetUri(option.event), *it); + if (err != 0) { + LOG_ERROR("UnSubscribe failed."); + return err; + } + it = list.erase(it); } - tmpBindArgs.insert(tmpBindArgs.end(), bindArgs.begin(), bindArgs.end()); + localSharedObservers_.erase(option.event); + return E_OK; +} - int64_t changes = -1; - auto errCode = ExecuteForChangedRowCount(changes, sql, tmpBindArgs); +int32_t RdbStoreImpl::UnsubscribeLocalDetail(const SubscribeOption& option, + const std::shared_ptr &observer) +{ + auto connection = connectionPool_->AcquireConnection(false); + if (connection == nullptr) { + return E_DATABASE_BUSY; + } + int32_t errCode = connection->Unsubscribe(option.event, observer); if (errCode != E_OK) { - return errCode; + LOG_ERROR("unsubscribe local detail observer failed. db name:%{public}s errCode:%{public}" PRId32, + SqliteUtils::Anonymous(config_.GetName()).c_str(), errCode); } - changedRows = changes; - DoCloudSync(table); return errCode; } -int RdbStoreImpl::Delete(int &deletedRows, const AbsRdbPredicates &predicates) -{ - SqlStatistic sqlStatistic("", SqlStatistic::Step::STEP_TOTAL); - return Delete(deletedRows, predicates.GetTableName(), predicates.GetWhereClause(), predicates.GetBindArgs()); -} - -int RdbStoreImpl::Delete(int &deletedRows, const std::string &table, const std::string &whereClause, - const std::vector &whereArgs) +int RdbStoreImpl::UnSubscribeRemote(const SubscribeOption& option, RdbStoreObserver *observer) { - SqlStatistic sqlStatistic("", SqlStatistic::Step::STEP_TOTAL); - std::vector bindArgs; - std::for_each( - whereArgs.begin(), whereArgs.end(), [&bindArgs](const auto &it) { bindArgs.push_back(ValueObject(it)); }); - return Delete(deletedRows, table, whereClause, bindArgs); + auto [errCode, service] = RdbMgr::GetInstance().GetRdbService(syncerParam_); + if (errCode != E_OK) { + return errCode; + } + return service->UnSubscribe(syncerParam_, option, observer); } -int RdbStoreImpl::Delete(int &deletedRows, const std::string &table, const std::string &whereClause, - const std::vector &bindArgs) +int RdbStoreImpl::UnSubscribe(const SubscribeOption &option, RdbStoreObserver *observer) { - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - if (isReadOnly_ || (config_.GetDBType() == DB_VECTOR)) { + if (config_.GetDBType() == DB_VECTOR) { return E_NOT_SUPPORT; } - if (table.empty()) { - return E_EMPTY_TABLE_NAME; - } - - std::string sql; - sql.append("DELETE FROM ").append(table); - if (!whereClause.empty()) { - sql.append(" WHERE ").append(whereClause); - } - int64_t changes = -1; - auto errCode = ExecuteForChangedRowCount(changes, sql, bindArgs); - if (errCode != E_OK) { - return errCode; + if (option.mode == SubscribeMode::LOCAL && observer) { + return UnSubscribeLocal(option, observer); + } else if (option.mode == SubscribeMode::LOCAL && !observer) { + return UnSubscribeLocalAll(option); + } else if (option.mode == SubscribeMode::LOCAL_SHARED && observer) { + return UnSubscribeLocalShared(option, observer); + } else if (option.mode == SubscribeMode::LOCAL_SHARED && !observer) { + return UnSubscribeLocalSharedAll(option); } - deletedRows = changes; - DoCloudSync(table); - return E_OK; + return UnSubscribeRemote(option, observer); } -std::shared_ptr RdbStoreImpl::QueryByStep( - const AbsRdbPredicates &predicates, const std::vector &columns) +int RdbStoreImpl::SubscribeObserver(const SubscribeOption& option, const std::shared_ptr &observer) { - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - std::string sql; - if (predicates.HasSpecificField()) { - std::string table = predicates.GetTableName(); - std::string logTable = DistributedDB::RelationalStoreManager::GetDistributedLogTableName(table); - sql = SqliteSqlBuilder::BuildLockRowQueryString(predicates, columns, logTable); - } else { - sql = SqliteSqlBuilder::BuildQueryString(predicates, columns); + if (config_.GetDBType() == DB_VECTOR) { + return E_NOT_SUPPORT; } - return QueryByStep(sql, predicates.GetBindArgs()); + return SubscribeLocalDetail(option, observer); } -#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) -std::shared_ptr RdbStoreImpl::Query( - const AbsRdbPredicates &predicates, const std::vector &columns) +int RdbStoreImpl::UnsubscribeObserver(const SubscribeOption& option, const std::shared_ptr &observer) { - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); if (config_.GetDBType() == DB_VECTOR) { - return nullptr; - } - std::string sql; - std::pair queryStatus = { ColHasSpecificField(columns), predicates.HasSpecificField() }; - if (queryStatus.first || queryStatus.second) { - std::string table = predicates.GetTableName(); - std::string logTable = DistributedDB::RelationalStoreManager::GetDistributedLogTableName(table); - sql = SqliteSqlBuilder::BuildCursorQueryString(predicates, columns, logTable, queryStatus); - } else { - sql = SqliteSqlBuilder::BuildQueryString(predicates, columns); + return E_NOT_SUPPORT; } - return QuerySql(sql, predicates.GetBindArgs()); + return UnsubscribeLocalDetail(option, observer); } -std::pair> RdbStoreImpl::QuerySharingResource( - const AbsRdbPredicates &predicates, const std::vector &columns) +int RdbStoreImpl::Notify(const std::string &event) { if (config_.GetDBType() == DB_VECTOR) { - return { E_NOT_SUPPORT, nullptr }; + return E_NOT_SUPPORT; } - auto [errCode, service] = RdbMgr::GetInstance().GetRdbService(syncerParam_); - if (errCode != E_OK) { - return { errCode, nullptr }; + auto client = OHOS::AAFwk::DataObsMgrClient::GetInstance(); + if (client == nullptr) { + LOG_ERROR("Failed to get DataObsMgrClient."); + return E_GET_DATAOBSMGRCLIENT_FAIL; } - auto [status, resultSet] = - service->QuerySharingResource(syncerParam_, predicates.GetDistributedPredicates(), columns); - if (status != E_OK) { - return { status, nullptr }; + int32_t err = client->NotifyChange(GetUri(event)); + if (err != 0) { + LOG_ERROR("Notify failed."); } - return { status, resultSet }; -} -std::shared_ptr RdbStoreImpl::RemoteQuery(const std::string &device, - const AbsRdbPredicates &predicates, const std::vector &columns, int &errCode) -{ - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - if (config_.GetDBType() == DB_VECTOR) { - return nullptr; - } - std::vector selectionArgs = predicates.GetWhereArgs(); - std::string sql = SqliteSqlBuilder::BuildQueryString(predicates, columns); - auto [err, service] = RdbMgr::GetInstance().GetRdbService(syncerParam_); - if (err == E_NOT_SUPPORT) { - errCode = err; - return nullptr; - } - if (err != E_OK) { - LOG_ERROR("RdbStoreImpl::RemoteQuery get service failed"); - errCode = err; - return nullptr; + std::lock_guard lock(mutex_); + auto obs = localObservers_.find(event); + if (obs != localObservers_.end()) { + auto &list = obs->second; + for (auto &it : list) { + it->OnChange(); + } } - auto [status, resultSet] = service->RemoteQuery(syncerParam_, device, sql, selectionArgs); - errCode = status; - return resultSet; + return E_OK; } -std::shared_ptr RdbStoreImpl::Query(int &errCode, bool distinct, - const std::string &table, const std::vector &columns, - const std::string &whereClause, const std::vector &bindArgs, const std::string &groupBy, - const std::string &indexName, const std::string &orderBy, const int &limit, const int &offset) +int RdbStoreImpl::SetSearchable(bool isSearchable) { - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - std::string sql; - errCode = SqliteSqlBuilder::BuildQueryString( - distinct, table, "", columns, whereClause, groupBy, indexName, orderBy, limit, offset, sql); - if (errCode != E_OK) { - return nullptr; + auto [errCode, service] = RdbMgr::GetInstance().GetRdbService(syncerParam_); + if (errCode != E_OK || service == nullptr) { + LOG_ERROR("GetRdbService is failed, err is %{public}d.", errCode); + return errCode; } - - auto resultSet = QuerySql(sql, bindArgs); - return resultSet; + return service->SetSearchable(syncerParam_, isSearchable); } -std::shared_ptr RdbStoreImpl::QuerySql(const std::string &sql, - const std::vector &sqlArgs) +int RdbStoreImpl::RegisterAutoSyncCallback(std::shared_ptr observer) { - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); if (config_.GetDBType() == DB_VECTOR) { - return nullptr; + return E_NOT_SUPPORT; } - std::vector bindArgs; - std::for_each(sqlArgs.begin(), sqlArgs.end(), [&bindArgs](const auto &it) { bindArgs.push_back(ValueObject(it)); }); - return std::make_shared(connectionPool_, path_, sql, bindArgs); + auto [errCode, service] = RdbMgr::GetInstance().GetRdbService(syncerParam_); + if (errCode != E_OK) { + return errCode; + } + return service->RegisterAutoSyncCallback(syncerParam_, observer); } -std::shared_ptr RdbStoreImpl::QuerySql(const std::string &sql, - const std::vector &bindArgs) +int RdbStoreImpl::UnregisterAutoSyncCallback(std::shared_ptr observer) { - SqlStatistic sqlStatistic("", SqlStatistic::Step::STEP_TOTAL); - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); if (config_.GetDBType() == DB_VECTOR) { - return nullptr; + return E_NOT_SUPPORT; + } + auto [errCode, service] = RdbMgr::GetInstance().GetRdbService(syncerParam_); + if (errCode != E_OK) { + return errCode; } - return std::make_shared(connectionPool_, path_, sql, bindArgs); + return service->UnregisterAutoSyncCallback(syncerParam_, observer); } -void RdbStoreImpl::NotifyDataChange() +void RdbStoreImpl::InitDelayNotifier() { - int errCode = RegisterDataChangeCallback(); - if (errCode != E_OK) { - LOG_ERROR("RegisterDataChangeCallback is failed, err is %{public}d.", errCode); + if (delayNotifier_ == nullptr) { + delayNotifier_ = std::make_shared(); } - DistributedRdb::RdbChangedData rdbChangedData; - if (delayNotifier_ != nullptr) { - delayNotifier_->UpdateNotify(rdbChangedData, true); + if (delayNotifier_ == nullptr) { + LOG_ERROR("Init delay notifier failed."); + return; } + delayNotifier_->SetExecutorPool(TaskExecutor::GetInstance().GetExecutor()); + delayNotifier_->SetTask([param = syncerParam_] + (const DistributedRdb::RdbChangedData& rdbChangedData, const RdbNotifyConfig& rdbNotifyConfig) -> int { + auto [errCode, service] = RdbMgr::GetInstance().GetRdbService(param); + if (errCode == E_NOT_SUPPORT) { + return errCode; + } + if (errCode != E_OK || service == nullptr) { + LOG_ERROR("GetRdbService is failed, err is %{public}d.", errCode); + return errCode; + } + return service->NotifyDataChange(param, rdbChangedData, rdbNotifyConfig); + }); } -#endif -#if defined(WINDOWS_PLATFORM) || defined(MAC_PLATFORM) || defined(ANDROID_PLATFORM) || defined(IOS_PLATFORM) -std::shared_ptr RdbStoreImpl::Query( - const AbsRdbPredicates &predicates, const std::vector &columns) +int RdbStoreImpl::RegisterDataChangeCallback() { - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - LOG_DEBUG("RdbStoreImpl::Query on called."); - std::string sql = SqliteSqlBuilder::BuildQueryString(predicates, columns); - return QueryByStep(sql, predicates.GetBindArgs()); + if (!config_.IsSearchable()) { + return E_OK; + } + + if (isReadOnly_ || (config_.GetDBType() == DB_VECTOR)) { + return E_NOT_SUPPORT; + } + InitDelayNotifier(); + auto callBack = [delayNotifier = delayNotifier_](const std::set &tables) { + DistributedRdb::RdbChangedData rdbChangedData; + for (const auto& table : tables) { + rdbChangedData.tableData[table].isTrackedDataChange = true; + } + if (delayNotifier != nullptr) { + delayNotifier->UpdateNotify(rdbChangedData); + } + }; + auto connection = connectionPool_->AcquireConnection(false); + if (connection == nullptr) { + return E_DATABASE_BUSY; + } + return connection->SubscribeTableChanges(callBack); } -#endif -int RdbStoreImpl::Count(int64_t &outValue, const AbsRdbPredicates &predicates) +int RdbStoreImpl::GetHashKeyForLockRow(const AbsRdbPredicates &predicates, std::vector> &hashKeys) { - if (config_.GetDBType() == DB_VECTOR) { - return E_NOT_SUPPORT; + std::string table = predicates.GetTableName(); + if (table.empty()) { + return E_EMPTY_TABLE_NAME; } - std::string sql = SqliteSqlBuilder::BuildCountString(predicates); - return ExecuteAndGetLong(outValue, sql, predicates.GetBindArgs()); + auto logTable = GetLogTableName(table); + std::string sql; + sql.append("SELECT ").append(logTable).append(".hash_key ").append("FROM ").append(logTable); + sql.append(" INNER JOIN ").append(table).append(" ON "); + sql.append(table).append(".ROWID = ").append(logTable).append(".data_key"); + auto whereClause = predicates.GetWhereClause(); + if (!whereClause.empty()) { + SqliteUtils::Replace(whereClause, SqliteUtils::REP, logTable + "."); + sql.append(" WHERE ").append(whereClause); + } + + auto result = QuerySql(sql, predicates.GetBindArgs()); + if (result == nullptr) { + return E_ERROR; + } + int count = 0; + if (result->GetRowCount(count) != E_OK) { + return E_NO_ROW_IN_QUERY; + } + + if (count <= 0) { + return E_NO_ROW_IN_QUERY; + } + while (result->GoToNextRow() == E_OK) { + std::vector hashKey; + if (result->GetBlob(0, hashKey) != E_OK) { + return E_ERROR; + } + hashKeys.push_back(std::move(hashKey)); + } + return E_OK; } -int RdbStoreImpl::ExecuteSql(const std::string &sql, const std::vector &bindArgs) +int RdbStoreImpl::ModifyLockStatus(const AbsRdbPredicates &predicates, bool isLock) { - return ExecuteSqlEntry(sql, bindArgs); + std::vector> hashKeys; + int ret = GetHashKeyForLockRow(predicates, hashKeys); + if (ret != E_OK) { + LOG_ERROR("GetHashKeyForLockRow failed, err is %{public}d.", ret); + return ret; + } + auto [err, statement] = GetStatement(GlobalExpr::PRAGMA_VERSION); + if (statement == nullptr || err != E_OK) { + return err; + } + int errCode = statement->ModifyLockStatus(predicates.GetTableName(), hashKeys, isLock); + if (errCode == E_WAIT_COMPENSATED_SYNC) { + LOG_DEBUG("Start compensation sync."); + DistributedRdb::RdbService::Option option = { DistributedRdb::TIME_FIRST, 0, true, true, true }; + InnerSync(option, AbsRdbPredicates(predicates.GetTableName()).GetDistributedPredicates(), nullptr); + return E_OK; + } + if (errCode != E_OK) { + LOG_ERROR("ModifyLockStatus failed, err is %{public}d.", errCode); + } + return errCode; } -int RdbStoreImpl::ExecuteSqlEntry(const std::string &sql, const std::vector &bindArgs) +std::pair RdbStoreImpl::LockCloudContainer() { - SqlStatistic sqlStatistic("", SqlStatistic::Step::STEP_TOTAL); DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - if (config_.GetDBType() == DB_VECTOR || isReadOnly_) { - return E_NOT_SUPPORT; + RdbRadar ret(Scene::SCENE_SYNC, __FUNCTION__, config_.GetBundleName()); + auto [errCode, service] = RdbMgr::GetInstance().GetRdbService(syncerParam_); + if (errCode == E_NOT_SUPPORT) { + LOG_ERROR("not support"); + return { errCode, 0 }; } - int ret = CheckAttach(sql); - if (ret != E_OK) { - return ret; + if (errCode != E_OK) { + LOG_ERROR("GetRdbService is failed, err is %{public}d, bundleName is %{public}s.", errCode, + syncerParam_.bundleName_.c_str()); + return { errCode, 0 }; + } + auto result = service->LockCloudContainer(syncerParam_); + if (result.first != E_OK) { + LOG_ERROR("LockCloudContainer failed, err is %{public}d.", result.first); } + return result; +} - auto [errCode, statement] = BeginExecuteSql(sql); - if (statement == nullptr) { +int32_t RdbStoreImpl::UnlockCloudContainer() +{ + DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); + RdbRadar ret(Scene::SCENE_SYNC, __FUNCTION__, config_.GetBundleName()); + auto [errCode, service] = RdbMgr::GetInstance().GetRdbService(syncerParam_); + if (errCode == E_NOT_SUPPORT) { + LOG_ERROR("not support"); return errCode; } - errCode = statement->Execute(bindArgs); if (errCode != E_OK) { - LOG_ERROR("RDB_STORE Execute SQL ERROR."); + LOG_ERROR("GetRdbService is failed, err is %{public}d, bundleName is %{public}s.", errCode, + syncerParam_.bundleName_.c_str()); return errCode; } - int sqlType = SqliteUtils::GetSqlStatementType(sql); - if (sqlType == SqliteUtils::STATEMENT_DDL) { - statement->Reset(); - statement->Prepare("PRAGMA schema_version"); - auto [err, version] = statement->ExecuteForValue(); - statement = nullptr; - if (vSchema_ < static_cast(version)) { - LOG_INFO("db:%{public}s exe DDL schema<%{public}" PRIi64 "->%{public}" PRIi64 "> sql:%{public}s.", - SqliteUtils::Anonymous(name_).c_str(), vSchema_, static_cast(version), sql.c_str()); - vSchema_ = version; - errCode = connectionPool_->RestartReaders(); - } - } - statement = nullptr; - if (errCode == E_OK && (sqlType == SqliteUtils::STATEMENT_UPDATE || sqlType == SqliteUtils::STATEMENT_INSERT)) { - DoCloudSync(""); + errCode = service->UnlockCloudContainer(syncerParam_); + if (errCode != E_OK) { + LOG_ERROR("UnlockCloudContainer failed, err is %{public}d.", errCode); } return errCode; } +#endif -std::pair RdbStoreImpl::Execute(const std::string &sql, const std::vector &bindArgs, - int64_t trxId) +RdbStoreImpl::RdbStoreImpl(const RdbStoreConfig &config) + : isMemoryRdb_(config.IsMemoryRdb()), config_(config), name_(config.GetName()), + fileType_(config.GetDatabaseFileType()) { - return ExecuteEntry(sql, bindArgs, trxId); + path_ = (config.GetRoleType() == VISITOR) ? config.GetVisitorDir() : config.GetPath(); + isReadOnly_ = config.IsReadOnly() || config.GetRoleType() == VISITOR; } -std::pair RdbStoreImpl::HandleDifferentSqlTypes(std::shared_ptr statement, - const std::string &sql, const ValueObject &object, int sqlType) +RdbStoreImpl::RdbStoreImpl(const RdbStoreConfig &config, int &errCode) + : isMemoryRdb_(config.IsMemoryRdb()), config_(config), name_(config.GetName()), + fileType_(config.GetDatabaseFileType()) { - int32_t errCode = E_OK; - if (sqlType == SqliteUtils::STATEMENT_INSERT) { - int outValue = statement->Changes() > 0 ? statement->LastInsertRowId() : -1; - return { errCode, ValueObject(outValue) }; + isReadOnly_ = config.IsReadOnly() || config.GetRoleType() == VISITOR; + path_ = (config.GetRoleType() == VISITOR) ? 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 !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) + RdbParam param; + param.bundleName_ = config_.GetBundleName(); + param.storeName_ = config_.GetName(); + auto [err, service] = RdbMgr::GetInstance().GetRdbService(param); + if (service != nullptr) { + service->Disable(param); + } +#endif + config_.SetIter(0); + std::tie(rebuild_, connectionPool_) = ConnectionPool::HandleDataCorruption(config_, errCode); + created = true; +#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) + if (service != nullptr) { + service->Enable(param); + } +#endif + } + if (connectionPool_ == nullptr || errCode != E_OK) { + connectionPool_ = nullptr; + LOG_ERROR("Create connPool failed, err is %{public}d, path:%{public}s", errCode, + SqliteUtils::Anonymous(path_).c_str()); + return; } + InitSyncerParam(config_, created); + InnerOpen(); +} - if (sqlType == SqliteUtils::STATEMENT_UPDATE) { - int outValue = statement->Changes(); - return { errCode, ValueObject(outValue) }; +RdbStoreImpl::~RdbStoreImpl() +{ + connectionPool_ = nullptr; + trxConnMap_ = {}; + for (auto &trans : transactions_) { + auto realTrans = trans.lock(); + if (realTrans) { + (void)realTrans->Close(); + } } + transactions_ = {}; +} - if (sqlType == SqliteUtils::STATEMENT_PRAGMA) { - if (statement->GetColumnCount() == 1) { - return statement->GetColumn(0); +const RdbStoreConfig &RdbStoreImpl::GetConfig() +{ + return config_; +} + +std::pair RdbStoreImpl::Insert(const std::string &table, const Row &row, Resolution resolution) +{ + DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); + if (isReadOnly_ || (config_.GetDBType() == DB_VECTOR)) { + return { E_NOT_SUPPORT, -1 }; + } + if (table.empty()) { + return { E_EMPTY_TABLE_NAME, -1 }; + } + + if (row.IsEmpty()) { + return { E_EMPTY_VALUES_BUCKET, -1 }; + } + + auto conflictClause = SqliteUtils::GetConflictClause(static_cast(resolution)); + if (conflictClause == nullptr) { + return { E_INVALID_CONFLICT_FLAG, -1 }; + } + SqlStatistic sqlStatistic("", SqlStatistic::Step::STEP_TOTAL); + std::string sql; + sql.append("INSERT").append(conflictClause).append(" INTO ").append(table).append("("); + size_t bindArgsSize = row.values_.size(); + std::vector bindArgs; + bindArgs.reserve(bindArgsSize); + const char *split = ""; + for (const auto &[key, val] : row.values_) { + sql.append(split).append(key); + if (val.GetType() == ValueObject::TYPE_ASSETS && resolution == ConflictResolution::ON_CONFLICT_REPLACE) { + return { E_INVALID_ARGS, -1 }; } + SqliteSqlBuilder::UpdateAssetStatus(val, AssetValue::STATUS_INSERT); + bindArgs.push_back(val); // columnValue + split = ","; + } - if (statement->GetColumnCount() > 1) { - LOG_ERROR("Not support the sql:%{public}s, column count more than 1", sql.c_str()); - return { E_NOT_SUPPORT_THE_SQL, object }; + sql.append(") VALUES ("); + if (bindArgsSize > 0) { + sql.append(SqliteSqlBuilder::GetSqlArgs(bindArgsSize)); + } + + sql.append(")"); + int64_t rowid = -1; + auto errCode = ExecuteForLastInsertedRowId(rowid, sql, bindArgs); + if (errCode == E_OK) { + DoCloudSync(table); + } + + return { errCode, rowid }; +} + +std::pair RdbStoreImpl::BatchInsert(const std::string &table, const ValuesBuckets &rows) +{ + if (isReadOnly_ || (config_.GetDBType() == DB_VECTOR)) { + return { E_NOT_SUPPORT, -1 }; + } + + if (rows.RowSize() == 0) { + return { E_OK, 0 }; + } + + SqlStatistic sqlStatistic("", SqlStatistic::Step::STEP_TOTAL); + auto connection = connectionPool_->AcquireConnection(false); + if (connection == nullptr) { + return { E_DATABASE_BUSY, -1 }; + } + + auto executeSqlArgs = SqliteSqlBuilder::GenerateSqls(table, rows, connection->GetMaxVariable()); + if (executeSqlArgs.empty()) { + LOG_ERROR("empty, table=%{public}s, values:%{public}zu, max number:%{public}d.", table.c_str(), rows.RowSize(), + connection->GetMaxVariable()); + return { E_INVALID_ARGS, -1 }; + } +#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) + PauseDelayNotify pauseDelayNotify(delayNotifier_); +#endif + for (const auto &[sql, bindArgs] : executeSqlArgs) { + auto [errCode, statement] = GetStatement(sql, connection); + if (statement == nullptr) { + continue; + } + for (const auto &args : bindArgs) { + auto errCode = statement->Execute(args); + if (errCode != E_OK) { + LOG_ERROR("failed, errCode:%{public}d,args:%{public}zu,table:%{public}s,sql:%{public}s", errCode, + bindArgs.size(), table.c_str(), sql.c_str()); + return { E_OK, -1 }; + } + } + } + connection = nullptr; + DoCloudSync(table); + return { E_OK, int64_t(rows.RowSize()) }; +} + +std::pair RdbStoreImpl::Update(const std::string &table, const Row &row, const std::string &where, + const Values &args, Resolution resolution) +{ + DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); + if (isReadOnly_ || (config_.GetDBType() == DB_VECTOR)) { + return { E_NOT_SUPPORT, -1 }; + } + if (table.empty()) { + return { E_EMPTY_TABLE_NAME, -1 }; + } + + if (row.IsEmpty()) { + return { E_EMPTY_VALUES_BUCKET, -1 }; + } + + auto clause = SqliteUtils::GetConflictClause(static_cast(resolution)); + if (clause == nullptr) { + return { E_INVALID_CONFLICT_FLAG, -1 }; + } + SqlStatistic sqlStatistic("", SqlStatistic::Step::STEP_TOTAL); + std::string sql; + sql.append("UPDATE").append(clause).append(" ").append(table).append(" SET "); + std::vector tmpBindArgs; + size_t tmpBindSize = row.values_.size() + args.size(); + tmpBindArgs.reserve(tmpBindSize); + const char *split = ""; + for (auto &[key, val] : row.values_) { + sql.append(split); + if (val.GetType() == ValueObject::TYPE_ASSETS) { + sql.append(key).append("=merge_assets(").append(key).append(", ?)"); // columnName + } else if (val.GetType() == ValueObject::TYPE_ASSET) { + sql.append(key).append("=merge_asset(").append(key).append(", ?)"); // columnName + } else { + sql.append(key).append("=?"); // columnName } + tmpBindArgs.push_back(val); // columnValue + split = ","; + } + + if (!where.empty()) { + sql.append(" WHERE ").append(where); + } + + tmpBindArgs.insert(tmpBindArgs.end(), args.begin(), args.end()); + + int64_t changes = 0; + auto errCode = ExecuteForChangedRowCount(changes, sql, tmpBindArgs); + if (errCode == E_OK) { + DoCloudSync(table); + } + return { errCode, int32_t(changes) }; +} + +int RdbStoreImpl::Delete(int &deletedRows, const std::string &table, const std::string &whereClause, const Values &args) +{ + DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); + if (isReadOnly_ || (config_.GetDBType() == DB_VECTOR)) { + return E_NOT_SUPPORT; + } + if (table.empty()) { + return E_EMPTY_TABLE_NAME; + } + + SqlStatistic sqlStatistic("", SqlStatistic::Step::STEP_TOTAL); + std::string sql; + sql.append("DELETE FROM ").append(table); + if (!whereClause.empty()) { + sql.append(" WHERE ").append(whereClause); + } + int64_t changes = 0; + auto errCode = ExecuteForChangedRowCount(changes, sql, args); + if (errCode != E_OK) { + return errCode; + } + deletedRows = changes; + DoCloudSync(table); + return E_OK; +} + +std::shared_ptr RdbStoreImpl::QuerySql(const std::string &sql, const Values &bindArgs) +{ + DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); + if (config_.GetDBType() == DB_VECTOR) { + return nullptr; + } + SqlStatistic sqlStatistic("", SqlStatistic::Step::STEP_TOTAL); +#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) + auto start = std::chrono::steady_clock::now(); + return std::make_shared(start, connectionPool_->AcquireRef(true), sql, bindArgs, path_); +#else + (void)sql; + (void)bindArgs; + return nullptr; +#endif +} + +std::shared_ptr RdbStoreImpl::QueryByStep(const std::string &sql, const Values &args) +{ + SqlStatistic sqlStatistic("", SqlStatistic::Step::STEP_TOTAL); + auto start = std::chrono::steady_clock::now(); + return std::make_shared(start, connectionPool_->AcquireRef(true), sql, args); +} + +int RdbStoreImpl::Count(int64_t &outValue, const AbsRdbPredicates &predicates) +{ + if (config_.GetDBType() == DB_VECTOR) { + return E_NOT_SUPPORT; } + std::string sql = SqliteSqlBuilder::BuildCountString(predicates); + return ExecuteAndGetLong(outValue, sql, predicates.GetBindArgs()); +} +int RdbStoreImpl::ExecuteSql(const std::string &sql, const Values &args) +{ + DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); + if (config_.GetDBType() == DB_VECTOR || isReadOnly_) { + return E_NOT_SUPPORT; + } + int ret = CheckAttach(sql); + if (ret != E_OK) { + return ret; + } + SqlStatistic sqlStatistic("", SqlStatistic::Step::STEP_TOTAL); + auto [errCode, statement] = BeginExecuteSql(sql); + if (statement == nullptr) { + return errCode; + } + errCode = statement->Execute(args); + if (errCode != E_OK) { + LOG_ERROR("RDB_STORE Execute SQL ERROR."); + return errCode; + } + int sqlType = SqliteUtils::GetSqlStatementType(sql); if (sqlType == SqliteUtils::STATEMENT_DDL) { statement->Reset(); statement->Prepare("PRAGMA schema_version"); auto [err, version] = statement->ExecuteForValue(); + statement = nullptr; if (vSchema_ < static_cast(version)) { LOG_INFO("db:%{public}s exe DDL schema<%{public}" PRIi64 "->%{public}" PRIi64 "> sql:%{public}s.", - SqliteUtils::Anonymous(name_).c_str(), vSchema_, static_cast(version), sql.c_str()); + SqliteUtils::Anonymous(name_).c_str(), vSchema_, static_cast(version), sql.c_str()); vSchema_ = version; errCode = connectionPool_->RestartReaders(); } } - return { errCode, object }; + statement = nullptr; + if (errCode == E_OK && (sqlType == SqliteUtils::STATEMENT_UPDATE || sqlType == SqliteUtils::STATEMENT_INSERT)) { + DoCloudSync(""); + } + return errCode; } -std::pair RdbStoreImpl::ExecuteEntry(const std::string &sql, - const std::vector &bindArgs, int64_t trxId) +std::pair RdbStoreImpl::Execute(const std::string &sql, const Values &args, int64_t trxId) { ValueObject object; if (isReadOnly_) { @@ -924,7 +1193,7 @@ std::pair RdbStoreImpl::ExecuteEntry(const std::string &sq } if (config_.IsVector() && trxId > 0) { - return { ExecuteByTrxId(sql, trxId, false, bindArgs), ValueObject() }; + return { ExecuteByTrxId(sql, trxId, false, args), ValueObject() }; } auto connect = connectionPool_->AcquireConnection(false); @@ -937,7 +1206,7 @@ std::pair RdbStoreImpl::ExecuteEntry(const std::string &sq return { errCode, object }; } - errCode = statement->Execute(bindArgs); + errCode = statement->Execute(args); if (errCode != E_OK) { LOG_ERROR("execute sql failed, sql: %{public}s, error: %{public}d.", sql.c_str(), errCode); return { errCode, object }; @@ -950,62 +1219,114 @@ std::pair RdbStoreImpl::ExecuteEntry(const std::string &sq return HandleDifferentSqlTypes(statement, sql, object, sqlType); } -int RdbStoreImpl::ExecuteAndGetLong(int64_t &outValue, const std::string &sql, const std::vector &bindArgs) +std::pair RdbStoreImpl::HandleDifferentSqlTypes(std::shared_ptr statement, + const std::string &sql, const ValueObject &object, int sqlType) { - if (config_.GetDBType() == DB_VECTOR) { - return E_NOT_SUPPORT; - } - auto [errCode, statement] = BeginExecuteSql(sql); - if (statement == nullptr) { - return errCode; - } - auto [err, object] = statement->ExecuteForValue(bindArgs); - if (err != E_OK) { - LOG_ERROR("failed, sql %{public}s, ERROR is %{public}d.", sql.c_str(), errCode); + int32_t errCode = E_OK; + if (sqlType == SqliteUtils::STATEMENT_INSERT) { + int outValue = statement->Changes() > 0 ? statement->LastInsertRowId() : -1; + return { errCode, ValueObject(outValue) }; } - outValue = object; - return errCode; -} -int RdbStoreImpl::ExecuteAndGetString( - std::string &outValue, const std::string &sql, const std::vector &bindArgs) -{ - if (config_.GetDBType() == DB_VECTOR) { - return E_NOT_SUPPORT; - } - auto [errCode, statement] = BeginExecuteSql(sql); - if (statement == nullptr) { - return errCode; - } - ValueObject object; - std::tie(errCode, object) = statement->ExecuteForValue(bindArgs); - if (errCode != E_OK) { - LOG_ERROR("failed, sql %{public}s, ERROR is %{public}d.", sql.c_str(), errCode); + if (sqlType == SqliteUtils::STATEMENT_UPDATE) { + int outValue = statement->Changes(); + return { errCode, ValueObject(outValue) }; } - outValue = static_cast(object); - return errCode; -} -int RdbStoreImpl::ExecuteForLastInsertedRowId(int64_t &outValue, const std::string &sql, - const std::vector &bindArgs) + if (sqlType == SqliteUtils::STATEMENT_PRAGMA) { + if (statement->GetColumnCount() == 1) { + return statement->GetColumn(0); + } + + if (statement->GetColumnCount() > 1) { + LOG_ERROR("Not support the sql:%{public}s, column count more than 1", sql.c_str()); + return { E_NOT_SUPPORT_THE_SQL, object }; + } + } + + if (sqlType == SqliteUtils::STATEMENT_DDL) { + statement->Reset(); + statement->Prepare("PRAGMA schema_version"); + auto [err, version] = statement->ExecuteForValue(); + if (vSchema_ < static_cast(version)) { + LOG_INFO("db:%{public}s exe DDL schema<%{public}" PRIi64 "->%{public}" PRIi64 "> sql:%{public}s.", + SqliteUtils::Anonymous(name_).c_str(), vSchema_, static_cast(version), sql.c_str()); + vSchema_ = version; + errCode = connectionPool_->RestartReaders(); + } + } + return { errCode, object }; +} + +int RdbStoreImpl::ExecuteAndGetLong(int64_t &outValue, const std::string &sql, const Values &args) +{ + if (config_.GetDBType() == DB_VECTOR) { + return E_NOT_SUPPORT; + } + auto [errCode, statement] = BeginExecuteSql(sql); + if (statement == nullptr) { + return errCode; + } + auto [err, object] = statement->ExecuteForValue(args); + if (err != E_OK) { + LOG_ERROR("failed, sql %{public}s, ERROR is %{public}d.", sql.c_str(), errCode); + } + outValue = object; + return errCode; +} + +int RdbStoreImpl::ExecuteAndGetString(std::string &outValue, const std::string &sql, const Values &args) +{ + if (config_.GetDBType() == DB_VECTOR) { + return E_NOT_SUPPORT; + } + auto [errCode, statement] = BeginExecuteSql(sql); + if (statement == nullptr) { + return errCode; + } + ValueObject object; + std::tie(errCode, object) = statement->ExecuteForValue(args); + if (errCode != E_OK) { + LOG_ERROR("failed, sql %{public}s, ERROR is %{public}d.", sql.c_str(), errCode); + } + outValue = static_cast(object); + return errCode; +} + +int RdbStoreImpl::ExecuteForLastInsertedRowId(int64_t &outValue, const std::string &sql, const Values &args) { if (isReadOnly_ || (config_.GetDBType() == DB_VECTOR)) { return E_NOT_SUPPORT; } + auto begin = std::chrono::steady_clock::now(); auto [errCode, statement] = GetStatement(sql, false); if (statement == nullptr) { return errCode; } - errCode = statement->Execute(bindArgs); + auto beginExec = std::chrono::steady_clock::now(); + errCode = statement->Execute(args); if (errCode != E_OK) { return errCode; } + auto beginResult = std::chrono::steady_clock::now(); outValue = statement->Changes() > 0 ? statement->LastInsertRowId() : -1; + auto allEnd = std::chrono::steady_clock::now(); + int64_t totalCostTime = std::chrono::duration_cast(begin - allEnd).count(); + if (totalCostTime >= TIME_OUT) { + int64_t prepareCost = + std::chrono::duration_cast(beginExec - begin).count(); + int64_t execCost = + std::chrono::duration_cast(beginExec - beginResult).count(); + int64_t resultCost = std::chrono::duration_cast(allEnd - beginResult).count(); + LOG_WARN("total[%{public}" PRId64 "] stmt[%{public}" PRId64 "] exec[%{public}" PRId64 + "] result[%{public}" PRId64 "] " + "sql[%{public}s]", + totalCostTime, prepareCost, execCost, resultCost, SqliteUtils::Anonymous(sql).c_str()); + } return E_OK; } -int RdbStoreImpl::ExecuteForChangedRowCount(int64_t &outValue, const std::string &sql, - const std::vector &bindArgs) +int RdbStoreImpl::ExecuteForChangedRowCount(int64_t &outValue, const std::string &sql, const Values &args) { if (isReadOnly_ || (config_.GetDBType() == DB_VECTOR)) { return E_NOT_SUPPORT; @@ -1014,7 +1335,7 @@ int RdbStoreImpl::ExecuteForChangedRowCount(int64_t &outValue, const std::string if (statement == nullptr) { return errCode; } - errCode = statement->Execute(bindArgs); + errCode = statement->Execute(args); if (errCode != E_OK) { return errCode; } @@ -1066,7 +1387,7 @@ int RdbStoreImpl::GetSlaveName(const std::string &path, std::string &backupFileP /** * Backup a database from a specified encrypted or unencrypted database file. */ -int RdbStoreImpl::Backup(const std::string &databasePath, const std::vector &destEncryptKey) +int RdbStoreImpl::Backup(const std::string &databasePath, const std::vector &encryptKey) { LOG_INFO("Backup db: %{public}s.", SqliteUtils::Anonymous(config_.GetName()).c_str()); if (isReadOnly_) { @@ -1074,7 +1395,7 @@ int RdbStoreImpl::Backup(const std::string &databasePath, const std::vector RdbStoreImpl::CreateBackupBindArgs(const std::string &databasePath, + const std::vector &destEncryptKey) +{ + std::vector bindArgs; + bindArgs.emplace_back(databasePath); + if (!destEncryptKey.empty() && !config_.IsEncrypt()) { + bindArgs.emplace_back(destEncryptKey); + } else if (config_.IsEncrypt()) { + std::vector key = config_.GetEncryptKey(); + bindArgs.emplace_back(key); + key.assign(key.size(), 0); + } else { + bindArgs.emplace_back(""); + } + return bindArgs; +} + /** * Backup a database from a specified encrypted or unencrypted database file. */ @@ -1149,24 +1487,20 @@ int RdbStoreImpl::InnerBackup(const std::string &databasePath, const std::vector return conn == nullptr ? E_BASE : conn->Backup(databasePath, {}, false, slaveStatus_); } - auto [errCode, statement] = CreateWriteableStmt(GlobalExpr::CIPHER_DEFAULT_ATTACH_HMAC_ALGO); - if (errCode != E_OK || statement == nullptr) { - return errCode; + auto [result, conn] = CreateWritableConn(); + if (result != E_OK) { + return result; } - std::vector bindArgs; - bindArgs.emplace_back(databasePath); - if (!destEncryptKey.empty() && !config_.IsEncrypt()) { - bindArgs.emplace_back(destEncryptKey); - statement->Execute(); - } else if (config_.IsEncrypt()) { - std::vector key = config_.GetEncryptKey(); - bindArgs.emplace_back(key); - key.assign(key.size(), 0); - statement->Execute(); - } else { - bindArgs.emplace_back(""); + + if (config_.IsEncrypt()) { + result = SetDefaultEncryptAlgo(conn, config_); + if (result != E_OK) { + return result; + } } - errCode = statement->Prepare(GlobalExpr::ATTACH_BACKUP_SQL); + + std::vector bindArgs = CreateBackupBindArgs(databasePath, destEncryptKey); + auto [errCode, statement] = conn->CreateStatement(GlobalExpr::ATTACH_BACKUP_SQL, conn); errCode = statement->Execute(bindArgs); if (errCode != E_OK) { return errCode; @@ -1215,8 +1549,78 @@ bool RdbStoreImpl::IsHoldingConnection() return connectionPool_ != nullptr; } -int RdbStoreImpl::AttachInner( - const std::string &attachName, const std::string &dbPath, const std::vector &key, int32_t waitTime) +int RdbStoreImpl::SetDefaultEncryptSql( + const std::shared_ptr &statement, std::string sql, const RdbStoreConfig &config) +{ + auto errCode = statement->Prepare(sql); + if (errCode != E_OK) { + LOG_ERROR("Prepare failed: %{public}s, %{public}d, %{public}d, %{public}d, %{public}d, %{public}d", + SqliteUtils::Anonymous(config.GetName()).c_str(), config.GetCryptoParam().iterNum, + config.GetCryptoParam().encryptAlgo, config.GetCryptoParam().hmacAlgo, config.GetCryptoParam().kdfAlgo, + config.GetCryptoParam().cryptoPageSize); + return errCode; + } + errCode = statement->Execute(); + if (errCode != E_OK) { + LOG_ERROR("Execute failed: %{public}s, %{public}d, %{public}d, %{public}d, %{public}d, %{public}d", + SqliteUtils::Anonymous(config.GetName()).c_str(), config.GetCryptoParam().iterNum, + config.GetCryptoParam().encryptAlgo, config.GetCryptoParam().hmacAlgo, config.GetCryptoParam().kdfAlgo, + config.GetCryptoParam().cryptoPageSize); + return errCode; + } + return E_OK; +} + +int RdbStoreImpl::SetDefaultEncryptAlgo(const ConnectionPool::SharedConn &conn, const RdbStoreConfig &config) +{ + if (conn == nullptr) { + return E_DATABASE_BUSY; + } + + if (!config.GetCryptoParam().IsValid()) { + LOG_ERROR("Invalid crypto param, name:%{public}s", SqliteUtils::Anonymous(config.GetName()).c_str()); + return E_INVALID_ARGS; + } + + std::string sql = std::string(GlobalExpr::CIPHER_DEFAULT_ATTACH_CIPHER_PREFIX) + + SqliteUtils::EncryptAlgoDescription(config.GetEncryptAlgo()) + + std::string(GlobalExpr::ALGO_SUFFIX); + auto [errCode, statement] = conn->CreateStatement(sql, conn); + errCode = SetDefaultEncryptSql(statement, sql, config); + if (errCode != E_OK) { + return errCode; + } + + if (config.GetIter() > 0) { + sql = std::string(GlobalExpr::CIPHER_DEFAULT_ATTACH_KDF_ITER_PREFIX) + std::to_string(config.GetIter()); + errCode = SetDefaultEncryptSql(statement, sql, config); + if (errCode != E_OK) { + return errCode; + } + } + + sql = std::string(GlobalExpr::CIPHER_DEFAULT_ATTACH_HMAC_ALGO_PREFIX) + + SqliteUtils::HmacAlgoDescription(config.GetCryptoParam().hmacAlgo) + std::string(GlobalExpr::ALGO_SUFFIX); + errCode = SetDefaultEncryptSql(statement, sql, config); + if (errCode != E_OK) { + return errCode; + } + + sql = std::string(GlobalExpr::CIPHER_DEFAULT_ATTACH_KDF_ALGO_PREFIX) + + SqliteUtils::KdfAlgoDescription(config.GetCryptoParam().kdfAlgo) + + std::string(GlobalExpr::ALGO_SUFFIX); + errCode = SetDefaultEncryptSql(statement, sql, config); + if (errCode != E_OK) { + return errCode; + } + + sql = std::string(GlobalExpr::CIPHER_DEFAULT_ATTACH_PAGE_SIZE_PREFIX) + + std::to_string(config.GetCryptoParam().cryptoPageSize); + return SetDefaultEncryptSql(statement, sql, config); +} + +int RdbStoreImpl::AttachInner(const RdbStoreConfig &config, const std::string &attachName, const std::string &dbPath, + const std::vector &key, int32_t waitTime) { auto [conn, readers] = connectionPool_->AcquireAll(waitTime); if (conn == nullptr) { @@ -1239,14 +1643,12 @@ int RdbStoreImpl::AttachInner( bindArgs.emplace_back(ValueObject(dbPath)); bindArgs.emplace_back(ValueObject(attachName)); if (!key.empty()) { - auto [errCode, statement] = conn->CreateStatement(GlobalExpr::CIPHER_DEFAULT_ATTACH_HMAC_ALGO, conn); - if (statement == nullptr) { - LOG_ERROR("Attach get statement failed, code is %{public}d", errCode); - return errCode; + auto ret = SetDefaultEncryptAlgo(conn, config); + if (ret != E_OK) { + return ret; } - errCode = statement->Execute(); bindArgs.emplace_back(ValueObject(key)); - std::tie(errCode, statement) = conn->CreateStatement(GlobalExpr::ATTACH_WITH_KEY_SQL, conn); + auto [errCode, statement] = conn->CreateStatement(GlobalExpr::ATTACH_WITH_KEY_SQL, conn); if (statement == nullptr || errCode != E_OK) { LOG_ERROR("Attach get statement failed, code is %{public}d", errCode); return E_ERROR; @@ -1287,15 +1689,11 @@ std::pair RdbStoreImpl::Attach( } std::vector key; -#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) + config.Initialize(); if (config.IsEncrypt()) { - RdbPassword rdbPwd = - RdbSecurityManager::GetInstance().GetRdbPassword(dbPath, RdbSecurityManager::KeyFileType::PUB_KEY_FILE); - key = std::vector(rdbPwd.GetData(), rdbPwd.GetData() + rdbPwd.GetSize()); - rdbPwd.Clear(); + key = config.GetEncryptKey(); } -#endif - err = AttachInner(attachName, dbPath, key, waitTime); + err = AttachInner(config, attachName, dbPath, key, waitTime); key.assign(key.size(), 0); if (err == E_SQLITE_ERROR) { // only when attachName is already in use, SQLITE-ERROR will be reported here. @@ -1377,7 +1775,7 @@ int RdbStoreImpl::GetVersion(int &version) */ int RdbStoreImpl::SetVersion(int version) { - if ((config_.GetRoleType() == VISITOR) || isReadOnly_) { + if (isReadOnly_) { return E_NOT_SUPPORT; } std::string sql = std::string(GlobalExpr::PRAGMA_VERSION) + " = " + std::to_string(version); @@ -1429,12 +1827,11 @@ std::pair RdbStoreImpl::BeginTrans() return {E_NOT_SUPPORT, 0}; } - auto time = static_cast(duration_cast(system_clock::now().time_since_epoch()).count()); int64_t tmpTrxId = 0; - auto [errCode, connection] = connectionPool_->CreateConnection(false); + auto [errCode, connection] = connectionPool_->CreateTransConn(false); if (connection == nullptr) { - LOG_ERROR("Get null connection, storeName: %{public}s time:%{public}" PRIu64 ".", - SqliteUtils::Anonymous(name_).c_str(), time); + LOG_ERROR("Get null connection, storeName: %{public}s errCode:0x%{public}x.", + SqliteUtils::Anonymous(name_).c_str(), errCode); return {errCode, 0}; } tmpTrxId = newTrxId_.fetch_add(1); @@ -1562,6 +1959,9 @@ int RdbStoreImpl::Commit() } auto [errCode, statement] = GetStatement(sqlStr); if (statement == nullptr) { + if (errCode == E_DATABASE_BUSY || errCode == E_SQLITE_BUSY || E_SQLITE_LOCKED) { + Reportor::Report(Reportor::Create(config_, E_DATABASE_BUSY, "ErrorType: Busy")); + } LOG_ERROR("id: %{public}zu, storeName: %{public}s, statement error", transactionId, SqliteUtils::Anonymous(name_).c_str()); return E_DATABASE_BUSY; @@ -1655,770 +2055,161 @@ bool RdbStoreImpl::IsMemoryRdb() const return isMemoryRdb_; } -std::string RdbStoreImpl::GetName() -{ - return name_; -} - -void RdbStoreImpl::DoCloudSync(const std::string &table) -{ -#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) - { - std::shared_lock lock(rwMutex_); - if (cloudTables_.empty() || (!table.empty() && cloudTables_.find(table) == cloudTables_.end())) { - return; - } - } - { - std::lock_guard lock(mutex_); - if (syncTables_ == nullptr) { - syncTables_ = std::make_shared>(); - } - auto empty = syncTables_->empty(); - if (table.empty()) { - syncTables_->insert(cloudTables_.begin(), cloudTables_.end()); - } else { - syncTables_->insert(table); - } - if (!empty) { - return; - } - } - auto pool = TaskExecutor::GetInstance().GetExecutor(); - if (pool == nullptr) { - return; - } - auto interval = - std::chrono::duration_cast(std::chrono::milliseconds(INTERVAL)); - pool->Schedule(interval, [this]() { - std::shared_ptr> ptr; - { - std::lock_guard lock(mutex_); - ptr = syncTables_; - syncTables_ = nullptr; - } - if (ptr == nullptr) { - return; - } - DistributedRdb::RdbService::Option option = { DistributedRdb::TIME_FIRST, 0, true, true }; - InnerSync(option, - AbsRdbPredicates(std::vector(ptr->begin(), ptr->end())).GetDistributedPredicates(), nullptr); - }); -#endif -} -std::string RdbStoreImpl::GetFileType() -{ - return fileType_; -} - -/** - * Sets the database locale. - */ -int RdbStoreImpl::ConfigLocale(const std::string &localeStr) -{ - if (!isOpen_) { - LOG_ERROR("The connection pool has been closed."); - return E_ERROR; - } - - if (connectionPool_ == nullptr) { - LOG_ERROR("connectionPool_ is null."); - return E_ERROR; - } - return connectionPool_->ConfigLocale(localeStr); -} - -int RdbStoreImpl::GetDestPath(const std::string &backupPath, std::string &destPath) -{ - int ret = GetDataBasePath(backupPath, destPath); - if (ret != E_OK) { - return ret; - } - std::string tempPath = destPath + ".tmp"; - if (access(tempPath.c_str(), F_OK) == E_OK) { - destPath = tempPath; - } else { - auto walFile = destPath + "-wal"; - if (access(walFile.c_str(), F_OK) == E_OK) { - return E_ERROR; - } - } - - if (access(destPath.c_str(), F_OK) != E_OK) { - LOG_ERROR("The backupFilePath does not exists."); - return E_INVALID_FILE_PATH; - } - return E_OK; -} - -int RdbStoreImpl::Restore(const std::string &backupPath, const std::vector &newKey) -{ - LOG_INFO("Restore db: %{public}s.", SqliteUtils::Anonymous(config_.GetName()).c_str()); - if (isReadOnly_) { - return E_NOT_SUPPORT; - } - - if (!isOpen_ || connectionPool_ == nullptr) { - LOG_ERROR("The connection pool is created: %{public}d, pool is null: %{public}d", isOpen_, - connectionPool_ == nullptr); - return E_ERROR; - } - - std::string destPath; - if (!TryGetMasterSlaveBackupPath(backupPath, destPath, true)) { - int ret = GetDestPath(backupPath, destPath); - if (ret != E_OK) { - return ret; - } - } -#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) - auto [err, service] = RdbMgr::GetInstance().GetRdbService(syncerParam_); - if (service != nullptr) { - service->Disable(syncerParam_); - } -#endif - int errCode = connectionPool_->ChangeDbFileForRestore(path_, destPath, newKey, slaveStatus_); -#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) - NotifyDataChange(); - SecurityPolicy::SetSecurityLabel(config_); - if (service != nullptr) { - service->Enable(syncerParam_); - if (errCode == E_OK) { - auto syncerParam = syncerParam_; - syncerParam.infos_ = Connection::Collect(config_); - service->AfterOpen(syncerParam); - } - } -#endif - if (errCode == E_OK) { - RdbFaultHiViewReporter::ReportRestore(RdbFaultHiViewReporter::Create(config_, E_OK)); - rebuild_ = RebuiltType::NONE; - } - if (!cloudTables_.empty()) { - DoCloudSync(""); - } - return errCode; -} - -/** - * Queries data in the database based on specified conditions. - */ -std::shared_ptr RdbStoreImpl::QueryByStep(const std::string &sql, - const std::vector &sqlArgs) -{ - SqlStatistic sqlStatistic("", SqlStatistic::Step::STEP_TOTAL); - std::vector bindArgs; - std::for_each(sqlArgs.begin(), sqlArgs.end(), [&bindArgs](const auto &it) { bindArgs.push_back(ValueObject(it)); }); - return std::make_shared(connectionPool_, sql, bindArgs); -} - -std::shared_ptr RdbStoreImpl::QueryByStep(const std::string &sql, const std::vector &args) -{ - SqlStatistic sqlStatistic("", SqlStatistic::Step::STEP_TOTAL); - return std::make_shared(connectionPool_, sql, args); -} - -#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) -int RdbStoreImpl::SetDistributedTables(const std::vector &tables, int32_t type, - const DistributedRdb::DistributedConfig &distributedConfig) -{ - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - if (config_.GetDBType() == DB_VECTOR || isReadOnly_) { - return E_NOT_SUPPORT; - } - if (tables.empty()) { - LOG_WARN("The distributed tables to be set is empty."); - return E_OK; - } - auto [errCode, service] = RdbMgr::GetInstance().GetRdbService(syncerParam_); - if (errCode != E_OK) { - return errCode; - } - int32_t errorCode = service->SetDistributedTables(syncerParam_, tables, distributedConfig.references, type); - if (errorCode != E_OK) { - LOG_ERROR("Fail to set distributed tables, error=%{public}d", errorCode); - return errorCode; - } - if (type == DistributedRdb::DISTRIBUTED_CLOUD) { - auto conn = connectionPool_->AcquireConnection(false); - if (conn != nullptr) { - auto strategy = conn->GenerateExchangeStrategy(slaveStatus_); - if (strategy == ExchangeStrategy::BACKUP) { - (void)conn->Backup({}, {}, false, slaveStatus_); - } - } - } - if (type != DistributedRdb::DISTRIBUTED_CLOUD || !distributedConfig.autoSync) { - return E_OK; - } - { - std::unique_lock lock(rwMutex_); - cloudTables_.insert(tables.begin(), tables.end()); - } - auto isRebuilt = RebuiltType::NONE; - GetRebuilt(isRebuilt); - if (isRebuilt == RebuiltType::REBUILT) { - DoCloudSync(""); - } - return E_OK; -} - -std::string RdbStoreImpl::ObtainDistributedTableName(const std::string &device, const std::string &table, int &errCode) -{ - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - if (config_.GetDBType() == DB_VECTOR) { - return ""; - } - std::string uuid; - DeviceManagerAdaptor::RdbDeviceManagerAdaptor &deviceManager = - DeviceManagerAdaptor::RdbDeviceManagerAdaptor::GetInstance(syncerParam_.bundleName_); - errCode = deviceManager.GetEncryptedUuidByNetworkId(device, uuid); - if (errCode != E_OK) { - LOG_ERROR("GetUuid is failed."); - return ""; - } - - auto translateCall = [uuid](const std::string &oriDevId, const DistributedDB::StoreInfo &info) { - return uuid; - }; - DistributedDB::RuntimeConfig::SetTranslateToDeviceIdCallback(translateCall); - - return DistributedDB::RelationalStoreManager::GetDistributedTableName(uuid, table); -} - -int RdbStoreImpl::Sync(const SyncOption &option, const AbsRdbPredicates &predicate, const AsyncBrief &callback) -{ - if (config_.GetDBType() == DB_VECTOR) { - return E_NOT_SUPPORT; - } - return Sync(option, predicate, [callback](Details &&details) { - Briefs briefs; - for (auto &[key, value] : details) { - briefs.insert_or_assign(key, value.code); - } - if (callback != nullptr) { - callback(briefs); - } - }); -} - -int RdbStoreImpl::Sync(const SyncOption &option, const std::vector &tables, const AsyncDetail &async) -{ - return Sync(option, AbsRdbPredicates(tables), async); -} - -int RdbStoreImpl::Sync(const SyncOption &option, const AbsRdbPredicates &predicate, const AsyncDetail &async) -{ - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - DistributedRdb::RdbService::Option rdbOption; - rdbOption.mode = option.mode; - rdbOption.isAsync = !option.isBlock; - RdbRadar ret(Scene::SCENE_SYNC, __FUNCTION__, config_.GetBundleName()); - ret = InnerSync(rdbOption, predicate.GetDistributedPredicates(), async); - return ret; -} - -int RdbStoreImpl::InnerSync(const DistributedRdb::RdbService::Option &option, - const DistributedRdb::PredicatesMemo &predicates, const RdbStore::AsyncDetail &async) -{ - auto [errCode, service] = RdbMgr::GetInstance().GetRdbService(syncerParam_); - if (errCode == E_NOT_SUPPORT) { - return errCode; - } - if (errCode != E_OK) { - LOG_ERROR("GetRdbService is failed, err is %{public}d, bundleName is %{public}s.", - errCode, syncerParam_.bundleName_.c_str()); - return errCode; - } - errCode = service->Sync(syncerParam_, option, predicates, async); - if (errCode != E_OK) { - LOG_ERROR("Sync is failed, err is %{public}d.", errCode); - return errCode; - } - return E_OK; -} - -Uri RdbStoreImpl::GetUri(const std::string &event) -{ - std::string rdbUri; - if (config_.GetDataGroupId().empty()) { - rdbUri = SCHEME_RDB + config_.GetBundleName() + "/" + path_ + "/" + event; - } else { - rdbUri = SCHEME_RDB + config_.GetDataGroupId() + "/" + path_ + "/" + event; - } - return Uri(rdbUri); -} - -int RdbStoreImpl::SubscribeLocal(const SubscribeOption& option, RdbStoreObserver *observer) -{ - std::lock_guard lock(mutex_); - localObservers_.try_emplace(option.event); - auto &list = localObservers_.find(option.event)->second; - for (auto it = list.begin(); it != list.end(); it++) { - if ((*it)->getObserver() == observer) { - LOG_ERROR("duplicate subscribe."); - return E_OK; - } - } - - localObservers_[option.event].push_back(std::make_shared(observer)); - return E_OK; -} - -int RdbStoreImpl::SubscribeLocalShared(const SubscribeOption& option, RdbStoreObserver *observer) -{ - std::lock_guard lock(mutex_); - localSharedObservers_.try_emplace(option.event); - auto &list = localSharedObservers_.find(option.event)->second; - for (auto it = list.begin(); it != list.end(); it++) { - if ((*it)->getObserver() == observer) { - LOG_ERROR("duplicate subscribe."); - return E_OK; - } - } - - auto client = OHOS::AAFwk::DataObsMgrClient::GetInstance(); - if (client == nullptr) { - LOG_ERROR("Failed to get DataObsMgrClient."); - return E_GET_DATAOBSMGRCLIENT_FAIL; - } - sptr localSharedObserver(new (std::nothrow) RdbStoreLocalSharedObserver(observer)); - int32_t err = client->RegisterObserver(GetUri(option.event), localSharedObserver); - if (err != 0) { - LOG_ERROR("Subscribe failed."); - return err; - } - localSharedObservers_[option.event].push_back(std::move(localSharedObserver)); - return E_OK; -} - -int32_t RdbStoreImpl::SubscribeLocalDetail(const SubscribeOption &option, - const std::shared_ptr &observer) -{ - auto connection = connectionPool_->AcquireConnection(false); - if (connection == nullptr) { - return E_DATABASE_BUSY; - } - int32_t errCode = connection->Subscribe(option.event, observer); - if (errCode != E_OK) { - LOG_ERROR("subscribe local detail observer failed. db name:%{public}s errCode:%{public}" PRId32, - SqliteUtils::Anonymous(config_.GetName()).c_str(), errCode); - } - return errCode; -} - -int RdbStoreImpl::SubscribeRemote(const SubscribeOption& option, RdbStoreObserver *observer) -{ - auto [errCode, service] = RdbMgr::GetInstance().GetRdbService(syncerParam_); - if (errCode != E_OK) { - return errCode; - } - return service->Subscribe(syncerParam_, option, observer); -} - -int RdbStoreImpl::Subscribe(const SubscribeOption &option, RdbStoreObserver *observer) -{ - if (config_.GetDBType() == DB_VECTOR) { - return E_NOT_SUPPORT; - } - if (option.mode == SubscribeMode::LOCAL) { - return SubscribeLocal(option, observer); - } - if (option.mode == SubscribeMode::LOCAL_SHARED) { - return SubscribeLocalShared(option, observer); - } - return SubscribeRemote(option, observer); -} - -int RdbStoreImpl::UnSubscribeLocal(const SubscribeOption& option, RdbStoreObserver *observer) -{ - std::lock_guard lock(mutex_); - auto obs = localObservers_.find(option.event); - if (obs == localObservers_.end()) { - return E_OK; - } - - auto &list = obs->second; - for (auto it = list.begin(); it != list.end(); it++) { - if ((*it)->getObserver() == observer) { - it = list.erase(it); - break; - } - } - - if (list.empty()) { - localObservers_.erase(option.event); - } - return E_OK; -} - -int RdbStoreImpl::UnSubscribeLocalAll(const SubscribeOption& option) -{ - std::lock_guard lock(mutex_); - auto obs = localObservers_.find(option.event); - if (obs == localObservers_.end()) { - return E_OK; - } - - localObservers_.erase(option.event); - return E_OK; -} - -int RdbStoreImpl::UnSubscribeLocalShared(const SubscribeOption& option, RdbStoreObserver *observer) -{ - std::lock_guard lock(mutex_); - auto obs = localSharedObservers_.find(option.event); - if (obs == localSharedObservers_.end()) { - return E_OK; - } - - auto client = OHOS::AAFwk::DataObsMgrClient::GetInstance(); - if (client == nullptr) { - LOG_ERROR("Failed to get DataObsMgrClient."); - return E_GET_DATAOBSMGRCLIENT_FAIL; - } - - auto &list = obs->second; - for (auto it = list.begin(); it != list.end(); it++) { - if ((*it)->getObserver() == observer) { - int32_t err = client->UnregisterObserver(GetUri(option.event), *it); - if (err != 0) { - LOG_ERROR("UnSubscribeLocalShared failed."); - return err; - } - list.erase(it); - break; - } - } - if (list.empty()) { - localSharedObservers_.erase(option.event); - } - return E_OK; -} - -int RdbStoreImpl::UnSubscribeLocalSharedAll(const SubscribeOption& option) -{ - std::lock_guard lock(mutex_); - auto obs = localSharedObservers_.find(option.event); - if (obs == localSharedObservers_.end()) { - return E_OK; - } - - auto client = OHOS::AAFwk::DataObsMgrClient::GetInstance(); - if (client == nullptr) { - LOG_ERROR("Failed to get DataObsMgrClient."); - return E_GET_DATAOBSMGRCLIENT_FAIL; - } - - auto &list = obs->second; - auto it = list.begin(); - while (it != list.end()) { - int32_t err = client->UnregisterObserver(GetUri(option.event), *it); - if (err != 0) { - LOG_ERROR("UnSubscribe failed."); - return err; - } - it = list.erase(it); - } - - localSharedObservers_.erase(option.event); - return E_OK; -} - -int32_t RdbStoreImpl::UnsubscribeLocalDetail(const SubscribeOption& option, - const std::shared_ptr &observer) -{ - auto connection = connectionPool_->AcquireConnection(false); - if (connection == nullptr) { - return E_DATABASE_BUSY; - } - int32_t errCode = connection->Unsubscribe(option.event, observer); - if (errCode != E_OK) { - LOG_ERROR("unsubscribe local detail observer failed. db name:%{public}s errCode:%{public}" PRId32, - SqliteUtils::Anonymous(config_.GetName()).c_str(), errCode); - } - return errCode; -} - -int RdbStoreImpl::UnSubscribeRemote(const SubscribeOption& option, RdbStoreObserver *observer) -{ - auto [errCode, service] = RdbMgr::GetInstance().GetRdbService(syncerParam_); - if (errCode != E_OK) { - return errCode; - } - return service->UnSubscribe(syncerParam_, option, observer); -} - -int RdbStoreImpl::UnSubscribe(const SubscribeOption &option, RdbStoreObserver *observer) -{ - if (config_.GetDBType() == DB_VECTOR) { - return E_NOT_SUPPORT; - } - if (option.mode == SubscribeMode::LOCAL && observer) { - return UnSubscribeLocal(option, observer); - } else if (option.mode == SubscribeMode::LOCAL && !observer) { - return UnSubscribeLocalAll(option); - } else if (option.mode == SubscribeMode::LOCAL_SHARED && observer) { - return UnSubscribeLocalShared(option, observer); - } else if (option.mode == SubscribeMode::LOCAL_SHARED && !observer) { - return UnSubscribeLocalSharedAll(option); - } - return UnSubscribeRemote(option, observer); -} - -int RdbStoreImpl::SubscribeObserver(const SubscribeOption& option, const std::shared_ptr &observer) -{ - if (config_.GetDBType() == DB_VECTOR) { - return E_NOT_SUPPORT; - } - return SubscribeLocalDetail(option, observer); -} - -int RdbStoreImpl::UnsubscribeObserver(const SubscribeOption& option, const std::shared_ptr &observer) -{ - if (config_.GetDBType() == DB_VECTOR) { - return E_NOT_SUPPORT; - } - return UnsubscribeLocalDetail(option, observer); -} - -int RdbStoreImpl::Notify(const std::string &event) -{ - if (config_.GetDBType() == DB_VECTOR) { - return E_NOT_SUPPORT; - } - auto client = OHOS::AAFwk::DataObsMgrClient::GetInstance(); - if (client == nullptr) { - LOG_ERROR("Failed to get DataObsMgrClient."); - return E_GET_DATAOBSMGRCLIENT_FAIL; - } - int32_t err = client->NotifyChange(GetUri(event)); - if (err != 0) { - LOG_ERROR("Notify failed."); - } - - std::lock_guard lock(mutex_); - auto obs = localObservers_.find(event); - if (obs != localObservers_.end()) { - auto &list = obs->second; - for (auto &it : list) { - it->OnChange(); - } - } - return E_OK; -} - -int RdbStoreImpl::SetSearchable(bool isSearchable) -{ - auto [errCode, service] = RdbMgr::GetInstance().GetRdbService(syncerParam_); - if (errCode != E_OK || service == nullptr) { - LOG_ERROR("GetRdbService is failed, err is %{public}d.", errCode); - return errCode; - } - return service->SetSearchable(syncerParam_, isSearchable); -} - -int RdbStoreImpl::RegisterAutoSyncCallback(std::shared_ptr observer) -{ - if (config_.GetDBType() == DB_VECTOR) { - return E_NOT_SUPPORT; - } - auto [errCode, service] = RdbMgr::GetInstance().GetRdbService(syncerParam_); - if (errCode != E_OK) { - return errCode; - } - return service->RegisterAutoSyncCallback(syncerParam_, observer); -} - -int RdbStoreImpl::UnregisterAutoSyncCallback(std::shared_ptr observer) +std::string RdbStoreImpl::GetName() { - if (config_.GetDBType() == DB_VECTOR) { - return E_NOT_SUPPORT; - } - auto [errCode, service] = RdbMgr::GetInstance().GetRdbService(syncerParam_); - if (errCode != E_OK) { - return errCode; - } - return service->UnregisterAutoSyncCallback(syncerParam_, observer); + return name_; } -void RdbStoreImpl::InitDelayNotifier() +void RdbStoreImpl::DoCloudSync(const std::string &table) { - if (delayNotifier_ == nullptr) { - delayNotifier_ = std::make_shared(); - } - if (delayNotifier_ == nullptr) { - LOG_ERROR("Init delay notifier failed."); - return; +#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) + { + std::shared_lock lock(rwMutex_); + if (cloudTables_.empty() || (!table.empty() && cloudTables_.find(table) == cloudTables_.end())) { + return; + } } - delayNotifier_->SetExecutorPool(TaskExecutor::GetInstance().GetExecutor()); - delayNotifier_->SetTask([param = syncerParam_] - (const DistributedRdb::RdbChangedData& rdbChangedData, const RdbNotifyConfig& rdbNotifyConfig) -> int { - auto [errCode, service] = RdbMgr::GetInstance().GetRdbService(param); - if (errCode == E_NOT_SUPPORT) { - return errCode; + { + std::lock_guard lock(mutex_); + if (syncTables_ == nullptr) { + syncTables_ = std::make_shared>(); } - if (errCode != E_OK || service == nullptr) { - LOG_ERROR("GetRdbService is failed, err is %{public}d.", errCode); - return errCode; + auto empty = syncTables_->empty(); + if (table.empty()) { + syncTables_->insert(cloudTables_.begin(), cloudTables_.end()); + } else { + syncTables_->insert(table); + } + if (!empty) { + return; } - return service->NotifyDataChange(param, rdbChangedData, rdbNotifyConfig); - }); -} - -int RdbStoreImpl::RegisterDataChangeCallback() -{ - if (!config_.IsSearchable()) { - return E_OK; } - - if (isReadOnly_ || (config_.GetDBType() == DB_VECTOR)) { - return E_NOT_SUPPORT; + auto pool = TaskExecutor::GetInstance().GetExecutor(); + if (pool == nullptr) { + return; } - InitDelayNotifier(); - auto callBack = [delayNotifier = delayNotifier_](const std::set &tables) { - DistributedRdb::RdbChangedData rdbChangedData; - for (const auto& table : tables) { - rdbChangedData.tableData[table].isTrackedDataChange = true; + auto interval = + std::chrono::duration_cast(std::chrono::milliseconds(INTERVAL)); + pool->Schedule(interval, [this]() { + std::shared_ptr> ptr; + { + std::lock_guard lock(mutex_); + ptr = syncTables_; + syncTables_ = nullptr; } - if (delayNotifier != nullptr) { - delayNotifier->UpdateNotify(rdbChangedData); + if (ptr == nullptr) { + return; } - }; - auto connection = connectionPool_->AcquireConnection(false); - if (connection == nullptr) { - return E_DATABASE_BUSY; - } - return connection->SubscribeTableChanges(callBack); + DistributedRdb::RdbService::Option option = { DistributedRdb::TIME_FIRST, 0, true, true }; + InnerSync(option, + AbsRdbPredicates(std::vector(ptr->begin(), ptr->end())).GetDistributedPredicates(), nullptr); + }); +#endif } - -bool RdbStoreImpl::ColHasSpecificField(const std::vector &columns) +std::string RdbStoreImpl::GetFileType() { - for (const std::string &column : columns) { - if (column.find(SqliteUtils::REP) != std::string::npos) { - return true; - } - } - return false; + return fileType_; } -int RdbStoreImpl::GetHashKeyForLockRow(const AbsRdbPredicates &predicates, std::vector> &hashKeys) +/** + * Sets the database locale. + */ +int RdbStoreImpl::ConfigLocale(const std::string &localeStr) { - std::string table = predicates.GetTableName(); - if (table.empty()) { - return E_EMPTY_TABLE_NAME; - } - auto logTable = DistributedDB::RelationalStoreManager::GetDistributedLogTableName(table); - std::string sql; - sql.append("SELECT ").append(logTable).append(".hash_key ").append("FROM ").append(logTable); - sql.append(" INNER JOIN ").append(table).append(" ON "); - sql.append(table).append(".ROWID = ").append(logTable).append(".data_key"); - auto whereClause = predicates.GetWhereClause(); - if (!whereClause.empty()) { - SqliteUtils::Replace(whereClause, SqliteUtils::REP, logTable + "."); - sql.append(" WHERE ").append(whereClause); - } - - auto result = QuerySql(sql, predicates.GetBindArgs()); - if (result == nullptr) { + if (!isOpen_) { + LOG_ERROR("The connection pool has been closed."); return E_ERROR; } - int count = 0; - if (result->GetRowCount(count) != E_OK) { - return E_NO_ROW_IN_QUERY; - } - if (count <= 0) { - return E_NO_ROW_IN_QUERY; - } - while (result->GoToNextRow() == E_OK) { - std::vector hashKey; - if (result->GetBlob(0, hashKey) != E_OK) { - return E_ERROR; - } - hashKeys.push_back(std::move(hashKey)); + if (connectionPool_ == nullptr) { + LOG_ERROR("connectionPool_ is null."); + return E_ERROR; } - return E_OK; + return connectionPool_->ConfigLocale(localeStr); } -int RdbStoreImpl::ModifyLockStatus(const AbsRdbPredicates &predicates, bool isLock) +int RdbStoreImpl::GetDestPath(const std::string &backupPath, std::string &destPath) { - std::vector> hashKeys; - int ret = GetHashKeyForLockRow(predicates, hashKeys); + int ret = GetDataBasePath(backupPath, destPath); if (ret != E_OK) { - LOG_ERROR("GetHashKeyForLockRow failed, err is %{public}d.", ret); return ret; } - auto [err, statement] = GetStatement(GlobalExpr::PRAGMA_VERSION); - if (statement == nullptr || err != E_OK) { - return err; - } - int errCode = statement->ModifyLockStatus(predicates.GetTableName(), hashKeys, isLock); - if (errCode == E_WAIT_COMPENSATED_SYNC) { - LOG_DEBUG("Start compensation sync."); - DistributedRdb::RdbService::Option option = { DistributedRdb::TIME_FIRST, 0, true, true, true }; - InnerSync(option, AbsRdbPredicates(predicates.GetTableName()).GetDistributedPredicates(), nullptr); - return E_OK; + std::string tempPath = destPath + ".tmp"; + if (access(tempPath.c_str(), F_OK) == E_OK) { + destPath = tempPath; + } else { + auto walFile = destPath + "-wal"; + if (access(walFile.c_str(), F_OK) == E_OK) { + return E_ERROR; + } } - if (errCode != E_OK) { - LOG_ERROR("ModifyLockStatus failed, err is %{public}d.", errCode); + + if (access(destPath.c_str(), F_OK) != E_OK) { + LOG_ERROR("The backupFilePath does not exists."); + return E_INVALID_FILE_PATH; } - return errCode; + return E_OK; } -std::pair RdbStoreImpl::LockCloudContainer() +int RdbStoreImpl::Restore(const std::string &backupPath, const std::vector &newKey) { - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - RdbRadar ret(Scene::SCENE_SYNC, __FUNCTION__, config_.GetBundleName()); - auto [errCode, service] = RdbMgr::GetInstance().GetRdbService(syncerParam_); - if (errCode == E_NOT_SUPPORT) { - LOG_ERROR("not support"); - return { errCode, 0 }; - } - if (errCode != E_OK) { - LOG_ERROR("GetRdbService is failed, err is %{public}d, bundleName is %{public}s.", errCode, - syncerParam_.bundleName_.c_str()); - return { errCode, 0 }; + LOG_INFO("Restore db: %{public}s.", SqliteUtils::Anonymous(config_.GetName()).c_str()); + if (isReadOnly_) { + return E_NOT_SUPPORT; } - auto result = service->LockCloudContainer(syncerParam_); - if (result.first != E_OK) { - LOG_ERROR("LockCloudContainer failed, err is %{public}d.", result.first); + + if (!isOpen_ || connectionPool_ == nullptr) { + LOG_ERROR("The connection pool is created: %{public}d, pool is null: %{public}d", isOpen_, + connectionPool_ == nullptr); + return E_ERROR; } - return result; -} -int32_t RdbStoreImpl::UnlockCloudContainer() -{ - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - RdbRadar ret(Scene::SCENE_SYNC, __FUNCTION__, config_.GetBundleName()); - auto [errCode, service] = RdbMgr::GetInstance().GetRdbService(syncerParam_); - if (errCode == E_NOT_SUPPORT) { - LOG_ERROR("not support"); - return errCode; + std::string destPath; + if (!TryGetMasterSlaveBackupPath(backupPath, destPath, true)) { + int ret = GetDestPath(backupPath, destPath); + if (ret != E_OK) { + return ret; + } } - if (errCode != E_OK) { - LOG_ERROR("GetRdbService is failed, err is %{public}d, bundleName is %{public}s.", errCode, - syncerParam_.bundleName_.c_str()); - return errCode; +#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) + auto [err, service] = RdbMgr::GetInstance().GetRdbService(syncerParam_); + if (service != nullptr) { + service->Disable(syncerParam_); } - errCode = service->UnlockCloudContainer(syncerParam_); - if (errCode != E_OK) { - LOG_ERROR("UnlockCloudContainer failed, err is %{public}d.", errCode); +#endif + int errCode = connectionPool_->ChangeDbFileForRestore(path_, destPath, newKey, slaveStatus_); +#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) + NotifyDataChange(); + SecurityPolicy::SetSecurityLabel(config_); + if (service != nullptr) { + service->Enable(syncerParam_); + if (errCode == E_OK) { + auto syncerParam = syncerParam_; + syncerParam.infos_ = Connection::Collect(config_); + service->AfterOpen(syncerParam); + } + } +#endif + if (errCode == E_OK) { + Reportor::ReportRestore(Reportor::Create(config_, E_OK)); + rebuild_ = RebuiltType::NONE; + } + if (!cloudTables_.empty()) { + DoCloudSync(""); } return errCode; } -#endif -std::pair> RdbStoreImpl::CreateWriteableStmt(const std::string &sql) +std::pair> RdbStoreImpl::CreateWritableConn() { auto config = config_; config.SetHaMode(HAMode::SINGLE); - auto [errCode, conn] = Connection::Create(config, true); - if (errCode != E_OK || conn == nullptr) { - LOG_ERROR("create connection failed, err:%{public}d", errCode); - return { errCode, nullptr }; + auto [result, conn] = Connection::Create(config, true); + if (result != E_OK || conn == nullptr) { + LOG_ERROR("create connection failed, err:%{public}d", result); + return { result, nullptr }; } - return conn->CreateStatement(sql, conn); + return { E_OK, conn }; } std::pair> RdbStoreImpl::GetStatement( @@ -2454,7 +2245,7 @@ int RdbStoreImpl::InterruptBackup() slaveStatus_ = SlaveStatus::BACKUP_INTERRUPT; return E_OK; } - return E_INVALID_INTERRUPT; + return E_CANCEL; } int32_t RdbStoreImpl::GetBackupStatus() const @@ -2513,4 +2304,33 @@ int32_t RdbStoreImpl::ExchangeSlaverToMaster() } return ret; } + +int32_t RdbStoreImpl::GetDbType() const +{ + return config_.GetDBType(); +} + +std::pair> RdbStoreImpl::CreateTransaction(int32_t type) +{ + auto [errCode, conn] = connectionPool_->CreateTransConn(); + if (conn == nullptr) { + return { errCode, nullptr }; + } + std::shared_ptr trans; + std::tie(errCode, trans) = Transaction::Create(type, conn, config_.GetName()); + if (trans == nullptr) { + return { errCode, nullptr }; + } + + std::lock_guard guard(mutex_); + for (auto it = transactions_.begin(); it != transactions_.end();) { + if (it->expired()) { + it = transactions_.erase(it); + } else { + it++; + } + } + transactions_.push_back(trans); + return { errCode, trans }; +} } // namespace OHOS::NativeRdb \ No newline at end of file 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 7a069b479dc8a28bf454e2b771373a8e46f6e8de..c1cb34977992cf7410c761daa0074772a86c815b 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_store_manager.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_store_manager.cpp @@ -40,8 +40,10 @@ namespace OHOS { namespace NativeRdb { using namespace OHOS::Rdb; +using Reportor = RdbFaultHiViewReporter; __attribute__((used)) const bool RdbStoreManager::regCollector_ = RdbFaultHiViewReporter::RegCollector(RdbStoreManager::Collector); +constexpr int RETRY_INTERVAL = 1; RdbStoreManager &RdbStoreManager::GetInstance() { static RdbStoreManager manager; @@ -57,17 +59,8 @@ RdbStoreManager::RdbStoreManager() : configCache_(BUCKET_MAX_SIZE) { } -std::shared_ptr RdbStoreManager::GetRdbStore(const RdbStoreConfig &config, - int &errCode, int version, RdbOpenCallback &openCallback) +std::shared_ptr RdbStoreManager::GetStoreFromCache(const RdbStoreConfig &config, const std::string &path) { - if (config.IsVector() && config.GetStorageMode() == StorageMode::MODE_MEMORY) { - LOG_ERROR("GetRdbStore type not support memory mode."); - return nullptr; - } - // 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(); - bundleName_ = config.GetBundleName(); if (storeCache_.find(path) != storeCache_.end()) { std::shared_ptr rdbStore = storeCache_[path].lock(); if (rdbStore != nullptr && rdbStore->GetConfig() == config) { @@ -75,9 +68,43 @@ std::shared_ptr RdbStoreManager::GetRdbStore(const RdbStoreConfig &con } // TOD reconfigure store should be repeated this 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; +} - std::shared_ptr rdbStore = std::make_shared(config, errCode); +std::shared_ptr RdbStoreManager::GetRdbStore( + const RdbStoreConfig &config, int &errCode, int version, RdbOpenCallback &openCallback) +{ + if (config.IsVector() && config.GetStorageMode() == StorageMode::MODE_MEMORY) { + LOG_ERROR("GetRdbStore type not support memory mode."); + return nullptr; + } + // 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); + if (rdbStore != nullptr) { + return rdbStore; + } + rdbStore = std::make_shared(config, errCode); if (errCode != E_OK) { LOG_ERROR("RdbStoreManager GetRdbStore fail to open RdbStore as memory issue, rc=%{public}d", errCode); return nullptr; @@ -98,8 +125,8 @@ std::shared_ptr RdbStoreManager::GetRdbStore(const RdbStoreConfig &con errCode = ProcessOpenCallback(*rdbStore, config, 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(config.GetName()).c_str(), SqliteUtils::Anonymous(config.GetPath()).c_str(), + errCode); return nullptr; } } diff --git a/relational_store/frameworks/native/rdb/src/sqlite_connection.cpp b/relational_store/frameworks/native/rdb/src/sqlite_connection.cpp index e06f41c89889632da97442144d20be419448c907..e64a12e1cb94c56dcfc53f3ea613318f38075f7d 100644 --- a/relational_store/frameworks/native/rdb/src/sqlite_connection.cpp +++ b/relational_store/frameworks/native/rdb/src/sqlite_connection.cpp @@ -54,6 +54,7 @@ namespace NativeRdb { using namespace OHOS::Rdb; using namespace std::chrono; using RdbKeyFile = RdbSecurityManager::KeyFileType; +using Reportor = RdbFaultHiViewReporter; constexpr const char *INTEGRITIES[] = {nullptr, "PRAGMA quick_check", "PRAGMA integrity_check"}; constexpr SqliteConnection::Suffix SqliteConnection::FILE_SUFFIXES[]; constexpr const char *SqliteConnection::MERGE_ASSETS_FUNC; @@ -61,7 +62,9 @@ constexpr const char *SqliteConnection::MERGE_ASSET_FUNC; 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 uint32_t SqliteConnection::NO_ITER; +constexpr uint32_t SqliteConnection::WAL_INDEX; __attribute__((used)) const int32_t SqliteConnection::regCreator_ = Connection::RegisterCreator(DB_SQLITE, SqliteConnection::Create); __attribute__((used)) @@ -127,29 +130,43 @@ SqliteConnection::SqliteConnection(const RdbStoreConfig &config, bool isWriteCon : dbHandle_(nullptr), isWriter_(isWriteConnection), isReadOnly_(false), maxVariableNumber_(0), filePath(""), config_(config) { + backupId_ = TaskExecutor::INVALID_TASK_ID; } -int SqliteConnection::CreateSlaveConnection(const RdbStoreConfig &config, bool isWrite, bool checkSlaveExist) +int SqliteConnection::CreateSlaveConnection(const RdbStoreConfig &config, bool checkSlaveExist) { if (config.GetHaMode() != HAMode::MAIN_REPLICA && config.GetHaMode() != HAMode::MANUAL_TRIGGER) { return E_OK; } + std::map bugInfo = Connection::Collect(config); bool isSlaveExist = access(config.GetPath().c_str(), F_OK) == 0; bool isSlaveLockExist = SqliteUtils::TryAccessSlaveLock(config_.GetPath(), false, false); - if (config.GetHaMode() == HAMode::MANUAL_TRIGGER && (checkSlaveExist && (!isSlaveExist || isSlaveLockExist))) { - LOG_INFO("not dual write on manual, slave:%{public}d, lock:%{public}d", - isSlaveExist, isSlaveLockExist); + bool hasFailure = SqliteUtils::TryAccessSlaveLock(config_.GetPath(), false, false, true); + 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 " + "%{public}s,[%{public}d,%{public}d,%{public}d,%{public}d]", + config.GetDBType(), config.GetHaMode(), config.IsEncrypt(), config.GetArea(), config.GetSecurityLevel(), + config.GetRoleType(), config.IsReadOnly(), + 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 (walOverLimit) { + SqliteUtils::TryAccessSlaveLock(config_.GetPath(), false, true, true); + } return E_OK; } - slaveConnection_ = std::make_shared(config, isWrite); - int errCode = slaveConnection_->InnerOpen(config); + std::shared_ptr connection = std::make_shared(config, true); + int errCode = connection->InnerOpen(config); if (errCode != E_OK) { SqliteUtils::TryAccessSlaveLock(config_.GetPath(), false, true, true); if (errCode == E_SQLITE_CORRUPT) { LOG_WARN("slave corrupt, rebuild:%{public}s", SqliteUtils::Anonymous(config.GetPath()).c_str()); (void)Delete(config); - errCode = slaveConnection_->InnerOpen(config); + errCode = connection->InnerOpen(config); if (errCode != E_OK) { LOG_ERROR("reopen slave failed:%{public}d", errCode); return errCode; @@ -157,8 +174,10 @@ int SqliteConnection::CreateSlaveConnection(const RdbStoreConfig &config, bool i } else { LOG_WARN("open slave failed:%{public}d, %{public}s", errCode, SqliteUtils::Anonymous(config.GetPath()).c_str()); + return errCode; } } + slaveConnection_ = connection; return errCode; } @@ -177,22 +196,20 @@ RdbStoreConfig SqliteConnection::GetSlaveRdbStoreConfig(const RdbStoreConfig &rd rdbStoreConfig.SetReadOnly(rdbConfig.IsReadOnly()); rdbStoreConfig.SetAutoCheck(rdbConfig.IsAutoCheck()); rdbStoreConfig.SetCreateNecessary(rdbConfig.IsCreateNecessary()); - rdbStoreConfig.SetIter(rdbConfig.GetIter()); rdbStoreConfig.SetJournalSize(rdbConfig.GetJournalSize()); rdbStoreConfig.SetPageSize(rdbConfig.GetPageSize()); rdbStoreConfig.SetReadConSize(rdbConfig.GetReadConSize()); rdbStoreConfig.SetReadTime(rdbConfig.GetReadTime()); rdbStoreConfig.SetDBType(rdbConfig.GetDBType()); rdbStoreConfig.SetVisitorDir(rdbConfig.GetVisitorDir()); - rdbStoreConfig.SetEncryptKey(rdbConfig.GetEncryptKey()); - rdbStoreConfig.SetNewEncryptKey(rdbConfig.GetNewEncryptKey()); rdbStoreConfig.SetScalarFunctions(rdbConfig.GetScalarFunctions()); rdbStoreConfig.SetJournalMode(rdbConfig.GetJournalMode()); rdbStoreConfig.SetModuleName(rdbConfig.GetModuleName()); - rdbStoreConfig.SetArea(rdbConfig.GetArea()); rdbStoreConfig.SetPluginLibs(rdbConfig.GetPluginLibs()); rdbStoreConfig.SetHaMode(rdbConfig.GetHaMode()); + + rdbStoreConfig.SetCryptoParam(rdbConfig.GetCryptoParam()); return rdbStoreConfig; } @@ -227,17 +244,7 @@ int SqliteConnection::InnerOpen(const RdbStoreConfig &config) } if (isWriter_) { - struct stat fileInfo; - if (stat(dbPath.c_str(), &fileInfo) == 0) { - LOG_INFO("open database path [%{public}s] ino[%{public}" PRIu32 - "] config is [%{public}d, %{public}d, %{public}d, %{public}d, %{public}s, %{public}s, %{public}d," - "%{public}d, %{public}d]", - SqliteUtils::Anonymous(dbPath).c_str(), static_cast(fileInfo.st_ino), config.IsEncrypt(), - config.GetArea(), config.GetHaMode(), config.GetSecurityLevel(), - SqliteUtils::Anonymous(config.GetName()).c_str(), config.GetBundleName().c_str(), config.GetRoleType(), - config.IsReadOnly(), config.GetDBType()); - } - TryCheckPoint(); + TryCheckPoint(true); ValueObject checkResult{"ok"}; auto index = static_cast(config.GetIntegrityCheck()); if (index < static_cast(sizeof(INTEGRITIES) / sizeof(INTEGRITIES[0]))) { @@ -250,12 +257,7 @@ int SqliteConnection::InnerOpen(const RdbStoreConfig &config) LOG_ERROR("%{public}s integrity check result is %{public}s, sql:%{public}s", SqliteUtils::Anonymous(config.GetName()).c_str(), static_cast(checkResult).c_str(), sql); - RdbFaultHiViewReporter::ReportFault( - RdbFaultHiViewReporter::Create(config, errCode, static_cast(checkResult))); - } else { - LOG_DEBUG("%{public}s integrity check err:%{public}d, result is %{public}s, sql:%{public}s", - SqliteUtils::Anonymous(config.GetName()).c_str(), errCode, - static_cast(checkResult).c_str(), sql); + Reportor::ReportFault(Reportor::Create(config, errCode, static_cast(checkResult))); } } } @@ -517,28 +519,55 @@ int SqliteConnection::SetPageSize(const RdbStoreConfig &config) return errCode; } -int SqliteConnection::SetEncryptAgo(int32_t iter) +int SqliteConnection::SetEncryptAgo(const RdbStoreConfig &config) { - int errCode = E_ERROR; - if (iter != NO_ITER) { - errCode = ExecuteSql(GlobalExpr::CIPHER_DEFAULT_ALGO); + if (!config.GetCryptoParam().IsValid()) { + LOG_ERROR("Invalid crypto param: %{public}s, %{public}d, %{public}d, %{public}d, %{public}d, %{public}d", + SqliteUtils::Anonymous(config.GetName()).c_str(), config.GetCryptoParam().iterNum, + config.GetCryptoParam().encryptAlgo, config.GetCryptoParam().hmacAlgo, config.GetCryptoParam().kdfAlgo, + config.GetCryptoParam().cryptoPageSize); + return E_INVALID_ARGS; + } + + if (config.GetIter() != NO_ITER) { + auto errCode = ExecuteSql(std::string(GlobalExpr::CIPHER_ALGO_PREFIX) + + SqliteUtils::EncryptAlgoDescription(config.GetEncryptAlgo()) + + std::string(GlobalExpr::ALGO_SUFFIX)); if (errCode != E_OK) { LOG_ERROR("set cipher algo failed, err = %{public}d", errCode); return errCode; } - errCode = ExecuteSql(std::string(GlobalExpr::CIPHER_KDF_ITER) + std::to_string(iter)); + + errCode = ExecuteSql(std::string(GlobalExpr::CIPHER_KDF_ITER) + std::to_string(config.GetIter())); if (errCode != E_OK) { LOG_ERROR("set kdf iter number V1 failed, err = %{public}d", errCode); return errCode; } } - errCode = ExecuteSql(GlobalExpr::CODEC_HMAC_ALGO); + auto errCode = ExecuteSql(std::string(GlobalExpr::CODEC_HMAC_ALGO_PREFIX) + + SqliteUtils::HmacAlgoDescription(config.GetCryptoParam().hmacAlgo) + + std::string(GlobalExpr::ALGO_SUFFIX)); if (errCode != E_OK) { LOG_ERROR("set codec hmac algo failed, err = %{public}d", errCode); return errCode; } + errCode = ExecuteSql(std::string(GlobalExpr::CODEC_KDF_ALGO_PREFIX) + + SqliteUtils::KdfAlgoDescription(config.GetCryptoParam().kdfAlgo) + + std::string(GlobalExpr::ALGO_SUFFIX)); + if (errCode != E_OK) { + LOG_ERROR("set codec kdf algo failed, err = %{public}d", errCode); + return errCode; + } + + errCode = ExecuteSql( + std::string(GlobalExpr::CODEC_PAGE_SIZE_PREFIX) + std::to_string(config.GetCryptoParam().cryptoPageSize)); + if (errCode != E_OK) { + LOG_ERROR("set codec page size failed, err = %{public}d", errCode); + return errCode; + } + errCode = ExecuteSql(GlobalExpr::CODEC_REKEY_HMAC_ALGO); if (errCode != E_OK) { LOG_ERROR("set rekey sha algo failed, err = %{public}d", errCode); @@ -574,13 +603,13 @@ int SqliteConnection::SetEncrypt(const RdbStoreConfig &config) std::vector key = config.GetEncryptKey(); std::vector newKey = config.GetNewEncryptKey(); - auto errCode = SetEncryptKey(key, config.GetIter()); + auto errCode = SetEncryptKey(key, config); key.assign(key.size(), 0); if (errCode != E_OK) { if (!newKey.empty()) { LOG_INFO("use new key, iter=%{public}d err=%{public}d errno=%{public}d name=%{public}s", config.GetIter(), errCode, errno, SqliteUtils::Anonymous(config.GetName()).c_str()); - errCode = SetEncryptKey(newKey, config.GetIter()); + errCode = SetEncryptKey(newKey, config); } newKey.assign(newKey.size(), 0); if (errCode != E_OK) { @@ -600,7 +629,7 @@ int SqliteConnection::SetEncrypt(const RdbStoreConfig &config) return E_OK; } -int SqliteConnection::SetEncryptKey(const std::vector &key, int32_t iter) +int SqliteConnection::SetEncryptKey(const std::vector &key, const RdbStoreConfig &config) { if (key.empty()) { return E_INVALID_ARGS; @@ -611,7 +640,7 @@ int SqliteConnection::SetEncryptKey(const std::vector &key, int32_t ite return SQLiteError::ErrNo(errCode); } - errCode = SetEncryptAgo(iter); + errCode = SetEncryptAgo(config); if (errCode != E_OK) { return errCode; } @@ -622,6 +651,7 @@ int SqliteConnection::SetEncryptKey(const std::vector &key, int32_t ite if (errCode != E_OK || version.GetType() == ValueObject::TYPE_NULL) { return errCode; } + return E_OK; } return errCode; } @@ -911,40 +941,47 @@ int SqliteConnection::ConfigLocale(const std::string &localeStr) int SqliteConnection::CleanDirtyData(const std::string &table, uint64_t cursor) { if (table.empty()) { + LOG_ERROR("table is empty"); return E_INVALID_ARGS; } uint64_t tmpCursor = cursor == UINT64_MAX ? 0 : cursor; auto status = DropLogicDeletedData(dbHandle_, table, tmpCursor); + LOG_INFO("status:%{public}d, table:%{public}s, cursor:%{public}" PRIu64 "", status, + SqliteUtils::Anonymous(table).c_str(), cursor); return status == DistributedDB::DBStatus::OK ? E_OK : E_ERROR; } -int SqliteConnection::TryCheckPoint() +int SqliteConnection::TryCheckPoint(bool timeout) { if (!isWriter_) { return E_NOT_SUPPORT; } + std::shared_ptr autoCheck(slaveConnection_.get(), [this, timeout](Connection *conn) { + if (conn != nullptr && backupId_ == TaskExecutor::INVALID_TASK_ID) { + conn->TryCheckPoint(timeout); + } + }); std::string walName = sqlite3_filename_wal(sqlite3_db_filename(dbHandle_, "main")); - int fileSize = SqliteUtils::GetFileSize(walName); - if (fileSize < 0) { - LOG_ERROR("Invalid file size for WAL: %{public}s size is %{public}d", - SqliteUtils::Anonymous(walName).c_str(), fileSize); - return E_WAL_SIZE_OVER_LIMIT; + ssize_t size = SqliteUtils::GetFileSize(walName); + if (size < 0) { + LOG_ERROR("Invalid size for WAL:%{public}s size:%{public}zd", SqliteUtils::Anonymous(walName).c_str(), size); + return E_ERROR; } - if (static_cast(fileSize) <= GlobalExpr::DB_WAL_SIZE_LIMIT_MIN) { + + if (size <= GlobalExpr::DB_WAL_SIZE_LIMIT_MIN) { return E_OK; } - int errCode = sqlite3_wal_checkpoint_v2(dbHandle_, nullptr, SQLITE_CHECKPOINT_TRUNCATE, nullptr, nullptr); - if (errCode != SQLITE_OK) { - LOG_WARN("sqlite3_wal_checkpoint_v2 failed err %{public}d.", errCode); - return E_ERROR; + + if (!timeout && size < GlobalExpr::DB_WAL_WARNING_SIZE) { + return E_INNER_WARNING; } - if (slaveConnection_) { - int errCode = slaveConnection_->TryCheckPoint(); - if (errCode != E_OK) { - LOG_ERROR("slaveConnection tryCheckPoint failed:%{public}d", errCode); - } + int errCode = sqlite3_wal_checkpoint_v2(dbHandle_, nullptr, SQLITE_CHECKPOINT_TRUNCATE, nullptr, nullptr); + if (errCode != SQLITE_OK) { + LOG_WARN("sqlite3_wal_checkpoint_v2 failed err:%{public}d,size:%{public}zd,wal:%{public}s.", errCode, size, + SqliteUtils::Anonymous(walName).c_str()); + return SQLiteError::ErrNo(errCode); } return E_OK; } @@ -956,9 +993,9 @@ int SqliteConnection::LimitWalSize() } std::string walName = sqlite3_filename_wal(sqlite3_db_filename(dbHandle_, "main")); - int fileSize = SqliteUtils::GetFileSize(walName); - if (fileSize < 0 || static_cast(fileSize) > GlobalExpr::DB_WAL_SIZE_LIMIT_MAX) { - LOG_ERROR("The WAL file size exceeds the limit, %{public}s size is %{public}d", + ssize_t fileSize = SqliteUtils::GetFileSize(walName); + if (fileSize < 0 || fileSize > GlobalExpr::DB_WAL_SIZE_LIMIT_MAX) { + LOG_ERROR("The WAL file size exceeds the limit, %{public}s size is %{public}zd", SqliteUtils::Anonymous(walName).c_str(), fileSize); return E_WAL_SIZE_OVER_LIMIT; } @@ -1184,7 +1221,7 @@ int32_t SqliteConnection::Backup(const std::string &databasePath, const std::vec if (!isAsync) { if (slaveConnection_ == nullptr) { RdbStoreConfig rdbSlaveStoreConfig = GetSlaveRdbStoreConfig(config_); - int errCode = CreateSlaveConnection(rdbSlaveStoreConfig, true, false); + int errCode = CreateSlaveConnection(rdbSlaveStoreConfig, false); if (errCode != E_OK) { LOG_ERROR("manual slave conn failed:%{public}d", errCode); return errCode; @@ -1285,7 +1322,7 @@ int SqliteConnection::SetServiceKey(const RdbStoreConfig &config, int32_t errCod } #endif - errCode = SetEncryptKey(key, config.GetIter()); + errCode = SetEncryptKey(key, config); if (errCode == E_OK) { config.RestoreEncryptKey(key); } @@ -1296,8 +1333,8 @@ int SqliteConnection::SetServiceKey(const RdbStoreConfig &config, int32_t errCod int SqliteConnection::ExchangeSlaverToMaster(bool isRestore, SlaveStatus &curStatus) { curStatus = SlaveStatus::BACKING_UP; - auto [isReturn, err] = ExchangeVerify(isRestore); - if (isReturn) { + auto err = ExchangeVerify(isRestore); + if (err != E_OK) { curStatus = SlaveStatus::UNDEFINED; return err; } @@ -1314,7 +1351,7 @@ int SqliteConnection::ExchangeSlaverToMaster(bool isRestore, SlaveStatus &curSta do { if (!isRestore && curStatus == SlaveStatus::BACKUP_INTERRUPT) { LOG_INFO("backup slave was interrupt!"); - rc = E_BACKUP_INTERRUPT; + rc = E_CANCEL; break; } rc = sqlite3_backup_step(pBackup, BACKUP_PAGES_PRE_STEP); @@ -1336,9 +1373,16 @@ int SqliteConnection::ExchangeSlaverToMaster(bool isRestore, SlaveStatus &curSta } curStatus = SlaveStatus::BACKUP_INTERRUPT; } - return rc == E_BACKUP_INTERRUPT ? E_BACKUP_INTERRUPT : SQLiteError::ErrNo(rc); + return rc == E_CANCEL ? E_CANCEL : SQLiteError::ErrNo(rc); + } + rc = isRestore ? TryCheckPoint(true) : slaveConnection_->TryCheckPoint(true); + if (rc != E_OK && config_.GetHaMode() == HAMode::MANUAL_TRIGGER) { + if (!isRestore) { + curStatus = SlaveStatus::BACKUP_INTERRUPT; + } + LOG_WARN("CheckPoint failed err:%{public}d, isRestore:%{public}d", rc, isRestore); + return E_OK; } - isRestore ? TryCheckPoint() : slaveConnection_->TryCheckPoint(); curStatus = SlaveStatus::BACKUP_FINISHED; SqliteUtils::TryAccessSlaveLock(config_.GetPath(), true, false); SqliteUtils::TryAccessSlaveLock(config_.GetPath(), true, false, true); @@ -1354,7 +1398,7 @@ ExchangeStrategy SqliteConnection::GenerateExchangeStrategy(const SlaveStatus &s } static const std::string querySql = "SELECT COUNT(*) FROM sqlite_master WHERE type='table';"; auto [mRet, mObj] = ExecuteForValue(querySql); - if (mRet != E_OK) { + if (mRet == E_SQLITE_CORRUPT) { LOG_WARN("main abnormal, err:%{public}d", mRet); return ExchangeStrategy::RESTORE; } @@ -1364,7 +1408,7 @@ ExchangeStrategy SqliteConnection::GenerateExchangeStrategy(const SlaveStatus &s return mCount == 0 ? ExchangeStrategy::RESTORE : ExchangeStrategy::NOT_HANDLE; } auto [sRet, sObj] = slaveConnection_->ExecuteForValue(querySql); - if (sRet != E_OK) { + if (sRet == E_SQLITE_CORRUPT) { LOG_WARN("slave db abnormal, need backup, err:%{public}d", sRet); return ExchangeStrategy::BACKUP; } @@ -1381,12 +1425,6 @@ ExchangeStrategy SqliteConnection::GenerateExchangeStrategy(const SlaveStatus &s LOG_INFO("main empty, main:%{public}" PRId64 ",slave:%{public}" PRId64, mCount, sCount); return ExchangeStrategy::RESTORE; } - auto [cRet, cObj] = ExecuteForValue(INTEGRITIES[1]); // 1 is quick_check - if (cRet != E_OK || (static_cast(cObj) != "ok")) { - LOG_ERROR("main corrupt, need restore, ret:%{public}s, cRet:%{public}d, slave:%{public}" PRId64, - static_cast(cObj).c_str(), cRet, sCount); - return sCount == 0 ? ExchangeStrategy::NOT_HANDLE : ExchangeStrategy::RESTORE; - } LOG_INFO("backup, main:%{public}" PRId64 ",slave:%{public}" PRId64, mCount, sCount); return ExchangeStrategy::BACKUP; } @@ -1401,12 +1439,13 @@ int32_t SqliteConnection::Repair(const RdbStoreConfig &config) return E_NOT_SUPPORT; } RdbStoreConfig rdbSlaveStoreConfig = connection->GetSlaveRdbStoreConfig(config); - int ret = connection->CreateSlaveConnection(rdbSlaveStoreConfig, true); + int ret = connection->CreateSlaveConnection(rdbSlaveStoreConfig); if (ret != E_OK) { return ret; } - if (!connection->IsRepairable()) { - return E_NOT_SUPPORT; + ret = connection->IsRepairable(); + if (ret != E_OK) { + return ret; } LOG_WARN("begin repair main:%{public}s", SqliteUtils::Anonymous(config.GetPath()).c_str()); (void)SqliteConnection::Delete(config); @@ -1428,46 +1467,67 @@ int32_t SqliteConnection::Repair(const RdbStoreConfig &config) return ret; } -bool SqliteConnection::IsRepairable() +int SqliteConnection::IsRepairable() { if (slaveConnection_ == nullptr || slaveConnection_->dbHandle_ == nullptr) { - return false; + return E_STORE_CLOSED; } - static const std::string querySql = "SELECT COUNT(*) FROM sqlite_master WHERE type='table';"; + 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_OK || (static_cast(qObj) == 0L)) { + if (qRet == E_SQLITE_CORRUPT || (static_cast(qObj) == 0L)) { LOG_INFO("cancel repair, ret:%{public}d", qRet); - return false; + return E_SQLITE_CORRUPT; } - return true; + return E_OK; } -std::pair SqliteConnection::ExchangeVerify(bool isRestore) +int SqliteConnection::ExchangeVerify(bool isRestore) { if (dbHandle_ == nullptr || slaveConnection_ == nullptr || slaveConnection_->dbHandle_ == nullptr) { LOG_WARN("slave conn invalid"); - return { true, E_OK }; + 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 { true, E_DB_NOT_EXIST }; + return E_DB_NOT_EXIST; } if (isRestore) { + int err = IsRepairable(); + 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 { true, E_SQLITE_CORRUPT }; + return E_SQLITE_CORRUPT; } - if (!IsRepairable()) { - return { true, E_OK }; + 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()); + return E_OK; + } + if (SqliteUtils::TryAccessSlaveLock(config_.GetPath(), false, false, true)) { + 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 { false, E_OK }; + return E_OK; } std::pair> SqliteConnection::InnerCreate(const RdbStoreConfig &config, @@ -1481,16 +1541,16 @@ std::pair> SqliteConnection::InnerCre return result; } - RdbStoreConfig rdbSlaveStoreConfig = connection->GetSlaveRdbStoreConfig(config); + RdbStoreConfig slaveCfg = connection->GetSlaveRdbStoreConfig(config); errCode = connection->InnerOpen(config); if (errCode != E_OK) { return result; } conn = connection; if (isWrite) { - (void)connection->CreateSlaveConnection(rdbSlaveStoreConfig, isWrite); + (void)connection->CreateSlaveConnection(slaveCfg, isWrite); } return result; } } // namespace NativeRdb -} // namespace OHOS +} // namespace OHOS \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb/src/sqlite_global_config.cpp b/relational_store/frameworks/native/rdb/src/sqlite_global_config.cpp index 9ce21e20a95ddc997a90292505ba8424b5297a08..c86614ccb422ad099459b8c5a8f9066d2dba9e61 100644 --- a/relational_store/frameworks/native/rdb/src/sqlite_global_config.cpp +++ b/relational_store/frameworks/native/rdb/src/sqlite_global_config.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include "logger.h" #include "sqlite3sym.h" #include "sqlite_utils.h" @@ -57,6 +58,9 @@ void SqliteGlobalConfig::Log(const void *data, int err, const char *msg) bool verboseLog = (data != nullptr); auto errType = static_cast(err); errType &= 0xFF; + if (errType == SQLITE_ERROR && strstr(msg, "\"?\": syntax error in \"PRAGMA user_ve") != nullptr) { + return; + } if (errType == 0 || errType == SQLITE_CONSTRAINT || errType == SQLITE_SCHEMA || errType == SQLITE_NOTICE || err == SQLITE_WARNING_AUTOINDEX) { if (verboseLog) { diff --git a/relational_store/frameworks/native/rdb/src/sqlite_shared_result_set.cpp b/relational_store/frameworks/native/rdb/src/sqlite_shared_result_set.cpp index 0bf0b00e5c98f0cb787dbd9cfd5aca7f6b532b6b..057bd4424c2d2e5294a7d62fa146a045914d6732 100644 --- a/relational_store/frameworks/native/rdb/src/sqlite_shared_result_set.cpp +++ b/relational_store/frameworks/native/rdb/src/sqlite_shared_result_set.cpp @@ -36,40 +36,36 @@ namespace OHOS { namespace NativeRdb { using namespace OHOS::Rdb; - +using namespace std::chrono; constexpr int64_t TIME_OUT = 1500; -SqliteSharedResultSet::SqliteSharedResultSet(std::shared_ptr pool, std::string path, - std::string sql, const std::vector& bindArgs) - : AbsSharedResultSet(path), isOnlyFillBlock_(false), blockCapacity_(0), qrySql_(std::move(sql)), - bindArgs_(std::move(bindArgs)) +SqliteSharedResultSet::SqliteSharedResultSet(Time start, Conn conn, std::string sql, const Values &args, + const std::string &path) + : AbsSharedResultSet(path), conn_(std::move(conn)), qrySql_(std::move(sql)), bindArgs_(args) { - auto queryStart = std::chrono::steady_clock::now(); - conn_ = pool->AcquireRef(true); if (conn_ == nullptr) { isClosed_ = true; return; } - auto preparStart = std::chrono::steady_clock::now(); + + auto prepareBegin = steady_clock::now(); auto [statement, errCode] = PrepareStep(); if (errCode != E_OK) { LOG_ERROR("step resultset ret %{public}d", errCode); return; } statement_ = statement; - auto initCountStart = std::chrono::steady_clock::now(); + auto countBegin = steady_clock::now(); rowCount_ = InitRowCount(); - auto queryEnd = std::chrono::steady_clock::now(); - int64_t totalCostTime = std::chrono::duration_cast(queryEnd - queryStart).count(); - if (totalCostTime >= TIME_OUT) { - int64_t acquirCost = std::chrono::duration_cast(preparStart - queryStart).count(); - int64_t preparCost = - std::chrono::duration_cast(initCountStart - preparStart).count(); - int64_t initCountCost = - std::chrono::duration_cast(queryEnd - initCountStart).count(); - LOG_WARN("query totalCostTime[%{public}" PRId64 "] acquirCost[%{public}" PRId64 "] preparCost[%{public}" PRId64 - "] " - "initCountCost[%{public}" PRId64 "] rowCount[%{public}d] sql[%{public}s] path[%{public}s]", - totalCostTime, acquirCost, preparCost, initCountCost, rowCount_, qrySql_.c_str(), path.c_str()); + auto endTime = steady_clock::now(); + int64_t totalCost = duration_cast(endTime - start).count(); + if (totalCost >= TIME_OUT) { + int64_t acquireCost = duration_cast(prepareBegin - start).count(); + int64_t prepareCost = duration_cast(countBegin - prepareBegin).count(); + int64_t countCost = duration_cast(endTime - countBegin).count(); + LOG_WARN("total[%{public}" PRId64 "]<%{public}" PRId64 ",%{public}" PRId64 ",%{public}" PRId64 + "> rowCount[%{public}d] sql[%{public}s] path[%{public}s]", + totalCost, acquireCost, prepareCost, countCost, rowCount_, qrySql_.c_str(), + SqliteUtils::Anonymous(path).c_str()); } } 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 f480718208d32724d559e22daf0b6d50c54fd1e1..2fa7e9bd8f1dc48d6efe9275938b16b40ebe6b9e 100644 --- a/relational_store/frameworks/native/rdb/src/sqlite_sql_builder.cpp +++ b/relational_store/frameworks/native/rdb/src/sqlite_sql_builder.cpp @@ -23,13 +23,16 @@ #include "rdb_trace.h" #include "sqlite_utils.h" #include "string_utils.h" - +#include "traits.h" namespace OHOS { namespace NativeRdb { using namespace OHOS::Rdb; std::vector g_onConflictClause = { "", " OR ROLLBACK", " OR ABORT", " OR FAIL", " OR IGNORE", " OR REPLACE" }; +ValueObject SqliteSqlBuilder::nullObject_; +std::reference_wrapper SqliteSqlBuilder::nullRef_ = SqliteSqlBuilder::nullObject_; + SqliteSqlBuilder::SqliteSqlBuilder() {} SqliteSqlBuilder::~SqliteSqlBuilder() {} @@ -295,22 +298,47 @@ std::string SqliteSqlBuilder::GetSqlArgs(size_t size) return args; } -SqliteSqlBuilder::ExecuteSqls SqliteSqlBuilder::MakeExecuteSqls( - const std::string &sql, std::vector &&args, int fieldSize, int limit) +SqliteSqlBuilder::BatchRefSqls SqliteSqlBuilder::GenerateSqls(const std::string &table, const ValuesBuckets &buckets, + int limit) +{ + 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; + for (auto &field : *fields) { + 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); + args[columnIndex + row * columnSize] = value; + } + columnIndex++; + sql.append(field).append(","); + } + sql.pop_back(); + sql.append(") VALUES "); + return SqliteSqlBuilder::MakeExecuteSqls(sql, args, columnSize, limit); +} + +SqliteSqlBuilder::BatchRefSqls SqliteSqlBuilder::MakeExecuteSqls(const std::string &sql, + const std::vector &args, int fieldSize, int limit) { if (fieldSize == 0) { - return ExecuteSqls(); + return BatchRefSqls(); } size_t rowNumbers = args.size() / static_cast(fieldSize); size_t maxRowNumbersOneTimes = static_cast(limit / fieldSize); if (maxRowNumbersOneTimes == 0) { - return ExecuteSqls(); + return BatchRefSqls(); } size_t executeTimes = rowNumbers / maxRowNumbersOneTimes; size_t remainingRows = rowNumbers % maxRowNumbersOneTimes; - LOG_DEBUG("rowNumbers %{public}zu, maxRowNumbersOneTimes %{public}zu, executeTimes %{public}zu," - "remainingRows %{public}zu, fieldSize %{public}d, limit %{public}d", - rowNumbers, maxRowNumbersOneTimes, executeTimes, remainingRows, fieldSize, limit); std::string singleRowSqlArgs = "(" + SqliteSqlBuilder::GetSqlArgs(fieldSize) + ")"; auto appendAgsSql = [&singleRowSqlArgs, &sql](size_t rowNumber) { std::string sqlStr = sql; @@ -321,14 +349,14 @@ SqliteSqlBuilder::ExecuteSqls SqliteSqlBuilder::MakeExecuteSqls( return sqlStr; }; std::string executeSql; - ExecuteSqls executeSqls; + BatchRefSqls executeSqls; auto start = args.begin(); if (executeTimes != 0) { executeSql = appendAgsSql(maxRowNumbersOneTimes); - std::vector> sqlArgs; + std::vector> sqlArgs; size_t maxVariableNumbers = maxRowNumbersOneTimes * static_cast(fieldSize); for (size_t i = 0; i < executeTimes; ++i) { - std::vector bindValueArgs(start, start + maxVariableNumbers); + std::vector bindValueArgs(start, start + maxVariableNumbers); sqlArgs.emplace_back(std::move(bindValueArgs)); start += maxVariableNumbers; } @@ -337,7 +365,7 @@ SqliteSqlBuilder::ExecuteSqls SqliteSqlBuilder::MakeExecuteSqls( if (remainingRows != 0) { executeSql = appendAgsSql(remainingRows); - std::vector> sqlArgs(1, std::vector(start, args.end())); + std::vector> sqlArgs(1, std::vector(start, args.end())); executeSqls.emplace_back(std::make_pair(executeSql, std::move(sqlArgs))); } return executeSqls; @@ -354,5 +382,23 @@ std::string SqliteSqlBuilder::HandleTable(const std::string &tableName) } return "'" + tableName + "'"; } + +void SqliteSqlBuilder::UpdateAssetStatus(const ValueObject &val, int32_t status) +{ + if (val.GetType() == ValueObject::TYPE_ASSET) { + auto *asset = Traits::get_if(&val.value); + if (asset != nullptr) { + asset->status = static_cast(status); + } + } + if (val.GetType() == ValueObject::TYPE_ASSETS) { + auto *assets = Traits::get_if(&val.value); + if (assets != nullptr) { + for (auto &asset : *assets) { + asset.status = static_cast(status); + } + } + } +} } // namespace NativeRdb } // namespace OHOS diff --git a/relational_store/frameworks/native/rdb/src/sqlite_statement.cpp b/relational_store/frameworks/native/rdb/src/sqlite_statement.cpp index c393aefd3e6ae964121513b729a0595e3dc830e8..bd08afbeee355dc0b9a9729c88598a933e670186 100644 --- a/relational_store/frameworks/native/rdb/src/sqlite_statement.cpp +++ b/relational_store/frameworks/native/rdb/src/sqlite_statement.cpp @@ -43,6 +43,7 @@ namespace NativeRdb { using namespace OHOS::Rdb; using namespace std::chrono; using SqlStatistic = DistributedRdb::SqlStatistic; +using Reportor = RdbFaultHiViewReporter; // Setting Data Precision constexpr SqliteStatement::Action SqliteStatement::ACTIONS[ValueObject::TYPE_MAX]; SqliteStatement::SqliteStatement() : readOnly_(false), columnCount_(0), numParameters_(0), stmt_(nullptr), sql_("") @@ -76,10 +77,11 @@ int SqliteStatement::Prepare(sqlite3 *dbHandle, const std::string &newSql) ReadFile2Buffer(); } int ret = SQLiteError::ErrNo(errCode); - if (ret == E_SQLITE_CORRUPT && config_ != nullptr) { - RdbFaultHiViewReporter::ReportFault(RdbFaultHiViewReporter::Create(*config_, ret)); + if (config_ != nullptr && + (errCode == SQLITE_CORRUPT || (errCode == SQLITE_NOTADB && config_->GetIter() != 0))) { + Reportor::ReportFault(Reportor::Create(*config_, ret)); } - PrintInfoForDbError(ret); + PrintInfoForDbError(ret, newSql); return ret; } InnerFinalize(); // finalize the old @@ -92,14 +94,19 @@ int SqliteStatement::Prepare(sqlite3 *dbHandle, const std::string &newSql) return E_OK; } -void SqliteStatement::PrintInfoForDbError(int errorCode) +void SqliteStatement::PrintInfoForDbError(int errCode, const std::string &sql) { if (config_ == nullptr) { return; } - if (errorCode == E_SQLITE_ERROR || errorCode == E_SQLITE_BUSY || errorCode == E_SQLITE_LOCKED || - errorCode == E_SQLITE_IOERR || errorCode == E_SQLITE_CORRUPT || errorCode == E_SQLITE_CANTOPEN) { - LOG_ERROR(" DbError errorCode: %{public}d DbName: %{public}s ", errorCode, + + if (errCode == E_SQLITE_ERROR && sql == std::string(GlobalExpr::PRAGMA_VERSION) + "=?") { + return; + } + + if (errCode == E_SQLITE_ERROR || errCode == E_SQLITE_BUSY || errCode == E_SQLITE_LOCKED || + errCode == E_SQLITE_IOERR || errCode == E_SQLITE_CANTOPEN) { + LOG_ERROR("DbError errCode:%{public}d errno:%{public}d DbName: %{public}s ", errCode, errno, SqliteUtils::Anonymous(config_->GetName()).c_str()); } } @@ -135,6 +142,15 @@ void SqliteStatement::ReadFile2Buffer() } int SqliteStatement::BindArgs(const std::vector &bindArgs) +{ + std::vector> refBindArgs; + for (auto &object : bindArgs) { + refBindArgs.emplace_back(std::ref(const_cast(object))); + } + return BindArgs(refBindArgs); +} + +int SqliteStatement::BindArgs(const std::vector> &bindArgs) { SqlStatistic sqlStatistic("", SqlStatistic::Step::STEP_PREPARE, seqId_); if (bound_) { @@ -144,12 +160,12 @@ int SqliteStatement::BindArgs(const std::vector &bindArgs) bound_ = true; int index = 1; for (auto &arg : bindArgs) { - auto action = ACTIONS[arg.value.index()]; + auto action = ACTIONS[arg.get().value.index()]; if (action == nullptr) { - LOG_ERROR("not support the type %{public}zu", arg.value.index()); + LOG_ERROR("not support the type %{public}zu", arg.get().value.index()); return E_INVALID_ARGS; } - auto errCode = action(stmt_, index, arg.value); + auto errCode = action(stmt_, index, arg.get().value); if (errCode != SQLITE_OK) { LOG_ERROR("Bind has error: %{public}d, sql: %{public}s, errno %{public}d", errCode, sql_.c_str(), errno); return SQLiteError::ErrNo(errCode); @@ -268,7 +284,7 @@ int SqliteStatement::Step() return ret; } if (slave_) { - ret = slave_->InnerStep(); + ret = slave_->Step(); if (ret != E_OK) { LOG_WARN("slave step error:%{public}d", ret); } @@ -279,11 +295,12 @@ int SqliteStatement::Step() int SqliteStatement::InnerStep() { SqlStatistic sqlStatistic("", SqlStatistic::Step::STEP_EXECUTE, seqId_); - int ret = SQLiteError::ErrNo(sqlite3_step(stmt_)); - if (ret == E_SQLITE_CORRUPT && config_ != nullptr) { - RdbFaultHiViewReporter::ReportFault(RdbFaultHiViewReporter::Create(*config_, ret)); + auto errCode = sqlite3_step(stmt_); + int ret = SQLiteError::ErrNo(errCode); + if (config_ != nullptr && (errCode == SQLITE_CORRUPT || (errCode == SQLITE_NOTADB && config_->GetIter() != 0))) { + Reportor::ReportFault(Reportor::Create(*config_, ret)); } - PrintInfoForDbError(ret); + PrintInfoForDbError(ret, sql_); return ret; } @@ -324,6 +341,15 @@ int SqliteStatement::Finalize() } int SqliteStatement::Execute(const std::vector &args) +{ + std::vector> refArgs; + for (auto &object : args) { + refArgs.emplace_back(std::ref(const_cast(object))); + } + return Execute(refArgs); +} + +int32_t SqliteStatement::Execute(const std::vector> &args) { int count = static_cast(args.size()); if (count != numParameters_) { diff --git a/relational_store/frameworks/native/rdb/src/sqlite_utils.cpp b/relational_store/frameworks/native/rdb/src/sqlite_utils.cpp index 74a02a04d24be226ad0fc748b37cc79249c7a34a..4b724ff2b77ed550c0fe849d369a25c39638cd09 100644 --- a/relational_store/frameworks/native/rdb/src/sqlite_utils.cpp +++ b/relational_store/frameworks/native/rdb/src/sqlite_utils.cpp @@ -30,16 +30,14 @@ #include "logger.h" #include "rdb_errno.h" -#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) #include "rdb_store_config.h" -#endif namespace OHOS { namespace NativeRdb { using namespace OHOS::Rdb; /* A continuous number must contain at least eight digits, because the employee ID has eight digits, and the mobile phone number has 11 digits. The UUID is longer */ -constexpr int32_t CONTINUOUS_DIGITS_MINI_SIZE = 5; +constexpr int32_t CONTINUOUS_DIGITS_MINI_SIZE = 6; constexpr int32_t FILE_PATH_MINI_SIZE = 6; constexpr int32_t AREA_MINI_SIZE = 4; constexpr int32_t AREA_OFFSET_SIZE = 5; @@ -137,7 +135,7 @@ bool SqliteUtils::RenameFile(const std::string &srcFile, const std::string &dest auto ret = rename(srcFile.c_str(), destFile.c_str()); if (ret != 0) { LOG_WARN("rename failed errno %{public}d ret %{public}d %{public}s -> %{public}s", errno, ret, - SqliteUtils::Anonymous(destFile).c_str(), srcFile.c_str()); + SqliteUtils::Anonymous(destFile).c_str(), SqliteUtils::Anonymous(srcFile).c_str()); return false; } return true; @@ -190,7 +188,7 @@ std::string SqliteUtils::GetAnonymousName(const std::string &fileName) noAlnum.push_back(""); } if (!noAlnumStr.empty()) { - noAlnum.push_back(alnumStr); + noAlnum.push_back(noAlnumStr); alnum.push_back(""); } std::string res = ""; @@ -202,21 +200,19 @@ std::string SqliteUtils::GetAnonymousName(const std::string &fileName) std::string SqliteUtils::AnonyDigits(const std::string &fileName) { - int digitsNum = fileName.size(); + std::string::size_type digitsNum = fileName.size(); if (digitsNum < CONTINUOUS_DIGITS_MINI_SIZE) { return fileName; } - constexpr int longDigits = 7; - int endDigitsNum = 4; - int shortEndDigitsNum = 3; + std::string::size_type endDigitsNum = 4; + std::string::size_type shortEndDigitsNum = 3; std::string name = fileName; std::string last = ""; - if (digitsNum >= CONTINUOUS_DIGITS_MINI_SIZE && digitsNum < longDigits) { + if (digitsNum == CONTINUOUS_DIGITS_MINI_SIZE) { last = name.substr(name.size() - shortEndDigitsNum); } else { last = name.substr(name.size() - endDigitsNum); } - return "***" + last; } @@ -241,16 +237,17 @@ std::string SqliteUtils::Anonymous(const std::string &srcFile) return srcFile.substr(0, pre + PRE_OFFSET_SIZE) + "***" + path + fileName; } -int SqliteUtils::GetFileSize(const std::string &fileName) +ssize_t SqliteUtils::GetFileSize(const std::string &fileName) { struct stat fileStat; if (fileName.empty() || stat(fileName.c_str(), &fileStat) < 0) { - LOG_ERROR("Failed to get file infos, errno: %{public}d, fileName:%{public}s", - errno, Anonymous(fileName).c_str()); + if (errno != ENOENT) { + LOG_ERROR("failed, errno: %{public}d, fileName:%{public}s", errno, Anonymous(fileName).c_str()); + } return 0; } - return static_cast(fileStat.st_size); + return fileStat.st_size; } bool SqliteUtils::IsSlaveDbName(const std::string &fileName) @@ -269,10 +266,9 @@ bool SqliteUtils::TryAccessSlaveLock(const std::string &dbPath, bool isDelete, b std::string lockFile = isSlaveFailure ? dbPath + "-slaveFailure" : dbPath + "-syncInterrupt"; if (isDelete) { if (std::remove(lockFile.c_str()) != 0) { - LOG_WARN("remove slave lock failed errno %{public}d %{public}s", errno, Anonymous(lockFile).c_str()); return false; } else { - LOG_INFO("remove slave lock %{public}s", Anonymous(lockFile).c_str()); + LOG_INFO("remove %{public}s", Anonymous(lockFile).c_str()); return true; } } else { @@ -282,11 +278,11 @@ bool SqliteUtils::TryAccessSlaveLock(const std::string &dbPath, bool isDelete, b if (needCreate) { std::ofstream src(lockFile.c_str(), std::ios::binary); if (src.is_open()) { - LOG_INFO("create slave lock %{public}s", Anonymous(lockFile).c_str()); + LOG_INFO("open %{public}s", Anonymous(lockFile).c_str()); src.close(); return true; } else { - LOG_WARN("open slave lock failed errno %{public}d %{public}s", errno, Anonymous(lockFile).c_str()); + LOG_WARN("open errno %{public}d %{public}s", errno, Anonymous(lockFile).c_str()); return false; } } @@ -304,5 +300,48 @@ std::string SqliteUtils::GetSlavePath(const std::string& name) } return name.substr(0, pos) + slaveSuffix; } + +const char *SqliteUtils::HmacAlgoDescription(int32_t hmacAlgo) +{ + HmacAlgo hmacEnum = static_cast(hmacAlgo); + switch (hmacEnum) { + case HmacAlgo::SHA1: + return "sha1"; + case HmacAlgo::SHA256: + return "sha256"; + case HmacAlgo::SHA512: + return "sha512"; + default: + return "sha256"; + } +} + +const char *SqliteUtils::KdfAlgoDescription(int32_t kdfAlgo) +{ + KdfAlgo kdfEnum = static_cast(kdfAlgo); + switch (kdfEnum) { + case KdfAlgo::KDF_SHA1: + return "kdf_sha1"; + case KdfAlgo::KDF_SHA256: + return "kdf_sha256"; + case KdfAlgo::KDF_SHA512: + return "kdf_sha512"; + default: + return "kdf_sha256"; + } +} + +const char *SqliteUtils::EncryptAlgoDescription(int32_t encryptAlgo) +{ + EncryptAlgo encryptEnum = static_cast(encryptAlgo); + switch (encryptEnum) { + case EncryptAlgo::AES_256_CBC: + return "aes-256-cbc"; + case EncryptAlgo::AES_256_GCM: + default: + return "aes-256-gcm"; + } +} + } // namespace NativeRdb } // namespace OHOS diff --git a/relational_store/frameworks/native/rdb/src/step_result_set.cpp b/relational_store/frameworks/native/rdb/src/step_result_set.cpp index 6e1204464177ee646e84f0e44a9a9a870b0924c0..228283b2d0c8e4bf704152757ff39a02c4b05167 100644 --- a/relational_store/frameworks/native/rdb/src/step_result_set.cpp +++ b/relational_store/frameworks/native/rdb/src/step_result_set.cpp @@ -29,21 +29,23 @@ namespace OHOS { namespace NativeRdb { using namespace OHOS::Rdb; -StepResultSet::StepResultSet(std::shared_ptr pool, const std::string &sql, - const std::vector &args) - : AbsResultSet(), sql_(sql), args_(std::move(args)) + +constexpr int64_t TIME_OUT = 1500; +StepResultSet::StepResultSet(Time start, Conn conn, const std::string &sql, const Values &args, bool safe) + : AbsResultSet(safe), conn_(std::move(conn)), sql_(sql), args_(args) { - conn_ = pool->AcquireRef(true); if (conn_ == nullptr) { isClosed_ = true; return; } + auto prepareStart = std::chrono::steady_clock::now(); auto errCode = PrepareStep(); if (errCode != E_OK) { LOG_ERROR("step resultset ret %{public}d", errCode); return; } + auto prepareEnd = std::chrono::steady_clock::now(); auto statement = GetStatement(); if (statement == nullptr) { return; @@ -53,6 +55,16 @@ StepResultSet::StepResultSet(std::shared_ptr pool, const std::st isSupportCountRow_ = false; lastErr_ = E_OK; } + auto queryEnd = std::chrono::steady_clock::now(); + int64_t totalCost = std::chrono::duration_cast(queryEnd - start).count(); + if (totalCost >= TIME_OUT) { + int64_t acquireCost = std::chrono::duration_cast(prepareStart - start).count(); + int64_t prepareCost = std::chrono::duration_cast(prepareEnd - prepareStart).count(); + int64_t countCost = std::chrono::duration_cast(queryEnd - prepareEnd).count(); + LOG_WARN("total[%{public}" PRId64 "]<%{public}" PRId64 ",%{public}" PRId64 ",%{public}" PRId64 + "> count[%{public}d] sql[%{public}s]", + totalCost, acquireCost, prepareCost, countCost, rowCount_, SqliteUtils::Anonymous(sql_).c_str()); + } } StepResultSet::~StepResultSet() @@ -65,18 +77,19 @@ StepResultSet::~StepResultSet() */ int StepResultSet::PrepareStep() { - if (sqliteStatement_ != nullptr) { + std::lock_guard lockGuard(globalMtx_); + if (statement_ != nullptr) { return E_OK; } - if (conn_ == nullptr) { + if (isClosed_ || conn_ == nullptr) { lastErr_ = E_ALREADY_CLOSED; return lastErr_; } auto type = SqliteUtils::GetSqlStatementType(sql_); if (type == SqliteUtils::STATEMENT_ERROR) { - LOG_ERROR("invalid sql_ %{public}s!", sql_.c_str()); + LOG_ERROR("invalid sql_ %{public}s!", SqliteUtils::Anonymous(sql_).c_str()); lastErr_ = E_INVALID_ARGS; return lastErr_; } @@ -102,10 +115,7 @@ int StepResultSet::PrepareStep() return lastErr_; } - sqliteStatement_ = std::move(statement); - if (sqliteStatement_ == nullptr) { - LOG_ERROR("sqliteStatement_ is nullptr."); - } + statement_ = std::move(statement); return E_OK; } @@ -254,9 +264,13 @@ int StepResultSet::Close() return E_OK; } isClosed_ = true; - conn_ = nullptr; - sqliteStatement_ = nullptr; - auto args = std::move(args_); + { + std::lock_guard lockGuard(globalMtx_); + conn_ = nullptr; + statement_ = nullptr; + auto args = std::move(args_); + auto sql = std::move(sql_); + } Reset(); return E_OK; } @@ -354,11 +368,12 @@ std::pair StepResultSet::GetValueObject(int32_t col, size_t in std::shared_ptr StepResultSet::GetStatement() { + std::lock_guard lockGuard(globalMtx_); if (isClosed_ || conn_ == nullptr) { return nullptr; } - return sqliteStatement_; + return statement_; } } // namespace NativeRdb } // namespace OHOS \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb/src/trans_db.cpp b/relational_store/frameworks/native/rdb/src/trans_db.cpp new file mode 100644 index 0000000000000000000000000000000000000000..937230259cd7e95a17b2e3f5c12c5e968ad6b936 --- /dev/null +++ b/relational_store/frameworks/native/rdb/src/trans_db.cpp @@ -0,0 +1,269 @@ +/* + * 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 "TransDB" +#include "trans_db.h" + +#include "logger.h" +#include "rdb_sql_statistic.h" +#include "rdb_trace.h" +#include "sqlite_sql_builder.h" +#include "sqlite_utils.h" +#include "step_result_set.h" +#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) +#include "sqlite_shared_result_set.h" +#endif +namespace OHOS::NativeRdb { +using namespace OHOS::Rdb; +using namespace DistributedRdb; +TransDB::TransDB(std::shared_ptr conn, const std::string &name) : conn_(conn), name_(name) +{ + maxArgs_ = conn->GetMaxVariable(); +} + +std::pair TransDB::Insert(const std::string &table, const Row &row, Resolution resolution) +{ + DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); + auto conflictClause = SqliteUtils::GetConflictClause(static_cast(resolution)); + if (table.empty() || row.IsEmpty() || conflictClause == nullptr) { + return { E_INVALID_ARGS, -1 }; + } + + std::string sql("INSERT"); + sql.append(conflictClause).append(" INTO ").append(table).append("("); + std::vector args; + args.reserve(row.values_.size()); + const char *split = ""; + for (const auto &[key, val] : row.values_) { + sql.append(split).append(key); + if (val.GetType() == ValueObject::TYPE_ASSETS && resolution == ConflictResolution::ON_CONFLICT_REPLACE) { + return { E_INVALID_ARGS, -1 }; + } + SqliteSqlBuilder::UpdateAssetStatus(val, AssetValue::STATUS_INSERT); + args.push_back(val); // columnValue + split = ","; + } + + sql.append(") VALUES ("); + if (!args.empty()) { + sql.append(SqliteSqlBuilder::GetSqlArgs(args.size())); + } + + sql.append(")"); + int64_t rowid = -1; + auto [errCode, statement] = GetStatement(sql); + if (statement == nullptr) { + return { errCode, rowid }; + } + errCode = statement->Execute(args); + if (errCode != E_OK) { + return { errCode, rowid }; + } + rowid = statement->Changes() > 0 ? statement->LastInsertRowId() : -1; + return { errCode, rowid }; +} + +std::pair TransDB::BatchInsert(const std::string &table, const RefRows &rows) +{ + if (rows.RowSize() == 0) { + return { E_OK, 0 }; + } + + auto batchInfo = SqliteSqlBuilder::GenerateSqls(table, rows, maxArgs_); + if (table.empty() || batchInfo.empty()) { + LOG_ERROR("empty,table=%{public}s,rows:%{public}zu,max:%{public}d.", table.c_str(), rows.RowSize(), maxArgs_); + return { E_INVALID_ARGS, -1 }; + } + + for (const auto &[sql, batchArgs] : batchInfo) { + auto [errCode, statement] = GetStatement(sql); + if (statement == nullptr) { + return { errCode, -1 }; + } + for (const auto &args : batchArgs) { + errCode = statement->Execute(args); + if (errCode == E_OK) { + continue; + } + LOG_ERROR("failed(0x%{public}x) db:%{public}s table:%{public}s args:%{public}zu", errCode, + SqliteUtils::Anonymous(name_).c_str(), table.c_str(), args.size()); + return { errCode, -1 }; + } + } + return { E_OK, int64_t(rows.RowSize()) }; +} + +std::pair TransDB::Update(const std::string &table, const Row &row, const std::string &where, + const Values &args, Resolution resolution) +{ + DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); + auto clause = SqliteUtils::GetConflictClause(static_cast(resolution)); + if (table.empty() || row.IsEmpty() || clause == nullptr) { + return { E_INVALID_ARGS, 0 }; + } + + std::string sql("UPDATE"); + sql.append(clause).append(" ").append(table).append(" SET "); + std::vector totalArgs; + totalArgs.reserve(row.values_.size() + args.size()); + const char *split = ""; + for (auto &[key, val] : row.values_) { + sql.append(split); + if (val.GetType() == ValueObject::TYPE_ASSETS) { + sql.append(key).append("=merge_assets(").append(key).append(", ?)"); + } else if (val.GetType() == ValueObject::TYPE_ASSET) { + sql.append(key).append("=merge_asset(").append(key).append(", ?)"); + } else { + sql.append(key).append("=?"); + } + totalArgs.push_back(val); + split = ","; + } + + if (!where.empty()) { + sql.append(" WHERE ").append(where); + } + + totalArgs.insert(totalArgs.end(), args.begin(), args.end()); + auto [errCode, statement] = GetStatement(sql); + if (statement == nullptr) { + return { errCode, 0 }; + } + + errCode = statement->Execute(totalArgs); + if (errCode != E_OK) { + return { errCode, 0 }; + } + return { errCode, int32_t(statement->Changes()) }; +} + +int TransDB::Delete(int &deletedRows, const std::string &table, const std::string &whereClause, const Values &args) +{ + DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); + if (table.empty()) { + return E_INVALID_ARGS; + } + + std::string sql; + sql.append("DELETE FROM ").append(table); + if (!whereClause.empty()) { + sql.append(" WHERE ").append(whereClause); + } + auto [errCode, statement] = GetStatement(sql); + if (statement == nullptr) { + return errCode; + } + errCode = statement->Execute(args); + if (errCode != E_OK) { + return errCode; + } + deletedRows = statement->Changes(); + return E_OK; +} + +std::shared_ptr TransDB::QuerySql(const std::string &sql, const Values &args) +{ +#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) + auto start = std::chrono::steady_clock::now(); + return std::make_shared(start, conn_.lock(), sql, args, name_); +#else + (void)sql; + (void)args; + return nullptr; +#endif +} + +std::shared_ptr TransDB::QueryByStep(const std::string &sql, const Values &args) +{ + auto start = std::chrono::steady_clock::now(); + return std::make_shared(start, conn_.lock(), sql, args, true); +} + +std::pair TransDB::Execute(const std::string &sql, const Values &args, int64_t trxId) +{ + (void)trxId; + ValueObject object; + int sqlType = SqliteUtils::GetSqlStatementType(sql); + if (!SqliteUtils::IsSupportSqlForExecute(sqlType) && !SqliteUtils::IsSpecial(sqlType)) { + LOG_ERROR("Not support the sql:%{public}s", sql.c_str()); + return { E_INVALID_ARGS, object }; + } + + auto [errCode, statement] = GetStatement(sql); + if (errCode != E_OK) { + return { errCode, object }; + } + + errCode = statement->Execute(args); + if (errCode != E_OK) { + LOG_ERROR("failed,sql:%{public}s, error:0x%{public}x.", sql.c_str(), errCode); + return { errCode, object }; + } + + if (sqlType == SqliteUtils::STATEMENT_INSERT) { + int64_t outValue = statement->Changes() > 0 ? statement->LastInsertRowId() : -1; + return { errCode, ValueObject(outValue) }; + } + + if (sqlType == SqliteUtils::STATEMENT_UPDATE) { + int outValue = statement->Changes(); + return { errCode, ValueObject(outValue) }; + } + + if (sqlType == SqliteUtils::STATEMENT_PRAGMA) { + if (statement->GetColumnCount() == 1) { + return statement->GetColumn(0); + } + } + + if (sqlType == SqliteUtils::STATEMENT_DDL) { + statement->Reset(); + statement->Prepare("PRAGMA schema_version"); + auto [err, version] = statement->ExecuteForValue(); + if (vSchema_ < static_cast(version)) { + LOG_INFO("db:%{public}s exe DDL schema<%{public}" PRIi64 "->%{public}" PRIi64 "> sql:%{public}s.", + SqliteUtils::Anonymous(name_).c_str(), vSchema_, static_cast(version), sql.c_str()); + vSchema_ = version; + } + } + return { errCode, object }; +} + +int TransDB::GetVersion(int &version) +{ + return E_NOT_SUPPORT; +} + +int TransDB::SetVersion(int version) +{ + return E_NOT_SUPPORT; +} + +int TransDB::Sync(const SyncOption &option, const std::vector &tables, const AsyncDetail &async) +{ + if (option.mode != TIME_FIRST || tables.empty()) { + return E_INVALID_ARGS; + } + return RdbStore::Sync(option, tables, async); +} + +std::pair> TransDB::GetStatement(const std::string &sql) const +{ + auto connection = conn_.lock(); + if (connection == nullptr) { + return { E_ALREADY_CLOSED, nullptr }; + } + return connection->CreateStatement(sql, connection); +} +} // namespace OHOS::NativeRdb \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/customutdinstaller_fuzzer/corpus/init b/relational_store/frameworks/native/rdb/src/transaction.cpp similarity index 57% rename from datamgr_service/services/distributeddataservice/service/test/fuzztest/customutdinstaller_fuzzer/corpus/init rename to relational_store/frameworks/native/rdb/src/transaction.cpp index 6198079a28e860189d4294f6598f8ac6804c0dff..201a6ffee808126f191e47533c7bea7c84978e35 100644 --- a/datamgr_service/services/distributeddataservice/service/test/fuzztest/customutdinstaller_fuzzer/corpus/init +++ b/relational_store/frameworks/native/rdb/src/transaction.cpp @@ -12,5 +12,21 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include "transaction.h" -FUZZ \ No newline at end of file +namespace OHOS::NativeRdb { +std::pair> Transaction::Create( + int32_t type, std::shared_ptr connection, const std::string &name) +{ + if (creator_ != nullptr) { + return creator_(type, std::move(connection), name); + } + return { E_ERROR, nullptr }; +} + +int32_t Transaction::RegisterCreator(Creator creator) +{ + creator_ = std::move(creator); + return E_OK; +} +} diff --git a/relational_store/frameworks/native/rdb/src/transaction_impl.cpp b/relational_store/frameworks/native/rdb/src/transaction_impl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3806db3b521d111bcea6169d5701ccb2a66481b0 --- /dev/null +++ b/relational_store/frameworks/native/rdb/src/transaction_impl.cpp @@ -0,0 +1,266 @@ +/* + * 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 "TransactionImpl" + +#include "transaction_impl.h" +#include "logger.h" +#include "rdb_errno.h" +#include "rdb_store.h" +#include "trans_db.h" + +using namespace OHOS::Rdb; +namespace OHOS::NativeRdb { + +__attribute__((used)) +const int32_t TransactionImpl::regCreator_ = Transaction::RegisterCreator(TransactionImpl::Create); + +TransactionImpl::TransactionImpl(std::shared_ptr connection, const std::string &name) + : name_(name), connection_(std::move(connection)) +{ + LOG_INFO("constructor name=%{public}s", name_.c_str()); +} + +TransactionImpl::~TransactionImpl() +{ + LOG_INFO("destructor name=%{public}s", name_.c_str()); + CloseInner(); +} + +std::pair> TransactionImpl::Create( + int32_t type, std::shared_ptr connection, const std::string &name) +{ + auto trans = std::make_shared(std::move(connection), name); + if (trans == nullptr) { + return { E_ERROR, nullptr }; + } + auto errorCode = trans->Begin(type); + if (errorCode != E_OK) { + LOG_ERROR("transaction begin failed, errorCode=%{public}d", errorCode); + return { errorCode, nullptr }; + } + return { E_OK, trans }; +} + +std::string TransactionImpl::GetBeginSql(int32_t type) +{ + if (type < TransactionType::DEFERRED || type >= static_cast(TransactionType::TRANS_BUTT)) { + LOG_ERROR("invalid type=%{public}d", type); + return {}; + } + return BEGIN_SQLS[type]; +} + +int32_t TransactionImpl::Begin(int32_t type) +{ + LOG_INFO("type=%{public}d", static_cast(type)); + std::lock_guard lock(mutex_); + store_ = std::make_shared(connection_, name_); + if (store_ == nullptr) { + return E_ERROR; + } + auto beginSql = GetBeginSql(type); + if (beginSql.empty()) { + CloseInner(); + return E_INVALID_ARGS; + } + auto [errorCode, statement] = connection_->CreateStatement(beginSql, connection_); + if (errorCode != E_OK) { + LOG_ERROR("create statement failed, errorCode=%{public}d", errorCode); + CloseInner(); + return errorCode; + } + errorCode = statement->Execute(); + if (errorCode != E_OK) { + LOG_ERROR("statement execute failed, errorCode=%{public}d", errorCode); + CloseInner(); + return errorCode; + } + return E_OK; +} + +int32_t TransactionImpl::Commit() +{ + std::lock_guard lock(mutex_); + if (connection_ == nullptr) { + LOG_ERROR("connection already closed"); + return E_ALREADY_CLOSED; + } + + auto [errorCode, statement] = connection_->CreateStatement(COMMIT_SQL, connection_); + if (errorCode != E_OK) { + LOG_ERROR("create statement failed, errorCode=%{public}d", errorCode); + CloseInner(); + return errorCode; + } + + errorCode = statement->Execute(); + CloseInner(); + if (errorCode != E_OK) { + LOG_ERROR("statement execute failed, errorCode=%{public}d", errorCode); + return errorCode; + } + return E_OK; +} + +int32_t TransactionImpl::Rollback() +{ + std::lock_guard lock(mutex_); + if (connection_ == nullptr) { + LOG_ERROR("connection already closed"); + return E_ALREADY_CLOSED; + } + + auto [errorCode, statement] = connection_->CreateStatement(ROLLBACK_SQL, connection_); + if (errorCode != E_OK) { + LOG_ERROR("create statement failed, errorCode=%{public}d", errorCode); + CloseInner(); + return errorCode; + } + + errorCode = statement->Execute(); + CloseInner(); + if (errorCode != E_OK) { + LOG_ERROR("statement execute failed, errorCode=%{public}d", errorCode); + return errorCode; + } + return E_OK; +} + +int32_t TransactionImpl::CloseInner() +{ + std::lock_guard lock(mutex_); + store_ = nullptr; + connection_ = nullptr; + for (auto &resultSet : resultSets_) { + auto sp = resultSet.lock(); + if (sp != nullptr) { + sp->Close(); + } + } + return E_OK; +} + +int32_t TransactionImpl::Close() +{ + return CloseInner(); +} + +std::shared_ptr TransactionImpl::GetStore() +{ + std::lock_guard lock(mutex_); + return store_; +} + +std::pair TransactionImpl::Insert(const std::string &table, const Row &row, Resolution resolution) +{ + auto store = GetStore(); + if (store == nullptr) { + LOG_ERROR("transaction already close"); + return { E_ALREADY_CLOSED, -1 }; + } + return store->Insert(table, row, resolution); +} + +std::pair TransactionImpl::BatchInsert(const std::string &table, const Rows &rows) +{ + auto store = GetStore(); + if (store == nullptr) { + LOG_ERROR("transaction already close"); + return { E_ALREADY_CLOSED, -1 }; + } + int64_t insertRows{}; + auto errorCode = store->BatchInsert(insertRows, table, rows); + return { errorCode, insertRows }; +} + +std::pair TransactionImpl::BatchInsert(const std::string &table, const RefRows &rows) +{ + auto store = GetStore(); + if (store == nullptr) { + LOG_ERROR("transaction already close"); + return { E_ALREADY_CLOSED, -1 }; + } + return store->BatchInsert(table, rows); +} + +std::pair TransactionImpl::Update(const Row &row, const AbsRdbPredicates &predicates, + Resolution resolution) +{ + auto store = GetStore(); + if (store == nullptr) { + LOG_ERROR("transaction already close"); + return { E_ALREADY_CLOSED, -1 }; + } + return store->Update(predicates.GetTableName(), row, predicates.GetWhereClause(), predicates.GetBindArgs(), + resolution); +} + +std::pair TransactionImpl::Delete(const AbsRdbPredicates &predicates) +{ + auto store = GetStore(); + if (store == nullptr) { + LOG_ERROR("transaction already close"); + return { E_ALREADY_CLOSED, -1 }; + } + int deletedRows{}; + auto errorCode = store->Delete(deletedRows, predicates); + return { errorCode, deletedRows }; +} + +void TransactionImpl::AddResultSet(std::weak_ptr resultSet) +{ + std::lock_guard lock(mutex_); + resultSets_.push_back(std::move(resultSet)); +} + +std::shared_ptr TransactionImpl::QueryByStep(const std::string &sql, const Values &args) +{ + auto store = GetStore(); + if (store == nullptr) { + LOG_ERROR("transaction already close"); + return nullptr; + } + auto resultSet = store->QueryByStep(sql, args); + if (resultSet != nullptr) { + AddResultSet(resultSet); + } + return resultSet; +} + +std::shared_ptr TransactionImpl::QueryByStep(const AbsRdbPredicates &predicates, const Fields &columns) +{ + auto store = GetStore(); + if (store == nullptr) { + LOG_ERROR("transaction already close"); + return nullptr; + } + auto resultSet = store->QueryByStep(predicates, columns); + if (resultSet != nullptr) { + AddResultSet(resultSet); + } + return resultSet; +} + +std::pair TransactionImpl::Execute(const std::string &sql, const Values &args) +{ + auto store = GetStore(); + if (store == nullptr) { + LOG_ERROR("transaction already close"); + return { E_ALREADY_CLOSED, ValueObject() }; + } + return store->Execute(sql, args); +} +} diff --git a/relational_store/frameworks/native/rdb/src/value_object.cpp b/relational_store/frameworks/native/rdb/src/value_object.cpp index c950e6f40bbe39f11883ca0ff52cfde25edb0b2a..52e014a5594fc813b459bf6b17771e1df9b17286 100644 --- a/relational_store/frameworks/native/rdb/src/value_object.cpp +++ b/relational_store/frameworks/native/rdb/src/value_object.cpp @@ -341,5 +341,59 @@ int ValueObject::Get(T &output) const output = static_cast(*v); return E_OK; } + +bool ValueObject::operator<(const ValueObject &rhs) const +{ + if (GetType() != rhs.GetType()) { + return GetType() < rhs.GetType(); + } + + bool result = true; + switch (GetType()) { + case TYPE_NULL: + result = false; + break; + case TYPE_INT: + result = int64_t(*this) < int64_t(rhs); + break; + case TYPE_DOUBLE: + result = double(*this) < double(rhs); + break; + case TYPE_STRING: + result = std::string(*this) < std::string(rhs); + break; + case TYPE_BOOL: + result = bool(*this) < bool(rhs); + break; + case TYPE_BLOB: + result = Blob(*this) < Blob(rhs); + break; + case TYPE_ASSET: + result = Asset(*this) < Asset(rhs); + break; + case TYPE_ASSETS: + result = Assets(*this) < Assets(rhs); + break; + case TYPE_VECS: + result = FloatVector(*this) < FloatVector(rhs); + break; + case TYPE_BIGINT: + result = BigInt(*this) < BigInt(rhs); + break; + default: + break; + } + return result; +} + +bool ValueObject::operator==(const ValueObject &rhs) const +{ + return !(rhs < *this || *this < rhs); +} + +bool ValueObject::operator!=(const ValueObject &rhs) const +{ + return (rhs < *this || *this < rhs); +} } // namespace NativeRdb } // namespace OHOS diff --git a/relational_store/interfaces/inner_api/rdb/mock/include/big_integer.h b/relational_store/frameworks/native/rdb/src/values_buckets.cpp similarity index 30% rename from relational_store/interfaces/inner_api/rdb/mock/include/big_integer.h rename to relational_store/frameworks/native/rdb/src/values_buckets.cpp index fd97853b1e10bb43fa6618bafad0c2c8d941e26a..5a8d65bfa41b7982af3930bd2972eba04fbbbd31 100644 --- a/relational_store/interfaces/inner_api/rdb/mock/include/big_integer.h +++ b/relational_store/frameworks/native/rdb/src/values_buckets.cpp @@ -12,35 +12,54 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include "values_buckets.h" +#include "rdb_errno.h" -#ifndef OHOS_DISTRIBUTED_DATA_RELATIONAL_STORE_INTERFACES_INNER_API_RDB_INCLUDE_BIG_INTEGER_H -#define OHOS_DISTRIBUTED_DATA_RELATIONAL_STORE_INTERFACES_INNER_API_RDB_INCLUDE_BIG_INTEGER_H -#include -#include -#include +namespace OHOS { +namespace NativeRdb { +ValuesBuckets::ValuesBuckets() +{ + fields_ = std::make_shared>(); + values_ = std::make_shared>(); +} + +size_t ValuesBuckets::RowSize() const +{ + return buckets_.size(); +} + +std::pair ValuesBuckets::GetFieldsAndValues() const +{ + return { fields_, values_ }; +} -namespace OHOS::NativeRdb { -class BigInteger final { -public: - BigInteger() = default; - ~BigInteger() = default; +void ValuesBuckets::Put(const ValuesBucket &bucket) +{ + BucketType row; + for (const auto &[field, value] : bucket.values_) { + auto fieldResult = fields_->insert(field); + auto valueResult = values_->insert(value); + row.insert(std::make_pair(std::ref(const_cast(*fieldResult.first)), + std::ref(const_cast(*valueResult.first)))); + } + buckets_.push_back(std::move(row)); +} - BigInteger(int64_t value); - BigInteger(int32_t sign, std::vector &&trueForm); - BigInteger(const BigInteger &other); - BigInteger(BigInteger &&other); - BigInteger &operator=(const BigInteger &other); - BigInteger &operator=(BigInteger &&other); - bool operator==(const BigInteger &other); +std::pair ValuesBuckets::Get(size_t row, const FieldType &field) const +{ + ValueObject empty; + std::reference_wrapper emptyRef(empty); + if (row >= buckets_.size()) { + return { E_INVALID_ARGS, emptyRef }; + } - int32_t Sign() const; - size_t Size() const; - const uint64_t *TrueForm() const; + auto &bucket = buckets_[row]; + auto it = bucket.find(field); + if (it == bucket.end()) { + return { E_INVALID_ARGS, emptyRef }; + } - std::vector Value() const; -private: - int32_t sign_ = 0; - std::vector value_; -}; + return { E_OK, it->second }; +} +} } -#endif // OHOS_DISTRIBUTED_DATA_RELATIONAL_STORE_INTERFACES_INNER_API_RDB_INCLUDE_BIG_INTEGER_H diff --git a/relational_store/interfaces/inner_api/rdb/BUILD.gn b/relational_store/interfaces/inner_api/rdb/BUILD.gn index 63e0aad494e690e419f75b3db256b88da9aca21c..927bd2f60836b5ae7ee416f607e0024320e84443 100644 --- a/relational_store/interfaces/inner_api/rdb/BUILD.gn +++ b/relational_store/interfaces/inner_api/rdb/BUILD.gn @@ -29,6 +29,7 @@ base_sources = [ "${relational_store_native_path}/rdb/src/rdb_security_manager.cpp", "${relational_store_native_path}/rdb/src/rdb_sql_statistic.cpp", "${relational_store_native_path}/rdb/src/rdb_sql_utils.cpp", + "${relational_store_native_path}/rdb/src/rdb_store.cpp", "${relational_store_native_path}/rdb/src/rdb_store_config.cpp", "${relational_store_native_path}/rdb/src/rdb_store_impl.cpp", "${relational_store_native_path}/rdb/src/rdb_store_manager.cpp", @@ -39,8 +40,12 @@ base_sources = [ "${relational_store_native_path}/rdb/src/sqlite_utils.cpp", "${relational_store_native_path}/rdb/src/step_result_set.cpp", "${relational_store_native_path}/rdb/src/string_utils.cpp", + "${relational_store_native_path}/rdb/src/trans_db.cpp", + "${relational_store_native_path}/rdb/src/transaction.cpp", + "${relational_store_native_path}/rdb/src/transaction_impl.cpp", "${relational_store_native_path}/rdb/src/value_object.cpp", "${relational_store_native_path}/rdb/src/values_bucket.cpp", + "${relational_store_native_path}/rdb/src/values_buckets.cpp", ] if (!is_ohos) { @@ -273,7 +278,10 @@ if (is_ohos && !build_ohos_sdk) { defines += [ "RDB_SUPPORT_ICU" ] } - defines += [ "WINDOWS_PLATFORM" ] + defines += [ + "WINDOWS_PLATFORM", + "CROSS_PLATFORM", + ] include_dirs += [ "//foundation/distributeddatamgr/kv_store/frameworks/common", "//third_party/sqlite/include", @@ -379,7 +387,10 @@ if (is_ohos && !build_ohos_sdk) { defines += [ "RDB_SUPPORT_ICU" ] } - defines += [ "MAC_PLATFORM" ] + defines += [ + "MAC_PLATFORM", + "CROSS_PLATFORM", + ] include_dirs += [ "//foundation/distributeddatamgr/kv_store/frameworks/common", "//third_party/sqlite/include", @@ -571,7 +582,10 @@ if (is_ohos && !build_ohos_sdk) { base_deps = [ "${plugins_path}/libs/icu:icu_ios" ] ohos_source_set("native_rdb") { - defines = [ "IOS_PLATFORM" ] + defines = [ + "IOS_PLATFORM", + "CROSS_PLATFORM", + ] part_name = "relational_store" sources = base_sources diff --git a/relational_store/interfaces/inner_api/rdb/include/abs_result_set.h b/relational_store/interfaces/inner_api/rdb/include/abs_result_set.h index ffca7af314042f736d31adc1f1da6646b284a58e..98f7df3f37a344edb297942896bf5ad7d1a8d062 100644 --- a/relational_store/interfaces/inner_api/rdb/include/abs_result_set.h +++ b/relational_store/interfaces/inner_api/rdb/include/abs_result_set.h @@ -297,6 +297,11 @@ public: API_EXPORT int Close() override; protected: + /** + * @brief Constructor. + */ + API_EXPORT explicit AbsResultSet(bool safe); + template class Lock { public: @@ -344,7 +349,8 @@ protected: int rowPos_ = INIT_POS; bool isClosed_ = false; int rowCount_ = NO_COUNT; - int32_t lastErr_; + int32_t lastErr_ = E_OK; + private: int InitColumnNames(); diff --git a/relational_store/interfaces/inner_api/rdb/include/asset_value.h b/relational_store/interfaces/inner_api/rdb/include/asset_value.h index c2cd5d350a9e1f27d761d118350ff6152e4efc0d..19b7df057b418da4a773bba7ba9a96c60e3bb75e 100644 --- a/relational_store/interfaces/inner_api/rdb/include/asset_value.h +++ b/relational_store/interfaces/inner_api/rdb/include/asset_value.h @@ -40,6 +40,35 @@ struct AssetValue { std::string size; std::string hash; std::string path; + + bool operator<(const AssetValue &ref) const + { + if (name != ref.name) { + return name < ref.name; + } + if (status != ref.status) { + return status < ref.status; + } + if (id != ref.id) { + return id < ref.id; + } + if (uri != ref.uri) { + return uri < ref.uri; + } + if (createTime != ref.createTime) { + return createTime < ref.createTime; + } + if (modifyTime != ref.modifyTime) { + return modifyTime < ref.modifyTime; + } + if (size != ref.size) { + return size < ref.size; + } + if (hash != ref.hash) { + return hash < ref.hash; + } + return path < ref.path; + } }; } #endif // OHOS_RELATIONAL_STORE_INNER_API_ASSET_VALUE_H diff --git a/relational_store/interfaces/inner_api/rdb/include/big_integer.h b/relational_store/interfaces/inner_api/rdb/include/big_integer.h index 41071f31d2bf2eb177b55dba5a1363d9d515d63e..dc713d664e6471352871b1e76b86c3610c804e95 100644 --- a/relational_store/interfaces/inner_api/rdb/include/big_integer.h +++ b/relational_store/interfaces/inner_api/rdb/include/big_integer.h @@ -33,6 +33,7 @@ public: BigInteger &operator=(const BigInteger &other); BigInteger &operator=(BigInteger &&other); bool operator==(const BigInteger &other); + bool operator<(const BigInteger &rhs); int32_t Sign() const; size_t Size() const; diff --git a/relational_store/interfaces/inner_api/rdb/include/rdb_errno.h b/relational_store/interfaces/inner_api/rdb/include/rdb_errno.h index 4ddd9bbd7b22fe674028bc6b088de9da5b7f2752..3f9c5bf856b6d91b2f1e89f52b5d6ff2d136bded 100644 --- a/relational_store/interfaces/inner_api/rdb/include/rdb_errno.h +++ b/relational_store/interfaces/inner_api/rdb/include/rdb_errno.h @@ -43,372 +43,372 @@ constexpr int E_ERROR = E_BASE; /** * @brief The error code for common invalid args. */ -constexpr int E_INVALID_ARGS = (E_BASE + 1); +constexpr int E_INVALID_ARGS = (E_BASE + 0x1); /** * @brief The error code for upgrade the read-only store. */ -constexpr int E_CANNOT_UPDATE_READONLY = (E_BASE + 2); +constexpr int E_CANNOT_UPDATE_READONLY = (E_BASE + 0x2); /** * @brief The error code when deleting a file fails. */ -constexpr int E_REMOVE_FILE = (E_BASE + 3); +constexpr int E_REMOVE_FILE = (E_BASE + 0x3); /** * @brief The error code indicates that the SQL statement is incorrect. */ -constexpr int E_INCORRECT_SQL = (E_BASE + 4); +constexpr int E_INCORRECT_SQL = (E_BASE + 0x4); /** * @brief The error code for a table name is empty. */ -constexpr int E_EMPTY_TABLE_NAME = (E_BASE + 5); +constexpr int E_EMPTY_TABLE_NAME = (E_BASE + 0x5); /** * @brief The error code for a values bucket is empty. */ -constexpr int E_EMPTY_VALUES_BUCKET = (E_BASE + 6); +constexpr int E_EMPTY_VALUES_BUCKET = (E_BASE + 0x6); /** * @brief The error code when the sql is not select. */ -constexpr int E_NOT_SELECT = (E_BASE + 7); +constexpr int E_NOT_SELECT = (E_BASE + 0x7); /** * @brief The error code for the column out of bounds. */ -constexpr int E_COLUMN_OUT_RANGE = (E_BASE + 8); +constexpr int E_COLUMN_OUT_RANGE = (E_BASE + 0x8); /** * @brief The error code for the column type is invalid. */ -constexpr int E_INVALID_COLUMN_TYPE = (E_BASE + 9); +constexpr int E_INVALID_COLUMN_TYPE = (E_BASE + 0x9); /** * @brief The error code for a file name is empty. */ -constexpr int E_EMPTY_FILE_NAME = (E_BASE + 10); +constexpr int E_EMPTY_FILE_NAME = (E_BASE + 0xa); /** * @brief The error for the current file path is invalid. */ -constexpr int E_INVALID_FILE_PATH = (E_BASE + 11); +constexpr int E_INVALID_FILE_PATH = (E_BASE + 0xb); /** * @brief The error code when using transactions. */ -constexpr int E_TRANSACTION_IN_EXECUTE = (E_BASE + 12); +constexpr int E_TRANSACTION_IN_EXECUTE = (E_BASE + 0xc); /** * @brief The error code for the row out of bounds. */ -constexpr int E_ROW_OUT_RANGE = (E_BASE + 13); +constexpr int E_ROW_OUT_RANGE = (E_BASE + 0xd); /** * @brief The error code when execute write operation in read connection. */ -constexpr int E_EXECUTE_WRITE_IN_READ_CONNECTION = (E_BASE + 14); +constexpr int E_EXECUTE_WRITE_IN_READ_CONNECTION = (E_BASE + 0xe); /** * @brief The error code for execute begin transaction operation in read connection. */ -constexpr int E_BEGIN_TRANSACTION_IN_READ_CONNECTION = (E_BASE + 15); +constexpr int E_BEGIN_TRANSACTION_IN_READ_CONNECTION = (E_BASE + 0xf); /** * @brief The error code for there are no transactions in this connection. */ -constexpr int E_NO_TRANSACTION_IN_SESSION = (E_BASE + 16); +constexpr int E_NO_TRANSACTION_IN_SESSION = (E_BASE + 0x10); /** * @brief The error code when begin more step query in one session. */ -constexpr int E_MORE_STEP_QUERY_IN_ONE_SESSION = (E_BASE + 17); +constexpr int E_MORE_STEP_QUERY_IN_ONE_SESSION = (E_BASE + 0x11); /** * @brief The error code when the current statement doesn't contains one row result data. */ -constexpr int E_NO_ROW_IN_QUERY = (E_BASE + 18); +constexpr int E_NO_ROW_IN_QUERY = (E_BASE + 0x12); /** * @brief The error code for the bind arguments count is invalid. */ -constexpr int E_INVALID_BIND_ARGS_COUNT = (E_BASE + 19); +constexpr int E_INVALID_BIND_ARGS_COUNT = (E_BASE + 0x13); /** * @brief The error code for the object type is invalid. */ -constexpr int E_INVALID_OBJECT_TYPE = (E_BASE + 20); +constexpr int E_INVALID_OBJECT_TYPE = (E_BASE + 0x14); /** * @brief The error code for the conflict flag is invalid. */ -constexpr int E_INVALID_CONFLICT_FLAG = (E_BASE + 21); +constexpr int E_INVALID_CONFLICT_FLAG = (E_BASE + 0x15); /** * @brief The error code for having clause not in group. */ -constexpr int E_HAVING_CLAUSE_NOT_IN_GROUP_BY = (E_BASE + 22); +constexpr int E_HAVING_CLAUSE_NOT_IN_GROUP_BY = (E_BASE + 0x16); /** * @brief The error code for not supported by step result set. */ -constexpr int E_NOT_SUPPORTED_BY_STEP_RESULT_SET = (E_BASE + 23); +constexpr int E_NOT_SUPPORTED_BY_STEP_RESULT_SET = (E_BASE + 0x17); /** * @brief The error code for step result current tid not equal to object's tid. */ -constexpr int E_STEP_RESULT_SET_CROSS_THREADS = (E_BASE + 24); +constexpr int E_STEP_RESULT_SET_CROSS_THREADS = (E_BASE + 0x18); /** * @brief The error code when the result query was not executed. */ -constexpr int E_NOT_INIT = (E_BASE + 25); +constexpr int E_NOT_INIT = (E_BASE + 0x19); /** * @brief The error code for the result set cursor is after the last row. */ -constexpr int E_NO_MORE_ROWS = (E_BASE + 26); +constexpr int E_NO_MORE_ROWS = (E_BASE + 0x1a); /** * @brief The error code for the result set query exceeded. */ -constexpr int E_STEP_RESULT_QUERY_EXCEEDED = (E_BASE + 27); +constexpr int E_STEP_RESULT_QUERY_EXCEEDED = (E_BASE + 0x1b); /** * @brief The error code for the statement not prepared. */ -constexpr int E_STATEMENT_NOT_PREPARED = (E_BASE + 28); +constexpr int E_STATEMENT_NOT_PREPARED = (E_BASE + 0x1c); /** * @brief The error code for the result set is incorrect. */ -constexpr int E_EXECUTE_RESULT_INCORRECT = (E_BASE + 29); +constexpr int E_EXECUTE_RESULT_INCORRECT = (E_BASE + 0x1d); /** * @brief The error code when the result set is closed. */ -constexpr int E_ALREADY_CLOSED = (E_BASE + 30); +constexpr int E_ALREADY_CLOSED = (E_BASE + 0x1e); /** * @brief The error code when input relative path. */ -constexpr int E_RELATIVE_PATH = (E_BASE + 31); +constexpr int E_RELATIVE_PATH = (E_BASE + 0x1f); /** * @brief The error code for the new encrypt key is empty. */ -constexpr int E_EMPTY_NEW_ENCRYPT_KEY = (E_BASE + 32); +constexpr int E_EMPTY_NEW_ENCRYPT_KEY = (E_BASE + 0x20); /** * @brief The error code for change unencrypted to encrypted. */ -constexpr int E_CHANGE_UNENCRYPTED_TO_ENCRYPTED = (E_BASE + 33); +constexpr int E_CHANGE_UNENCRYPTED_TO_ENCRYPTED = (E_BASE + 0x21); /** * @brief The error code for database busy. */ -constexpr int E_DATABASE_BUSY = (E_BASE + 34); +constexpr int E_DATABASE_BUSY = (E_BASE + 0x22); /** * @brief The error code when the statement not initialized. */ -constexpr int E_STORE_CLOSED = (E_BASE + 35); +constexpr int E_STORE_CLOSED = (E_BASE + 0x23); /** * @brief The error code for the attach is not supported in WAL journal mode. */ -constexpr int E_NOT_SUPPORTED_ATTACH_IN_WAL_MODE = (E_BASE + 36); +constexpr int E_NOT_SUPPORTED_ATTACH_IN_WAL_MODE = (E_BASE + 0x24); /** * @brief The error code when create folder failed. */ -constexpr int E_CREATE_FOLDER_FAIL = (E_BASE + 37); +constexpr int E_CREATE_FOLDER_FAIL = (E_BASE + 0x25); /** * @brief The error for SQL builder normalize failed. */ -constexpr int E_SQLITE_SQL_BUILDER_NORMALIZE_FAIL = (E_BASE + 38); +constexpr int E_SQLITE_SQL_BUILDER_NORMALIZE_FAIL = (E_BASE + 0x26); /** * @brief The error for store session not give connection temporarily. */ -constexpr int E_STORE_SESSION_NOT_GIVE_CONNECTION_TEMPORARILY = (E_BASE + 39); +constexpr int E_STORE_SESSION_NOT_GIVE_CONNECTION_TEMPORARILY = (E_BASE + 0x27); /** * @brief The error for store session not current transaction. */ -constexpr int E_STORE_SESSION_NO_CURRENT_TRANSACTION = (E_BASE + 40); +constexpr int E_STORE_SESSION_NO_CURRENT_TRANSACTION = (E_BASE + 0x28); /** * @brief The error for not supported the current operation. */ -constexpr int E_NOT_SUPPORTED = (E_BASE + 41); +constexpr int E_NOT_SUPPORTED = (E_BASE + 0x29); /** * @brief The error for the current parcel is invalid. */ -constexpr int E_INVALID_PARCEL = (E_BASE + 42); +constexpr int E_INVALID_PARCEL = (E_BASE + 0x2a); /** * @brief The error code when using sqlite3_step function failed. */ -constexpr int E_QUERY_IN_EXECUTE = (E_BASE + 43); +constexpr int E_QUERY_IN_EXECUTE = (E_BASE + 0x2b); /** * @brief The error for set persist WAL. */ -constexpr int E_SET_PERSIST_WAL = (E_BASE + 44); +constexpr int E_SET_PERSIST_WAL = (E_BASE + 0x2c); /** * @brief The error when the database does not exist. */ -constexpr int E_DB_NOT_EXIST = (E_BASE + 45); +constexpr int E_DB_NOT_EXIST = (E_BASE + 0x2d); /** * @brief The error when the read connection count is overload. */ -constexpr int E_ARGS_READ_CON_OVERLOAD = (E_BASE + 46); +constexpr int E_ARGS_READ_CON_OVERLOAD = (E_BASE + 0x2e); /** * @brief The error when the wal file size over default limit. */ -static constexpr int E_WAL_SIZE_OVER_LIMIT = (E_BASE + 47); +static constexpr int E_WAL_SIZE_OVER_LIMIT = (E_BASE + 0x2f); /** * @brief The error when the connection count is used up. */ -static constexpr int E_CON_OVER_LIMIT = (E_BASE + 48); +static constexpr int E_CON_OVER_LIMIT = (E_BASE + 0x30); /** * @brief The error when the sharedblock unit is null. */ -static constexpr int E_NULL_OBJECT = (E_BASE + 49); +static constexpr int E_NULL_OBJECT = (E_BASE + 0x31); /** * @brief Failed to get DataObsMgrClient. */ -static constexpr int E_GET_DATAOBSMGRCLIENT_FAIL = (E_BASE + 50); +static constexpr int E_GET_DATAOBSMGRCLIENT_FAIL = (E_BASE + 0x32); /** * @brief The error when the type of the distributed table does not match. */ -static constexpr int E_TYPE_MISMATCH = (E_BASE + 51); +static constexpr int E_TYPE_MISMATCH = (E_BASE + 0x33); /** * @brief Insertion failed because database is full. */ -static constexpr int E_SQLITE_FULL = (E_BASE + 52); +static constexpr int E_SQLITE_FULL = (E_BASE + 0x34); /** * @brief The error when sql is not supported in execute */ -static constexpr int E_NOT_SUPPORT_THE_SQL = (E_BASE + 53); +static constexpr int E_NOT_SUPPORT_THE_SQL = (E_BASE + 0x35); /** * @brief The database is already attached. */ -static constexpr int E_ATTACHED_DATABASE_EXIST = (E_BASE + 54); +static constexpr int E_ATTACHED_DATABASE_EXIST = (E_BASE + 0x36); /** * @brief Generic error. */ -static constexpr int E_SQLITE_ERROR = (E_BASE + 55); +static constexpr int E_SQLITE_ERROR = (E_BASE + 0x37); /** * @brief The database disk image is malformed. Used by vector db, too. */ -static constexpr int E_SQLITE_CORRUPT = (E_BASE + 56); +static constexpr int E_SQLITE_CORRUPT = (E_BASE + 0x38); /** * @brief The error when unlocking data needs to be compensated sync */ -static constexpr int E_WAIT_COMPENSATED_SYNC = (E_BASE + 57); +static constexpr int E_WAIT_COMPENSATED_SYNC = (E_BASE + 0x39); /** * @brief Callback routine requested an abort. */ -static constexpr int E_SQLITE_ABORT = (E_BASE + 58); +static constexpr int E_SQLITE_ABORT = (E_BASE + 0x3a); /** * @brief Access permission denied. */ -static constexpr int E_SQLITE_PERM = (E_BASE + 59); +static constexpr int E_SQLITE_PERM = (E_BASE + 0x3b); /** * @brief The database file is locked. */ -static constexpr int E_SQLITE_BUSY = (E_BASE + 60); +static constexpr int E_SQLITE_BUSY = (E_BASE + 0x3c); /** * @brief A table in the database is locked. */ -static constexpr int E_SQLITE_LOCKED = (E_BASE + 61); +static constexpr int E_SQLITE_LOCKED = (E_BASE + 0x3d); /** * @brief A malloc() failed. */ -static constexpr int E_SQLITE_NOMEM = (E_BASE + 62); +static constexpr int E_SQLITE_NOMEM = (E_BASE + 0x3e); /** * @brief Attempt to write a readonly database. */ -static constexpr int E_SQLITE_READONLY = (E_BASE + 63); +static constexpr int E_SQLITE_READONLY = (E_BASE + 0x3f); /** * @brief Some kind of disk I/O error occurred. */ -static constexpr int E_SQLITE_IOERR = (E_BASE + 64); +static constexpr int E_SQLITE_IOERR = (E_BASE + 0x40); /** * @brief Unable to open the database file. */ -static constexpr int E_SQLITE_CANTOPEN = (E_BASE + 65); +static constexpr int E_SQLITE_CANTOPEN = (E_BASE + 0x41); /** * @brief String or BLOB exceeds size limit. */ -static constexpr int E_SQLITE_TOOBIG = (E_BASE + 66); +static constexpr int E_SQLITE_TOOBIG = (E_BASE + 0x42); /** * @brief Abort due to constraint violation. */ -static constexpr int E_SQLITE_CONSTRAINT = (E_BASE + 67); +static constexpr int E_SQLITE_CONSTRAINT = (E_BASE + 0x43); /** * @brief Data type mismatch. */ -static constexpr int E_SQLITE_MISMATCH = (E_BASE + 68); +static constexpr int E_SQLITE_MISMATCH = (E_BASE + 0x44); /** * @brief Library used incorrectly. */ -static constexpr int E_SQLITE_MISUSE = (E_BASE + 69); +static constexpr int E_SQLITE_MISUSE = (E_BASE + 0x45); /** * @brief Config changed. */ -static constexpr int E_CONFIG_INVALID_CHANGE = (E_BASE + 70); +static constexpr int E_CONFIG_INVALID_CHANGE = (E_BASE + 0x46); /** * @brief Not get service. */ -static constexpr int E_SERVICE_NOT_FOUND = (E_BASE + 71); +static constexpr int E_SERVICE_NOT_FOUND = (E_BASE + 0x47); /** * @brief Database schema has changed. */ -static constexpr int E_SQLITE_SCHEMA = (E_BASE + 72); +static constexpr int E_SQLITE_SCHEMA = (E_BASE + 0x48); /** - * @brief Database backup was interrupted. + * @brief Operation cancel. */ -static constexpr int E_BACKUP_INTERRUPT = (E_BASE + 0x49); +static constexpr int E_CANCEL = (E_BASE + 0x49); /** - * @brief Backup interrupt operation is invalid + * @brief Do not use except relational_store */ -static constexpr int E_INVALID_INTERRUPT = (E_BASE + 0x4a); +static constexpr int E_INNER_WARNING = (E_BASE + 0x4c); } // namespace NativeRdb } // namespace OHOS 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 d7b66279896a52a94161022009f2af0bde202cbb..9cd34fadd4d55e3fda0f4ab99a25565f8db27b8c 100644 --- a/relational_store/interfaces/inner_api/rdb/include/rdb_service.h +++ b/relational_store/interfaces/inner_api/rdb/include/rdb_service.h @@ -42,7 +42,7 @@ public: virtual int32_t SetDistributedTables( const RdbSyncerParam ¶m, const std::vector &tables, - const std::vector &references, int32_t type = DISTRIBUTED_DEVICE) = 0; + const std::vector &references, bool isRebuild, int32_t type = DISTRIBUTED_DEVICE) = 0; virtual int32_t Sync(const RdbSyncerParam ¶m, const Option &option, const PredicatesMemo &predicates, const AsyncDetail &async) = 0; diff --git a/relational_store/interfaces/inner_api/rdb/include/rdb_store.h b/relational_store/interfaces/inner_api/rdb/include/rdb_store.h index 8f1b9c5a9ad54c607ac442da2e6d4ca9ce73ceca..b9fd988284c2d750b36e1b23f835c238254c139e 100644 --- a/relational_store/interfaces/inner_api/rdb/include/rdb_store.h +++ b/relational_store/interfaces/inner_api/rdb/include/rdb_store.h @@ -16,20 +16,22 @@ #ifndef NATIVE_RDB_RDB_STORE_H #define NATIVE_RDB_RDB_STORE_H -#include #include +#include #include #include #include "abs_rdb_predicates.h" #include "abs_shared_result_set.h" -#include "result_set.h" -#include "value_object.h" -#include "values_bucket.h" -#include "rdb_types.h" #include "rdb_common.h" #include "rdb_errno.h" #include "rdb_store_config.h" +#include "rdb_types.h" +#include "result_set.h" +#include "transaction.h" +#include "value_object.h" +#include "values_bucket.h" +#include "values_buckets.h" namespace OHOS::NativeRdb { class API_EXPORT RdbStore { @@ -82,125 +84,219 @@ public: */ using Date = DistributedRdb::Date; + /** + * @brief Use Fields replace std::vector columns. + */ + using Fields = std::vector; + + /** + * @brief Use Olds replace std::vector args. + */ + using Olds = std::vector; + + /** + * @brief Use Values replace std::vector args. + */ + using Values = std::vector; + + /** + * @brief Use Row replace ValuesBucket. + */ + using Row = ValuesBucket; + + /** + * @brief Use Rows replace std::vector. + */ + using Rows = std::vector; + + /** + * @brief Use Rows replace std::vector. + */ + using RefRows = ValuesBuckets; + + /** + * @brief Use Resolution replace ConflictResolution. + */ + using Resolution = ConflictResolution; + + class API_EXPORT ModifyTime { + public: + ModifyTime() = default; + API_EXPORT ModifyTime(std::shared_ptr result, std::map, PRIKey> hashKeys, + bool isFromRowId); + API_EXPORT operator std::map(); + API_EXPORT operator std::shared_ptr(); + API_EXPORT PRIKey GetOriginKey(const std::vector &hash); + API_EXPORT size_t GetMaxOriginKeySize(); + API_EXPORT bool NeedConvert() const; + + private: + std::shared_ptr result_; + std::map, PRIKey> hash_; + size_t maxOriginKeySize_ = sizeof(int64_t); + bool isFromRowId_{ false }; + }; + + static constexpr Resolution NO_ACTION = ConflictResolution::ON_CONFLICT_NONE; + /** * @brief Destructor. */ - virtual ~RdbStore() {} + virtual ~RdbStore() = default; /** * @brief Inserts a row of data into the target table. * * @param table Indicates the target table. - * @param values Indicates the row of data {@link ValuesBucket} to be inserted into the table. + * @param row Indicates the row of data {@link ValuesBucket} to be inserted into the table. + * @param resolution Indicates the {@link ConflictResolution} to insert data into the table. */ - virtual int Insert(int64_t &outRowId, const std::string &table, const ValuesBucket &values) = 0; + virtual std::pair Insert(const std::string &table, const Row &row, Resolution resolution = NO_ACTION); /** - * @brief Inserts a batch of data into the target table. + * @brief Inserts a row of data into the target table. * * @param table Indicates the target table. - * @param initialBatchValue Indicates the rows of data {@link ValuesBucket} to be inserted into the table. + * @param row Indicates the row of data {@link ValuesBucket} to be inserted into the table. */ - virtual int BatchInsert( - int64_t &outInsertNum, const std::string &table, const std::vector &values) = 0; + virtual int Insert(int64_t &outRowId, const std::string &table, const Row &row); + + /** + * @brief Inserts a row of data into the target table. + * + * @param table Indicates the target table. + * @param row Indicates the row of data {@link ValuesBucket} to be inserted into the table. + * @param resolution Indicates the {@link ConflictResolution} to insert data into the table. + */ + [[deprecated("Use Insert(const std::string &, const Row &, Resolution) instead.")]] + virtual int InsertWithConflictResolution(int64_t &outRowId, const std::string &table, const Row &row, + Resolution resolution = NO_ACTION); /** * @brief Replaces a row of data into the target table. * * @param table Indicates the target table. - * @param initialBatchValue Indicates the row of data {@link ValuesBucket} to be replaced into the table. + * @param row Indicates the row of data {@link ValuesBucket} to be replaced into the table. */ - virtual int Replace(int64_t &outRowId, const std::string &table, const ValuesBucket &values) = 0; + virtual int Replace(int64_t &outRowId, const std::string &table, const Row &row); /** - * @brief Inserts a row of data into the target table. + * @brief Inserts a batch of data into the target table. * * @param table Indicates the target table. - * @param initialValues Indicates the row of data {@link ValuesBucket} to be inserted into the table. - * @param conflictResolution Indicates the {@link ConflictResolution} to insert data into the table. + * @param rows Indicates the rows of data {@link ValuesBucket} to be inserted into the table. */ - virtual int InsertWithConflictResolution(int64_t &outRowId, const std::string &table, - const ValuesBucket &initialValues, - ConflictResolution conflictResolution = ConflictResolution::ON_CONFLICT_NONE) = 0; + virtual int BatchInsert(int64_t &outInsertNum, const std::string &table, const Rows &rows); + + /** + * @brief Inserts a batch of data into the target table. + * + * @param table Indicates the target table. + * @param values Indicates the rows of data {@link ValuesBuckets} to be inserted into the table. + */ + virtual std::pair BatchInsert(const std::string &table, const RefRows &rows); /** * @brief Updates data in the database based on specified conditions. * * @param table Indicates the target table. - * @param values Indicates the row of data to be updated in the database. + * @param row Indicates the row of data to be updated in the database. * The key-value pairs are associated with column names of the database table. * @param whereClause Indicates the where clause. - * @param whereArgs Indicates the where arguments. + * @param args Indicates the where arguments. */ - [[deprecated("Use Update(int &, const std::string &, const ValuesBucket &, const std::string &," - " const std::vector &) instead.")]] - virtual int Update(int &changedRows, const std::string &table, const ValuesBucket &values, - const std::string &whereClause, const std::vector &whereArgs) = 0; + virtual std::pair Update(const std::string &table, const Row &row, const std::string &where = "", + const Values &args = {}, Resolution resolution = NO_ACTION); /** * @brief Updates data in the database based on specified conditions. * * @param table Indicates the target table. + * @param row Indicates the row of data to be updated in the database. + * The key-value pairs are associated with column names of the database table. + * @param whereClause Indicates the where clause. + * @param args Indicates the where arguments. + */ + virtual int Update(int &changedRows, const std::string &table, const Row &row, const std::string &whereClause = "", + const Values &args = {}); + + /** + * @brief Updates data in the database based on a a specified instance object of AbsRdbPredicates. + * * @param values Indicates the row of data to be updated in the database. * The key-value pairs are associated with column names of the database table. + * @param predicates Indicates the specified update condition by the instance object of {@link AbsRdbPredicates}. + */ + virtual int Update(int &changedRows, const Row &row, const AbsRdbPredicates &predicates); + + /** + * @brief Updates data in the database based on specified conditions. + * + * @param table Indicates the target table. + * @param row Indicates the row of data to be updated in the database. + * The key-value pairs are associated with column names of the database table. * @param whereClause Indicates the where clause. - * @param bindArgs Indicates the where arguments. + * @param args Indicates the where arguments. */ - virtual int Update(int &changedRows, const std::string &table, const ValuesBucket &values, - const std::string &whereClause = "", const std::vector &bindArgs = {}) = 0; + [[deprecated("Use Update(int &, const std::string &, const Row &, const std::string &, const Values &) instead.")]] + virtual int Update(int &changedRows, const std::string &table, const Row &row, const std::string &whereClause, + const Olds &args); /** * @brief Updates data in the database based on a a specified instance object of RdbPredicates. * * @param table Indicates the target table. - * @param values Indicates the row of data to be updated in the database. + * @param row Indicates the row of data to be updated in the database. * The key-value pairs are associated with column names of the database table. * @param whereClause Indicates the where clause. - * @param whereArgs Indicates the where arguments. - * @param conflictResolution Indicates the {@link ConflictResolution} to insert data into the table. + * @param args Indicates the where arguments. + * @param resolution Indicates the {@link ConflictResolution} to insert data into the table. */ - [[deprecated("Use UpdateWithConflictResolution(int &, const std::string &, const ValuesBucket &, " - "const std::string &, const std::vector &," - " ConflictResolution conflictResolution) instead.")]] - virtual int UpdateWithConflictResolution(int &changedRows, const std::string &table, const ValuesBucket &values, - const std::string &whereClause, const std::vector &whereArgs, - ConflictResolution conflictResolution = ConflictResolution::ON_CONFLICT_NONE) = 0; + [[deprecated("Use UpdateWithConflictResolution(int &, const std::string &, const Row &, const std::string &, " + "const Values &, ConflictResolution conflictResolution) instead.")]] + virtual int UpdateWithConflictResolution(int &changedRows, const std::string &table, const Row &row, + const std::string &whereClause, const Olds &args, Resolution resolution = NO_ACTION); /** * @brief Updates data in the database based on a a specified instance object of RdbPredicates. * * @param table Indicates the target table. - * @param values Indicates the row of data to be updated in the database. + * @param row Indicates the row of data to be updated in the database. * The key-value pairs are associated with column names of the database table. * @param whereClause Indicates the where clause. - * @param whereArgs Indicates the where arguments. - * @param conflictResolution Indicates the {@link ConflictResolution} to insert data into the table. + * @param args Indicates the where arguments. + * @param resolution Indicates the {@link ConflictResolution} to update data into the table. */ - virtual int UpdateWithConflictResolution(int &changedRows, const std::string &table, - const ValuesBucket &values, const std::string &whereClause = "", const std::vector &bindArgs = {}, - ConflictResolution conflictResolution = ConflictResolution::ON_CONFLICT_NONE) = 0; + virtual int UpdateWithConflictResolution(int &changedRows, const std::string &table, const Row &row, + const std::string &whereClause = "", const Values &args = {}, Resolution resolution = NO_ACTION); /** * @brief Deletes data from the database based on specified conditions. * * @param table Indicates the target table. * @param whereClause Indicates the where clause. - * @param whereArgs Indicates the where arguments. + * @param args Indicates the where arguments. */ - [[deprecated("Use Delete(int &, const std::string &, const std::string &, const std::vector &) " - "instead.")]] + [[deprecated("Use Delete(int &, const std::string &, const std::string &, const Values &) instead.")]] virtual int Delete(int &deletedRows, const std::string &table, const std::string &whereClause, - const std::vector &whereArgs) = 0; + const Olds &args); + + /** + * @brief Deletes data from the database based on a specified instance object of AbsRdbPredicates. + * + * @param predicates Indicates the specified update condition by the instance object of {@link AbsRdbPredicates}. + */ + virtual int Delete(int &deletedRows, const AbsRdbPredicates &predicates); /** * @brief Deletes data from the database based on specified conditions. * * @param table Indicates the target table. * @param whereClause Indicates the where clause. - * @param bindArgs Indicates the where arguments. + * @param args Indicates the where arguments. */ virtual int Delete(int &deletedRows, const std::string &table, const std::string &whereClause = "", - const std::vector &bindArgs = {}) = 0; + const Values &args = {}) = 0; /** * @brief Queries data in the database based on specified conditions. @@ -209,45 +305,51 @@ public: * @param table Indicates the target table. * @param columns Indicates the columns to query. If the value is empty array, the query applies to all columns. * @param whereClause Indicates the selection. - * @param bindArgs Indicates the selection arguments. + * @param args Indicates the selection arguments. * @param groupBy Indicates the groupBy argument. * @param indexName Indicates the index by argument. * @param orderBy Indicates the orderBy argument. * @param limit Indicates the limit argument. */ + [[deprecated("Use Query(int &, const std::string &, const std::string &, const Values &) instead.")]] virtual std::shared_ptr Query(int &errCode, bool distinct, const std::string &table, - const std::vector &columns, const std::string &whereClause = "", - const std::vector &bindArgs = {}, const std::string &groupBy = "", - const std::string &indexName = "", const std::string &orderBy = "", - const int &limit = AbsPredicates::INIT_LIMIT_VALUE, const int &offset = AbsPredicates::INIT_LIMIT_VALUE) = 0; + const Fields &columns, const std::string &whereClause = "", const Values &args = {}, + const std::string &groupBy = "", const std::string &indexName = "", const std::string &orderBy = "", + const int &limit = AbsPredicates::INIT_LIMIT_VALUE, const int &offset = AbsPredicates::INIT_LIMIT_VALUE); + + /** + * @brief Queries data in the database based on specified conditions. + * + * @param predicates Indicates the specified query condition by the instance object of {@link AbsRdbPredicates}. + * @param columns Indicates the columns to query. If the value is empty array, the query applies to all columns. + */ + virtual std::shared_ptr Query(const AbsRdbPredicates &predicates, const Fields &columns = {}); /** * @brief Queries data in the database based on SQL statement. * * @param sql Indicates the SQL statement to execute. - * @param sqlArgs Indicates the selection arguments. + * @param args Indicates the selection arguments. */ - [[deprecated("Use QuerySql(const std::string &, const std::vector &) instead.")]] - virtual std::shared_ptr QuerySql( - const std::string &sql, const std::vector &sqlArgs) = 0; + [[deprecated("Use QuerySql(const std::string &, const Values &) instead.")]] + virtual std::shared_ptr QuerySql(const std::string &sql, const Olds &args); /** * @brief Queries data in the database based on SQL statement. * * @param sql Indicates the SQL statement to execute. - * @param bindArgs Indicates the selection arguments. + * @param args Indicates the selection arguments. */ - virtual std::shared_ptr QuerySql( - const std::string &sql, const std::vector &bindArgs = {}) = 0; + virtual std::shared_ptr QuerySql(const std::string &sql, const Values &args = {}) = 0; /** * @brief Queries data in the database based on SQL statement. * * @param sql Indicates the SQL statement to execute. - * @param sqlArgs Indicates the selection arguments. + * @param args Indicates the selection arguments. */ - [[deprecated("Use ExecuteSql(const std::string &, const std::vector &) instead.")]] - virtual std::shared_ptr QueryByStep(const std::string &sql, const std::vector &sqlArgs) = 0; + [[deprecated("Use QueryByStep(const std::string &, const Values &) instead.")]] + virtual std::shared_ptr QueryByStep(const std::string &sql, const Olds &args); /** * @brief Queries data in the database based on SQL statement. @@ -255,73 +357,94 @@ public: * @param sql Indicates the SQL statement to execute. * @param args Indicates the selection arguments. */ - virtual std::shared_ptr QueryByStep(const std::string &sql, - const std::vector &args = {}) = 0; + virtual std::shared_ptr QueryByStep(const std::string &sql, const Values &args = {}) = 0; + + /** + * @brief Queries data in the database based on specified conditions. + * + * @param predicates Indicates the specified query condition by the instance object of {@link AbsRdbPredicates}. + * @param columns Indicates the columns to query. If the value is empty array, the query applies to all columns. + */ + virtual std::shared_ptr QueryByStep(const AbsRdbPredicates &predicates, const Fields &columns = {}); + + /** + * @brief Queries remote data in the database based on specified conditions before Synchronizing Data. + * + * @param device Indicates specified remote device. + * @param predicates Indicates the specified query condition by the instance object of {@link AbsRdbPredicates}. + * @param columns Indicates the columns to query. If the value is empty array, the query applies to all columns. + */ + virtual std::shared_ptr RemoteQuery(const std::string &device, const AbsRdbPredicates &predicates, + const Fields &columns, int &errCode); + + /** + * @brief Queries data in the database based on specified conditions. + * + * @param predicates Indicates the specified query condition by the instance object of {@link AbsRdbPredicates}. + * @param columns Indicates the columns to query. If the value is empty array, the query applies to all columns. + */ + virtual std::pair> QuerySharingResource(const AbsRdbPredicates &predicates, + const Fields &columns); /** * @brief Executes an SQL statement that contains specified parameters. * * @param sql Indicates the SQL statement to execute. - * @param bindArgs Indicates the {@link ValueObject} values of the parameters in the SQL statement. + * @param args Indicates the {@link ValueObject} values of the parameters in the SQL statement. */ - virtual int ExecuteSql(const std::string &sql, const std::vector &bindArgs = {}) = 0; + [[deprecated("Use Execute(const std::string &, const Values &, int64_t) instead.")]] + virtual int ExecuteSql(const std::string &sql, const Values &args = {}); /** * @brief Executes an SQL statement that contains specified parameters and * get two values of type int and ValueObject. * * @param sql Indicates the SQL statement to execute. - * @param bindArgs Indicates the {@link ValueObject} values of the parameters in the SQL statement. + * @param args Indicates the {@link ValueObject} values of the parameters in the SQL statement. */ - virtual std::pair Execute(const std::string &sql, - const std::vector &bindArgs = {}, int64_t trxId = 0) - { - return { E_NOT_SUPPORT, ValueObject() }; - } + virtual std::pair Execute(const std::string &sql, const Values &args = {}, int64_t trxId = 0); /** * @brief Executes an SQL statement that contains specified parameters and get a long integer value. * * @param sql Indicates the SQL statement to execute. - * @param bindArgs Indicates the {@link ValueObject} values of the parameters in the SQL statement. + * @param args Indicates the {@link ValueObject} values of the parameters in the SQL statement. */ - virtual int ExecuteAndGetLong(int64_t &outValue, const std::string &sql, - const std::vector &bindArgs = {}) = 0; + [[deprecated("Use Execute(const std::string &, const Values &, int64_t) instead.")]] + virtual int ExecuteAndGetLong(int64_t &outValue, const std::string &sql, const Values &args = {}); /** * @brief Executes an SQL statement that contains specified parameters. * * @param sql Indicates the SQL statement to execute. - * @param bindArgs Indicates the {@link ValueObject} values of the parameters in the SQL statement. + * @param args Indicates the {@link ValueObject} values of the parameters in the SQL statement. */ - virtual int ExecuteAndGetString(std::string &outValue, const std::string &sql, - const std::vector &bindArgs = {}) = 0; + [[deprecated("Use Execute(const std::string &, const Values &, int64_t) instead.")]] + virtual int ExecuteAndGetString(std::string &outValue, const std::string &sql, const Values &args = {}); /** * @brief Executes for last insert row id that contains specified parameters. * * @param sql Indicates the SQL statement to execute. - * @param bindArgs Indicates the {@link ValueObject} values of the parameters in the SQL statement. + * @param args Indicates the {@link ValueObject} values of the parameters in the SQL statement. */ - virtual int ExecuteForLastInsertedRowId(int64_t &outValue, const std::string &sql, - const std::vector &bindArgs = {}) = 0; + virtual int ExecuteForLastInsertedRowId(int64_t &outValue, const std::string &sql, const Values &args = {}); /** * @brief Executes for change row count that contains specified parameters. * * @param sql Indicates the SQL statement to execute. - * @param bindArgs Indicates the {@link ValueObject} values of the parameters in the SQL statement. + * @param args Indicates the {@link ValueObject} values of the parameters in the SQL statement. */ - virtual int ExecuteForChangedRowCount(int64_t &outValue, const std::string &sql, - const std::vector &bindArgs = {}) = 0; + virtual int ExecuteForChangedRowCount(int64_t &outValue, const std::string &sql, const Values &args = {}); /** * @brief Restores a database from a specified encrypted or unencrypted database file. * * @param databasePath Indicates the database file path. - * @param destEncryptKey Indicates the database encrypt key. + * @param encryptKey Indicates the database encrypt key. */ - virtual int Backup(const std::string &databasePath, const std::vector &destEncryptKey = {}) = 0; + virtual int Backup(const std::string &databasePath, const std::vector &encryptKey = {}); /** * @brief Attaches a database. @@ -330,76 +453,15 @@ public: * @param pathName Indicates the database file pathname. * @param destEncryptKey Indicates the database encrypt key. */ - [[deprecated("Use Attach(const RdbStoreConfig &config, const std::string &attachName, int32_t waitTime = 2) " - "instead.")]] - virtual int Attach( - const std::string &alias, const std::string &pathName, const std::vector destEncryptKey) - { - return E_OK; - } + [[deprecated("Use Attach(const RdbStoreConfig &, const std::string &, int32_t) instead.")]] + virtual int Attach(const std::string &alias, const std::string &pathName, const std::vector encryptKey); /** * @brief Get the value of the column based on specified conditions. * * @param predicates Indicates the {@link AbsRdbPredicates} AbsRdbPredicates object. */ - virtual int Count(int64_t &outValue, const AbsRdbPredicates &predicates) = 0; - - /** - * @brief Queries data in the database based on specified conditions. - * - * @param predicates Indicates the specified query condition by the instance object of {@link AbsRdbPredicates}. - * @param columns Indicates the columns to query. If the value is empty array, the query applies to all columns. - */ - virtual std::shared_ptr Query( - const AbsRdbPredicates &predicates, const std::vector &columns) = 0; - - /** - * @brief Queries data in the database based on specified conditions. - * - * @param predicates Indicates the specified query condition by the instance object of {@link AbsRdbPredicates}. - * @param columns Indicates the columns to query. If the value is empty array, the query applies to all columns. - */ - virtual std::pair> QuerySharingResource( - const AbsRdbPredicates &predicates, const std::vector &columns) - { - return { E_NOT_SUPPORT, nullptr }; - } - - /** - * @brief Queries data in the database based on specified conditions. - * - * @param predicates Indicates the specified query condition by the instance object of {@link AbsRdbPredicates}. - * @param columns Indicates the columns to query. If the value is empty array, the query applies to all columns. - */ - virtual std::shared_ptr QueryByStep( - const AbsRdbPredicates &predicates, const std::vector &columns) = 0; - - /** - * @brief Queries remote data in the database based on specified conditions before Synchronizing Data. - * - * @param device Indicates specified remote device. - * @param predicates Indicates the specified query condition by the instance object of {@link AbsRdbPredicates}. - * @param columns Indicates the columns to query. If the value is empty array, the query applies to all columns. - */ - virtual std::shared_ptr RemoteQuery(const std::string &device, - const AbsRdbPredicates &predicates, const std::vector &columns, int &errCode) = 0; - - /** - * @brief Updates data in the database based on a a specified instance object of AbsRdbPredicates. - * - * @param values Indicates the row of data to be updated in the database. - * The key-value pairs are associated with column names of the database table. - * @param predicates Indicates the specified update condition by the instance object of {@link AbsRdbPredicates}. - */ - virtual int Update(int &changedRows, const ValuesBucket &values, const AbsRdbPredicates &predicates) = 0; - - /** - * @brief Deletes data from the database based on a specified instance object of AbsRdbPredicates. - * - * @param predicates Indicates the specified update condition by the instance object of {@link AbsRdbPredicates}. - */ - virtual int Delete(int &deletedRows, const AbsRdbPredicates &predicates) = 0; + virtual int Count(int64_t &outValue, const AbsRdbPredicates &predicates); /** * @brief Gets the version of the database. @@ -411,62 +473,61 @@ public: */ virtual int SetVersion(int version) = 0; + /** + * @brief Create a transaction of a new database connection. + */ + virtual std::pair> CreateTransaction(int32_t type); + /** * @brief Begins a transaction in EXCLUSIVE mode. */ - virtual int BeginTransaction() = 0; - virtual std::pair BeginTrans() - { - return { E_NOT_SUPPORT, 0 }; - } + [[deprecated("Use CreateTransaction(int32_t) instead.")]] + virtual int BeginTransaction(); + virtual std::pair BeginTrans(); /** * @brief Rollback a transaction in EXCLUSIVE mode. */ - virtual int RollBack() = 0; - virtual int RollBack(int64_t trxId) - { - return E_NOT_SUPPORT; - } + [[deprecated("Use CreateTransaction(int32_t) instead.")]] + virtual int RollBack(); + virtual int RollBack(int64_t trxId); /** * @brief Commit a transaction in EXCLUSIVE mode. */ - virtual int Commit() = 0; - virtual int Commit(int64_t trxId) - { - return E_NOT_SUPPORT; - } + [[deprecated("Use CreateTransaction(int32_t) instead.")]] + virtual int Commit(); + virtual int Commit(int64_t trxId); /** * @brief Check the current connection is in transaction. */ - virtual bool IsInTransaction() = 0; + virtual bool IsInTransaction(); /** * @brief Get database path. */ - virtual std::string GetPath() = 0; + virtual std::string GetPath(); /** * @brief Check the current connection pool is holding connection. */ - virtual bool IsHoldingConnection() = 0; + virtual bool IsHoldingConnection(); /** * @brief Check the current database is open. */ - virtual bool IsOpen() const = 0; + virtual bool IsOpen() const; /** * @brief Check the current database is read only. */ - virtual bool IsReadOnly() const = 0; + virtual bool IsReadOnly() const; /** * @brief Check the current database is memory database. */ - virtual bool IsMemoryRdb() const = 0; + virtual bool IsMemoryRdb() const; /** * @brief Restores a database from a specified database file. @@ -474,7 +535,7 @@ public: * @param backupPath Indicates the name that saves the database file path. * @param newKey Indicates the database new key. */ - virtual int Restore(const std::string &backupPath, const std::vector &newKey = {}) = 0; + virtual int Restore(const std::string &backupPath, const std::vector &newKey = {}); /** * @brief Set table to be distributed table. @@ -483,7 +544,7 @@ public: */ virtual int SetDistributedTables(const std::vector &tables, int32_t type = DistributedRdb::DistributedTableType::DISTRIBUTED_DEVICE, - const DistributedRdb::DistributedConfig &distributedConfig = { true }) = 0; + const DistributedRdb::DistributedConfig &distributedConfig = { true }); /** * @brief Obtain distributed table name of specified remote device according to local table name. @@ -493,8 +554,7 @@ public: * * @return Returns the distributed table name. */ - virtual std::string ObtainDistributedTableName( - const std::string &device, const std::string &table, int &errCode) = 0; + virtual std::string ObtainDistributedTableName(const std::string &device, const std::string &table, int &errCode); /** * @brief Sync data between devices or cloud. @@ -502,8 +562,7 @@ public: * @param device Indicates the remote device. * @param predicate Indicates the AbsRdbPredicates {@link AbsRdbPredicates} object. */ - virtual int Sync( - const SyncOption &option, const AbsRdbPredicates &predicate, const AsyncBrief &async) = 0; + virtual int Sync(const SyncOption &option, const AbsRdbPredicates &predicate, const AsyncBrief &async); /** * @brief Sync data between devices or cloud. @@ -511,8 +570,7 @@ public: * @param device Indicates the remote device. * @param predicate Indicates the AbsRdbPredicates {@link AbsRdbPredicates} object. */ - virtual int Sync( - const SyncOption &option, const std::vector &tables, const AsyncDetail &async) = 0; + virtual int Sync(const SyncOption &option, const std::vector &tables, const AsyncDetail &async); /** * @brief Sync data between devices or cloud. @@ -520,110 +578,68 @@ public: * @param device Indicates the remote device. * @param predicate Indicates the AbsRdbPredicates {@link AbsRdbPredicates} object. */ - virtual int Sync(const SyncOption &option, const AbsRdbPredicates &predicate, const AsyncDetail &async) = 0; + virtual int Sync(const SyncOption &option, const AbsRdbPredicates &predicate, const AsyncDetail &async); /** * @brief Subscribe to event changes. */ - virtual int Subscribe(const SubscribeOption& option, RdbStoreObserver *observer) = 0; + virtual int Subscribe(const SubscribeOption& option, RdbStoreObserver *observer); /** * @brief UnSubscribe to event changes. */ - virtual int UnSubscribe(const SubscribeOption& option, RdbStoreObserver *observer) = 0; + virtual int UnSubscribe(const SubscribeOption& option, RdbStoreObserver *observer); /** * @brief SubscribeObserver to event changes. */ - virtual int SubscribeObserver(const SubscribeOption& option, const std::shared_ptr &observer) - { - return E_OK; - } + virtual int SubscribeObserver(const SubscribeOption& option, const std::shared_ptr &observer); /** * @brief UnsubscribeObserver to event changes. */ - virtual int UnsubscribeObserver(const SubscribeOption& option, const std::shared_ptr &observer) - { - return E_OK; - } + virtual int UnsubscribeObserver(const SubscribeOption& option, const std::shared_ptr &observer); /** * @brief Register message for auto sync operation. */ - virtual int RegisterAutoSyncCallback(std::shared_ptr observer) = 0; + virtual int RegisterAutoSyncCallback(std::shared_ptr observer); /** * @brief UnRegister message for auto sync operation. */ - virtual int UnregisterAutoSyncCallback(std::shared_ptr observer) = 0; + virtual int UnregisterAutoSyncCallback(std::shared_ptr observer); /** * @brief When SubscribeMode is LOCAL or LOCALSHARED, this function needs to be called to trigger callback. */ - virtual int Notify(const std::string &event) = 0; + virtual int Notify(const std::string &event); /** * @brief Check the slave database is different from current database. */ - virtual bool IsSlaveDiffFromMaster() const - { - return false; - } - - virtual int32_t GetDbType() const - { - return DB_SQLITE; - } - - virtual std::pair LockCloudContainer() - { - return std::pair(E_OK, 0); - } - - virtual int32_t UnlockCloudContainer() - { - return E_OK; - } - - virtual int InterruptBackup() - { - return E_OK; - } - - virtual int32_t GetBackupStatus() const - { - return SlaveStatus::UNDEFINED; - } - - class ModifyTime { - public: - ModifyTime() = default; - ModifyTime(std::shared_ptr result, std::map, PRIKey> hashKeys, - bool isFromRowId); - operator std::map(); - operator std::shared_ptr(); - PRIKey GetOriginKey(const std::vector& hash); - size_t GetMaxOriginKeySize(); - bool NeedConvert() const; + virtual bool IsSlaveDiffFromMaster() const; + + virtual int32_t GetDbType() const; + + virtual std::pair LockCloudContainer(); + + virtual int32_t UnlockCloudContainer(); + + virtual int InterruptBackup(); + + virtual int32_t GetBackupStatus() const; - private: - std::shared_ptr result_; - std::map, PRIKey> hash_; - size_t maxOriginKeySize_ = sizeof(int64_t); - bool isFromRowId_{ false }; - }; /** * @brief Get the the specified column modify time. * * @param table Indicates the specified table. - * @param columnName Indicates the column. - * @param PRIKey Indicates the primary key. + * @param column Indicates the column. + * @param keys Indicates the primary key. * * @return Returns the specified column modify time. */ - virtual ModifyTime GetModifyTime(const std::string& table, const std::string& columnName, - std::vector& keys) = 0; + virtual ModifyTime GetModifyTime(const std::string &table, const std::string &column, std::vector &keys); /** * @brief Cleans dirty data deleted in the cloud. @@ -633,12 +649,13 @@ public: * * @param table Indicates the specified table. */ - virtual int CleanDirtyData(const std::string &table, uint64_t cursor = UINT64_MAX) = 0; + virtual int CleanDirtyData(const std::string &table, uint64_t cursor = UINT64_MAX); /** * @brief Gets the rebuilt_ status of the database. */ - virtual int GetRebuilt(RebuiltType &rebuilt) = 0; + virtual int GetRebuilt(RebuiltType &rebuilt); + /** * @brief Attaches a database file to the currently linked database. * @@ -647,10 +664,7 @@ public: * @param waitTime Indicates the maximum time allowed for attaching the database file. */ virtual std::pair Attach( - const RdbStoreConfig &config, const std::string &attachName, int32_t waitTime = 2) - { - return std::pair(0, E_OK); - } + const RdbStoreConfig &config, const std::string &attachName, int32_t waitTime = 2); /** * @brief Detaches a database from this database. @@ -658,30 +672,24 @@ public: * @param attachName Indicates the alias of the database. * @param waitTime Indicates the maximum time allowed for attaching the database file. */ - virtual std::pair Detach(const std::string &attachName, int32_t waitTime = 2) - { - return std::pair(0, E_OK); - } + virtual std::pair Detach(const std::string &attachName, int32_t waitTime = 2); /** * @brief Locks/Unlocks data from the database based on a specified instance object of AbsRdbPredicates. * * @param predicates Indicates the specified update condition by the instance object of {@link AbsRdbPredicates}. */ - virtual int ModifyLockStatus(const AbsRdbPredicates &predicates, bool isLock) - { - return E_ERROR; - } + virtual int ModifyLockStatus(const AbsRdbPredicates &predicates, bool isLock); /** * @brief Set search enable or disable. * * @param isSearchable Indicates enable or disable. */ - virtual int SetSearchable(bool isSearchable) - { - return E_ERROR; - } + virtual int SetSearchable(bool isSearchable); + +protected: + virtual std::string GetLogTableName(const std::string &tableName); }; } // namespace OHOS::NativeRdb #endif 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 3b86b0c2e269322dbeabc50044a2813ab9f0ab23..a286a9daa07a44ae530702f8796f005985c775c9 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 @@ -161,6 +161,31 @@ enum DBType : uint32_t { DB_BUTT }; +enum HmacAlgo : int32_t { + /** The HMAC_SHA1 algorithm. */ + SHA1 = 0, + /** The HMAC_SHA256 algorithm. */ + SHA256, + /** The HMAC_SHA512 algorithm. */ + SHA512 +}; + +enum KdfAlgo : int32_t { + /** The PBKDF2_HMAC_SHA1 algorithm. */ + KDF_SHA1 = 0, + /** The PBKDF2_HMAC_SHA256 algorithm. */ + KDF_SHA256, + /** The PBKDF2_HMAC_SHA512 algorithm. */ + KDF_SHA512 +}; + +enum EncryptAlgo : int32_t { + /** The AES_256_GCM encryption algorithm. */ + AES_256_GCM = 0, + /** The AES_256_CBC encryption algorithm. */ + AES_256_CBC +}; + /** * @brief Use DistributedType replace OHOS::DistributedRdb::RdbDistributedType. */ @@ -181,6 +206,21 @@ struct ScalarFunctionInfo { */ class API_EXPORT RdbStoreConfig { public: + /** + * @brief The struct indicates the database crypto parameters. + */ + struct API_EXPORT CryptoParam { + mutable int32_t iterNum = 0; + int32_t encryptAlgo = EncryptAlgo::AES_256_GCM; + int32_t hmacAlgo = HmacAlgo::SHA256; + int32_t kdfAlgo = KdfAlgo::KDF_SHA256; + int32_t cryptoPageSize = RdbStoreConfig::DB_DEFAULT_CRYPTO_PAGE_SIZE; + mutable std::vector encryptKey_{}; + API_EXPORT CryptoParam(); + API_EXPORT ~CryptoParam(); + API_EXPORT bool IsValid() const; + }; + /** * @brief The constant indicates the database default page size. */ @@ -197,9 +237,24 @@ public: static constexpr char DB_DEFAULT_JOURNAL_MODE[] = "WAL"; /** - * @brief The constant indicates the database default encrypt algorithm. + * @brief The constant indicates the database default encrypt algorithm. + */ + static constexpr EncryptAlgo DB_DEFAULT_ENCRYPT_ALGO = AES_256_GCM; + + /** + * @brief The constant indicates the database default crypto page size. + */ + static constexpr int DB_DEFAULT_CRYPTO_PAGE_SIZE = 1024; + + /** + * @brief The constant indicates the database minimum crypto page size. */ - static constexpr char DB_DEFAULT_ENCRYPT_ALGO[] = "sha256"; + static constexpr int DB_MIN_CRYPTO_PAGE_SIZE = 1024; + + /** + * @brief The constant indicates the database maximum crypto page size. + */ + static constexpr int DB_MAX_CRYPTO_PAGE_SIZE = 65536; /** * @brief Constructor. @@ -218,14 +273,13 @@ public: * @param autoCheck Indicates whether the database is auto check. * @param journalSize Indicates the journal size of the database. * @param pageSize Indicates the page size of the database. - * @param encryptAlgo Indicates the encrypt algorithm of the database. */ API_EXPORT RdbStoreConfig(const std::string &path, StorageMode storageMode = StorageMode::MODE_DISK, bool readOnly = false, const std::vector &encryptKey = std::vector(), const std::string &journalMode = DB_DEFAULT_JOURNAL_MODE, const std::string &syncMode = "", const std::string &databaseFileType = "", SecurityLevel securityLevel = SecurityLevel::LAST, bool isCreateNecessary = true, bool autoCheck = false, int journalSize = DB_JOURNAL_SIZE, - int pageSize = DB_PAGE_SIZE, const std::string &encryptAlgo = DB_DEFAULT_ENCRYPT_ALGO); + int pageSize = DB_PAGE_SIZE); /** * @brief Destructor. */ @@ -424,12 +478,12 @@ public: /** * @brief Obtains the encrypt algorithm in this {@code StoreConfig} object. */ - API_EXPORT const std::string GetEncryptAlgo() const; + API_EXPORT EncryptAlgo GetEncryptAlgo() const; /** * @brief Sets the encrypt algorithm for the object. */ - API_EXPORT void SetEncryptAlgo(const std::string &encryptAlgo); + API_EXPORT void SetEncryptAlgo(EncryptAlgo encryptAlgo); /** * @brief Obtains the read connection size in this {@code StoreConfig} object. @@ -549,9 +603,9 @@ public: this->journalMode_ == config.journalMode_ && this->syncMode_ == config.syncMode_ && this->databaseFileType == config.databaseFileType && IsEncrypt() == config.IsEncrypt() && this->securityLevel_ == config.securityLevel_ && this->journalSize_ == config.journalSize_ && - this->pageSize_ == config.pageSize_ && this->readConSize_ == config.readConSize_ && - this->customDir_ == config.customDir_ && this->allowRebuilt_ == config.allowRebuilt_ && - this->pluginLibs_ == config.pluginLibs_ && this->haMode_ == config.haMode_; + this->pageSize_ == config.pageSize_ && this->dbType_ == config.dbType_ && + this->customDir_ == config.customDir_ && this->pluginLibs_ == config.pluginLibs_ && + this->haMode_ == config.haMode_; } /** @@ -615,6 +669,10 @@ public: void SetScalarFunctions(const std::map functions); + void SetCryptoParam(CryptoParam cryptoParam); + + CryptoParam GetCryptoParam() const; + void SetJournalMode(const std::string &journalMode); void EnableRekey(bool enable); @@ -631,7 +689,6 @@ private: bool isAutoClean_ = true; bool isVector_ = false; bool autoRekey_ = false; - mutable int32_t iter_ = 0; int32_t journalSize_; int32_t pageSize_; int32_t readConSize_ = 4; @@ -645,6 +702,7 @@ private: DistributedType distributedType_ = DistributedRdb::RdbDistributedType::RDB_DEVICE_COLLABORATION; StorageMode storageMode_; IntegrityCheck checkType_ = IntegrityCheck::NONE; + CryptoParam cryptoParam_; std::string name_; std::string path_; std::string journalMode_; @@ -654,10 +712,8 @@ private: std::string bundleName_; std::string moduleName_; std::string visitorDir_; - std::string encryptAlgo_; std::string dataGroupId_; std::string customDir_; - mutable std::vector encryptKey_{}; mutable std::vector newEncryptKey_{}; std::map customScalarFunctions; std::vector pluginLibs_{}; 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 96ba6ce3600373b8d510821f0fd9e4b2a54bbcfd..7d0d9fc16c535b0b8970d706215b02c966b61bbf 100644 --- a/relational_store/interfaces/inner_api/rdb/include/rdb_types.h +++ b/relational_store/interfaces/inner_api/rdb/include/rdb_types.h @@ -46,7 +46,7 @@ struct RdbDebugInfo { DebugTime atime_; DebugTime mtime_; DebugTime ctime_; - size_t size_ = 0; + ssize_t size_ = 0; uint32_t dev_ = 0; uint32_t mode_ = 0; uint32_t uid_ = 0; @@ -95,7 +95,8 @@ struct SyncOption { enum DistributedTableType { DISTRIBUTED_DEVICE = 0, - DISTRIBUTED_CLOUD + DISTRIBUTED_CLOUD, + DISTRIBUTED_SEARCH }; struct Reference { @@ -107,6 +108,7 @@ struct Reference { struct DistributedConfig { bool autoSync = true; std::vector references = {}; + bool isRebuild = false; }; enum Progress { diff --git a/relational_store/interfaces/inner_api/rdb/include/transaction.h b/relational_store/interfaces/inner_api/rdb/include/transaction.h new file mode 100644 index 0000000000000000000000000000000000000000..c4dba75ab2823727f6392f28e25ee005933ff5fd --- /dev/null +++ b/relational_store/interfaces/inner_api/rdb/include/transaction.h @@ -0,0 +1,161 @@ +/* + * 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. + */ + +#ifndef NATIVE_RDB_TRANSACTION_H +#define NATIVE_RDB_TRANSACTION_H + +#include +#include +#include +#include + +#include "abs_rdb_predicates.h" +#include "result_set.h" +#include "rdb_common.h" +#include "rdb_errno.h" +#include "rdb_types.h" +#include "rdb_visibility.h" +#include "values_bucket.h" +#include "values_buckets.h" + +namespace OHOS::NativeRdb { +class Connection; +class API_EXPORT Transaction { +public: + /** + * @brief Use Fields replace std::vector columns. + */ + using Fields = std::vector; + + /** + * @brief Use Values replace std::vector args. + */ + using Values = std::vector; + + /** + * @brief Use Row replace ValuesBucket. + */ + using Row = ValuesBucket; + + /** + * @brief Use Rows replace std::vector. + */ + using Rows = std::vector; + + /** + * @brief Use Rows replace std::vector. + */ + using RefRows = ValuesBuckets; + + /** + * @brief Use Resolution replace ConflictResolution. + */ + using Resolution = ConflictResolution; + + static constexpr Resolution NO_ACTION = ConflictResolution::ON_CONFLICT_NONE; + + enum TransactionType : int32_t { + DEFERRED, + IMMEDIATE, + EXCLUSIVE, + TRANS_BUTT, + }; + + using Creator = std::function>( + int32_t type, std::shared_ptr connection, const std::string&)>; + + static std::pair> Create( + int32_t type, std::shared_ptr connection, const std::string &name); + static int32_t RegisterCreator(Creator creator); + + virtual ~Transaction() = default; + + virtual int32_t Commit() = 0; + virtual int32_t Rollback() = 0; + virtual int32_t Close() = 0; + + /** + * @brief Inserts a row of data into the target table. + * + * @param table Indicates the target table. + * @param row Indicates the row of data {@link ValuesBucket} to be inserted into the table. + * @param resolution Indicates the {@link ConflictResolution} to insert data into the table. + */ + virtual std::pair Insert(const std::string &table, const Row &row, + Resolution resolution = NO_ACTION) = 0; + + /** + * @brief Inserts a batch of data into the target table. + * + * @param table Indicates the target table. + * @param rows Indicates the rows of data {@link ValuesBucket} to be inserted into the table. + */ + virtual std::pair BatchInsert(const std::string &table, const Rows &rows) = 0; + + /** + * @brief Inserts a batch of data into the target table. + * + * @param table Indicates the target table. + * @param values Indicates the rows of data {@link ValuesBuckets} to be inserted into the table. + */ + virtual std::pair BatchInsert(const std::string &table, const RefRows &rows) = 0; + + /** + * @brief Updates data in the database based on a a specified instance object of AbsRdbPredicates. + * + * @param values Indicates the row of data to be updated in the database. + * The key-value pairs are associated with column names of the database table. + * @param predicates Indicates the specified update condition by the instance object of {@link AbsRdbPredicates}. + */ + virtual std::pair Update(const Row &row, const AbsRdbPredicates &predicates, + Resolution resolution = NO_ACTION) = 0; + + /** + * @brief Deletes data from the database based on a specified instance object of AbsRdbPredicates. + * + * @param predicates Indicates the specified update condition by the instance object of {@link AbsRdbPredicates}. + */ + virtual std::pair Delete(const AbsRdbPredicates &predicates) = 0; + + /** + * @brief Queries data in the database based on SQL statement. + * + * @param sql Indicates the SQL statement to execute. + * @param args Indicates the selection arguments. + */ + virtual std::shared_ptr QueryByStep(const std::string &sql, const Values &args = {}) = 0; + + /** + * @brief Queries data in the database based on specified conditions. + * + * @param predicates Indicates the specified query condition by the instance object of {@link AbsRdbPredicates}. + * @param columns Indicates the columns to query. If the value is empty array, the query applies to all columns. + */ + virtual std::shared_ptr QueryByStep(const AbsRdbPredicates &predicates, const Fields &columns = {}) = 0; + + /** + * @brief Executes an SQL statement that contains specified parameters and + * get two values of type int and ValueObject. + * + * @param sql Indicates the SQL statement to execute. + * @param args Indicates the {@link ValueObject} values of the parameters in the SQL statement. + */ + virtual std::pair Execute(const std::string &sql, const Values &args = {}) = 0; + +private: + static inline Creator creator_; +}; +} +#endif diff --git a/relational_store/interfaces/inner_api/rdb/include/value_object.h b/relational_store/interfaces/inner_api/rdb/include/value_object.h index 91d93fcff637416fc6d227fe66ba47dfd9c0cf4a..7f47be84a6465054de04a1e832bbf33a891c28d6 100644 --- a/relational_store/interfaces/inner_api/rdb/include/value_object.h +++ b/relational_store/interfaces/inner_api/rdb/include/value_object.h @@ -230,7 +230,7 @@ public: * @param val Indicates an Assets input parameter. */ API_EXPORT ValueObject(BigInt val); - + /** * @brief Constructor. * This constructor is used to convert the FloatVector input parameter to a value of type ValueObject. @@ -379,6 +379,12 @@ public: return value; } + bool operator<(const ValueObject &rhs) const; + + bool operator==(const ValueObject &rhs) const; + + bool operator!=(const ValueObject &rhs) const; + private: template int Get(T &output) const; diff --git a/relational_store/interfaces/inner_api/rdb/mock/include/rdb_predicates.h b/relational_store/interfaces/inner_api/rdb/include/values_buckets.h similarity index 41% rename from relational_store/interfaces/inner_api/rdb/mock/include/rdb_predicates.h rename to relational_store/interfaces/inner_api/rdb/include/values_buckets.h index b4acf697e7d61b1280ba0a37063be7a7d7220652..5f99d6db7034c90f867c2ce973e6a5d6fafa54b4 100644 --- a/relational_store/interfaces/inner_api/rdb/mock/include/rdb_predicates.h +++ b/relational_store/interfaces/inner_api/rdb/include/values_buckets.h @@ -1,44 +1,52 @@ -/* - * Copyright (c) 2022 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 NATIVE_RDB_RDBPREDICATES_H -#define NATIVE_RDB_RDBPREDICATES_H - - -#include "abs_rdb_predicates.h" - -namespace OHOS { -namespace NativeRdb { -class RdbPredicates : public AbsRdbPredicates { -public: - explicit RdbPredicates(const std::string &tableName); - ~RdbPredicates() override {} - - std::string GetJoinClause() const override; - RdbPredicates *CrossJoin(const std::string &tableName); - RdbPredicates *InnerJoin(const std::string &tableName); - RdbPredicates *LeftOuterJoin(const std::string &tableName); - RdbPredicates *Using(const std::vector &fields); - RdbPredicates *On(const std::vector &clauses); - -private: - std::string ProcessJoins() const; - std::string GetGrammar(int type) const; - RdbPredicates *Join(int join, const std::string &tableName); -}; -} // namespace NativeRdb -} // namespace OHOS - -#endif \ No newline at end of file +/* + * 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. + */ + +#ifndef NATIVE_RDB_VALUES_BUCKETS_H +#define NATIVE_RDB_VALUES_BUCKETS_H + +#include +#include +#include + +#include "value_object.h" +#include "values_bucket.h" + +namespace OHOS { +namespace NativeRdb { +class API_EXPORT ValuesBuckets { +public: + using FieldsType = std::shared_ptr>; + using ValuesType = std::shared_ptr>; + using FieldType = std::reference_wrapper; + using ValueType = std::reference_wrapper; + using BucketType = std::map>; + + API_EXPORT ValuesBuckets(); + + API_EXPORT size_t RowSize() const; + API_EXPORT std::pair GetFieldsAndValues() const; + + API_EXPORT void Put(const ValuesBucket &bucket); + API_EXPORT std::pair Get(size_t row, const FieldType &field) const; + +private: + FieldsType fields_; + ValuesType values_; + std::vector buckets_; +}; + +} // namespace NativeRdb +} // namespace OHOS +#endif diff --git a/relational_store/interfaces/inner_api/rdb/mock/include/abs_result_set.h b/relational_store/interfaces/inner_api/rdb/mock/include/abs_result_set.h deleted file mode 100644 index 561b70fb3b6c944b5e586a8d69d3b528e8ae1644..0000000000000000000000000000000000000000 --- a/relational_store/interfaces/inner_api/rdb/mock/include/abs_result_set.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - * 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 NATIVE_RDB_ABS_RESULT_SET_H -#define NATIVE_RDB_ABS_RESULT_SET_H - -#include -#include -#include -#include -#include - -#include "result_set.h" -#include "value_object.h" - -namespace OHOS { -namespace NativeRdb { -class AbsResultSet : public ResultSet { -public: - AbsResultSet(); - virtual ~AbsResultSet(); - int GetRowCount(int &count) override; - int GetAllColumnNames(std::vector &columnNames) override; - int GetBlob(int columnIndex, std::vector &blob) override; - int GetString(int columnIndex, std::string &value) override; - int GetInt(int columnIndex, int &value) override; - int GetLong(int columnIndex, int64_t &value) override; - int GetDouble(int columnIndex, double &value) override; - int GetAsset(int32_t col, ValueObject::Asset &value) override; - int GetAssets(int32_t col, ValueObject::Assets &value) override; - int GetFloat32Array(int32_t index, ValueObject::FloatVector &vecs) override; - int IsColumnNull(int columnIndex, bool &isNull) override; - int GetRow(RowEntity &rowEntity) override; - int GoToRow(int position) override; - int GetColumnType(int columnIndex, ColumnType &columnType) override; - int GetRowIndex(int &position) const override; - int GoTo(int offset) override; - int GoToFirstRow() override; - int GoToLastRow() override; - int GoToNextRow() override; - int GoToPreviousRow() override; - int IsAtFirstRow(bool &result) const override; - int IsAtLastRow(bool &result) override; - int IsStarted(bool &result) const override; - int IsEnded(bool &result) override; - int GetColumnCount(int &count) override; - int GetColumnIndex(const std::string &columnName, int &columnIndex) override; - int GetColumnName(int columnIndex, std::string &columnName) override; - bool IsClosed() const override; - int Close() override; - -protected: - template - class Lock { - public: - Lock(bool enable = false) - { - if (enable) { - mutex_ = new Mtx(); - } - }; - ~Lock() - { - delete mutex_; - mutex_ = nullptr; - } - void lock() - { - if (mutex_ != nullptr) { - mutex_->lock(); - } - }; - void unlock() - { - if (mutex_ != nullptr) { - mutex_->unlock(); - } - }; - - private: - Mtx* mutex_ = nullptr; - }; - using Mutex = Lock; - - virtual std::pair> GetColumnNames(); - std::pair IsEnded(); - - // The default position of the result set - static const int INIT_POS = -1; - static constexpr int NO_COUNT = -1; - - Mutex globalMtx_; - /* - * The value can be in the range [-1 ~ n], where -1 represents the start flag position and N represents the data end - * flag position, and [0, n-1] represents the real data index. - */ - int rowPos_ = INIT_POS; - bool isClosed_ = false; - int rowCount_ = NO_COUNT; - int32_t lastErr_; -private: - int InitColumnNames(); - - // Indicates whether the result set is closed - int columnCount_ = -1; - std::map columnMap_; -}; -} // namespace NativeRdb -} // namespace OHOS - -#endif \ No newline at end of file diff --git a/relational_store/interfaces/inner_api/rdb/mock/include/asset_value.h b/relational_store/interfaces/inner_api/rdb/mock/include/asset_value.h deleted file mode 100644 index c2cd5d350a9e1f27d761d118350ff6152e4efc0d..0000000000000000000000000000000000000000 --- a/relational_store/interfaces/inner_api/rdb/mock/include/asset_value.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * 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_RELATIONAL_STORE_INNER_API_ASSET_VALUE_H -#define OHOS_RELATIONAL_STORE_INNER_API_ASSET_VALUE_H -#include -namespace OHOS::NativeRdb { -struct AssetValue { - enum Status : int32_t { - STATUS_UNKNOWN, - STATUS_NORMAL, - STATUS_INSERT, - STATUS_UPDATE, - STATUS_DELETE, - STATUS_ABNORMAL, - STATUS_DOWNLOADING, - STATUS_BUTT - }; - static constexpr uint64_t NO_EXPIRES_TIME = 0; - uint32_t version = 0; - mutable uint32_t status = STATUS_UNKNOWN; - uint64_t expiresTime = NO_EXPIRES_TIME; - std::string id; - std::string name; - std::string uri; - std::string createTime; - std::string modifyTime; - std::string size; - std::string hash; - std::string path; -}; -} -#endif // OHOS_RELATIONAL_STORE_INNER_API_ASSET_VALUE_H diff --git a/relational_store/interfaces/inner_api/rdb/mock/include/rdb_open_callback.h b/relational_store/interfaces/inner_api/rdb/mock/include/rdb_open_callback.h deleted file mode 100644 index 25a72d6ea7fa82bfc21e50f2a8c37e64525d0999..0000000000000000000000000000000000000000 --- a/relational_store/interfaces/inner_api/rdb/mock/include/rdb_open_callback.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2021 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 NATIVE_RDB_RDB_OPEN_CALLBACK_H -#define NATIVE_RDB_RDB_OPEN_CALLBACK_H - -#include "rdb_store.h" - -namespace OHOS { -namespace NativeRdb { -class RdbOpenCallback { -public: - /** - * Called when the database associate whit this RdbStore is created with the first time. - * This is where the creation of tables and insert the initial data of tables should happen. - * - * param store The RdbStore object. - */ - virtual int OnCreate(RdbStore &rdbStore) = 0; - - /** - * Called when the database associate whit this RdbStore needs to be upgrade. - * - * param store The RdbStore object. - * param oldVersion The old database version. - * param newVersion The new database version. - */ - virtual int OnUpgrade(RdbStore &rdbStore, int currentVersion, int targetVersion) = 0; - - /** - * Called when the database associate whit this RdbStore needs to be downgrade. - * - * param store The RdbStore object. - * param oldVersion The old database version. - * param newVersion The new database version. - */ - virtual int OnDowngrade(RdbStore &rdbStore, int currentVersion, int targetVersion) - { - return 0; - } - - /** - * Called when the RdbStore has been opened. - * - * param store The RdbStore object. - */ - virtual int OnOpen(RdbStore &rdbStore) - { - return 0; - } - - virtual int onCorruption(std::string databaseFile) - { - return 0; - } -}; -} // namespace NativeRdb -} // namespace OHOS -#endif diff --git a/relational_store/interfaces/inner_api/rdb/mock/include/rdb_store.h b/relational_store/interfaces/inner_api/rdb/mock/include/rdb_store.h deleted file mode 100644 index 9b2e021c53bd7db8fa7456262cd4e959bfeac464..0000000000000000000000000000000000000000 --- a/relational_store/interfaces/inner_api/rdb/mock/include/rdb_store.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (c) 2022 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 NATIVE_RDB_RDB_STORE_H -#define NATIVE_RDB_RDB_STORE_H - -#include -#include -#include - -#include "abs_rdb_predicates.h" -#include "rdb_common.h" -#include "rdb_errno.h" -#include "rdb_store_config.h" -#include "rdb_types.h" -#include "result_set.h" -#include "value_object.h" -#include "values_bucket.h" -namespace OHOS::NativeRdb { -class RdbStore { -public: - using RdbStoreObserver = DistributedRdb::RdbStoreObserver; - using PRIKey = RdbStoreObserver::PrimaryKey; - using Date = DistributedRdb::Date; - - virtual ~RdbStore() {} - virtual int Insert(int64_t &outRowId, const std::string &table, const ValuesBucket &values) = 0; - virtual int BatchInsert(int64_t &outInsertNum, const std::string &table, - const std::vector &values) = 0; - virtual int Replace(int64_t &outRowId, const std::string &table, const ValuesBucket &values) = 0; - virtual int InsertWithConflictResolution( - int64_t &outRowId, const std::string &table, const ValuesBucket &values, - ConflictResolution conflictResolution = ConflictResolution::ON_CONFLICT_NONE) = 0; - virtual int Update(int &changedRows, const std::string &table, const ValuesBucket &values, - const std::string &whereClause, const std::vector &whereArgs) = 0; - virtual int Update(int &changedRows, const std::string &table, const ValuesBucket &values, - const std::string &whereClause, const std::vector &bindArgs) = 0; - virtual int UpdateWithConflictResolution(int &changedRows, const std::string &table, const ValuesBucket &values, - const std::string &whereClause, const std::vector &whereArgs, - ConflictResolution conflictResolution) = 0; - virtual int UpdateWithConflictResolution(int &changedRows, const std::string &table, const ValuesBucket &values, - const std::string &whereClause, const std::vector &bindArgs, - ConflictResolution conflictResolution) = 0; - virtual int Delete(int &deletedRows, const std::string &table, const std::string &whereClause, - const std::vector &whereArgs) = 0; - virtual int Delete(int &deletedRows, const std::string &table, const std::string &whereClause, - const std::vector &bindArgs) = 0; - virtual std::shared_ptr QueryByStep(const std::string &sql, - const std::vector &sqlArgs) = 0; - virtual std::shared_ptr QueryByStep(const std::string &sql, const std::vector &args) = 0; - virtual std::shared_ptr QueryByStep( - const AbsRdbPredicates &predicates, const std::vector &columns) = 0; - virtual int ExecuteSql(const std::string &sql, const std::vector &bindArgs = {}) = 0; - virtual std::pair Execute(const std::string &sql, - const std::vector &bindArgs = {}, int64_t txId = 0) = 0; - virtual int ExecuteAndGetLong(int64_t &outValue, const std::string &sql, - const std::vector &bindArgs = {}) = 0; - virtual int ExecuteAndGetString(std::string &outValue, const std::string &sql, - const std::vector &bindArgs = {}) = 0; - virtual int ExecuteForLastInsertedRowId(int64_t &outValue, const std::string &sql, - const std::vector &bindArgs = {}) = 0; - virtual int ExecuteForChangedRowCount(int64_t &outValue, const std::string &sql, - const std::vector &bindArgs = {}) = 0; - virtual int Backup(const std::string &databasePath, const std::vector &destEncryptKey = {}) = 0; - virtual int Attach( - const std::string &alias, const std::string &pathName, const std::vector destEncryptKey) - { - return E_OK; - } - - virtual int Count(int64_t &outValue, const AbsRdbPredicates &predicates) = 0; - virtual std::shared_ptr Query( - const AbsRdbPredicates &predicates, const std::vector &columns) = 0; - virtual int Update(int &changedRows, const ValuesBucket &values, const AbsRdbPredicates &predicates) = 0; - virtual int Delete(int &deletedRows, const AbsRdbPredicates &predicates) = 0; - - virtual int GetVersion(int &version) = 0; - virtual int SetVersion(int version) = 0; - virtual int BeginTransaction() = 0; - virtual std::pair BeginTrans() = 0; - virtual int RollBack() = 0; - virtual int RollBack(int64_t trxId) = 0; - virtual int Commit() = 0; - virtual int Commit(int64_t trxId) = 0; - virtual bool IsInTransaction() = 0; - virtual std::string GetPath() = 0; - virtual bool IsHoldingConnection() = 0; - virtual bool IsOpen() const = 0; - virtual bool IsReadOnly() const = 0; - virtual bool IsMemoryRdb() const = 0; - virtual int Restore(const std::string &backupPath, const std::vector &newKey = {}) = 0; - virtual std::pair Attach( - const RdbStoreConfig &config, const std::string &attachName, int32_t waitTime = 2) = 0; - virtual std::pair Detach(const std::string &attachName, int32_t waitTime = 2) = 0; - virtual int GetRebuilt(RebuiltType &rebuilt) = 0; - virtual int32_t GetDbType() const - { - return DB_SQLITE; - } - virtual int InterruptBackup() - { - return E_OK; - } - virtual bool IsSlaveDiffFromMaster() const - { - return false; - } - virtual int32_t GetBackupStatus() const - { - return SlaveStatus::UNDEFINED; - } -}; -} // namespace OHOS::NativeRdb -#endif 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 faf4b73b2d95de0b813e6bf7bbcb682e86d47dc2..630e68835354a923e45ccbb4895756bd6a4e25ba 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 @@ -86,6 +86,24 @@ enum DistributedType { RDB_DISTRIBUTED_TYPE_MAX }; +enum HmacAlgo : int32_t { + SHA1 = 0, + SHA256, + SHA512 +}; + +enum KdfAlgo : int32_t { + KDF_SHA1 = 0, + KDF_SHA256, + KDF_SHA512 +}; + +enum EncryptAlgo : int32_t { + AES_256_GCM = 0, + AES_256_CBC +}; + + using ScalarFunction = std::function&)>; struct ScalarFunctionInfo { @@ -96,17 +114,29 @@ struct ScalarFunctionInfo { class RdbStoreConfig { public: + struct CryptoParam { + mutable int32_t iterNum = 0; + int32_t encryptAlgo = EncryptAlgo::AES_256_GCM; + int32_t hmacAlgo = HmacAlgo::SHA256; + int32_t kdfAlgo = KdfAlgo::KDF_SHA256; + int32_t cryptoPageSize = RdbStoreConfig::DB_DEFAULT_CRYPTO_PAGE_SIZE; + mutable std::vector encryptKey_{}; + CryptoParam(); + ~CryptoParam(); + bool IsValid() const; + }; static constexpr int DB_PAGE_SIZE = 4096; /* default page size : 4k */ static constexpr int DB_JOURNAL_SIZE = 1024 * 1024; /* default file size : 1M */ static constexpr char DB_DEFAULT_JOURNAL_MODE[] = "WAL"; - static constexpr char DB_DEFAULT_ENCRYPT_ALGO[] = "sha256"; + static constexpr EncryptAlgo DB_DEFAULT_ENCRYPT_ALGO = AES_256_GCM; + static constexpr int DB_DEFAULT_CRYPTO_PAGE_SIZE = 1024; + static constexpr int DB_MIN_CRYPTO_PAGE_SIZE = 1024; + static constexpr int DB_MAX_CRYPTO_PAGE_SIZE = 65536; RdbStoreConfig(const std::string &path, StorageMode storageMode = StorageMode::MODE_DISK, bool readOnly = false, const std::vector &encryptKey = std::vector(), - const std::string &journalMode = DB_DEFAULT_JOURNAL_MODE, - const std::string &syncMode = "", const std::string &databaseFileType = "", - SecurityLevel securityLevel = SecurityLevel::LAST, bool isCreateNecessary = true, - bool autoCheck = false, int journalSize = 1048576, int pageSize = 4096, - const std::string &encryptAlgo = "sha256"); + const std::string &journalMode = DB_DEFAULT_JOURNAL_MODE, const std::string &syncMode = "", + const std::string &databaseFileType = "", SecurityLevel securityLevel = SecurityLevel::LAST, + bool isCreateNecessary = true, bool autoCheck = false, int journalSize = 1048576, int pageSize = 4096); ~RdbStoreConfig(); std::string GetName() const; std::string GetPath() const; @@ -150,8 +180,8 @@ public: void SetJournalSize(int journalSize); int GetPageSize() const; void SetPageSize(int pageSize); - const std::string GetEncryptAlgo() const; - void SetEncryptAlgo(const std::string &encryptAlgo); + EncryptAlgo GetEncryptAlgo() const; + void SetEncryptAlgo(EncryptAlgo encryptAlgo); int GetReadConSize() const; void SetReadConSize(int readConSize); void SetEncryptKey(const std::vector &encryptKey); @@ -219,8 +249,9 @@ public: 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); private: @@ -235,7 +266,6 @@ private: bool isAutoClean_ = true; bool isVector_ = false; bool autoRekey_ = false; - mutable int32_t iter_ = 0; int32_t journalSize_; int32_t pageSize_; int32_t readConSize_ = 4; @@ -249,6 +279,7 @@ private: DistributedType distributedType_ = DistributedType::RDB_DEVICE_COLLABORATION; StorageMode storageMode_; IntegrityCheck checkType_ = IntegrityCheck::NONE; + CryptoParam cryptoParam_; std::string name_; std::string path_; std::string journalMode_; @@ -258,10 +289,8 @@ private: std::string bundleName_; std::string moduleName_; std::string visitorDir_; - std::string encryptAlgo_; std::string dataGroupId_; std::string customDir_; - mutable std::vector encryptKey_{}; mutable std::vector newEncryptKey_{}; std::map customScalarFunctions; std::vector pluginLibs_{}; diff --git a/relational_store/interfaces/inner_api/rdb/mock/include/result_set.h b/relational_store/interfaces/inner_api/rdb/mock/include/result_set.h deleted file mode 100644 index c3bda3ef3f0e216df8c815814a6c2c64b73c844b..0000000000000000000000000000000000000000 --- a/relational_store/interfaces/inner_api/rdb/mock/include/result_set.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * 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 NATIVE_RDB_RESULT_SET_H -#define NATIVE_RDB_RESULT_SET_H - -#include -#include -#include -#include "remote_result_set.h" -#include "value_object.h" - -namespace OHOS { -namespace NativeRdb { -struct RowEntity { -public: - void Put(const std::string &name, int32_t index, ValueObject &&value); - ValueObject Get(const std::string &name) const; - ValueObject Get(int index) const; - const std::map &Get() const; - std::map Steal(); - void Clear(int32_t size); - -private: - std::map values_; - std::vector indexs_; -}; - -class ResultSet : public RemoteResultSet { -public: - virtual ~ResultSet() {} - - virtual int GetAsset(int32_t col, ValueObject::Asset &value) = 0; - virtual int GetAssets(int32_t col, ValueObject::Assets &value) = 0; - virtual int GetFloat32Array(int32_t index, ValueObject::FloatVector &vecs) = 0; - virtual int Get(int32_t col, ValueObject &value) = 0; - /** - * @brief Gets the entire row of data for the current row from the result set. - */ - virtual int GetRow(RowEntity &rowEntity) = 0; - virtual int GetSize(int columnIndex, size_t &size) = 0; -}; - -} // namespace NativeRdb -} // namespace OHOS -#endif diff --git a/relational_store/interfaces/inner_api/rdb/mock/include/value_object.h b/relational_store/interfaces/inner_api/rdb/mock/include/value_object.h deleted file mode 100644 index cddf8464f3304b0c18877169225dac30714a06c3..0000000000000000000000000000000000000000 --- a/relational_store/interfaces/inner_api/rdb/mock/include/value_object.h +++ /dev/null @@ -1,357 +0,0 @@ -/* - * Copyright (c) 2021 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 NATIVE_RDB_VALUE_OBJECT_H -#define NATIVE_RDB_VALUE_OBJECT_H - -#include -#include -#include -#include "big_integer.h" -#include "asset_value.h" -namespace OHOS { -namespace NativeRdb { -/** - * The ValueObject class of RDB. - */ -class ValueObject { -public: - /** - * @brief Use Type replace std::variant. - */ - using Nil = std::monostate; - using Blob = std::vector; - using Asset = AssetValue; - using Assets = std::vector; - using BigInt = BigInteger; - using FloatVector = std::vector; - using Type = std::variant; - template - struct index_of : std::integral_constant {}; - - template - inline static constexpr size_t index_of_v = index_of::value; - - template - struct index_of - : std::integral_constant ? 0 : index_of_v + 1> {}; - - template - struct variant_size_of { - static constexpr size_t value = sizeof...(Types); - }; - - template - struct variant_index_of { - static constexpr size_t value = index_of_v; - }; - - template - static variant_size_of variant_size_test(const std::variant &); - - template - static variant_index_of variant_index_test(const T &, const std::variant &); - - template - inline constexpr static int32_t TYPE_INDEX = - decltype(variant_index_test(std::declval(), std::declval()))::value; - - inline constexpr static int32_t TYPE_MAX = decltype(variant_size_test(std::declval()))::value; - - /** - * @brief Indicates the ValueObject {@link ValueObject} type. - * */ - enum TypeId : int32_t { - /** Indicates the ValueObject type is NULL.*/ - TYPE_NULL = TYPE_INDEX, - /** Indicates the ValueObject type is int.*/ - TYPE_INT = TYPE_INDEX, - /** Indicates the ValueObject type is double.*/ - TYPE_DOUBLE = TYPE_INDEX, - /** Indicates the ValueObject type is string.*/ - TYPE_STRING = TYPE_INDEX, - /** Indicates the ValueObject type is bool.*/ - TYPE_BOOL = TYPE_INDEX, - /** Indicates the ValueObject type is blob.*/ - TYPE_BLOB = TYPE_INDEX, - /** Indicates the ValueObject type is asset.*/ - TYPE_ASSET = TYPE_INDEX, - /** Indicates the ValueObject type is assets.*/ - TYPE_ASSETS = TYPE_INDEX, - /** Indicates the ValueObject type is vecs.*/ - TYPE_VECS = TYPE_INDEX, - /** Indicates the ValueObject type is bigint.*/ - TYPE_BIGINT = TYPE_INDEX, - /** the BUTT.*/ - TYPE_BUTT = TYPE_MAX - }; - Type value; - - /** - * @brief convert a std::variant input to another std::variant output with different (..._Types) - */ - template - static inline std::enable_if_t<(TYPE_INDEX) < TYPE_MAX, const char *> DeclType() - { - return DECLARE_TYPES[TYPE_INDEX]; - } - /** - * @brief Constructor. - */ - ValueObject(); - - /** - * @brief Destructor. - */ - ~ValueObject(); - - /** - * @brief Constructor. - * - * A parameterized constructor used to create a ValueObject instance. - */ - ValueObject(Type val) noexcept; - - /** - * @brief Move constructor. - */ - ValueObject(ValueObject &&val) noexcept; - - /** - * @brief Copy constructor. - */ - ValueObject(const ValueObject &val); - - /** - * @brief Constructor. - * - * This constructor is used to convert the int input parameter to a value of type ValueObject. - * - * @param val Indicates an int input parameter. - */ - ValueObject(int32_t val); - - /** - * @brief Constructor. - * - * This constructor is used to convert the int64_t input parameter to a value of type ValueObject. - * - * @param val Indicates an int64_t input parameter. - */ - ValueObject(int64_t val); - - /** - * @brief Constructor. - * - * This constructor is used to convert the double input parameter to a value of type ValueObject. - * - * @param val Indicates an double input parameter. - */ - ValueObject(double val); - - /** - * @brief Constructor. - * - * This constructor is used to convert the bool input parameter to a value of type ValueObject. - * - * @param val Indicates an bool input parameter. - */ - ValueObject(bool val); - - /** - * @brief Constructor. - * - * This constructor is used to convert the string input parameter to a value of type ValueObject. - * - * @param val Indicates an string input parameter. - */ - ValueObject(std::string val); - - /** - * @brief Constructor. - * - * This constructor is used to convert the const char * input parameter to a value of type ValueObject. - * - * @param val Indicates an const char * input parameter. - */ - ValueObject(const char *val); - - /** - * @brief Constructor. - * - * This constructor is used to convert the vector input parameter to a value of type ValueObject. - * - * @param val Indicates an vector input parameter. - */ - ValueObject(const std::vector &blob); - - /** - * @brief Constructor. - * - * This constructor is used to convert the Asset input parameter to a value of type ValueObject. - * - * @param val Indicates an Asset input parameter. - */ - ValueObject(Asset val); - - /** - * @brief Constructor. - * - * This constructor is used to convert the Assets input parameter to a value of type ValueObject. - * - * @param val Indicates an Assets input parameter. - */ - ValueObject(Assets val); - - /** - * @brief Constructor. - * - * This constructor is used to convert the Assets input parameter to a value of type ValueObject. - * - * @param val Indicates an Assets input parameter. - */ - ValueObject(BigInt val); - - /** - * @brief Constructor. - * This constructor is used to convert the FloatVector input parameter to a value of type ValueObject. - * - * @param val Indicates an FloatVector input parameter. - */ - ValueObject(FloatVector val); - - /** - * @brief Move assignment operator overloaded function. - */ - ValueObject &operator=(ValueObject &&valueObject) noexcept; - - /** - * @brief Copy assignment operator overloaded function. - */ - ValueObject &operator=(const ValueObject &valueObject); - - /** - * @brief Obtains the type in this {@code ValueObject} object. - */ - TypeId GetType() const; - - /** - * @brief Obtains the int value in this {@code ValueObject} object. - */ - int GetInt(int &val) const; - - /** - * @brief Obtains the long value in this {@code ValueObject} object. - */ - int GetLong(int64_t &val) const; - - /** - * @brief Obtains the double value in this {@code ValueObject} object. - */ - int GetDouble(double &val) const; - - /** - * @brief Obtains the bool value in this {@code ValueObject} object. - */ - int GetBool(bool &val) const; - - /** - * @brief Obtains the string value in this {@code ValueObject} object. - */ - int GetString(std::string &val) const; - - /** - * @brief Obtains the vector value in this {@code ValueObject} object. - */ - int GetBlob(std::vector &val) const; - - /** - * @brief Obtains the vector value in this {@code ValueObject} object. - */ - int GetAsset(Asset &val) const; - - /** - * @brief Obtains the vector value in this {@code ValueObject} object. - */ - int GetAssets(Assets &val) const; - - /** - * @brief Obtains the vector value in this {@code ValueObject} object. - */ - int GetVecs(FloatVector &val) const; - - operator int() const; - operator int64_t() const; - operator double() const; - operator bool() const; - operator std::string() const; - operator Blob() const; - operator Asset() const; - operator Assets() const; - - /** - * @brief Type conversion function. - * - * @return Returns the vector type ValueObject. - */ - operator FloatVector() const; - - /** - * @brief Type conversion function. - * - * @return Returns the BigInt type ValueObject. - */ - operator BigInt() const; - - /** - * @brief Type conversion function. - * - * @return Returns the Type type ValueObject. - */ - operator Type() const - { - return value; - } - -private: - template - int Get(T &output) const; - static constexpr const char *DECLARE_TYPES[TypeId::TYPE_BUTT] = { - /** Indicates the ValueObject type is NULL.*/ - "", - /** Indicates the ValueObject type is int.*/ - "INT", - /** Indicates the ValueObject type is double.*/ - "REAL", - /** Indicates the ValueObject type is string.*/ - "TEXT", - /** Indicates the ValueObject type is bool.*/ - "BOOL", - /** Indicates the ValueObject type is blob.*/ - "BLOB", - /** Indicates the ValueObject type is asset.*/ - "ASSET", - /** Indicates the ValueObject type is assets.*/ - "ASSETS", - /** Indicates the ValueObject type is vecs.*/ - "FLOATVECTOR", - /** Indicates the ValueObject type is bigint.*/ - "UNLIMITED INT" - }; -}; -using ValueObjectType = ValueObject::TypeId; -} // namespace NativeRdb -} // namespace OHOS -#endif diff --git a/relational_store/interfaces/ndk/include/relational_store.h b/relational_store/interfaces/ndk/include/relational_store.h index 6c6290543f9cbc55d85a154f204042e67ea333cf..72d9f83433a3c52beaf40fbbbb58c5cf5fde01a2 100644 --- a/relational_store/interfaces/ndk/include/relational_store.h +++ b/relational_store/interfaces/ndk/include/relational_store.h @@ -156,6 +156,166 @@ typedef struct { int64_t id; } OH_Rdb_Store; +/** + * @brief Define OH_Rdb_ConfigV2 type. + * + * @since 13 + */ +typedef struct OH_Rdb_ConfigV2 OH_Rdb_ConfigV2; + +/** + * @brief Define Rdb_DBType type. + * + * @since 13 + */ +typedef enum Rdb_DBType { + /** + * @brief Means using SQLITE as the db kernal + */ + RDB_SQLITE = 1, + /** + * @brief Means using CARLEY_DB as the db kernal + */ + RDB_CAYLEY = 2, + /** + * @brief Means largest value for Rdb_DBType + */ + DBTYPE_BUTT = 64, +} Rdb_DBType; + +/** + * @brief Create OH_Rdb_ConfigV2 which is used to open store + * + * @return Returns the newly created OH_Rdb_ConfigV2 object. If NULL is returned, the creation fails. + * The possible cause is that the address space of the application is full, As a result, the space + * cannot be allocated. + * @see OH_Rdb_ConfigV2 + * @since 13 + */ +OH_Rdb_ConfigV2 *OH_Rdb_CreateConfig(); + +/** + * @brief Destroy OH_Rdb_ConfigV2 which is created by OH_Rdb_CreateConfig + * + * @param config Represents a pointer to {@link OH_Rdb_ConfigV2} instance. + * Indicates the configuration of the database related to this RDB store. + * @return Returns the status code of the execution. Successful execution returns RDB_OK, + * {@link RDB_OK} - success. + * {@link RDB_E_INVALID_ARGS} - The error code for common invalid args. + * @since 13 + */ +int OH_Rdb_DestroyConfig(OH_Rdb_ConfigV2 *config); + +/** + * @brief Set property databaseDir into config + * + * @param config Represents a pointer to {@link OH_Rdb_ConfigV2} instance. + * Indicates the configuration of the database related to this RDB store. + * @param dataBaseDir Indicates the directory of the database. + * @return Returns the status code of the execution. Successful execution returns RDB_OK, + * {@link RDB_OK} - success. + * {@link RDB_E_INVALID_ARGS} - The error code for common invalid args. + * @since 13 + */ +int OH_Rdb_SetDatabaseDir(OH_Rdb_ConfigV2 *config, const char *databaseDir); + +/** + * @brief Set property storeName into config + * + * @param config Represents a pointer to {@link OH_Rdb_ConfigV2} instance. + * Indicates the configuration of the database related to this RDB store. + * @param storeName Indicates the name of the database. + * @return Returns the status code of the execution. Successful execution returns RDB_OK, + * {@link RDB_OK} - success. + * {@link RDB_E_INVALID_ARGS} - The error code for common invalid args. + * @since 13 + */ +int OH_Rdb_SetStoreName(OH_Rdb_ConfigV2 *config, const char *storeName); + +/** + * @brief Set property bundleName into config + * + * @param config Represents a pointer to {@link OH_Rdb_ConfigV2} instance. + * Indicates the configuration of the database related to this RDB store. + * @param bundleName Indicates the bundle name of the application + * @return Returns the status code of the execution. Successful execution returns RDB_OK, + * {@link RDB_OK} - success. + * {@link RDB_E_INVALID_ARGS} - The error code for common invalid args. + * @since 13 + */ +int OH_Rdb_SetBundleName(OH_Rdb_ConfigV2 *config, const char *bundleName); + +/** + * @brief Set property moduleName into config + * + * @param config Represents a pointer to {@link OH_Rdb_ConfigV2} instance. + * Indicates the configuration of the database related to this RDB store. + * @param moduleName Indicates the module name of the application. + * @return Returns the status code of the execution. Successful execution returns RDB_OK, + * {@link RDB_OK} - success. + * {@link RDB_E_INVALID_ARGS} - The error code for common invalid args. + * @since 13 + */ +int OH_Rdb_SetModuleName(OH_Rdb_ConfigV2 *config, const char *moduleName); + +/** + * @brief Set property isEncrypted into config + * + * @param config Represents a pointer to {@link OH_Rdb_ConfigV2} instance. + * Indicates the configuration of the database related to this RDB store. + * @param isEncrypt Indicates whether the database is encrypted. + * @return Returns the status code of the execution. Successful execution returns RDB_OK, + * {@link RDB_OK} - success. + * {@link RDB_E_INVALID_ARGS} - The error code for common invalid args. + * @since 13 + */ +int OH_Rdb_SetEncrypted(OH_Rdb_ConfigV2 *config, bool isEncrypted); + +/** + * @brief Set property securityLevel into config + * + * @param config Represents a pointer to {@link OH_Rdb_ConfigV2} instance. + * Indicates the configuration of the database related to this RDB store. + * @param securityLevel Indicates the security level {@link OH_Rdb_SecurityLevel} of the database. + * @return Returns the status code of the execution. Successful execution returns RDB_OK, + * {@link RDB_OK} - success. + * {@link RDB_E_INVALID_ARGS} - The error code for common invalid args. + * @since 13 + */ +int OH_Rdb_SetSecurityLevel(OH_Rdb_ConfigV2 *config, int securityLevel); + +/** + * @brief Set property area into config + * + * @param config Represents a pointer to {@link OH_Rdb_ConfigV2} instance. + * Indicates the configuration of the database related to this RDB store + * @return Returns the status code of the execution. Successful execution returns RDB_OK, + * {@link RDB_OK} - success. + * {@link RDB_E_INVALID_ARGS} - The error code for common invalid args. + * @since 13 + */ +int OH_Rdb_SetArea(OH_Rdb_ConfigV2 *config, int area); + +/** + * @brief Set property dbType into config + * @param config Represents a pointer to {@link OH_Rdb_ConfigV2} instance. + * @param dbType Indicates the dbType {@link Rdb_DBType} of the database + * @return Returns the status code of the execution. Successful execution returns RDB_OK, + * {@link RDB_OK} - success. + * {@link RDB_E_INVALID_ARGS} - The error code for common invalid args. + * {@link RDB_E_NOT_SUPPORTED} - The error code for not support db types. + * @since 13 + */ +int OH_Rdb_SetDbType(OH_Rdb_ConfigV2 *config, int dbType); + +/** + * @brief Get support db type list + * @param numType The output parameter, which is used to recieve the length of the support db type array. + * @return Return Rdb_DBType array contains supported db type, array length is number of support type + * @since 13 + */ +const int *OH_Rdb_GetSupportedDbType(int *typeCount); + /** * @brief Creates an {@link OH_VObject} instance. * @@ -205,6 +365,24 @@ OH_Predicates *OH_Rdb_CreatePredicates(const char *table); */ OH_Rdb_Store *OH_Rdb_GetOrOpen(const OH_Rdb_Config *config, int *errCode); +/** + * @brief Obtains an RDB store with OH_Rdb_ConfigV2. + * + * You can set parameters of the RDB store as required. In general, + * this method is recommended to obtain a rdb store. + * + * @param config Represents a pointer to an {@link OH_Rdb_ConfigV2} instance. + * Indicates the configuration of the database related to this RDB store. + * @param errCode This parameter is the output parameter, + * and the execution status of a function is written to this variable. + * @return If the creation is successful, a pointer to the instance of the @link OH_Rdb_Store} structure is returned. + * If the Config is empty, config.size does not match, or errCode is empty. + * Get database path failed.Get RDB Store fail. Nullptr is returned. + * @see OH_Rdb_ConfigV2, OH_Rdb_Store. + * @since 13 + */ +OH_Rdb_Store *OH_Rdb_CreateOrOpen(const OH_Rdb_ConfigV2 *config, int *errCode); + /** * @brief Close the {@link OH_Rdb_Store} object and reclaim the memory occupied by the object. * @@ -232,6 +410,20 @@ int OH_Rdb_CloseStore(OH_Rdb_Store *store); */ int OH_Rdb_DeleteStore(const OH_Rdb_Config *config); +/** + * @brief Deletes the database with a specified path. + * + * @param config Represents a pointer to an {@link OH_Rdb_ConfigV2} instance. + * Indicates the configuration of the database related to this RDB store. + * @return Returns the status code of the execution. Successful execution returns RDB_OK, + * {@link RDB_OK} - success. + * {@link RDB_E_INVALID_ARGS} - The error code for common invalid args. + * while failure returns a specific error code. Specific error codes can be referenced {@link OH_Rdb_ErrCode}. + * @see OH_Rdb_ErrCode. + * @since 13 + */ +int OH_Rdb_DeleteStoreV2(const OH_Rdb_ConfigV2 *config); + /** * @brief Inserts a row of data into the target table. * @@ -306,6 +498,21 @@ OH_Cursor *OH_Rdb_Query(OH_Rdb_Store *store, OH_Predicates *predicates, const ch */ int OH_Rdb_Execute(OH_Rdb_Store *store, const char *sql); +/** + * @brief Write operations are performed using the specified transaction represented by the transaction ID + * + * @param store Represents a pointer to an {@link OH_Rdb_Store} instance. + * @param sql Indicates the SQL statement to execute. + * @param trxId The transaction ID of the specified transaction, must be greater than 0 + * @return Returns the status code of the execution. + * {@link RDB_OK} - success. + * {@link RDB_E_INVALID_ARGS} - The error code for common invalid args. + * {@link RDB_E_NOT_SUPPORTED} - The error code for not supprt. + * @see OH_Rdb_Store. + * @since 13 + */ +int OH_Rdb_ExecuteByTrxId(OH_Rdb_Store *store, int64_t trxId, const char *sql); + /** * @brief Queries data in the database based on an SQL statement. * @@ -354,6 +561,48 @@ int OH_Rdb_RollBack(OH_Rdb_Store *store); */ int OH_Rdb_Commit(OH_Rdb_Store *store); +/** + * @brief Begin a transaction and the transaction ID corresponding to the transaction. + * + * @param store Represents a pointer to an {@link OH_Rdb_Store} instance. + * @param trxId The output parameter, which is used to receive the transaction ID corresponding to the transaction + * @return Returns the status code of the execution. + * {@link RDB_OK} - success. + * {@link RDB_E_INVALID_ARGS} - The error code for common invalid args. + * {@link RDB_E_NOT_SUPPORTED} - The error code for not supprt. + * @see OH_Rdb_Store. + * @since 13 + */ +int OH_Rdb_BeginTransWithTrxId(OH_Rdb_Store *store, int64_t *trxId); + +/** + * @brief Roll back a transaction that is represented by a specified transaction ID + * + * @param store Represents a pointer to an {@link OH_Rdb_Store} instance. + * @param trxId The transaction ID of the specified transaction, must be greater than 0 + * @return Returns the status code of the execution. + * {@link RDB_OK} - success. + * {@link RDB_E_INVALID_ARGS} - The error code for common invalid args. + * {@link RDB_E_NOT_SUPPORTED} - The error code for not supprt. + * @see OH_Rdb_Store. + * @since 13 + */ +int OH_Rdb_RollBackByTrxId(OH_Rdb_Store *store, int64_t trxId); + +/** + * @brief Commit a transaction that is represented by a specified transaction ID + * + * @param store Represents a pointer to an {@link OH_Rdb_Store} instance. + * @param trxId The transaction ID of the specified transaction, must be greater than 0 + * @return Returns the status code of the execution. + * {@link RDB_OK} - success. + * {@link RDB_E_INVALID_ARGS} - The error code for common invalid args. + * {@link RDB_E_NOT_SUPPORTED} - The error code for not supprt. + * @see OH_Rdb_Store. + * @since 13 + */ +int OH_Rdb_CommitByTrxId(OH_Rdb_Store *store, int64_t trxId); + /** * @brief Backs up a database on specified path. * diff --git a/relational_store/interfaces/ndk/src/relational_store.cpp b/relational_store/interfaces/ndk/src/relational_store.cpp index dd51957ce36bdec55bc4874545b2573fda1f596b..e500aa718ec432d38d5e854cbb6b727dba1d2635 100644 --- a/relational_store/interfaces/ndk/src/relational_store.cpp +++ b/relational_store/interfaces/ndk/src/relational_store.cpp @@ -30,7 +30,6 @@ #include "relational_predicates_objects.h" #include "relational_store_error_code.h" #include "relational_store_impl.h" -#include "relational_store_inner.h" #include "relational_types_v0.h" #include "relational_values_bucket.h" #include "securec.h" @@ -42,10 +41,8 @@ constexpr int RDB_STORE_CID = 1234560; // The class id used to uniquely identify constexpr int RDB_CONFIG_SIZE_V0 = 41; constexpr int RDB_CONFIG_SIZE_V1 = 45; constexpr int RDB_CONFIG_V2_MAGIC_CODE = 0xDBCF2ADE; -constexpr int RDB_SQLITE = 1; -constexpr int RDB_CARLEY = 2; -static int g_supportDbTypes[] = {RDB_SQLITE, RDB_CARLEY}; +static int g_supportDbTypes[] = {RDB_SQLITE, RDB_CAYLEY}; struct OH_Rdb_ConfigV2 { int magicNum = RDB_CONFIG_V2_MAGIC_CODE; @@ -76,11 +73,12 @@ int OH_Rdb_DestroyConfig(OH_Rdb_ConfigV2 *config) return OH_Rdb_ErrCode::RDB_OK; } -int OH_Rdb_SetDataBaseDir(OH_Rdb_ConfigV2 *config, const char *dataBaseDir) +int OH_Rdb_SetDatabaseDir(OH_Rdb_ConfigV2 *config, const char *dataBaseDir) { - if (config == nullptr || (config->magicNum != RDB_CONFIG_V2_MAGIC_CODE)) { - LOG_ERROR("config is null %{public}d or magic num not valid %{public}x when Set DataBaseDir.", - (config == nullptr), (config == nullptr ? 0 : config->magicNum)); + if (config == nullptr || dataBaseDir == nullptr || (config->magicNum != RDB_CONFIG_V2_MAGIC_CODE)) { + LOG_ERROR("config is null %{public}d or dataBaseDir %{public}d magic num not valid %{public}x " + "when Set DataBaseDir.", (config == nullptr), (dataBaseDir == nullptr), + (config == nullptr ? 0 : config->magicNum)); return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; } config->dataBaseDir = std::string(dataBaseDir); @@ -89,9 +87,10 @@ int OH_Rdb_SetDataBaseDir(OH_Rdb_ConfigV2 *config, const char *dataBaseDir) int OH_Rdb_SetStoreName(OH_Rdb_ConfigV2 *config, const char *storeName) { - if (config == nullptr || (config->magicNum != RDB_CONFIG_V2_MAGIC_CODE)) { - LOG_ERROR("config is null %{public}d or magic num not valid %{public}x When set storeName.", - (config == nullptr), (config == nullptr ? 0 : config->magicNum)); + if (config == nullptr || storeName == nullptr || (config->magicNum != RDB_CONFIG_V2_MAGIC_CODE)) { + LOG_ERROR("config is null %{public}d or storeName %{public}d or magic num not ok" + "%{public}x When set storeName.", (config == nullptr), (storeName == nullptr), + (config == nullptr ? 0 : config->magicNum)); return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; } config->storeName = std::string(storeName); @@ -100,9 +99,9 @@ int OH_Rdb_SetStoreName(OH_Rdb_ConfigV2 *config, const char *storeName) int OH_Rdb_SetBundleName(OH_Rdb_ConfigV2 *config, const char *bundleName) { - if (config == nullptr || (config->magicNum != RDB_CONFIG_V2_MAGIC_CODE)) { - LOG_ERROR("config is null %{public}d or magic num not valid %{public}x when set bundleName.", - (config == nullptr), (config == nullptr ? 0 : config->magicNum)); + if (config == nullptr || bundleName == nullptr || (config->magicNum != RDB_CONFIG_V2_MAGIC_CODE)) { + LOG_ERROR("config is null %{public}d or bundleName %{public}d magic num no ok %{public}x when set bundleName.", + (config == nullptr), (bundleName == nullptr), (config == nullptr ? 0 : config->magicNum)); return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; } config->bundleName = std::string(bundleName); @@ -111,23 +110,23 @@ int OH_Rdb_SetBundleName(OH_Rdb_ConfigV2 *config, const char *bundleName) int OH_Rdb_SetModuleName(OH_Rdb_ConfigV2 *config, const char *moduleName) { - if (config == nullptr || (config->magicNum != RDB_CONFIG_V2_MAGIC_CODE)) { - LOG_ERROR("config is null %{public}d or magic num not valid %{public}x when set moduleName.", - (config == nullptr), (config == nullptr ? 0 : config->magicNum)); + if (config == nullptr || moduleName == nullptr || (config->magicNum != RDB_CONFIG_V2_MAGIC_CODE)) { + LOG_ERROR("config is null %{public}d or moduleName %{public}d magic num no ok %{public}x when set moduleName.", + (config == nullptr), (moduleName == nullptr), (config == nullptr ? 0 : config->magicNum)); return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; } config->moduleName = std::string(moduleName); return OH_Rdb_ErrCode::RDB_OK; } -int OH_Rdb_SetEncrypt(OH_Rdb_ConfigV2 *config, bool isEncrypt) +int OH_Rdb_SetEncrypted(OH_Rdb_ConfigV2 *config, bool isEncrypted) { if (config == nullptr || (config->magicNum != RDB_CONFIG_V2_MAGIC_CODE)) { LOG_ERROR("config is null %{public}d or magic num not valid %{public}x when set encrypt.", (config == nullptr), (config == nullptr ? 0 : config->magicNum)); return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; } - config->isEncrypt = isEncrypt; + config->isEncrypt = isEncrypted; return OH_Rdb_ErrCode::RDB_OK; } @@ -164,24 +163,24 @@ int OH_Rdb_SetArea(OH_Rdb_ConfigV2 *config, int area) int OH_Rdb_SetDbType(OH_Rdb_ConfigV2 *config, int dbType) { if (config == nullptr || (config->magicNum != RDB_CONFIG_V2_MAGIC_CODE) || - (dbType < RDB_SQLITE || dbType > RDB_CARLEY)) { + (dbType < RDB_SQLITE || dbType > RDB_CAYLEY)) { LOG_ERROR("config is null %{public}d or magicNum not valid %{public}d or dbType is out of range %{public}d", (config == nullptr), (config == nullptr ? 0 : config->magicNum), dbType); return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; } - if (dbType == RDB_CARLEY && !(OHOS::NativeRdb::IsUsingArkData())) { + if (dbType == RDB_CAYLEY && !(OHOS::NativeRdb::IsUsingArkData())) { return OH_Rdb_ErrCode::RDB_E_NOT_SUPPORTED; } config->dbType = dbType; return OH_Rdb_ErrCode::RDB_OK; } -const int *OH_Rdb_GetSupportDBType(int *numType) +const int *OH_Rdb_GetSupportedDbType(int *numType) { if (numType == nullptr) { return nullptr; } - // if use arkData, then numType will be 2 {RDB_SQLITE and RDB_CARLEY}, otherwise only 1 {RDB_SQLITE} + // if use arkData, then numType will be 2 {RDB_SQLITE and RDB_CAYLEY}, otherwise only 1 {RDB_SQLITE} *numType = OHOS::NativeRdb::IsUsingArkData() ? 2 : 1; return g_supportDbTypes; } @@ -317,7 +316,7 @@ static OHOS::NativeRdb::RdbStoreConfig GetRdbStoreConfig(const OH_Rdb_ConfigV2 * (OHOS::NativeRdb::SecurityLevel(config->securityLevel) < OHOS::NativeRdb::SecurityLevel::S1 || OHOS::NativeRdb::SecurityLevel(config->securityLevel) >= OHOS::NativeRdb::SecurityLevel::LAST) || (config->area < RDB_SECURITY_AREA_EL1 || config->area > RDB_SECURITY_AREA_EL5) || - (config->dbType < RDB_SQLITE || config->dbType > RDB_CARLEY)) { + (config->dbType < RDB_SQLITE || config->dbType > RDB_CAYLEY)) { *errCode = OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; LOG_ERROR("Config magic number is not valid %{public}x or securityLevel %{public}d area %{public}d" "dbType %{public}d ret %{public}d", config->magicNum, config->securityLevel, config->area, config->dbType, @@ -335,7 +334,7 @@ static OHOS::NativeRdb::RdbStoreConfig GetRdbStoreConfig(const OH_Rdb_ConfigV2 * rdbStoreConfig.SetSecurityLevel(OHOS::NativeRdb::SecurityLevel(config->securityLevel)); rdbStoreConfig.SetEncryptStatus(config->isEncrypt); rdbStoreConfig.SetArea(config->area - 1); - rdbStoreConfig.SetIsVector(config->dbType == RDB_CARLEY); + rdbStoreConfig.SetIsVector(config->dbType == RDB_CAYLEY); rdbStoreConfig.SetBundleName(config->bundleName); rdbStoreConfig.SetName(config->storeName); return rdbStoreConfig; diff --git a/relational_store/interfaces/ndk/src/relational_store_inner.h b/relational_store/interfaces/ndk/src/relational_store_inner.h deleted file mode 100644 index ad27a587916f033b677483e07ea15dc6c585af74..0000000000000000000000000000000000000000 --- a/relational_store/interfaces/ndk/src/relational_store_inner.h +++ /dev/null @@ -1,54 +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. - */ -#ifndef RELATIONAL_STORE_INNER_H -#define RELATIONAL_STORE_INNER_H - -#include "relational_store.h" - -#ifndef API_EXPORT -#define API_EXPORT __attribute__((visibility("default"))) -#endif // API_EXPORT - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct OH_Rdb_ConfigV2 OH_Rdb_ConfigV2; -API_EXPORT OH_Rdb_ConfigV2 *OH_Rdb_CreateConfig(); -API_EXPORT int OH_Rdb_DestroyConfig(OH_Rdb_ConfigV2 *config); - -API_EXPORT int OH_Rdb_SetDataBaseDir(OH_Rdb_ConfigV2 *config, const char *dataBaseDir); -API_EXPORT int OH_Rdb_SetStoreName(OH_Rdb_ConfigV2 *config, const char *storeName); -API_EXPORT int OH_Rdb_SetBundleName(OH_Rdb_ConfigV2 *config, const char *bundleName); -API_EXPORT int OH_Rdb_SetModuleName(OH_Rdb_ConfigV2 *config, const char *moduleName); -API_EXPORT int OH_Rdb_SetEncrypt(OH_Rdb_ConfigV2 *config, bool isEncrypt); -API_EXPORT int OH_Rdb_SetSecurityLevel(OH_Rdb_ConfigV2 *config, int securityLevel); -API_EXPORT int OH_Rdb_SetArea(OH_Rdb_ConfigV2 *config, int area); -API_EXPORT int OH_Rdb_SetDbType(OH_Rdb_ConfigV2 *config, int dbType); -API_EXPORT const int *OH_Rdb_GetSupportDBType(int *numType); - -API_EXPORT OH_Rdb_Store *OH_Rdb_CreateOrOpen(const OH_Rdb_ConfigV2 *config, int *errCode); -API_EXPORT int OH_Rdb_DeleteStoreV2(const OH_Rdb_ConfigV2 *config); - -API_EXPORT int OH_Rdb_ExecuteByTrxId(OH_Rdb_Store *store, int64_t trxId, const char *sql); -API_EXPORT int OH_Rdb_BeginTransWithTrxId(OH_Rdb_Store *store, int64_t *trxId); -API_EXPORT int OH_Rdb_RollBackByTrxId(OH_Rdb_Store *store, int64_t trxId); -API_EXPORT int OH_Rdb_CommitByTrxId(OH_Rdb_Store *store, int64_t trxId); - -#ifdef __cplusplus -} -#endif - -#endif // RELATIONAL_STORE_INNER_H diff --git a/relational_store/test/js/clouddata/unittest/src/CloudSyncConfigPromise.js b/relational_store/test/js/clouddata/unittest/src/CloudSyncConfigPromise.js index 6945a9d6fa617f956826788b04842b4c54f6e3ae..63cbf17bd362cd38bdf0b6286d8c9cf417134f1c 100644 --- a/relational_store/test/js/clouddata/unittest/src/CloudSyncConfigPromise.js +++ b/relational_store/test/js/clouddata/unittest/src/CloudSyncConfigPromise.js @@ -683,6 +683,7 @@ describe('CloudConfigPromiseTest', function () { console.info('QueryLastSyncInfoInvalidArgsTest001'); try { await cloudData.Config.queryLastSyncInfo(123, "bundleName"); + expect(false).assertTrue(); } catch (e) { console.error('QueryLastSyncInfoInvalidArgsTest001 fail' + `, error code is ${e.code}, message is ${e.message}`); expect(e.code == 401).assertTrue(); @@ -700,6 +701,7 @@ describe('CloudConfigPromiseTest', function () { console.info('QueryLastSyncInfoInvalidArgsTest002'); try { await cloudData.Config.queryLastSyncInfo("id", 123); + expect(false).assertTrue(); } catch (e) { console.error('QueryLastSyncInfoInvalidArgsTest002 fail' + `, error code is ${e.code}, message is ${e.message}`); expect(e.code == 401).assertTrue(); @@ -717,6 +719,7 @@ describe('CloudConfigPromiseTest', function () { console.info('QueryLastSyncInfoInvalidArgsTest003'); try { await cloudData.Config.queryLastSyncInfo(); + expect(false).assertTrue(); } catch (e) { console.error('QueryLastSyncInfoInvalidArgsTest003 fail' + `, error code is ${e.code}, message is ${e.message}`); expect(e.code == 401).assertTrue(); @@ -734,10 +737,83 @@ describe('CloudConfigPromiseTest', function () { console.info('QueryLastSyncInfoInvalidArgsTest004'); try { await cloudData.Config.queryLastSyncInfo("id"); + expect(false).assertTrue(); } catch (e) { console.error('QueryLastSyncInfoInvalidArgsTest004 fail' + `, error code is ${e.code}, message is ${e.message}`); expect(e.code == 401).assertTrue(); } done(); }) + + /** + * @tc.name QueryLastSyncInfoInvalidArgsTest005 + * @tc.desc Test Js Api QueryLastSyncInfo that storeName parameter is undefined + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('QueryLastSyncInfoInvalidArgsTest005', 0, async function (done) { + console.info('QueryLastSyncInfoInvalidArgsTest005'); + try { + await cloudData.Config.queryLastSyncInfo("id", "bundleName", undefined); + expect(false).assertTrue(); + } catch (e) { + console.error('QueryLastSyncInfoInvalidArgsTest005 fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 201).assertTrue(); + } + done(); + }) + + /** + * @tc.name QueryLastSyncInfoInvalidArgsTest006 + * @tc.desc Test Js Api QueryLastSyncInfo that storeName parameter is null + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('QueryLastSyncInfoInvalidArgsTest006', 0, async function (done) { + console.info('QueryLastSyncInfoInvalidArgsTest006'); + try { + await cloudData.Config.queryLastSyncInfo("id", "bundleName", null); + expect(false).assertTrue(); + } catch (e) { + console.error('QueryLastSyncInfoInvalidArgsTest006 fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 201).assertTrue(); + } + done(); + }) + + /** + * @tc.name QueryLastSyncInfoValidArgsTest001 + * @tc.desc Test Js Api QueryLastSyncInfo that all parameters is valid + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('QueryLastSyncInfoValidArgsTest001', 0, async function (done) { + console.info('QueryLastSyncInfoValidArgsTest001'); + try { + await cloudData.Config.queryLastSyncInfo("id", "bundleName", "storeId"); + expect(false).assertTrue(); + } catch (e) { + console.error('QueryLastSyncInfoValidArgsTest001 fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 201).assertTrue(); + } + done(); + }) + + /** + * @tc.name QueryLastSyncInfoValidArgsTest002 + * @tc.desc Test Js Api QueryLastSyncInfo that lack storeId parameter + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('QueryLastSyncInfoValidArgsTest002', 0, async function (done) { + console.info('QueryLastSyncInfoValidArgsTest002'); + try { + await cloudData.Config.queryLastSyncInfo("id", "bundleName"); + expect(false).assertTrue(); + } catch (e) { + console.error('QueryLastSyncInfoValidArgsTest002 fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 201).assertTrue(); + } + done(); + }) }) \ No newline at end of file diff --git a/relational_store/test/js/relationalstore/unittest/src/RdbStoreResultSetGetRow.test.js b/relational_store/test/js/relationalstore/unittest/src/RdbStoreResultSetGetRow.test.js index 552de4625fec1c548c26fb356a6070a49ee67721..ddb8e74a4f169bd014203e59db6b7601649cf89e 100644 --- a/relational_store/test/js/relationalstore/unittest/src/RdbStoreResultSetGetRow.test.js +++ b/relational_store/test/js/relationalstore/unittest/src/RdbStoreResultSetGetRow.test.js @@ -270,5 +270,20 @@ describe('rdbStoreResultSetGetRowTest', function () { expect(false).assertEqual(resultSet.goToLastRow()); console.log(TAG + "************* rdbStoreInsertUndefinedValueTest0008 end *************"); }) + + /** + * @tc.name rdb store resultSet getRow test + * @tc.number rdbStoreResultSetGoToLastRow0009 + * @tc.desc resultSet goToFirstRow test + */ + it('rdbStoreResultSetGetRowTest0009', 0, async function () { + console.log(TAG + "************* rdbStoreResultSetGetRowTest0009 start *************"); + let querySql = "SELECT 1"; + let resultSet = await rdbStore.querySql(querySql); + expect(true).assertEqual(resultSet.goToFirstRow()); + let valueBucket_ret = resultSet.getRow(); + expect(1).assertEqual(valueBucket_ret["1"]); + console.log(TAG + "************* rdbStoreResultSetGetRowTest0009 end *************"); + }) console.log(TAG + "*************Unit Test End*************"); }) \ No newline at end of file diff --git a/relational_store/test/js/relationalstore/unittest/src/RdbStoreTransaction.test.js b/relational_store/test/js/relationalstore/unittest/src/RdbStoreTransaction.test.js new file mode 100644 index 0000000000000000000000000000000000000000..a468a83ec73eff558bbb996bd766b1b76165ca4d --- /dev/null +++ b/relational_store/test/js/relationalstore/unittest/src/RdbStoreTransaction.test.js @@ -0,0 +1,1464 @@ +/* + * 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. + */ + +import {describe, beforeAll, beforeEach, afterEach, afterAll, it, expect} from 'deccjsunit/index' +import data_relationalStore from '@ohos.data.relationalStore' +import ability_featureAbility from '@ohos.ability.featureAbility' + +var context = ability_featureAbility.getContext() + +const TAG = "[RELATIONAL_STORE_TRANSACTION_JSKITS_TEST]" +const CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test (" + "id INTEGER PRIMARY KEY, " + + "name TEXT NOT NULL, " + "age INTEGER, " + "salary REAL, " + "blobType BLOB)"; + +const STORE_CONFIG = { + name: "TransactionTest.db", + securityLevel: data_relationalStore.SecurityLevel.S1, +} + +var rdbStore = undefined; + +describe('rdbStoreTransactionTest', function () { + beforeAll(async function () { + console.info(TAG + 'beforeAll') + rdbStore = await data_relationalStore.getRdbStore(context, STORE_CONFIG); + await rdbStore.executeSql(CREATE_TABLE_TEST, null); + }) + + beforeEach(async function () { + await rdbStore.executeSql(CREATE_TABLE_TEST); + console.info(TAG + 'beforeEach') + }) + + afterEach(async function () { + await rdbStore.executeSql("DELETE FROM test"); + console.info(TAG + 'afterEach') + }) + + afterAll(async function () { + console.info(TAG + 'afterAll') + rdbStore = null + await data_relationalStore.deleteRdbStore(context, "TransactionTest.db"); + }) + + console.log(TAG + "*************Unit Test Begin*************"); + + /** + * @tc.number testTransactionInsert0001 + * @tc.name Normal test case of transactions, insert a row of data + * @tc.desc 1.Execute beginTransaction + * 2.Insert data + * 3.Execute commit + * 4.Query data + */ + it('testTransactionInsert0001', 0, async function (done) { + console.log(TAG + "************* testTransactionInsert0001 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction(data_relationalStore.TransactionType.DEFERRED) + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + var num = await transaction.insert("test", valueBucket) + expect(1).assertEqual(num); + + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await transaction.query(predicates) + console.log(TAG + "testTransactionInsert0001 result count " + resultSet.rowCount) + expect(1).assertEqual(resultSet.rowCount) + resultSet.close() + await transaction.commit() + } catch (e) { + await transaction.commit() + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testTransactionInsert0001 failed"); + } + done() + console.log(TAG + "************* testTransactionInsert0001 end *************"); + }) + + /** + * @tc.number testTransactionBatchInsert0001 + * @tc.name Normal test case of transactions, insert a row of data + * @tc.desc 1.Execute beginTransaction + * 2.BatchInsert data + * 3.Execute commit + * 4.Query data + */ + it('testTransactionBatchInsert0001', 0, async function (done) { + console.log(TAG + "************* testTransactionBatchInsert0001 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction() + try { + const valueBucket = { + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + let valueBucketArray = new Array(); + for (let i = 0; i < 2; i++) { + valueBucketArray.push(valueBucket); + } + var num = await transaction.batchInsert("test", valueBucketArray) + expect(2).assertEqual(num); + + let resultSet = await transaction.querySql("select * from test") + console.log(TAG + "testTransactionBatchInsert0001 result count " + resultSet.rowCount) + expect(2).assertEqual(resultSet.rowCount) + resultSet.close() + + await transaction.commit() + } catch (e) { + await transaction.rollback() + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testTransactionBatchInsert0001 failed"); + } + done() + console.log(TAG + "************* testTransactionBatchInsert0001 end *************"); + }) + + /** + * @tc.number testTransactionUpdate0001 + * @tc.name Normal test case of transactions, insert and update a row of data + * @tc.desc 1.Execute beginTransaction + * 2.Insert data + * 2.Update data + * 3.Execute commit + * 4.Query data + */ + it('testTransactionUpdate0001', 0, async function (done) { + console.log(TAG + "************* testTransactionUpdate0001 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction(data_relationalStore.TransactionType.IMMEDIATE) + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + await transaction.insert("test", valueBucket) + + let predicates = new data_relationalStore.RdbPredicates("test"); + predicates.equalTo("name", "lisi"); + const updateValueBucket = { + "name": "update", + "age": 28, + "salary": 25, + "blobType": u8, + } + var num = await transaction.update(updateValueBucket, predicates) + expect(1).assertEqual(num); + + let resultSet = await transaction.querySql("select * from test") + console.log(TAG + "testTransactionUpdate0001 result count " + resultSet.rowCount) + expect(1).assertEqual(resultSet.rowCount) + expect(true).assertEqual(resultSet.goToFirstRow()) + const name = resultSet.getString(resultSet.getColumnIndex("name")) + expect("update").assertEqual(name); + const age = resultSet.getLong(resultSet.getColumnIndex("age")) + expect(28).assertEqual(age); + const salary = resultSet.getLong(resultSet.getColumnIndex("salary")) + expect(25).assertEqual(salary); + resultSet.close() + await transaction.commit() + } catch (e) { + await transaction.rollback() + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testTransactionUpdate0001 failed"); + } + done() + console.log(TAG + "************* testTransactionUpdate0001 end *************"); + }) + + /** + * @tc.number testTransactionDelete0001 + * @tc.name Normal test case of transactions, insert and update a row of data + * @tc.desc 1.Execute beginTransaction + * 2.Insert data + * 2.Delete data + * 3.Execute commit + * 4.Query data + */ + it('testTransactionDelete0001', 0, async function (done) { + console.log(TAG + "************* testTransactionDelete0001 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction(data_relationalStore.TransactionType.EXCLUSIVE) + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + await transaction.insert("test", valueBucket) + + let predicates = new data_relationalStore.RdbPredicates("test"); + predicates.equalTo("name", "lisi"); + var num = await transaction.delete(predicates) + expect(1).assertEqual(num); + + let resultSet = await transaction.querySql("select * from test") + console.log(TAG + "testTransactionDelete0001 result count " + resultSet.rowCount) + expect(0).assertEqual(resultSet.rowCount) + resultSet.close() + await transaction.commit() + } catch (e) { + await transaction.rollback() + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testTransactionDelete0001 failed"); + } + done() + console.log(TAG + "************* testTransactionDelete0001 end *************"); + }) + + /** + * @tc.number testExecute0001 + * @tc.name Normal test case of Execute, check integrity for store + * @tc.desc 1. Execute sql: PRAGMA integrity_check + * 2. Check returned value + */ + it('testExecute0001', 0, async function (done) { + console.info(TAG + "************* testExecute0001 start *************"); + var transaction = await rdbStore.createTransaction(data_relationalStore.TransactionType.EXCLUSIVE) + try { + let ret = await transaction.execute("PRAGMA integrity_check"); + expect("ok").assertEqual(ret); + await transaction.commit(); + } catch (err) { + await transaction.rollback(); + expect(null).assertFail(); + console.error(`integrity_check failed, code:${err.code}, message: ${err.message}`); + } + done(); + console.info(TAG + "************* testExecute0001 end *************"); + }) + + + /** + * @tc.number testExecute0002 + * @tc.name Normal test case of ExecuteSql + * @tc.desc 1.Insert data + * 2.ExecuteSql(delete age = "18" OR "20") + * 3.QuerySql + */ + it('testExecute0002', 0, async function (done) { + console.log(TAG + "************* testExecute0002 start *************"); + var transaction = await rdbStore.createTransaction() + var u8 = new Uint8Array([1, 2, 3]) + try { + var valueBucket = { + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + for (let i = 0; i < 3; i++) { + valueBucket.age = valueBucket.age + 1; + var row = await transaction.insert("test", valueBucket) + console.log(TAG + "testExecute0002 insert row " + row) + } + await transaction.execute("DELETE FROM test WHERE age = ? OR age = ?", [21, 20]) + + let resultSet = await transaction.querySql("select * from test") + console.log(TAG + "testExecute0002 transaction.querySql result count " + resultSet.rowCount) + expect(1).assertEqual(resultSet.rowCount) + expect(true).assertEqual(resultSet.goToFirstRow()) + const age = resultSet.getLong(resultSet.getColumnIndex("age")) + expect(19).assertEqual(age); + await resultSet.close() + await transaction.commit() + } catch (e) { + await transaction.rollback() + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testExecute0002 failed"); + } + done(); + console.log(TAG + "************* testExecute0002 end *************"); + } + ) + + /** + * @tc.number testExecute0003 + * @tc.name Normal test case of ExecuteSql + * @tc.desc 1.Insert data (param is long string) + * 2.Query data + * 3.ExecuteSql (delete age = 19 AND name = nameStr) + * 4.Query data + */ + it('ExecuteSqlTest0003', 0, async function (done) { + console.log(TAG + "************* testExecute0003 start *************"); + var u8 = new Uint8Array([3, 4, 5]) + var transaction = await rdbStore.createTransaction() + var nameStr = "lisi" + "e".repeat(2000) + "zhangsan" + var valueBucket = { + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + var row = await transaction.insert("test", valueBucket) + console.log(TAG + "testExecute0003 insert row " + row) + valueBucket.name = nameStr + for (let i = 0; i < 2; i++) { + row = await transaction.insert("test", valueBucket) + valueBucket.age = valueBucket.age + 1; + console.log(TAG + "testExecute0003 insert row " + row) + } + { + let predicates = await new data_relationalStore.RdbPredicates("test") + predicates.equalTo("name", nameStr) + let querySqlPromise = transaction.query(predicates) + querySqlPromise.then(async (resultSet) => { + await expect(2).assertEqual(resultSet.rowCount) + resultSet.close() + }).catch((err) => { + expect(null).assertFail(); + }) + await querySqlPromise + } + { + let executeSqlPromise = transaction.execute("DELETE FROM test WHERE age = 19 AND name ='" + nameStr + "'") + executeSqlPromise.then(async () => { + await console.log(TAG + "executeSql done."); + }).catch((err) => { + console.log(TAG + "executeSql failed. " + err); + expect(null).assertFail(); + }) + await executeSqlPromise + } + await transaction.commit(); + { + let predicates = await new data_relationalStore.RdbPredicates("test") + predicates.equalTo("name", nameStr) + let querySqlPromise = rdbStore.query(predicates) + querySqlPromise.then(async (resultSet) => { + console.log(TAG + "testExecute0003 rdbStore.querySql result count " + resultSet.rowCount) + await expect(1).assertEqual(resultSet.rowCount) + expect(true).assertEqual(resultSet.goToFirstRow()) + const name = resultSet.getString(resultSet.getColumnIndex("name")) + expect(nameStr).assertEqual(name) + expect(2012).assertEqual(name.length) + expect(18).assertEqual(resultSet.getLong(resultSet.getColumnIndex("age"))) + expect(100.5).assertEqual(resultSet.getDouble(resultSet.getColumnIndex("salary"))) + const blobType = resultSet.getBlob(resultSet.getColumnIndex("blobType")) + expect(3).assertEqual(blobType[0]) + resultSet.close(); + done(); + }).catch((err) => { + console.log(TAG + err); + expect(null).assertFail(); + }) + await querySqlPromise + } + done(); + console.log(TAG + "************* testExecute0003 end *************"); + }) + + /** + * @tc.number testExecute0004 + * @tc.name Normal test case of ExecuteSql, drop table + * @tc.desc 1.Insert data + * 2.ExecuteSql (drop table) + */ + it('testExecute0004', 0, async function (done) { + console.log(TAG + "************* testExecute0004 start *************"); + var u8 = new Uint8Array([3, 4, 5]) + var transaction = await rdbStore.createTransaction() + try { + var valueBucket = { + "name": "zhangsan", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + let valueBucketArray = new Array(); + for (let i = 0; i < 3; i++) { + valueBucket.age = valueBucket.age + 1; + valueBucketArray.push(valueBucket); + } + var num = await transaction.batchInsert("test", valueBucketArray) + expect(3).assertEqual(num); + await transaction.execute("DROP TABLE IF EXISTS test") + + let resultSet = await transaction.querySql("select * from test") + console.log(TAG + "testExecute0004 transaction.querySql result count " + resultSet.rowCount) + expect(resultSet.rowCount < 1).assertTrue() + await transaction.commit() + } catch (e) { + await transaction.rollback() + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testExecute0004 failed"); + } + done(); + console.log(TAG + "************* testExecute0004 end *************"); + }) + + /** + * @tc.number testExecute0005 + * @tc.name Normal test case of executeSql and querySql, PRAGMA user_version + * @tc.desc 1.Set user_version + * 2.Get user_version + */ + it('testExecute0005', 0, async function (done) { + console.log(TAG + "************* testExecute0005 start *************"); + // 2 is used to set the store version + var transaction = await rdbStore.createTransaction() + try { + await transaction.execute("PRAGMA user_version = 2") + let resultSet = await transaction.querySql("PRAGMA user_version"); + console.log(TAG + "testExecute0005 transaction.querySql result count " + resultSet.rowCount) + resultSet.goToFirstRow(); + expect(2).assertEqual(resultSet.getLong(0)) + resultSet.close(); + await transaction.commit() + } catch (e) { + await transaction.rollback() + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testExecute0005 failed"); + } + done(); + console.log(TAG + "************* testExecute0005 end *************"); + }) + + /** + * @tc.number testExecute0006 + * @tc.name Normal test case of executeSql and querySql, PRAGMA table_info + * @tc.desc 1.Get table_info + * 2.Check table_info + */ + it('testExecute0006', 0, async function (done) { + console.log(TAG + "************* testExecute0006 start *************"); + var transaction = await rdbStore.createTransaction() + try { + let resultSet = await transaction.querySql("PRAGMA table_info(test)"); + console.log(TAG + "testExecute0006 transaction.querySql result count " + resultSet.rowCount) + resultSet.goToFirstRow(); + expect(0).assertEqual(resultSet.getLong(0)) + expect("id").assertEqual(resultSet.getString(1)) + expect("INTEGER").assertEqual(resultSet.getString(2)) + resultSet.goToNextRow(); + expect(1).assertEqual(resultSet.getLong(0)) + expect("name").assertEqual(resultSet.getString(1)) + expect("TEXT").assertEqual(resultSet.getString(2)) + expect(1).assertEqual(resultSet.getLong(3)) + resultSet.goToNextRow(); + expect(2).assertEqual(resultSet.getLong(0)) + expect("age").assertEqual(resultSet.getString(1)) + expect("INTEGER").assertEqual(resultSet.getString(2)) + resultSet.goToNextRow(); + expect(3).assertEqual(resultSet.getLong(0)) + expect("salary").assertEqual(resultSet.getString(1)) + expect("REAL").assertEqual(resultSet.getString(2)) + resultSet.goToNextRow(); + expect(4).assertEqual(resultSet.getLong(0)) + expect("blobType").assertEqual(resultSet.getString(1)) + expect("BLOB").assertEqual(resultSet.getString(2)) + resultSet.close(); + await transaction.commit() + } catch (e) { + await transaction.rollback() + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testExecute0006 failed"); + } + done(); + console.log(TAG + "************* testExecute0006 end *************"); + }) + + /** + * @tc.number testExecute0007 + * @tc.name Normal test case of executeSql, if spaces before the sql + * @tc.desc 1.Set user_version + * 2.Get user_version + */ + it('testExecute0007', 0, async function (done) { + console.log(TAG + "************* testExecute0007 start *************"); + var transaction = await rdbStore.createTransaction() + try { + // 2 is used to set the store version + await transaction.execute(" PRAGMA user_version = 2") + let resultSet = await transaction.querySql("PRAGMA user_version"); + console.log(TAG + "testExecute0007 transaction.querySql1 result count " + resultSet.rowCount) + resultSet.goToFirstRow(); + expect(2).assertEqual(resultSet.getLong(0)) + + await transaction.execute("\r\nPRAGMA user_version = 3") + resultSet = await transaction.querySql("PRAGMA user_version"); + console.log(TAG + "testExecute0007 transaction.querySql2 result count " + resultSet.rowCount) + resultSet.goToFirstRow(); + expect(3).assertEqual(resultSet.getLong(0)) + resultSet.close(); + await transaction.commit() + } catch (e) { + await transaction.rollback() + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testExecute0007 failed"); + } + done(); + console.log(TAG + "************* testExecute0007 end *************"); + }) + + /** + * @tc.number testTransactionSyncInterface0001 + * @tc.name Normal test case of transactions, insert a row of data + * @tc.desc 1.Execute beginTransaction + * 2.BatchInsertSync data + * 3.InsertSync data + * 4.UpdateSync data + * 5.DeleteSync data + * 6.Execute commit + * 7.querySqlSync + * 7.ExecuteSync + */ + it('testTransactionSyncInterface0001', 0, async function (done) { + console.log(TAG + "************* testTransactionSyncInterface0001 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction(data_relationalStore.TransactionType.DEFERRED) + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + var num = await transaction.insertSync("test", valueBucket, data_relationalStore.ConflictResolution.ON_CONFLICT_REPLACE); + expect(1).assertEqual(num); + const updateValueBucket = { + "name": "update", + "age": 28, + "salary": 25, + "blobType": u8, + } + let predicates = new data_relationalStore.RdbPredicates("test"); + predicates.equalTo("name", "lisi") + num = await transaction.updateSync(updateValueBucket, predicates) + expect(1).assertEqual(num); + + let deletePredicates = new data_relationalStore.RdbPredicates("test"); + predicates.equalTo("name", "update") + num = await transaction.deleteSync(deletePredicates); + expect(1).assertEqual(num); + + let resultSet = await transaction.querySqlSync("select * from test") + console.log(TAG + "testTransactionSyncInterface0001 result count " + resultSet.rowCount) + expect(0).assertEqual(resultSet.rowCount) + resultSet.close() + + await transaction.commit() + } catch (e) { + await transaction.rollback() + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testTransactionSyncInterface0001 failed"); + } + done() + console.log(TAG + "************* testTransactionSyncInterface0001 end *************"); + }) + + /** + * @tc.number testTransactionRollback0001 + * @tc.name Normal test case of transactions, insert and update a row of data + * @tc.desc 1.Execute beginTransaction + * 2.Insert data + * 3.rollback data + * 4.Query data + */ + it('testTransactionRollback0001', 0, async function (done) { + console.log(TAG + "************* testTransactionRollback0001 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction(data_relationalStore.TransactionType.EXCLUSIVE) + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + await transaction.insert("test", valueBucket) + + await transaction.rollback() + + let resultSet = rdbStore.querySqlSync("select * from test") + console.log(TAG + "testTransactionRollback0001 result count " + resultSet.rowCount) + expect(0).assertEqual(resultSet.rowCount) + resultSet.close() + } catch (e) { + await transaction.rollback() + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testTransactionRollback0001 failed"); + } + done() + console.log(TAG + "************* testTransactionRollback0001 end *************"); + }) + + /** + * @tc.number testTransactionIsolation0001 + * @tc.name testTransactionIsolation. EXCLUSIVE and EXCLUSIVE + * @tc.desc 1.begin EXCLUSIVE Transaction + * 2.begin EXCLUSIVE Transaction again + * 3.throw 14800024 + */ + it('testTransactionIsolation0001', 0, async function (done) { + console.log(TAG + "************* testTransactionIsolation0001 start *************"); + var exclusiveTrans = await rdbStore.createTransaction(data_relationalStore.TransactionType.EXCLUSIVE) + try { + var trans = await rdbStore.createTransaction(data_relationalStore.TransactionType.EXCLUSIVE) + trans.commit(); + expect(null).assertFail() + console.log(TAG + "testTransactionIsolation0001 failed"); + } catch (e) { + await exclusiveTrans.rollback(); + console.log(TAG + e); + expect(e.code).assertEqual(14800024) + console.log(TAG + "testTransactionIsolation0001 success"); + } + done() + console.log(TAG + "************* testTransactionIsolation0001 end *************"); + }) + + /** + * @tc.number testTransactionIsolation0002 + * @tc.name testTransactionIsolation. DEFERRED and EXCLUSIVE + * @tc.desc 1.begin DEFERRED Transaction + * 2.begin EXCLUSIVE Transaction again + * 3.insert data with EXCLUSIVE Transaction + * 4.query data with DEFERRED Transaction -> no data + * 5.execute commit with EXCLUSIVE Transaction + * 6.query data with DEFERRED Transaction -> no data -> why? step 4 start isolation + * 7.query data with Rdb -> has data + */ + it('testTransactionIsolation0002', 0, async function (done) { + console.log(TAG + "************* testTransactionIsolation0002 start *************"); + var deferredTrans = await rdbStore.createTransaction(data_relationalStore.TransactionType.DEFERRED) + try { + var exclusiveTrans = await rdbStore.createTransaction(data_relationalStore.TransactionType.EXCLUSIVE) + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + } + var insertRow = await exclusiveTrans.insert("test", valueBucket); + console.log(TAG + "testTransactionIsolation0002 exclusiveTrans.insert row " + insertRow) + expect(1).assertEqual(insertRow) + + var resultSet = deferredTrans.querySqlSync("select * from test where name = ?", ["lisi"]); + console.log(TAG + "testTransactionIsolation0002 deferredTrans querySqlSync before exclusiveTrans commit count " + resultSet.rowCount); + expect(0).assertEqual(resultSet.rowCount); + resultSet.close() + + await exclusiveTrans.commit(); + + resultSet = deferredTrans.querySqlSync("select * from test where name = ?", ["lisi"]); + console.log(TAG + "testTransactionIsolation0002 deferredTrans querySqlSync after exclusiveTrans commit count " + resultSet.rowCount); + expect(0).assertEqual(resultSet.rowCount); + + resultSet = rdbStore.querySqlSync("select * from test where name = ?", ["lisi"]); + console.log(TAG + "testTransactionIsolation0002 rdbStore querySqlSync after exclusiveTrans commit count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + resultSet.close() + + } catch (e) { + exclusiveTrans.rollback(); + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "insert failed"); + } + await deferredTrans.commit(); + } catch (e) { + await deferredTrans.rollback(); + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testTransactionIsolation0002 failed"); + } + done() + console.log(TAG + "************* testTransactionIsolation0002 end *************"); + }) + + /** + * @tc.number testTransactionIsolation0003 + * @tc.name testTransactionIsolation. IMMEDIATE and rdbStore + * @tc.desc 1.begin IMMEDIATE Transaction + * 2.insert data with rdbStore -> busy + * 3.insert data with IMMEDIATE Transaction + * 4.execute commit with IMMEDIATE Transaction + * 5.query data with rdbStore -> has data + */ + it('testTransactionIsolation0003', 0, async function (done) { + console.log(TAG + "************* testTransactionIsolation0003 start *************"); + var immediateTrans = await rdbStore.createTransaction(data_relationalStore.TransactionType.IMMEDIATE) + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + } + try { + await rdbStore.insert("test", valueBucket); + console.log(TAG + "testTransactionIsolation0003 rdbStore.insert success "); + expect(null).assertFail() + } catch (e) { + console.log(TAG + e); + expect(e.code).assertEqual(14800024) + console.log(TAG + "insert failed"); + } + var insertRow = await immediateTrans.insert("test", valueBucket); + console.log(TAG + "testTransactionIsolation0003 immediateTrans.insert row " + insertRow); + expect(insertRow).assertEqual(1); + + await immediateTrans.commit(); + + var resultSet = rdbStore.querySqlSync("select * from test where name = ?", ["lisi"]); + console.log(TAG + "testTransactionIsolation0003 querySqlSync count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + resultSet.close() + } catch (e) { + await immediateTrans.rollback(); + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testTransactionIsolation0003 failed"); + } + done() + console.log(TAG + "************* testTransactionIsolation0003 end *************"); + }) + + /** + * @tc.number testTransactionIsolation0004 + * @tc.name testTransactionIsolation. DEFERRED and rdbStore + * @tc.desc 1.begin DEFERRED Transaction + * 2.insert data with rdbStore + * 3.insert data with DEFERRED Transaction + * 4.query data with rdbStore -> has 2 row + * 5.insert data with rdbStore again -> busy + * 6.query data with DEFERRED Transaction -> has 2 row + * 7.execute commit with DEFERRED Transaction + * 8.insert data with rdbStore again + * 9.query data with rdbStore -> has 3 row + */ + it('testTransactionIsolation0004', 0, async function (done) { + console.log(TAG + "************* testTransactionIsolation0004 start *************"); + var deferredTrans = await rdbStore.createTransaction(data_relationalStore.TransactionType.DEFERRED) + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + } + await rdbStore.insert("test", valueBucket); + + await deferredTrans.insert("test", valueBucket); + + var resultSet = rdbStore.querySqlSync("select * from test where name = ?", ["lisi"]); + console.log(TAG + "testTransactionIsolation0004 rdbStore.querySqlSync count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + + try { + await rdbStore.insert("test", valueBucket); + console.log(TAG + "testTransactionIsolation0004 insert success "); + expect(null).assertFail() + } catch (e) { + console.log(TAG + e); + expect(e.code).assertEqual(14800024) + console.log(TAG + "insert failed"); + } + resultSet = deferredTrans.querySqlSync("select * from test where name = ?", ["lisi"]); + console.log(TAG + "testTransactionIsolation0004 deferredTrans.querySqlSync count " + resultSet.rowCount); + expect(2).assertEqual(resultSet.rowCount); + + await deferredTrans.commit(); + + await rdbStore.insert("test", valueBucket); + + resultSet = rdbStore.querySqlSync("select * from test where name = ?", ["lisi"]); + console.log(TAG + "testTransactionIsolation0004 rdbStore.querySqlSync after deferredTrans commit count " + resultSet.rowCount); + expect(3).assertEqual(resultSet.rowCount); + resultSet.close() + } catch (e) { + await deferredTrans.rollback(); + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testTransactionIsolation0004 failed"); + } + done() + console.log(TAG + "************* testTransactionIsolation0004 end *************"); + }) + + /** + * @tc.number testTransactionIsolation0005 + * @tc.name testTransactionIsolation. DEFERRED and IMMEDIATE + * @tc.desc 1.begin DEFERRED Transaction + * 2.begin IMMEDIATE Transaction + * 3.insert data with DEFERRED Transaction -> busy + * 4.insert data with IMMEDIATE Transaction + * 5.execute commit with IMMEDIATE Transaction + * 6.insert data with DEFERRED Transaction + * 7.execute commit with DEFERRED Transaction + * 8.query data with rdbStore -> has 4 row + */ + it('testTransactionIsolation0005', 0, async function (done) { + console.log(TAG + "************* testTransactionIsolation0005 start *************"); + var deferredTrans = await rdbStore.createTransaction(data_relationalStore.TransactionType.DEFERRED) + var immediateTrans = await rdbStore.createTransaction(data_relationalStore.TransactionType.IMMEDIATE) + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + } + try { + await deferredTrans.insert("test", valueBucket); + expect(null).assertFail() + } catch (e) { + console.log(TAG + e); + expect(e.code).assertEqual(14800024) + console.log(TAG + "insert failed"); + } + var insertRow = await immediateTrans.insert("test", valueBucket); + console.log(TAG + "testTransactionIsolation0005 immediateTrans.insert row " + insertRow); + expect(1).assertEqual(insertRow); + + await immediateTrans.commit(); + + insertRow = await deferredTrans.insert("test", valueBucket); + console.log(TAG + "testTransactionIsolation0005 deferredTrans.insert after immediateTrans.commit row " + insertRow); + expect(2).assertEqual(insertRow); + + await deferredTrans.commit(); + + var resultSet = rdbStore.querySqlSync("select * from test where name = ?", ["lisi"]); + console.log(TAG + "testTransactionIsolation0005 querySqlSync count " + resultSet.rowCount); + expect(2).assertEqual(resultSet.rowCount); + resultSet.close() + } catch (e) { + await immediateTrans.rollback(); + await deferredTrans.rollback(); + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testTransactionIsolation0005 failed"); + } + done() + console.log(TAG + "************* testTransactionIsolation0005 end *************"); + }) + + /** + * @tc.number testTransactionIsolation0006 + * @tc.name testTransactionIsolation. DEFERRED and DEFERRED + * @tc.desc 1.insert data with rdbStore + * 2.begin DEFERRED Transaction1 + * 3.begin DEFERRED Transaction2 + * 4.update data with DEFERRED Transaction1 + * 5.delete data with DEFERRED Transaction2 -> busy + * 6.execute commit with DEFERRED Transaction1 + * 7.query data with DEFERRED Transaction2 -> has updated data + * 8.delete data with DEFERRED Transaction2 + * 9.execute commit with DEFERRED Transaction2 + * 10.query data with rdbStore -> has 0 row + */ + it('testTransactionIsolation0006', 0, async function (done) { + console.log(TAG + "************* testTransactionIsolation0006 start *************"); + var deferredTrans1 = await rdbStore.createTransaction(data_relationalStore.TransactionType.DEFERRED) + var deferredTrans2 = await rdbStore.createTransaction(data_relationalStore.TransactionType.DEFERRED) + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + } + var rowId = await rdbStore.insert("test", valueBucket); + console.log(TAG + "testTransactionIsolation0006 insert row " + rowId); + expect(1).assertEqual(rowId); + + const updateValueBucket = { + "name": "deferredTrans1", + "age": 18, + "salary": 100.5, + } + let predicates = new data_relationalStore.RdbPredicates("test"); + predicates.equalTo("name", "lisi") + rowId = await deferredTrans1.updateSync(updateValueBucket, predicates) + console.log(TAG + "testTransactionIsolation0006 insert row " + rowId); + expect(1).assertEqual(rowId); + + let deletePredicates = new data_relationalStore.RdbPredicates("test"); + predicates.equalTo("age", "18"); + try { + await deferredTrans2.delete(deletePredicates) + console.log(TAG + "testTransactionIsolation0006 deferredTrans2.delete success "); + expect(null).assertFail() + } catch (e) { + console.log(TAG + e); + expect(e.code).assertEqual(14800024) + console.log(TAG + "insert failed"); + } + + await deferredTrans1.commit(); + + var resultSet = deferredTrans2.querySqlSync("select * from test"); + console.log(TAG + "testTransactionIsolation0006 deferredTrans2.querySqlSync count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + expect(true).assertEqual(resultSet.goToFirstRow()) + const name = resultSet.getString(resultSet.getColumnIndex("name")) + expect("deferredTrans1").assertEqual(name); + resultSet.close() + + var num = await deferredTrans2.deleteSync(deletePredicates) + console.log(TAG + "testTransactionIsolation0006 delete num " + num); + expect(1).assertEqual(num); + + await deferredTrans2.commit(); + + resultSet = rdbStore.querySqlSync("select * from test"); + console.log(TAG + "testTransactionIsolation0006 rdbStore.querySqlSync count " + resultSet.rowCount); + expect(0).assertEqual(resultSet.rowCount); + resultSet.close() + } catch (e) { + await deferredTrans2.rollback(); + await deferredTrans1.rollback(); + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testTransactionIsolation0006 failed"); + } + done() + console.log(TAG + "************* testTransactionIsolation0006 end *************"); + }) + + /** + * @tc.number testTransactionIsolation0007 + * @tc.name testTransactionIsolation. DEFERRED and EXCLUSIVE + * @tc.desc 1.begin DEFERRED Transaction1 + * 2.begin EXCLUSIVE Transaction + * 3.insert data with EXCLUSIVE Transaction + * 4.execute commit with EXCLUSIVE Transaction + * 5.query data with DEFERRED1 Transaction -> has data + * 6.begin DEFERRED Transaction2 + * 7.query data with DEFERRED2 Transaction -> has data + */ + it('testTransactionIsolation0007', 0, async function (done) { + console.log(TAG + "************* testTransactionIsolation0007 start *************"); + var deferredTrans1 = await rdbStore.createTransaction(data_relationalStore.TransactionType.DEFERRED) + try { + var exclusiveTrans = await rdbStore.createTransaction(data_relationalStore.TransactionType.EXCLUSIVE) + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + } + var insertRow = await exclusiveTrans.insert("test", valueBucket); + console.log(TAG + "testTransactionIsolation0007 exclusiveTrans.insert row " + insertRow) + expect(1).assertEqual(insertRow) + await exclusiveTrans.commit(); + + var resultSet = deferredTrans1.querySqlSync("select * from test where name = ?", ["lisi"]); + console.log(TAG + "testTransactionIsolation0007 deferredTrans1 querySqlSync after exclusiveTrans commit count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + + var deferredTrans2 = await rdbStore.createTransaction(data_relationalStore.TransactionType.DEFERRED) + try { + resultSet = deferredTrans2.querySqlSync("select * from test where name = ?", ["lisi"]); + console.log(TAG + "testTransactionIsolation0007 deferredTrans2 querySqlSync after exclusiveTrans commit count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + resultSet.close() + } catch (e) { + deferredTrans2.rollback(); + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "querySqlSync failed"); + } + + } catch (e) { + exclusiveTrans.rollback(); + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "insert failed"); + } + await deferredTrans1.commit(); + } catch (e) { + await deferredTrans1.rollback(); + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testTransactionIsolation0007 failed"); + } + done() + console.log(TAG + "************* testTransactionIsolation0007 end *************"); + }) + + /** + * @tc.number testTransactionIsolation0008 + * @tc.name testTransactionIsolation. DEFERRED and rdbStore + * @tc.desc 1.begin DEFERRED Transaction + * 2.insert data with rdbStore + * 3.query data with DEFERRED Transaction -> has 1 data + * 4.begin EXCLUSIVE Transaction -> busy + * 5.insert data with DEFERRED Transaction + * 6.execute commit with DEFERRED Transaction + * 7.begin EXCLUSIVE Transaction + * 8.query data with EXCLUSIVE Transaction -> has 2 data + */ + it('testTransactionIsolation0008', 0, async function (done) { + console.log(TAG + "************* testTransactionIsolation0008 start *************"); + var deferredTrans = await rdbStore.createTransaction(data_relationalStore.TransactionType.DEFERRED) + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + } + await rdbStore.insert("test", valueBucket); + + var resultSet = deferredTrans.querySqlSync("select * from test where name = ?", ["lisi"]); + console.log(TAG + "testTransactionIsolation0008 querySqlSync1 count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + resultSet.close() + try { + var exclusiveTrans = await rdbStore.createTransaction(data_relationalStore.TransactionType.EXCLUSIVE) + console.log(TAG + "begin EXCLUSIVE success abnormal"); + exclusiveTrans.rollback(); + } catch (e) { + console.log(TAG + e); + expect(e.code).assertEqual(14800024) + console.log(TAG + "begin EXCLUSIVE failed"); + } + var rowId = await deferredTrans.insert("test", valueBucket); + console.log(TAG + "testTransactionIsolation0008 deferredTrans.insert row " + rowId) + expect(2).assertEqual(rowId); + + await deferredTrans.commit(); + + try { + var exclusiveTrans = await rdbStore.createTransaction(data_relationalStore.TransactionType.EXCLUSIVE) + console.log(TAG + "begin EXCLUSIVE success"); + try { + resultSet = exclusiveTrans.querySqlSync("select * from test"); + console.log(TAG + "testTransactionIsolation0008 exclusiveTrans.querySqlSync count " + resultSet.rowCount); + expect(2).assertEqual(resultSet.rowCount); + resultSet.close() + } catch (e) { + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "exclusiveTrans.querySqlSync failed"); + } + exclusiveTrans.rollback(); + } catch (e) { + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "begin EXCLUSIVE failed"); + } + } catch (e) { + await deferredTrans.rollback(); + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testTransactionIsolation0008 failed"); + } + done() + console.log(TAG + "************* testTransactionIsolation0008 end *************"); + }) + + /** + * @tc.number testTransactionIsolation0009 + * @tc.name testTransactionIsolation. DEFERRED and DEFERRED + * @tc.desc 1.insert data with rdbStore + * 2.begin DEFERRED Transaction1 + * 3.begin DEFERRED Transaction2 + * 4.update data to update1 with DEFERRED Transaction1 + * 5.query data with DEFERRED Transaction2 -> has before update data + * 6.update update1 to update2 with DEFERRED Transaction1 + * 7.execute commit with DEFERRED Transaction1 + * 8.query data with DEFERRED Transaction2 -> has before update data + * 9.delete data with DEFERRED Transaction2 -> busy + * 10.execute commit with DEFERRED Transaction2 + * 11.query data with rdbStore -> has 1 row + */ + it('testTransactionIsolation0009', 0, async function (done) { + console.log(TAG + "************* testTransactionIsolation0009 start *************"); + var deferredTrans1 = await rdbStore.createTransaction(data_relationalStore.TransactionType.DEFERRED) + var deferredTrans2 = await rdbStore.createTransaction(data_relationalStore.TransactionType.DEFERRED) + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + } + var rowId = await rdbStore.insert("test", valueBucket); + console.log(TAG + "testTransactionIsolation0009 insert row " + rowId); + expect(1).assertEqual(rowId); + + const updateValueBucket1 = { + "name": "update1", + "age": 18, + "salary": 100.5, + } + let predicates = new data_relationalStore.RdbPredicates("test"); + predicates.equalTo("name", "lisi") + var num = await deferredTrans1.updateSync(updateValueBucket1, predicates) + console.log(TAG + "testTransactionIsolation0009 updateSync 1 num " + num); + expect(1).assertEqual(num); + + var resultSet = deferredTrans2.querySqlSync("select * from test"); + console.log(TAG + "testTransactionIsolation0009 deferredTrans2.querySqlSync1 count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + expect(true).assertEqual(resultSet.goToFirstRow()) + var name = resultSet.getString(resultSet.getColumnIndex("name")) + expect("lisi").assertEqual(name); + resultSet.close() + + const updateValueBucket2 = { + "name": "update2", + "age": 18, + "salary": 100.5, + } + predicates = new data_relationalStore.RdbPredicates("test"); + predicates.equalTo("name", "update1") + var num = await deferredTrans1.updateSync(updateValueBucket2, predicates) + console.log(TAG + "testTransactionIsolation0009 updateSync 2 num " + num); + expect(1).assertEqual(num); + + await deferredTrans1.commit(); + + resultSet = deferredTrans2.querySqlSync("select * from test"); + console.log(TAG + "testTransactionIsolation0009 deferredTrans2.querySqlSync2 count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + expect(true).assertEqual(resultSet.goToFirstRow()) + name = resultSet.getString(resultSet.getColumnIndex("name")) + expect("lisi").assertEqual(name); + resultSet.close() + + let deletePredicates = new data_relationalStore.RdbPredicates("test"); + predicates.equalTo("age", "18"); + try { + num = await deferredTrans2.delete(deletePredicates) + console.log(TAG + "testTransactionIsolation0009 delete num " + num); + expect(null).assertFail() + } catch (e) { + console.log(TAG + e); + expect(e.code).assertEqual(14800024) + } + await deferredTrans2.commit(); + + resultSet = rdbStore.querySqlSync("select * from test"); + console.log(TAG + "testTransactionIsolation0009 rdbStore.querySqlSync count " + resultSet.rowCount); + expect(1).assertEqual(resultSet.rowCount); + resultSet.close() + } catch (e) { + await deferredTrans2.rollback(); + await deferredTrans1.rollback(); + console.log(TAG + e); + expect(null).assertFail() + console.log(TAG + "testTransactionIsolation0009 failed"); + } + done() + console.log(TAG + "************* testTransactionIsolation0009 end *************"); + }) + + /** + * @tc.number testTransactionEnd0001 + * @tc.name Query data with closed transaction + * @tc.desc 1.Execute beginTransaction + * 2.Insert data + * 3.Execute commit + * 4.Query data with transaction -> throw 14800014 + */ + it('testTransactionEnd0001', 0, async function (done) { + console.log(TAG + "************* testTransactionEnd0001 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction(data_relationalStore.TransactionType.IMMEDIATE) + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + var num = await transaction.insert("test", valueBucket) + expect(1).assertEqual(num); + await transaction.commit() + } catch (e) { + await transaction.rollback() + console.log(TAG + e + " code: " + e.code); + expect(null).assertFail() + } + try { + let predicates = new data_relationalStore.RdbPredicates("test"); + let resultSet = await transaction.query(predicates) + console.log(TAG + "testTransactionEnd0001 result count " + resultSet.rowCount) + expect(null).assertFail() + resultSet.close() + } catch (e) { + console.log(TAG + e + " code: " + e.code); + expect(e.code).assertEqual(14800014) + } + done() + console.log(TAG + "************* testTransactionEnd0001 end *************"); + }) + + /** + * @tc.number testTransactionEnd0002 + * @tc.name Query data with closed transaction + * @tc.desc 1.Execute beginTransaction + * 2.Insert data + * 3.Query data with transaction -> get resultSet + * 4.Execute commit + * 5.resultSet go to first row -> throw 14800014 + */ + it('testTransactionEnd0002', 0, async function (done) { + console.log(TAG + "************* testTransactionEnd0002 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction(data_relationalStore.TransactionType.EXCLUSIVE) + let resultSet; + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + var num = await transaction.insert("test", valueBucket) + expect(1).assertEqual(num); + + let predicates = new data_relationalStore.RdbPredicates("test"); + resultSet = await transaction.query(predicates) + console.log(TAG + "testTransactionEnd0002 result count " + resultSet.rowCount) + await transaction.commit() + } catch (e) { + await transaction.rollback() + console.log(TAG + e + " code: " + e.code); + expect(null).assertFail() + } + expect(false).assertEqual(resultSet.goToFirstRow()) + done() + console.log(TAG + "************* testTransactionEnd0002 end *************"); + }) + + /** + * @tc.number testTransactionEnd0003 + * @tc.name Insert data with closed transaction + * @tc.desc 1.Execute beginTransaction + * 2.Insert data + * 3.Execute commit + * 4.Insert data with closed transaction -> throw 14800014 + */ + it('testTransactionEnd0003', 0, async function (done) { + console.log(TAG + "************* testTransactionEnd0003 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction(data_relationalStore.TransactionType.DEFERRED) + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + try { + var rowId = await transaction.insert("test", valueBucket) + expect(1).assertEqual(rowId); + await transaction.commit() + } catch (e) { + await transaction.rollback() + console.log(TAG + e + " code: " + e.code); + expect(null).assertFail() + } + try { + rowId = await transaction.insert("test", valueBucket) + console.log(TAG + "testTransactionEnd0003 insert rowId " + rowId) + expect(null).assertFail() + } catch (e) { + console.log(TAG + e + " code: " + e.code); + expect(e.code).assertEqual(14800014) + } + done() + console.log(TAG + "************* testTransactionEnd0003 end *************"); + }) + + /** + * @tc.number testTransactionEnd0004 + * @tc.name Update data with closed transaction + * @tc.desc 1.Execute beginTransaction + * 2.Insert data + * 3.Execute rollback + * 4.Update data with closed transaction -> throw 14800014 + */ + it('testTransactionEnd0004', 0, async function (done) { + console.log(TAG + "************* testTransactionEnd0004 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction(data_relationalStore.TransactionType.IMMEDIATE) + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + var rowId = await transaction.insert("test", valueBucket) + expect(1).assertEqual(rowId); + await transaction.rollback() + } catch (e) { + await transaction.rollback() + console.log(TAG + e + " code: " + e.code); + expect(null).assertFail() + } + try { + let predicates = new data_relationalStore.RdbPredicates("test"); + predicates.equalTo("name", "lisi"); + const updateValueBucket = { + "name": "update", + "age": 28, + "salary": 25, + "blobType": u8, + } + rowId = await transaction.update(updateValueBucket, predicates) + console.log(TAG + "testTransactionEnd0004 update rowId " + rowId) + expect(null).assertFail() + } catch (e) { + console.log(TAG + e + " code: " + e.code); + expect(e.code).assertEqual(14800014) + } + done() + console.log(TAG + "************* testTransactionEnd0004 end *************"); + }) + + /** + * @tc.number testTransactionEnd0005 + * @tc.name Delete data with closed transaction + * @tc.desc 1.Execute beginTransaction + * 2.Insert data + * 3.Execute rollback + * 4.Delete data with closed transaction -> throw 14800014 + */ + it('testTransactionEnd0005', 0, async function (done) { + console.log(TAG + "************* testTransactionEnd0005 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction(data_relationalStore.TransactionType.EXCLUSIVE) + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + var rowId = await transaction.insert("test", valueBucket) + expect(1).assertEqual(rowId); + await transaction.rollback() + } catch (e) { + await transaction.rollback() + console.log(TAG + e + " code: " + e.code); + expect(null).assertFail() + } + try { + let predicates = new data_relationalStore.RdbPredicates("test"); + predicates.equalTo("name", "lisi"); + var num = transaction.deleteSync(predicates) + console.log(TAG + "testTransactionEnd0005 delete num " + num) + expect(null).assertFail() + } catch (e) { + console.log(TAG + e + " code: " + e.code); + expect(e.code).assertEqual(14800014) + } + done() + console.log(TAG + "************* testTransactionEnd0005 end *************"); + }) + + /** + * @tc.number testTransactionEnd0006 + * @tc.name Execute Sql with closed transaction + * @tc.desc 1.Execute beginTransaction + * 2.Insert data + * 3.Execute rollback + * 4.Execute Sql with closed transaction -> throw 14800014 + */ + it('testTransactionEnd0006', 0, async function (done) { + console.log(TAG + "************* testTransactionEnd0006 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction(data_relationalStore.TransactionType.DEFERRED) + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + var rowId = await transaction.insert("test", valueBucket) + expect(1).assertEqual(rowId); + await transaction.rollback() + } catch (e) { + await transaction.rollback() + console.log(TAG + e + " code: " + e.code); + expect(null).assertFail() + } + try { + let ret = transaction.executeSync("PRAGMA integrity_check"); + console.log(TAG + "testTransactionEnd0006 executeSync PRAGMA integrity_check: " + ret) + expect(null).assertFail() + } catch (e) { + console.log(TAG + e + " code: " + e.code); + expect(e.code).assertEqual(14800014) + } + done() + console.log(TAG + "************* testTransactionEnd0006 end *************"); + }) + + /** + * @tc.number testTransactionEnd0007 + * @tc.name Execute Sql with closed transaction + * @tc.desc 1.Execute beginTransaction + * 2.Insert data + * 3.Execute rollback + * 4.Commit with closed transaction -> throw 14800014 + */ + it('testTransactionEnd0007', 0, async function (done) { + console.log(TAG + "************* testTransactionEnd0007 start *************"); + var u8 = new Uint8Array([1, 2, 3]) + var transaction = await rdbStore.createTransaction(data_relationalStore.TransactionType.DEFERRED) + try { + const valueBucket = { + "name": "lisi", + "age": 18, + "salary": 100.5, + "blobType": u8, + } + var rowId = await transaction.insert("test", valueBucket) + expect(1).assertEqual(rowId); + await transaction.rollback() + } catch (e) { + await transaction.rollback() + console.log(TAG + e + " code: " + e.code); + expect(null).assertFail() + } + try { + await transaction.commit(); + console.log(TAG + "testTransactionEnd0007 commit success") + expect(null).assertFail() + } catch (e) { + console.log(TAG + e + " code: " + e.code); + expect(e.code).assertEqual(14800014) + } + done() + console.log(TAG + "************* testTransactionEnd0007 end *************"); + }) + + console.log(TAG + "*************Unit Test End*************"); +}) \ No newline at end of file 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 fea83dfaa355f84a16f355393cc86882996e2182..046888aa325a13536ba1d65de490cf48cf4cfabc 100644 --- a/relational_store/test/js/relationalstore/unittest/src/RdbstoreEncryptionJsunit.test.js +++ b/relational_store/test/js/relationalstore/unittest/src/RdbstoreEncryptionJsunit.test.js @@ -42,6 +42,34 @@ const STORE_CONFIG_WRONG = { securityLevel: data_relationalStore.SecurityLevel.S1, } +const STORE_CONFIG_DEFAULT = { + name: "default.db", + securityLevel: data_relationalStore.SecurityLevel.S1, + encrypt: true, + cryptoParam: { + encryptionKey: new Uint8Array(['t', 'e', 's', 't', 'k', 'e', 'y']), + iterationCount: 10000, + encryptionAlgo: data_relationalStore.EncryptionAlgo.AES_256_GCM, + hmacAlgo: data_relationalStore.HmacAlgo.SHA256, + kdfAlgo: data_relationalStore.KdfAlgo.KDF_SHA256, + cryptoPageSize: 1024 + } +} + +const STORE_CONFIG_NON_DEFAULT = { + name: "nondefault.db", + securityLevel: data_relationalStore.SecurityLevel.S1, + encrypt: true, + cryptoParam: { + encryptionKey: new Uint8Array(['t', 'e', 's', 't', 'k', 'e', 'y']), + iterationCount: 25000, + encryptionAlgo: data_relationalStore.EncryptionAlgo.AES_256_CBC, + hmacAlgo: data_relationalStore.HmacAlgo.SHA512, + kdfAlgo: data_relationalStore.KdfAlgo.KDF_SHA512, + cryptoPageSize: 2048 + } +} + async function CreatRdbStore(context, STORE_CONFIG) { let rdbStore = await data_relationalStore.getRdbStore(context, STORE_CONFIG) await rdbStore.executeSql(CREATE_TABLE_TEST, null) @@ -76,8 +104,34 @@ async function CreatRdbStore(context, STORE_CONFIG) { return rdbStore } +async function CreateRdbStoreAndInsertData(context, store_config) { + let rdbStore = await data_relationalStore.getRdbStore(context, store_config) + await rdbStore.executeSql("CREATE TABLE t (x int, y int)", null) + const valueBucket = { + "x": 1, + "y": 1 + } + let insertPromise = rdbStore.insert("t", valueBucket) + insertPromise.then(async (ret) => { + expect(1).assertEqual(ret) + }) + return rdbStore +} + +async function CheckRdbStoreData(rdbStore) { + let resultSet = await rdbStore.querySql("SELECT * from t") + expect(1).assertEqual(resultSet.rowCount) + expect(true).assertEqual(resultSet.goToFirstRow()) + const x = resultSet.getLong(resultSet.getColumnIndex("x")) + const y = resultSet.getLong(resultSet.getColumnIndex("y")) + expect(1).assertEqual(x) + expect(1).assertEqual(y) + return resultSet +} + describe('rdbEncryptTest', function () { beforeAll(async function () { + await CreateRdbStoreAndInsertData(context, STORE_CONFIG_NON_DEFAULT) console.info(TAG + 'beforeAll') }) @@ -93,6 +147,7 @@ describe('rdbEncryptTest', function () { }) afterAll(async function () { + await data_relationalStore.deleteRdbStore(context, STORE_CONFIG_NON_DEFAULT.name) console.info(TAG + 'afterAll') }) @@ -289,5 +344,305 @@ describe('rdbEncryptTest', function () { } console.info(TAG + "************* RdbEncryptTest_0060 end *************") }) + + /** + * @tc.name RDB decrypt test + * @tc.number SUB_DDM_RDB_JS_RdbDecryptTest_0010 + * @tc.desc RDB decrypt function non-default test + */ + it('RdbDecryptTest_0010', 0, async function () { + console.info(TAG + "************* RdbDecryptTest_0010 start *************") + let default_config = { + name: "default.db", + securityLevel: data_relationalStore.SecurityLevel.S1, + encrypt: true, + cryptoParam: { + encryptionKey: new Uint8Array(['t', 'e', 's', 't', 'k', 'e', 'y']) + } + } + context = ability_featureAbility.getContext() + try { + let rdbStore = await CreateRdbStoreAndInsertData(context, default_config) + await rdbStore.close() + } catch (err) { + console.error(`Query rdbStore failed, error code: ${err.code}, err message: ${err.message}`); + expect().assertFail() + } + + try { + let rdbStore2 = await data_relationalStore.getRdbStore(context, STORE_CONFIG_DEFAULT) + let resultSet = await CheckRdbStoreData(rdbStore2) + resultSet.close() + } catch (err) { + console.error(`Query rdbStore failed, error code: ${err.code}, err message: ${err.message}`); + expect().assertFail() + } + console.log(TAG + "************* RdbDecryptTest_0010 end *************") + }) + + /** + * @tc.name RDB decrypt test + * @tc.number SUB_DDM_RDB_JS_RdbDecryptTest_0020 + * @tc.desc RDB decrypt function non-default test + */ + it('RdbDecryptTest_0020', 0, async function () { + console.info(TAG + "************* RdbDecryptTest_0020 start *************") + + context = ability_featureAbility.getContext() + try { + let rdbStore = await data_relationalStore.getRdbStore(context, STORE_CONFIG_NON_DEFAULT) + let resultSet = await CheckRdbStoreData(rdbStore) + await rdbStore.close() + } catch (err) { + console.error(`Query rdbStore failed, error code: ${err.code}, err message: ${err.message}`); + expect().assertFail() + } + console.info(TAG + "************* RdbDecryptTest_0020 end *************") + }) + + /** + * @tc.name RDB decrypt test + * @tc.number SUB_DDM_RDB_JS_RdbDecryptTest_0030 + * @tc.desc RDB decrypt function invalid key config test + */ + it('RdbDecryptTest_0030', 0, async function () { + console.info(TAG + "************* RdbDecryptTest_0030 start *************") + let invalid_key_config = { + name: "nondefault.db", + securityLevel: data_relationalStore.SecurityLevel.S1, + encrypt: true, + cryptoParam: { + iterationCount: 25000, + encryptionAlgo: data_relationalStore.EncryptionAlgo.AES_256_CBC, + hmacAlgo: data_relationalStore.HmacAlgo.SHA512, + kdfAlgo: data_relationalStore.KdfAlgo.KDF_SHA512, + cryptoPageSize: 2048 + } + } + try { + let rdbStore = await data_relationalStore.getRdbStore(context, invalid_key_config) + expect().assertFail() + } catch (err) { + console.error(`Invalid key config, error code: ${err.code}, err message: ${err.message}`); + expect("401").assertEqual(err.code) + } + console.info(TAG + "************* RdbDecryptTest_0030 end *************") + }) + + /** + * @tc.name RDB decrypt test + * @tc.number SUB_DDM_RDB_JS_RdbDecryptTest_0040 + * @tc.desc RDB decrypt function invalid iteration config test + */ + it('RdbDecryptTest_0040', 0, async function () { + console.info(TAG + "************* RdbDecryptTest_0040 start *************") + let invalid_iter_config = { + name: "nondefault.db", + securityLevel: data_relationalStore.SecurityLevel.S1, + encrypt: true, + cryptoParam: { + encryptionKey: new Uint8Array(['t', 'e', 's', 't', 'k', 'e', 'y']), + iterationCount: -1, + encryptionAlgo: data_relationalStore.EncryptionAlgo.AES_256_CBC, + hmacAlgo: data_relationalStore.HmacAlgo.SHA512, + kdfAlgo: data_relationalStore.KdfAlgo.KDF_SHA512, + cryptoPageSize: 2048 + } + } + try { + let rdbStore = await data_relationalStore.getRdbStore(context, invalid_iter_config) + expect().assertFail() + } catch (err) { + console.error(`Invalid iter config, error code: ${err.code}, err message: ${err.message}`); + expect("401").assertEqual(err.code) + } + console.info(TAG + "************* RdbDecryptTest_0040 end *************") + }) + + /** + * @tc.name RDB decrypt test + * @tc.number SUB_DDM_RDB_JS_RdbDecryptTest_0050 + * @tc.desc RDB decrypt function invalid algorithm config test + */ + it('RdbDecryptTest_0050', 0, async function () { + console.info(TAG + "************* RdbDecryptTest_0050 start *************") + let invalid_algo_config = { + name: "nondefault.db", + securityLevel: data_relationalStore.SecurityLevel.S1, + encrypt: true, + cryptoParam: { + encryptionKey: new Uint8Array(['t', 'e', 's', 't', 'k', 'e', 'y']), + iterationCount: 25000, + encryptionAlgo: data_relationalStore.EncryptionAlgo.AES_256_CBC + 1, + hmacAlgo: data_relationalStore.HmacAlgo.SHA512, + kdfAlgo: data_relationalStore.KdfAlgo.KDF_SHA512, + cryptoPageSize: 2048 + } + } + try { + let rdbStore = await data_relationalStore.getRdbStore(context, invalid_algo_config) + expect().assertFail() + } catch (err) { + console.error(`Invalid algorithm config, error code: ${err.code}, err message: ${err.message}`); + expect("401").assertEqual(err.code) + } + console.info(TAG + "************* RdbDecryptTest_0050 end *************") + }) + + /** + * @tc.name RDB decrypt test + * @tc.number SUB_DDM_RDB_JS_RdbDecryptTest_0060 + * @tc.desc RDB decrypt function invalid page size config test + */ + it('RdbDecryptTest_0060', 0, async function () { + console.info(TAG + "************* RdbDecryptTest_0060 start *************") + let invalid_page_size_config = { + name: "nondefault.db", + securityLevel: data_relationalStore.SecurityLevel.S1, + encrypt: true, + cryptoParam: { + encryptionKey: new Uint8Array(['t', 'e', 's', 't', 'k', 'e', 'y']), + iterationCount: 25000, + encryptionAlgo: data_relationalStore.EncryptionAlgo.AES_256_CBC, + hmacAlgo: data_relationalStore.HmacAlgo.SHA512, + kdfAlgo: data_relationalStore.KdfAlgo.KDF_SHA512, + cryptoPageSize: 128 + } + } + try { + let rdbStore = await data_relationalStore.getRdbStore(context, invalid_page_size_config) + expect().assertFail() + } catch (err) { + console.error(`Invalid algorithm config 1, error code: ${err.code}, err message: ${err.message}`); + expect("401").assertEqual(err.code) + } + + invalid_page_size_config.cryptoParam.cryptoPageSize = 131072 + try { + let rdbStore = await data_relationalStore.getRdbStore(context, invalid_page_size_config) + expect().assertFail() + } catch (err) { + console.error(`Invalid algorithm config 2, error code: ${err.code}, err message: ${err.message}`); + expect("401").assertEqual(err.code) + } + + invalid_page_size_config.cryptoParam.cryptoPageSize = 2049 + try { + let rdbStore = await data_relationalStore.getRdbStore(context, invalid_page_size_config) + expect().assertFail() + } catch (err) { + console.error(`Invalid algorithm config 3, error code: ${err.code}, err message: ${err.message}`); + expect("401").assertEqual(err.code) + } + console.log(TAG + "************* RdbDecryptTest_0060 end *************") + }) + + /** + * @tc.name RDB decrypt test + * @tc.number SUB_DDM_RDB_JS_RdbDecryptTest_0070 + * @tc.desc RDB decrypt function attach test + */ + it('RdbDecryptTest_0070', 0, async function () { + console.info(TAG + "************* RdbDecryptTest_0070 start *************") + let config = { + name: "DecryptTest0070.db", + securityLevel: data_relationalStore.SecurityLevel.S1, + encrypt: true, + cryptoParam: { + encryptionKey: new Uint8Array(['t', 'e', 's', 't', 'k', 'e', 'y']) + } + } + let plain_config = { + name: "plain.db", + securityLevel: data_relationalStore.SecurityLevel.S1, + encrypt: false + } + + context = ability_featureAbility.getContext() + try { + let rdbStore = await CreateRdbStoreAndInsertData(context, config) + await rdbStore.close() + let rdbStore1 = await data_relationalStore.getRdbStore(context, plain_config) + await rdbStore1.executeSql("CREATE table t (x int, y int)") + await rdbStore1.close() + } catch (err) { + console.error(`Create rdbStores failed, error code: ${err.code}, err message: ${err.message}`); + expect().assertFail() + } + + let store; + try { + store = await data_relationalStore.getRdbStore(context, plain_config) + let number = await store.attach(context, config, "attachDB") + expect(1).assertEqual(number) + } catch (err) { + console.error(`Query rdbStore failed, error code: ${err.code}, err message: ${err.message}`); + expect().assertFail() + } + + let valueBucket; + try { + let resultSet = await store.querySql("SELECT * from attachDB.t") + resultSet.goToFirstRow() + const x = resultSet.getLong(resultSet.getColumnIndex("x")) + const y = resultSet.getLong(resultSet.getColumnIndex("y")) + valueBucket = {"x" : x, "y" : y} + resultSet.close() + } catch (err) { + console.error(`Read data failed, error code: ${err.code}, err message: ${err.message}`); + expect().assertFail() + } + + try { + expect(0).assertEqual(await store.detach("attachDB")) + } catch (err) { + console.error(`Detach rdbStore, error code: ${err.code}, err message: ${err.message}`); + expect().assertFail() + } + + try { + let rowId = await store.insert("t", valueBucket) + expect(1).assertEqual(rowId) + await CheckRdbStoreData(store) + } catch (err) { + console.error(`Insert and check data, error code: ${err.code}, err message: ${err.message}`); + expect().assertFail() + } + + await store.close() + console.log(TAG + "************* RdbDecryptTest_0070 end *************") + }) + + /** + * @tc.name RDB decrypt test + * @tc.number SUB_DDM_RDB_JS_RdbDecryptTest_0080 + * @tc.desc RDB decrypt function invalid page size (512) test + */ + it('RdbDecryptTest_0080', 0, async function () { + console.info(TAG + "************* RdbDecryptTest_0080 start *************") + let invalid_page_size_config = { + name: "nondefault.db", + securityLevel: data_relationalStore.SecurityLevel.S1, + encrypt: true, + cryptoParam: { + encryptionKey: new Uint8Array(['t', 'e', 's', 't', 'k', 'e', 'y']), + iterationCount: 25000, + encryptionAlgo: data_relationalStore.EncryptionAlgo.AES_256_CBC, + hmacAlgo: data_relationalStore.HmacAlgo.SHA512, + kdfAlgo: data_relationalStore.KdfAlgo.KDF_SHA512, + cryptoPageSize: 512 + } + } + try { + let rdbStore = await data_relationalStore.getRdbStore(context, invalid_page_size_config) + expect().assertFail() + console.error(`Invalid page size 512 should fail, error code: ${err.code}, err message: ${err.message}`); + } catch (err) { + expect("401").assertEqual(err.code) + } + + console.log(TAG + "************* RdbDecryptTest_0080 end *************") + }) + console.log(TAG + "*************Unit Test End*************") }) diff --git a/relational_store/test/js/relationalstore/unittest/src/RdbstoreRdbstoreJsunit.test.js b/relational_store/test/js/relationalstore/unittest/src/RdbstoreRdbstoreJsunit.test.js index f5348f80ae4b55e70ad93587776063af35dfb3f0..0f7d06af06598a960622e0a31406eb91aa6c71e7 100644 --- a/relational_store/test/js/relationalstore/unittest/src/RdbstoreRdbstoreJsunit.test.js +++ b/relational_store/test/js/relationalstore/unittest/src/RdbstoreRdbstoreJsunit.test.js @@ -298,5 +298,61 @@ describe('rdbStoreTest', function () { console.log(TAG + "************* testRdbStore0011 end *************"); }) + /** + * @tc.name rdb store wal file overlimit test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_RdbStore_0012 + * @tc.desc Checkpoint failure delayed retry + */ + it('testRdbStore0012', 0, async function (done) { + console.log(TAG + "************* testRdbStore0012 start *************"); + + try { + const rowCount = 18; + const rdbStore = await data_relationalStore.getRdbStore(context, { + name: "walTest", + securityLevel: data_relationalStore.SecurityLevel.S3, + encrypt: true, + }) + const CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test (" + + "id INTEGER PRIMARY KEY AUTOINCREMENT, " + + "blobType BLOB)"; + + rdbStore.executeSync(CREATE_TABLE_TEST); + + const valueBuckets = Array(rowCount).fill(0).map(() => { + return { + blobType: new Uint8Array(Array(1024 * 1024).fill(1)), + } + }) + + rdbStore.batchInsertSync('test', valueBuckets); + + const predicates = new data_relationalStore.RdbPredicates('test'); + const resultSet = rdbStore.querySync(predicates); + expect(resultSet.rowCount).assertEqual(rowCount); + resultSet.goToFirstRow() + + const startTime = new Date().getTime(); + rdbStore.insertSync('test', { + blobType: new Uint8Array(Array(1024 * 1024).fill(1)), + }) + const middleTime = new Date().getTime(); + + expect((middleTime - startTime) > 2000).assertTrue(); + + rdbStore.insertSync('test', { + blobType: new Uint8Array(Array(1024 * 1024).fill(1)), + }) + const endTime = new Date().getTime(); + + expect((endTime - middleTime) < 2000).assertTrue(); + console.log(TAG + "************* testRdbStore0012 end *************"); + done(); + } catch (e) { + console.log(TAG + "testRdbStore0012 failed " + JSON.stringify(e)); + done(); + expect().assertFail(); + } + }) console.log(TAG + "*************Unit Test End*************"); }) \ No newline at end of file diff --git a/relational_store/test/native/rdb/BUILD.gn b/relational_store/test/native/rdb/BUILD.gn index 8266a72177e54291917236a3f09c8eb84854c98f..f4dc041cd5047c426318cdf707573d989b34241d 100644 --- a/relational_store/test/native/rdb/BUILD.gn +++ b/relational_store/test/native/rdb/BUILD.gn @@ -107,6 +107,7 @@ ohos_unittest("NativeRdbTest") { "unittest/rdb_store_interface_test.cpp", "unittest/rdb_store_rekey_test.cpp", "unittest/rdb_store_subscribe_test.cpp", + "unittest/rdb_trans_db_test.cpp", "unittest/rdb_transaction_test.cpp", "unittest/rdb_update_test.cpp", "unittest/rdb_upgrade_test.cpp", @@ -114,6 +115,7 @@ ohos_unittest("NativeRdbTest") { "unittest/rdb_value_bucket_test.cpp", "unittest/rdb_wal_limit_test.cpp", "unittest/sqlite_utils_test.cpp", + "unittest/transaction_test.cpp", "unittest/value_object_test.cpp", ] @@ -142,8 +144,10 @@ ohos_unittest("NativeRdbTest") { "../../../frameworks/native/rdb/src/sqlite_sql_builder.cpp", "../../../frameworks/native/rdb/src/sqlite_statement.cpp", "../../../frameworks/native/rdb/src/sqlite_utils.cpp", + "../../../frameworks/native/rdb/src/step_result_set.cpp", "../../../frameworks/native/rdb/src/string_utils.cpp", "../../../frameworks/native/rdb/src/task_executor.cpp", + "../../../frameworks/native/rdb/src/trans_db.cpp", ] configs = [ ":module_private_config" ] diff --git a/relational_store/test/native/rdb/unittest/rdb_double_write_concurrent_test.cpp b/relational_store/test/native/rdb/unittest/rdb_double_write_concurrent_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a967c56503d07182259399ae2a8b9075d48c7461 --- /dev/null +++ b/relational_store/test/native/rdb/unittest/rdb_double_write_concurrent_test.cpp @@ -0,0 +1,366 @@ +/* +* 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 "RdbDoubleWriteConcurrentTest" +#include + +#include +#include +#include "sys/types.h" +#include +#include + +#include "logger.h" +#include "common.h" +#include "sqlite_utils.h" +#include "file_ex.h" +#include "rdb_common.h" +#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 RdbDoubleWriteConcurrentTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + void CheckNumber(std::shared_ptr &store, int num, int errCode = E_OK, + const std::string &tableName = "test"); + void Insert(int64_t start, int count, bool isSlave = false, int dataSize = 0); + void WaitForBackupFinish(int32_t expectStatus, int maxTimes = 400); + void TryInterruptBackup(); + void InitDb(); + +protected: + const std::string DATABASE_NAME = RDB_TEST_PATH + "dual_concurrent.db"; + const std::string SLAVE_DATABASE_NAME = RDB_TEST_PATH + "dual_concurrent_slave.db"; + std::shared_ptr store = nullptr; + std::shared_ptr slaveStore = nullptr; + + class Callback : public RdbOpenCallback { + public: + int OnCreate(RdbStore &store) override; + int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override; + + protected: + const std::string CREATE_TABLE_TEST = + "CREATE TABLE IF NOT EXISTS test (id INTEGER PRIMARY KEY AUTOINCREMENT, " + "name TEXT NOT NULL, age INTEGER, salary " + "REAL, blobType BLOB)"; + }; + + enum SlaveStatus : uint32_t { + UNDEFINED, + DB_NOT_EXITS, + BACKING_UP, + BACKUP_INTERRUPT, + BACKUP_FINISHED, + }; +}; + +int RdbDoubleWriteConcurrentTest::Callback::OnCreate(RdbStore &store) +{ + return store.ExecuteSql(CREATE_TABLE_TEST); +} + +int RdbDoubleWriteConcurrentTest::Callback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) +{ + return E_OK; +} + +void RdbDoubleWriteConcurrentTest::SetUpTestCase(void) +{ +} + +void RdbDoubleWriteConcurrentTest::TearDownTestCase(void) +{ +} + +void RdbDoubleWriteConcurrentTest::SetUp(void) +{ +} + +void RdbDoubleWriteConcurrentTest::TearDown(void) +{ + store = nullptr; + slaveStore = nullptr; + RdbHelper::DeleteRdbStore(RdbDoubleWriteConcurrentTest::DATABASE_NAME); +} + +void RdbDoubleWriteConcurrentTest::InitDb() +{ + int errCode = E_OK; + RdbStoreConfig config(RdbDoubleWriteConcurrentTest::DATABASE_NAME); + config.SetHaMode(HAMode::MAIN_REPLICA); + RdbDoubleWriteConcurrentTest::Callback helper; + RdbDoubleWriteConcurrentTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(RdbDoubleWriteConcurrentTest::store, nullptr); + + RdbStoreConfig slaveConfig(RdbDoubleWriteConcurrentTest::SLAVE_DATABASE_NAME); + RdbDoubleWriteConcurrentTest::Callback slaveHelper; + RdbDoubleWriteConcurrentTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode); + EXPECT_NE(RdbDoubleWriteConcurrentTest::slaveStore, nullptr); + store->ExecuteSql("DELETE FROM test"); + slaveStore->ExecuteSql("DELETE FROM test"); +} + +void RdbDoubleWriteConcurrentTest::Insert(int64_t start, int count, bool isSlave, int dataSize) +{ + ValuesBucket values; + int64_t id = start; + int ret = E_OK; + for (int i = 0; i < count; i++) { + values.Clear(); + values.PutInt("id", id); + if (dataSize > 0) { + values.PutString("name", std::string(dataSize, 'a')); + } else { + values.PutString("name", std::string("zhangsan")); + } + values.PutInt("age", 18); // 18 is data + values.PutDouble("salary", 100.5); // 100.5 is data + values.PutBlob("blobType", std::vector{ 1, 2, 3 }); + if (isSlave) { + ret = slaveStore->Insert(id, "test", values); + } else { + ret = store->Insert(id, "test", values); + } + EXPECT_EQ(ret, E_OK); + id++; + } +} + +void RdbDoubleWriteConcurrentTest::WaitForBackupFinish(int32_t expectStatus, int maxTimes) +{ + int32_t curStatus = store->GetBackupStatus(); + int tryTimes = 0; + while (curStatus != expectStatus && (++tryTimes <= maxTimes)) { + usleep(50000); // 50000 delay + curStatus = store->GetBackupStatus(); + } + LOG_INFO("----------cur backup Status:%{public}d---------", curStatus); + ASSERT_EQ(curStatus, expectStatus); +} + +void RdbDoubleWriteConcurrentTest::TryInterruptBackup() +{ + int err = store->InterruptBackup(); + int tryTimes = 0; + while (err != E_OK && (++tryTimes <= 1000)) { // 1000 is try time + usleep(10000); // 10000 delay + err = store->InterruptBackup(); + } + EXPECT_EQ(err, E_OK); + LOG_INFO("----------interrupt backup---------"); +} + +void RdbDoubleWriteConcurrentTest::CheckNumber(std::shared_ptr &store, int num, int errCode, + const std::string &tableName) +{ + std::shared_ptr resultSet = + store->QuerySql("SELECT * FROM " + tableName); + ASSERT_NE(resultSet, nullptr); + int countNum; + int ret = resultSet->GetRowCount(countNum); + EXPECT_EQ(ret, errCode); + EXPECT_EQ(num, countNum); +} + +/** +* @tc.name: RdbStore_DoubleWrite_022 +* @tc.desc: open SINGLE db, write, close, reopen MAIN_REPLICA db, wait for backup, insert, check count +* @tc.type: FUNC +*/ +HWTEST_F(RdbDoubleWriteConcurrentTest, RdbStore_DoubleWrite_022, TestSize.Level1) +{ + int errCode = E_OK; + RdbStoreConfig config(RdbDoubleWriteConcurrentTest::DATABASE_NAME); + config.SetHaMode(HAMode::SINGLE); + RdbDoubleWriteConcurrentTest::Callback helper; + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + + int64_t id = 10; + int strSize = 1024 * 100; + int count = 1000; + Insert(id, count, false, strSize); + LOG_INFO("RdbStore_DoubleWrite_022 insert finish"); + + store = nullptr; + config.SetHaMode(HAMode::MAIN_REPLICA); + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + LOG_INFO("RdbStore_DoubleWrite_022 reopen db finish"); + + WaitForBackupFinish(BACKUP_FINISHED); + + id = 6666; + Insert(id, count); + LOG_INFO("RdbStore_DoubleWrite_022 insert db finish"); + + RdbStoreConfig slaveConfig(RdbDoubleWriteConcurrentTest::SLAVE_DATABASE_NAME); + RdbDoubleWriteConcurrentTest::Callback slaveHelper; + RdbDoubleWriteConcurrentTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode); + EXPECT_NE(RdbDoubleWriteConcurrentTest::slaveStore, nullptr); + LOG_INFO("RdbStore_DoubleWrite_022 reopen slave db finish"); + + RdbDoubleWriteConcurrentTest::CheckNumber(store, count + count); + RdbDoubleWriteConcurrentTest::CheckNumber(slaveStore, count + count); +} + +/** +* @tc.name: RdbStore_DoubleWrite_023 +* @tc.desc: open MANUAL_TRIGGER db, write, backup async, interrupt, backup async, wait finish, check count +* @tc.type: FUNC +*/ +HWTEST_F(RdbDoubleWriteConcurrentTest, RdbStore_DoubleWrite_023, TestSize.Level1) +{ + int errCode = E_OK; + RdbStoreConfig config(RdbDoubleWriteConcurrentTest::DATABASE_NAME); + config.SetHaMode(HAMode::MANUAL_TRIGGER); + RdbDoubleWriteConcurrentTest::Callback helper; + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + ASSERT_TRUE(store->IsSlaveDiffFromMaster()); + LOG_INFO("RdbStore_DoubleWrite_023 reopen finish"); + + int64_t id = 10; + int strSize = 1024 * 100; + int count = 1000; + Insert(id, count, false, strSize); + LOG_INFO("RdbStore_DoubleWrite_023 insert finish"); + + std::thread thread([this]() { + LOG_INFO("RdbStore_DoubleWrite_023 t1 backup begin"); + EXPECT_EQ(store->Backup(std::string(""), {}), E_CANCEL); + LOG_INFO("RdbStore_DoubleWrite_023 t1 backup end"); + }); + LOG_INFO("RdbStore_DoubleWrite_023 begin interrupt"); + TryInterruptBackup(); + LOG_INFO("RdbStore_DoubleWrite_023 interrupt end"); + EXPECT_EQ(store->GetBackupStatus(), SlaveStatus::BACKUP_INTERRUPT); + thread.join(); + + std::thread thread1([this]() { + LOG_INFO("RdbStore_DoubleWrite_023 t2 backup begin"); + EXPECT_EQ(store->Backup(std::string(""), {}), E_OK); + LOG_INFO("RdbStore_DoubleWrite_023 t2 backup end"); + }); + WaitForBackupFinish(BACKUP_FINISHED); + LOG_INFO("RdbStore_DoubleWrite_023 wait finish"); + thread1.join(); + + RdbStoreConfig slaveConfig(RdbDoubleWriteConcurrentTest::SLAVE_DATABASE_NAME); + RdbDoubleWriteConcurrentTest::Callback slaveHelper; + RdbDoubleWriteConcurrentTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode); + EXPECT_NE(RdbDoubleWriteConcurrentTest::slaveStore, nullptr); + LOG_INFO("RdbStore_DoubleWrite_023 reopen slave db finish"); + + RdbDoubleWriteConcurrentTest::CheckNumber(store, count); + RdbDoubleWriteConcurrentTest::CheckNumber(slaveStore, count); +} + +/** +* @tc.name: RdbStore_DoubleWrite_024 +* @tc.desc: open SINGLE db, write, close, reopen MAIN_REPLICA db, wait for backup, insert, check count +* @tc.type: FUNC +*/ +HWTEST_F(RdbDoubleWriteConcurrentTest, RdbStore_DoubleWrite_024, TestSize.Level1) +{ + int errCode = E_OK; + RdbStoreConfig config(RdbDoubleWriteConcurrentTest::DATABASE_NAME); + config.SetHaMode(HAMode::SINGLE); + RdbDoubleWriteConcurrentTest::Callback helper; + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + + int64_t id = 10; + int strSize = 1024 * 100; + int count = 1000; + Insert(id, count, false, strSize); + LOG_INFO("RdbStore_DoubleWrite_024 insert finish"); + + store = nullptr; + LOG_INFO("RdbStore_DoubleWrite_024 close finish"); + config.SetHaMode(HAMode::MAIN_REPLICA); + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + LOG_INFO("RdbStore_DoubleWrite_024 reopen db finish"); + + usleep(200000); // 200000 us delay + store = nullptr; + LOG_INFO("RdbStore_DoubleWrite_024 close again"); + + RdbStoreConfig slaveConfig(RdbDoubleWriteConcurrentTest::SLAVE_DATABASE_NAME); + RdbDoubleWriteConcurrentTest::Callback slaveHelper; + RdbDoubleWriteConcurrentTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode); + EXPECT_NE(RdbDoubleWriteConcurrentTest::slaveStore, nullptr); + LOG_INFO("RdbStore_DoubleWrite_024 reopen slave"); + RdbDoubleWriteConcurrentTest::CheckNumber(slaveStore, count); +} + +/** +* @tc.name: RdbStore_DoubleWrite_025 +* @tc.desc: open SINGLE db, write, close, reopen MAIN_REPLICA db, insert, wait for backup, check count +* @tc.type: FUNC +*/ +HWTEST_F(RdbDoubleWriteConcurrentTest, RdbStore_DoubleWrite_025, TestSize.Level1) +{ + int errCode = E_OK; + RdbStoreConfig config(RdbDoubleWriteConcurrentTest::DATABASE_NAME); + config.SetHaMode(HAMode::SINGLE); + RdbDoubleWriteConcurrentTest::Callback helper; + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + + int64_t id = 10; + int strSize = 1024 * 100; + int count = 1000; + Insert(id, count, false, strSize); + LOG_INFO("RdbStore_DoubleWrite_025 insert finish"); + + store = nullptr; + LOG_INFO("RdbStore_DoubleWrite_025 close finish"); + config.SetHaMode(HAMode::MAIN_REPLICA); + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + LOG_INFO("RdbStore_DoubleWrite_025 reopen db finish"); + + id = 6666; + LOG_INFO("RdbStore_DoubleWrite_025 begin insert"); + Insert(id, count, false, strSize); + LOG_INFO("RdbStore_DoubleWrite_025 insert end"); + + WaitForBackupFinish(BACKUP_FINISHED, 1000); // 1000 is max retry time + LOG_INFO("RdbStore_DoubleWrite_025 wait finish"); + + RdbStoreConfig slaveConfig(RdbDoubleWriteConcurrentTest::SLAVE_DATABASE_NAME); + RdbDoubleWriteConcurrentTest::Callback slaveHelper; + RdbDoubleWriteConcurrentTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode); + EXPECT_NE(RdbDoubleWriteConcurrentTest::slaveStore, nullptr); + LOG_INFO("RdbStore_DoubleWrite_025 reopen slave"); + + RdbDoubleWriteConcurrentTest::CheckNumber(store, count + count); + std::shared_ptr resultSet = slaveStore->QuerySql("SELECT * FROM test"); + ASSERT_NE(resultSet, nullptr); + int countNum; + EXPECT_EQ(resultSet->GetRowCount(countNum), errCode); + EXPECT_GT(countNum, count); + EXPECT_LE(countNum, count + count); +} \ No newline at end of file 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 44bf9c36f16fd1a7511be7d664c2d72b33d77271..ebabdbe9c80c7f2ff74992937ddd8c61cb98711c 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 @@ -817,47 +817,6 @@ HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_016, TestSize.Level1) RdbDoubleWriteTest::CheckNumber(slaveStore, count); } -/** - * @tc.name: RdbStore_DoubleWrite_017 - * @tc.desc: open MAIN_REPLICA db, write, close, reopen, corrupt db, restore, check count - * @tc.type: FUNC - */ -HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_017, TestSize.Level1) -{ - InitDb(); - int64_t id = 10; - int count = 100; - Insert(id, count); - LOG_INFO("RdbStore_DoubleWrite_017 insert finish"); - - store = nullptr; - RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); - config.SetHaMode(HAMode::MAIN_REPLICA); - config.SetAllowRebuild(true); - DoubleWriteTestOpenCallback helper; - int errCode; - store = RdbHelper::GetRdbStore(config, 1, helper, errCode); - EXPECT_EQ(errCode, E_OK); - ASSERT_NE(store, nullptr); - LOG_INFO("RdbStore_DoubleWrite_017 reopen db finish"); - - std::fstream file(DATABASE_NAME, std::ios::in | std::ios::out | std::ios::binary); - ASSERT_TRUE(file.is_open() == true); - file.seekp(0, std::ios::beg); - ASSERT_TRUE(file.good() == true); - char bytes[2] = {0x6, 0x6}; - file.write(bytes, 2); - ASSERT_TRUE(file.good() == true); - file.close(); - LOG_INFO("RdbStore_DoubleWrite_017 corrupt db finish"); - - EXPECT_EQ(store->Restore(std::string(""), {}), E_OK); - LOG_INFO("RdbStore_DoubleWrite_017 restore db finish"); - - RdbDoubleWriteTest::CheckNumber(store, count); - RdbDoubleWriteTest::CheckNumber(slaveStore, count); -} - /** * @tc.name: RdbStore_DoubleWrite_018 * @tc.desc: open MAIN_REPLICA db, update slave, insert, M succ && S failed, @@ -952,188 +911,6 @@ HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_019, TestSize.Level1) ASSERT_FALSE(isFlagFileExists); } -/** - * @tc.name: RdbStore_DoubleWrite_022 - * @tc.desc: open SINGLE db, write, close, reopen MAIN_REPLICA db, wait for backup, insert, check count - * @tc.type: FUNC - */ -HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_022, TestSize.Level1) -{ - int errCode = E_OK; - RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); - config.SetHaMode(HAMode::SINGLE); - DoubleWriteTestOpenCallback helper; - store = RdbHelper::GetRdbStore(config, 1, helper, errCode); - EXPECT_NE(store, nullptr); - - int64_t id = 10; - int strSize = 1024 * 100; - int count = 2000; - Insert(id, count, false, strSize); - LOG_INFO("RdbStore_DoubleWrite_022 insert finish"); - - store = nullptr; - config.SetHaMode(HAMode::MAIN_REPLICA); - store = RdbHelper::GetRdbStore(config, 1, helper, errCode); - ASSERT_NE(store, nullptr); - LOG_INFO("RdbStore_DoubleWrite_022 reopen db finish"); - - WaitForBackupFinish(BACKUP_FINISHED); - - id = 6666; - Insert(id, count); - LOG_INFO("RdbStore_DoubleWrite_022 insert db finish"); - - RdbStoreConfig slaveConfig(RdbDoubleWriteTest::SLAVE_DATABASE_NAME); - DoubleWriteTestOpenCallback slaveHelper; - RdbDoubleWriteTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode); - EXPECT_NE(RdbDoubleWriteTest::slaveStore, nullptr); - LOG_INFO("RdbStore_DoubleWrite_022 reopen slave db finish"); - - RdbDoubleWriteTest::CheckNumber(store, count + count); - RdbDoubleWriteTest::CheckNumber(slaveStore, count + count); -} - -/** - * @tc.name: RdbStore_DoubleWrite_023 - * @tc.desc: open MANUAL_TRIGGER db, write, backup async, interrupt, backup async, wait finish, check count - * @tc.type: FUNC - */ -HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_023, TestSize.Level1) -{ - int errCode = E_OK; - RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); - config.SetHaMode(HAMode::MANUAL_TRIGGER); - DoubleWriteTestOpenCallback helper; - store = RdbHelper::GetRdbStore(config, 1, helper, errCode); - EXPECT_NE(store, nullptr); - ASSERT_TRUE(store->IsSlaveDiffFromMaster()); - LOG_INFO("RdbStore_DoubleWrite_023 reopen finish"); - - int64_t id = 10; - int strSize = 1024 * 100; - int count = 2000; - Insert(id, count, false, strSize); - LOG_INFO("RdbStore_DoubleWrite_023 insert finish"); - - std::thread thread([this]() { - LOG_INFO("RdbStore_DoubleWrite_023 t1 backup begin"); - EXPECT_EQ(store->Backup(std::string(""), {}), E_BACKUP_INTERRUPT); - LOG_INFO("RdbStore_DoubleWrite_023 t1 backup end"); - }); - LOG_INFO("RdbStore_DoubleWrite_023 begin interrupt"); - TryInterruptBackup(); - LOG_INFO("RdbStore_DoubleWrite_023 interrupt end"); - EXPECT_EQ(store->GetBackupStatus(), SlaveStatus::BACKUP_INTERRUPT); - thread.join(); - - std::thread thread1([this]() { - LOG_INFO("RdbStore_DoubleWrite_023 t2 backup begin"); - EXPECT_EQ(store->Backup(std::string(""), {}), E_OK); - LOG_INFO("RdbStore_DoubleWrite_023 t2 backup end"); - }); - WaitForBackupFinish(BACKUP_FINISHED); - LOG_INFO("RdbStore_DoubleWrite_023 wait finish"); - thread1.join(); - - RdbStoreConfig slaveConfig(RdbDoubleWriteTest::SLAVE_DATABASE_NAME); - DoubleWriteTestOpenCallback slaveHelper; - RdbDoubleWriteTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode); - EXPECT_NE(RdbDoubleWriteTest::slaveStore, nullptr); - LOG_INFO("RdbStore_DoubleWrite_023 reopen slave db finish"); - - RdbDoubleWriteTest::CheckNumber(store, count); - RdbDoubleWriteTest::CheckNumber(slaveStore, count); -} - -/** - * @tc.name: RdbStore_DoubleWrite_024 - * @tc.desc: open SINGLE db, write, close, reopen MAIN_REPLICA db, wait for backup, insert, check count - * @tc.type: FUNC - */ -HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_024, TestSize.Level1) -{ - int errCode = E_OK; - RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); - config.SetHaMode(HAMode::SINGLE); - DoubleWriteTestOpenCallback helper; - store = RdbHelper::GetRdbStore(config, 1, helper, errCode); - EXPECT_NE(store, nullptr); - - int64_t id = 10; - int strSize = 1024 * 200; - int count = 1000; - Insert(id, count, false, strSize); - LOG_INFO("RdbStore_DoubleWrite_024 insert finish"); - - store = nullptr; - LOG_INFO("RdbStore_DoubleWrite_024 close finish"); - config.SetHaMode(HAMode::MAIN_REPLICA); - store = RdbHelper::GetRdbStore(config, 1, helper, errCode); - ASSERT_NE(store, nullptr); - LOG_INFO("RdbStore_DoubleWrite_024 reopen db finish"); - - store = nullptr; - LOG_INFO("RdbStore_DoubleWrite_024 close again"); - - RdbStoreConfig slaveConfig(RdbDoubleWriteTest::SLAVE_DATABASE_NAME); - DoubleWriteTestOpenCallback slaveHelper; - RdbDoubleWriteTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode); - EXPECT_NE(RdbDoubleWriteTest::slaveStore, nullptr); - LOG_INFO("RdbStore_DoubleWrite_024 reopen slave"); - RdbDoubleWriteTest::CheckNumber(slaveStore, count); -} - -/** - * @tc.name: RdbStore_DoubleWrite_025 - * @tc.desc: open SINGLE db, write, close, reopen MAIN_REPLICA db, insert, wait for backup, check count - * @tc.type: FUNC - */ -HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_025, TestSize.Level1) -{ - int errCode = E_OK; - RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); - config.SetHaMode(HAMode::SINGLE); - DoubleWriteTestOpenCallback helper; - store = RdbHelper::GetRdbStore(config, 1, helper, errCode); - EXPECT_NE(store, nullptr); - - int64_t id = 10; - int strSize = 1024 * 200; - int count = 1000; - Insert(id, count, false, strSize); - LOG_INFO("RdbStore_DoubleWrite_025 insert finish"); - - store = nullptr; - LOG_INFO("RdbStore_DoubleWrite_025 close finish"); - config.SetHaMode(HAMode::MAIN_REPLICA); - store = RdbHelper::GetRdbStore(config, 1, helper, errCode); - ASSERT_NE(store, nullptr); - LOG_INFO("RdbStore_DoubleWrite_025 reopen db finish"); - - id = 6666; - LOG_INFO("RdbStore_DoubleWrite_025 begin insert"); - Insert(id, count, false, strSize); - LOG_INFO("RdbStore_DoubleWrite_025 insert end"); - - WaitForBackupFinish(BACKUP_FINISHED, 1000); // 1000 is max retry time - LOG_INFO("RdbStore_DoubleWrite_025 wait finish"); - - RdbStoreConfig slaveConfig(RdbDoubleWriteTest::SLAVE_DATABASE_NAME); - DoubleWriteTestOpenCallback slaveHelper; - RdbDoubleWriteTest::slaveStore = RdbHelper::GetRdbStore(slaveConfig, 1, slaveHelper, errCode); - EXPECT_NE(RdbDoubleWriteTest::slaveStore, nullptr); - LOG_INFO("RdbStore_DoubleWrite_025 reopen slave"); - - RdbDoubleWriteTest::CheckNumber(store, count + count); - std::shared_ptr resultSet = slaveStore->QuerySql("SELECT * FROM test"); - ASSERT_NE(resultSet, nullptr); - int countNum; - EXPECT_EQ(resultSet->GetRowCount(countNum), errCode); - EXPECT_GT(countNum, count); - EXPECT_LE(countNum, count + count); -} - /** * @tc.name: RdbStore_DoubleWrite_026 * @tc.desc: open MANUAL_TRIGGER db, write, restore, insert, check count @@ -1250,92 +1027,28 @@ HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_029, TestSize.Level1) /** * @tc.name: RdbStore_DoubleWrite_030 - * @tc.desc: open db, write, delete main db, restore, check count + * @tc.desc: open db, write, update slave, insert, check failure, restore, check count * @tc.type: FUNC */ HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_030, TestSize.Level1) { - int errCode = E_OK; - RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); - config.SetHaMode(HAMode::MAIN_REPLICA); - config.SetAllowRebuild(true); - DoubleWriteTestOpenCallback helper; - RdbDoubleWriteTest::store = RdbHelper::GetRdbStore(config, 1, helper, errCode); - EXPECT_NE(RdbDoubleWriteTest::store, nullptr); - - int64_t id = 10; - int count = 100; - Insert(id, count); - - SqliteUtils::DeleteFile(DATABASE_NAME); - - EXPECT_EQ(store->Restore(std::string(""), {}), E_OK); - EXPECT_EQ(access(DATABASE_NAME.c_str(), F_OK) == 0, true); - - id = 666; - Insert(id, count); - RdbDoubleWriteTest::CheckNumber(store, count + count); -} - -/** - * @tc.name: RdbStore_DoubleWrite_031 - * @tc.desc: open MANUAL_TRIGGER db, write, backup, delete main db, restore, check count - * @tc.type: FUNC - */ -HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_031, TestSize.Level1) -{ - int errCode = E_OK; - RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); - config.SetHaMode(HAMode::MANUAL_TRIGGER); - DoubleWriteTestOpenCallback helper; - store = RdbHelper::GetRdbStore(config, 1, helper, errCode); - EXPECT_NE(RdbDoubleWriteTest::store, nullptr); - + InitDb(); int64_t id = 10; int count = 100; Insert(id, count); - EXPECT_EQ(store->Backup(std::string(""), {}), E_OK); - - SqliteUtils::DeleteFile(DATABASE_NAME); - - EXPECT_EQ(store->Restore(std::string(""), {}), E_OK); - EXPECT_EQ(access(DATABASE_NAME.c_str(), F_OK) == 0, true); + auto [ret2, outValue2] = slaveStore->Execute("UPDATE test SET id = 666 WHERE id = 22"); + EXPECT_EQ(E_OK, ret2); id = 666; - Insert(id, count); - RdbDoubleWriteTest::CheckNumber(store, count + count); -} + Insert(id, 1); -/** - * @tc.name: RdbStore_DoubleWrite_032 - * @tc.desc: open MANUAL_TRIGGER db, write, backup, close, delete main db, reopen, check count - * @tc.type: FUNC - */ -HWTEST_F(RdbDoubleWriteTest, RdbStore_DoubleWrite_032, TestSize.Level1) -{ - int errCode = E_OK; - RdbStoreConfig config(RdbDoubleWriteTest::DATABASE_NAME); - config.SetHaMode(HAMode::MANUAL_TRIGGER); - DoubleWriteTestOpenCallback helper; - store = RdbHelper::GetRdbStore(config, 1, helper, errCode); - EXPECT_NE(RdbDoubleWriteTest::store, nullptr); - - int64_t id = 10; - int count = 100; - Insert(id, count); - - EXPECT_EQ(store->Backup(std::string(""), {}), E_OK); - - store = nullptr; + std::string failureFlagPath = RdbDoubleWriteTest::DATABASE_NAME + + "-slaveFailure"; + bool isFlagFileExists = OHOS::FileExists(failureFlagPath); + ASSERT_TRUE(isFlagFileExists); - SqliteUtils::DeleteFile(DATABASE_NAME); + EXPECT_NE(store->Restore(std::string(""), {}), E_OK); - store = RdbHelper::GetRdbStore(config, 1, helper, errCode); - EXPECT_NE(RdbDoubleWriteTest::store, nullptr); - EXPECT_EQ(access(DATABASE_NAME.c_str(), F_OK) == 0, true); - - id = 666; - Insert(id, count); - RdbDoubleWriteTest::CheckNumber(store, count + count); + RdbDoubleWriteTest::CheckNumber(store, count + 1); + RdbDoubleWriteTest::CheckNumber(slaveStore, count); } \ No newline at end of file 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 d0600b8810ac93506a6bf1bb2f31a55a6f901fcc..7405b66556a6359a08c5b72dcb4fec379e364552 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 @@ -18,10 +18,10 @@ #include #include "common.h" +#include "grd_api_manager.h" #include "rdb_errno.h" #include "rdb_helper.h" #include "rdb_open_callback.h" - using namespace testing::ext; using namespace OHOS::NativeRdb; @@ -402,6 +402,9 @@ HWTEST_F(RdbReadOnlyTest, RdbStore_ReadOnly_0017, TestSize.Level1) */ HWTEST_F(RdbReadOnlyTest, RdbStore_ReadOnly_0018, TestSize.Level1) { + if (!OHOS::NativeRdb::IsUsingArkData()) { + return; + } int errCode = E_ERROR; RdbStoreConfig config(RdbReadOnlyTest::READONLY_DATABASE_NAME); config.SetBundleName("com.example.readOnly.rdb"); diff --git a/relational_store/test/native/rdb/unittest/rdb_security_manager_test.cpp b/relational_store/test/native/rdb/unittest/rdb_security_manager_test.cpp index 3f47bd561de835d47d5cf06a87c2cc7ed37c48c6..c1930c4a194661e1d57a5a119179be97a170467d 100644 --- a/relational_store/test/native/rdb/unittest/rdb_security_manager_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_security_manager_test.cpp @@ -21,6 +21,7 @@ #include "common.h" #include "rdb_errno.h" +#include "rdb_helper.h" #include "file_ex.h" using namespace testing::ext; @@ -57,6 +58,18 @@ void RdbSecurityManagerTest::TearDown(void) { } +class RdbStoreSecurityManagerTestOpenCallback : public RdbOpenCallback { +public: + int OnCreate(RdbStore &store) override + { + return E_OK; + } + int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override + { + return E_OK; + } +}; + /** * @tc.name: Insert_BigInt_INT64 * @tc.desc: test insert bigint to rdb store @@ -108,16 +121,30 @@ HWTEST_F(RdbSecurityManagerTest, LockUnlock, TestSize.Level1) */ HWTEST_F(RdbSecurityManagerTest, LoadSecretKeyFromDiskTest, TestSize.Level1) { + int errCode = E_OK; std::string name = "secret_key_load_test"; - auto keyPath = RDB_TEST_PATH + "key/" + name + ".pub_key"; - RdbSecurityManager::KeyFiles keyFile(keyPath); + RdbStoreConfig config(RDB_TEST_PATH + name); + config.SetEncryptStatus(true); + RdbStoreSecurityManagerTestOpenCallback helper; + + auto store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_EQ(errCode, E_OK); + EXPECT_NE(store, nullptr); + + RdbSecurityManager::KeyFiles keyFile(RDB_TEST_PATH); const std::string file = keyFile.GetKeyFile(RdbSecurityManager::KeyFileType::PUB_KEY_FILE); std::vector content = { 'a' }; bool ret = OHOS::SaveBufferToFile(file, content); ASSERT_TRUE(ret); RdbPassword pwd = - RdbSecurityManager::GetInstance().GetRdbPassword(keyPath, RdbSecurityManager::KeyFileType::PUB_KEY_FILE); + RdbSecurityManager::GetInstance().GetRdbPassword(RDB_TEST_PATH, RdbSecurityManager::KeyFileType::PUB_KEY_FILE); ASSERT_EQ(pwd.GetSize(), 0); + + auto store1 = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_EQ(errCode, E_OK); + EXPECT_NE(store1, nullptr); + + RdbHelper::DeleteRdbStore(config); } } \ 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 25a33b2201e16dec82920a95c0abc91ee8ab3799..d7f593e416af0a3cc23ab52f334b70ea94b34681 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 @@ -761,9 +761,9 @@ HWTEST_F(RdbStoreConfigTest, RdbStoreConfig_024, TestSize.Level1) const std::string dbPath = RDB_TEST_PATH + "config_test.db"; RdbStoreConfig config(dbPath); - std::string encryptAlgo = "sha256"; + EncryptAlgo encryptAlgo = EncryptAlgo::AES_256_GCM; config.SetEncryptAlgo(encryptAlgo); - std::string retEncryptAlgo = config.GetEncryptAlgo(); + EncryptAlgo retEncryptAlgo = config.GetEncryptAlgo(); EXPECT_EQ(encryptAlgo, retEncryptAlgo); ConfigTestOpenCallback helper; @@ -773,12 +773,6 @@ HWTEST_F(RdbStoreConfigTest, RdbStoreConfig_024, TestSize.Level1) store = nullptr; auto ret = RdbHelper::DeleteRdbStore(dbPath); EXPECT_EQ(ret, E_OK); - - config.SetEncryptAlgo(""); - retEncryptAlgo = config.GetEncryptAlgo(); - EXPECT_EQ("", retEncryptAlgo); - store = RdbHelper::GetRdbStore(config, 1, helper, errCode); - EXPECT_NE(store, nullptr); } /** diff --git a/relational_store/test/native/rdb/unittest/rdb_store_impl_test.cpp b/relational_store/test/native/rdb/unittest/rdb_store_impl_test.cpp index 767de0e485e960759b949147332680dee5f2e526..aad81faa4f2c353f84679088d26327756f0d5e21 100644 --- a/relational_store/test/native/rdb/unittest/rdb_store_impl_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_store_impl_test.cpp @@ -855,4 +855,80 @@ HWTEST_F(RdbStoreImplTest, SetSearchableTest, TestSize.Level2) EXPECT_EQ(E_OK, errCode); result = store->SetSearchable(true); EXPECT_EQ(E_OK, result); +} + +/* * + * @tc.name: CreateTransaction_001 + * @tc.desc: create the DEFERRED, IMMEDIATE, EXCLUSIVE transaction. + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplTest, CreateTransaction_001, TestSize.Level1) +{ + auto [errCode, trans] = store_->CreateTransaction(Transaction::DEFERRED); + ASSERT_EQ(errCode, E_OK); + ASSERT_NE(trans, nullptr); + trans = nullptr; + std::tie(errCode, trans) = store_->CreateTransaction(Transaction::IMMEDIATE); + ASSERT_EQ(errCode, E_OK); + ASSERT_NE(trans, nullptr); + trans = nullptr; + std::tie(errCode, trans) = store_->CreateTransaction(Transaction::EXCLUSIVE); + ASSERT_EQ(errCode, E_OK); + ASSERT_NE(trans, nullptr); +} + +/* * + * @tc.name: CreateTransaction_002 + * @tc.desc: create the invalid type transaction. + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplTest, CreateTransaction_002, TestSize.Level1) +{ + auto [errCode, trans] = store_->CreateTransaction(-1); + ASSERT_EQ(errCode, E_INVALID_ARGS); + ASSERT_EQ(trans, nullptr); + std::tie(errCode, trans) = store_->CreateTransaction(Transaction::TRANS_BUTT); + ASSERT_EQ(errCode, E_INVALID_ARGS); + ASSERT_EQ(trans, nullptr); + std::tie(errCode, trans) = store_->CreateTransaction(100); + ASSERT_EQ(errCode, E_INVALID_ARGS); + ASSERT_EQ(trans, nullptr); +} + +/* * + * @tc.name: CreateTransaction_003 + * @tc.desc: create the over the max trans. + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplTest, CreateTransaction_003, TestSize.Level1) +{ + constexpr size_t MAX_TRANS = 4; + std::vector> entries; + int32_t errCode = E_OK; + std::shared_ptr trans = nullptr; + for (int i = 0; i < 100; ++i) { + std::tie(errCode, trans) = store_->CreateTransaction(Transaction::DEFERRED); + if (trans == nullptr) { + break; + } + entries.push_back(std::move(trans)); + } + ASSERT_EQ(errCode, E_CON_OVER_LIMIT); + ASSERT_EQ(entries.size(), MAX_TRANS); +} + +/* * + * @tc.name: CreateTransaction_004 + * @tc.desc: create the auto release trans. + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplTest, CreateTransaction_004, TestSize.Level1) +{ + int i = 0; + for (i = 0; i < 20; ++i) { + auto [errCode, trans] = store_->CreateTransaction(Transaction::EXCLUSIVE); + ASSERT_EQ(errCode, E_OK); + ASSERT_NE(trans, nullptr); + } + ASSERT_EQ(i, 20); } \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/rdb_trans_db_test.cpp b/relational_store/test/native/rdb/unittest/rdb_trans_db_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..052e5fcba96e3b1275a6527ab472b382b7a4c56c --- /dev/null +++ b/relational_store/test/native/rdb/unittest/rdb_trans_db_test.cpp @@ -0,0 +1,1135 @@ +/* + * 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 + +#include "common.h" +#include "connection_pool.h" +#include "rdb_errno.h" +#include "rdb_predicates.h" +#include "sqlite_sql_builder.h" +#include "trans_db.h" +using namespace testing::ext; +using namespace OHOS::NativeRdb; +namespace Test { +class RdbTransDBTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + +protected: + static constexpr const char *CREATE_TABLE = "CREATE TABLE IF NOT EXISTS TEST (id INT PRIMARY KEY, name TEXT, " + "extend BLOB, code REAL, years UNLIMITED INT, attachment ASSET, " + "attachments ASSETS)"; + static constexpr const char *DROP_TABLE = "DROP TABLE IF EXISTS TEST"; + static constexpr const char *TABLE_NAME = "TEST"; + static std::shared_ptr connPool_; + static RdbStoreConfig config_; + static ValuesBucket row_; + std::shared_ptr transDB_; + std::shared_ptr conn_; +}; +std::shared_ptr RdbTransDBTest::connPool_ = nullptr; +RdbStoreConfig RdbTransDBTest::config_(RDB_TEST_PATH + "transDb_test.db"); +ValuesBucket RdbTransDBTest::row_(std::map{ + { "id", ValueObject(1) }, + { "name", ValueObject("xiaoming") }, + { "extend", ValueObject(std::vector(100, 128)) }, + { "code", ValueObject(3.1415926) }, + { "years", ValueObject(BigInteger(0, { 128, 225 })) }, + { "attachment", ValueObject(AssetValue{ .id = "119", .name = "picture1", .hash = "111" }) }, + { "attachments", ValueObject(ValueObject::Assets{ + AssetValue{ .id = "120", .name = "picture2", .hash = "112" }, + AssetValue{ .id = "121", .name = "picture3", .hash = "113" }, + AssetValue{ .id = "122", .name = "picture4", .hash = "114" }, + AssetValue{ .id = "123", .name = "picture5", .hash = "115" } + }) + } +}); + +void RdbTransDBTest::SetUpTestCase(void) +{ + config_.SetBundleName("arkdata_test"); + config_.SetSecurityLevel(OHOS::NativeRdb::SecurityLevel::S1); + Connection::Delete(config_); + int32_t errCode = E_OK; + connPool_ = ConnectionPool::Create(config_, errCode); + EXPECT_TRUE(connPool_ != nullptr); +} + +void RdbTransDBTest::TearDownTestCase(void) +{ + connPool_ = nullptr; + Connection::Delete(config_); +} + +void RdbTransDBTest::SetUp() +{ + auto [errCode, conn] = connPool_->CreateTransConn(); + ASSERT_NE(conn, nullptr); + ASSERT_EQ(errCode, E_OK); + transDB_ = std::make_shared(conn, config_.GetName()); + ASSERT_NE(transDB_, nullptr); + auto [err, object] = transDB_->Execute(DROP_TABLE); + ASSERT_EQ(err, E_OK); + std::tie(err, object) = transDB_->Execute(CREATE_TABLE); + ASSERT_EQ(err, E_OK); + conn_ = conn; +} + +void RdbTransDBTest::TearDown() +{ + transDB_ = nullptr; + conn_ = nullptr; +} + +/* * + * @tc.name: ALREADY_CLOSED_001 + * @tc.desc: closed db + * @tc.type: FUNC + */ +HWTEST_F(RdbTransDBTest, ALREADY_CLOSED_001, TestSize.Level1) +{ + conn_ = nullptr; + ValuesBucket row = row_; + int32_t changed = 0; + auto [errCode, rowId] = transDB_->Insert(TABLE_NAME, row); + ASSERT_EQ(errCode, E_ALREADY_CLOSED); + std::tie(errCode, changed) = transDB_->Update(TABLE_NAME, row); + ASSERT_EQ(errCode, E_ALREADY_CLOSED); + errCode = transDB_->Delete(changed, TABLE_NAME); + ASSERT_EQ(errCode, E_ALREADY_CLOSED); + auto resultSet = transDB_->QueryByStep("select * from TEST"); + ASSERT_NE(resultSet, nullptr); + errCode = resultSet->GoToNextRow(); + ASSERT_EQ(errCode, E_ALREADY_CLOSED); + resultSet = transDB_->QuerySql("select * from TEST"); + ASSERT_NE(resultSet, nullptr); + errCode = resultSet->GoToNextRow(); + ASSERT_EQ(errCode, E_ALREADY_CLOSED); +} + +/* * + * @tc.name: ALREADY_CLOSED_002 + * @tc.desc: closed db + * @tc.type: FUNC + */ +HWTEST_F(RdbTransDBTest, ALREADY_CLOSED_002, TestSize.Level1) +{ + ValuesBucket row = row_; + int32_t changed = 0; + auto [errCode, rowId] = transDB_->Insert(TABLE_NAME, row); + ASSERT_EQ(errCode, E_OK); + auto resultSet = transDB_->QueryByStep("select * from TEST"); + ASSERT_NE(resultSet, nullptr); + errCode = resultSet->GoToNextRow(); + ASSERT_EQ(errCode, E_OK); + conn_ = nullptr; + resultSet->Close(); + errCode = transDB_->Delete(changed, TABLE_NAME); + ASSERT_EQ(errCode, E_ALREADY_CLOSED); + errCode = resultSet->GoToNextRow(); + ASSERT_EQ(errCode, E_ALREADY_CLOSED); +} + +/* * + * @tc.name: Insert_NEW_001 + * @tc.desc: insert into test(...) values(?) + * @tc.type: FUNC + */ +HWTEST_F(RdbTransDBTest, Insert_NEW_001, TestSize.Level1) +{ + ValuesBucket row = row_; + auto [errCode, rowId] = transDB_->Insert(TABLE_NAME, row); + ASSERT_EQ(errCode, E_OK); + ASSERT_EQ(rowId, 1); + auto resultSet = transDB_->QueryByStep("select * from TEST"); + ASSERT_NE(resultSet, nullptr); + errCode = resultSet->GoToNextRow(); + ASSERT_EQ(errCode, E_OK); + RowEntity rowEntity; + errCode = resultSet->GetRow(rowEntity); + ASSERT_EQ(errCode, E_OK); + ASSERT_TRUE(row.values_ == rowEntity.Get()); +} + +/* * + * @tc.name: Insert_NEW_002 + * @tc.desc: insert or replace into test(...) values(?) + * @tc.type: FUNC + */ +HWTEST_F(RdbTransDBTest, Insert_NEW_002, TestSize.Level1) +{ + ValuesBucket row = row_; + auto [errCode, rowId] = transDB_->Insert(TABLE_NAME, row); + ASSERT_EQ(errCode, E_OK); + ASSERT_EQ(rowId, 1); + row.Put("name", "xiaohua"); + std::tie(errCode, rowId) = transDB_->Insert(TABLE_NAME, row, ConflictResolution::ON_CONFLICT_REPLACE); + ASSERT_EQ(errCode, E_INVALID_ARGS); + row.Put("attachments", ValueObject()); + std::tie(errCode, rowId) = transDB_->Insert(TABLE_NAME, row, ConflictResolution::ON_CONFLICT_REPLACE); + ASSERT_EQ(errCode, E_OK); + auto resultSet = transDB_->QueryByStep("select * from TEST"); + ASSERT_NE(resultSet, nullptr); + errCode = resultSet->GoToNextRow(); + ASSERT_EQ(errCode, E_OK); + RowEntity rowEntity; + errCode = resultSet->GetRow(rowEntity); + ASSERT_EQ(errCode, E_OK); + ASSERT_TRUE(row.values_ == rowEntity.Get()); +} + +/* * + * @tc.name: Insert_NEW_003 + * @tc.desc: insert or ignore into test(...) values(?) + * @tc.type: FUNC + */ +HWTEST_F(RdbTransDBTest, Insert_NEW_003, TestSize.Level1) +{ + ValuesBucket row = row_; + auto [errCode, rowId] = transDB_->Insert(TABLE_NAME, row); + ASSERT_EQ(errCode, E_OK); + ASSERT_EQ(rowId, 1); + row.Put("name", "xiaohua"); + std::tie(errCode, rowId) = transDB_->Insert(TABLE_NAME, row, ConflictResolution::ON_CONFLICT_IGNORE); + ASSERT_EQ(errCode, E_OK); + auto resultSet = transDB_->QueryByStep("select * from TEST"); + ASSERT_NE(resultSet, nullptr); + errCode = resultSet->GoToNextRow(); + ASSERT_EQ(errCode, E_OK); + RowEntity rowEntity; + errCode = resultSet->GetRow(rowEntity); + ASSERT_EQ(errCode, E_OK); + row = row_; + SqliteSqlBuilder::UpdateAssetStatus(row.values_["attachment"], AssetValue::STATUS_INSERT); + SqliteSqlBuilder::UpdateAssetStatus(row.values_["attachments"], AssetValue::STATUS_INSERT); + ASSERT_TRUE(row.values_ == rowEntity.Get()); +} + +/* * + * @tc.name: Insert_NEW_003 + * @tc.desc: insert or fail into test(...) values(?) + * @tc.type: FUNC + */ +HWTEST_F(RdbTransDBTest, Insert_NEW_004, TestSize.Level1) +{ + ValuesBucket row = row_; + auto [errCode, rowId] = transDB_->Insert(TABLE_NAME, row); + ASSERT_EQ(errCode, E_OK); + ASSERT_EQ(rowId, 1); + row.Put("name", "xiaohua"); + std::tie(errCode, rowId) = transDB_->Insert(TABLE_NAME, row, ConflictResolution::ON_CONFLICT_FAIL); + ASSERT_EQ(errCode, E_SQLITE_CONSTRAINT); + auto resultSet = transDB_->QueryByStep("select * from TEST"); + ASSERT_NE(resultSet, nullptr); + errCode = resultSet->GoToNextRow(); + ASSERT_EQ(errCode, E_OK); + RowEntity rowEntity; + errCode = resultSet->GetRow(rowEntity); + ASSERT_EQ(errCode, E_OK); + row = row_; + SqliteSqlBuilder::UpdateAssetStatus(row.values_["attachment"], AssetValue::STATUS_INSERT); + SqliteSqlBuilder::UpdateAssetStatus(row.values_["attachments"], AssetValue::STATUS_INSERT); + ASSERT_TRUE(row.values_ == rowEntity.Get()); +} + +/* * + * @tc.name: Insert_NEW_003 + * @tc.desc: insert or abort into test(...) values(?) + * @tc.type: FUNC + */ +HWTEST_F(RdbTransDBTest, Insert_NEW_005, TestSize.Level1) +{ + ValuesBucket row = row_; + auto [errCode, rowId] = transDB_->Insert(TABLE_NAME, row); + ASSERT_EQ(errCode, E_OK); + ASSERT_EQ(rowId, 1); + row.Put("name", "xiaohua"); + std::tie(errCode, rowId) = transDB_->Insert(TABLE_NAME, row, ConflictResolution::ON_CONFLICT_ABORT); + ASSERT_EQ(errCode, E_SQLITE_CONSTRAINT); + auto resultSet = transDB_->QueryByStep("select * from TEST"); + ASSERT_NE(resultSet, nullptr); + errCode = resultSet->GoToNextRow(); + ASSERT_EQ(errCode, E_OK); + RowEntity rowEntity; + errCode = resultSet->GetRow(rowEntity); + ASSERT_EQ(errCode, E_OK); + row = row_; + SqliteSqlBuilder::UpdateAssetStatus(row.values_["attachment"], AssetValue::STATUS_INSERT); + SqliteSqlBuilder::UpdateAssetStatus(row.values_["attachments"], AssetValue::STATUS_INSERT); + ASSERT_TRUE(row.values_ == rowEntity.Get()); +} + +/* * + * @tc.name: Insert_NEW_006 + * @tc.desc: insert or rollback into test(...) values(?) + * @tc.type: FUNC + */ +HWTEST_F(RdbTransDBTest, Insert_NEW_006, TestSize.Level1) +{ + ValuesBucket row = row_; + auto [errCode, rowId] = transDB_->Insert(TABLE_NAME, row); + ASSERT_EQ(errCode, E_OK); + ASSERT_EQ(rowId, 1); + row.Put("name", "xiaohua"); + std::tie(errCode, rowId) = transDB_->Insert(TABLE_NAME, row, ConflictResolution::ON_CONFLICT_ROLLBACK); + ASSERT_EQ(errCode, E_SQLITE_CONSTRAINT); + auto resultSet = transDB_->QueryByStep("select * from TEST"); + ASSERT_NE(resultSet, nullptr); + errCode = resultSet->GoToNextRow(); + ASSERT_EQ(errCode, E_OK); + RowEntity rowEntity; + errCode = resultSet->GetRow(rowEntity); + ASSERT_EQ(errCode, E_OK); + row = row_; + SqliteSqlBuilder::UpdateAssetStatus(row.values_["attachment"], AssetValue::STATUS_INSERT); + SqliteSqlBuilder::UpdateAssetStatus(row.values_["attachments"], AssetValue::STATUS_INSERT); + ASSERT_TRUE(row.values_ == rowEntity.Get()); +} + +/* * + * @tc.name: Insert_001 + * @tc.desc: insert into test(...) values(?) + * @tc.type: FUNC + */ +HWTEST_F(RdbTransDBTest, Insert_001, TestSize.Level1) +{ + int64_t rowId = -1; + ValuesBucket row = row_; + auto errCode = transDB_->Insert(rowId, TABLE_NAME, row); + ASSERT_EQ(errCode, E_OK); + ASSERT_EQ(rowId, 1); + auto resultSet = transDB_->QueryByStep("select * from TEST"); + ASSERT_NE(resultSet, nullptr); + errCode = resultSet->GoToNextRow(); + ASSERT_EQ(errCode, E_OK); + RowEntity rowEntity; + errCode = resultSet->GetRow(rowEntity); + ASSERT_EQ(errCode, E_OK); + ASSERT_TRUE(row.values_ == rowEntity.Get()); +} + +/* * + * @tc.name: Insert_002 + * @tc.desc: insert into test(...) values(?) + * @tc.type: FUNC + */ +HWTEST_F(RdbTransDBTest, Insert_002, TestSize.Level1) +{ + int64_t rowId = -1; + ValuesBucket row = row_; + auto errCode = transDB_->Insert(rowId, TABLE_NAME, row); + ASSERT_EQ(errCode, E_OK); + ASSERT_EQ(rowId, 1); + errCode = transDB_->Insert(rowId, TABLE_NAME, row); + ASSERT_EQ(errCode, E_SQLITE_CONSTRAINT); +} + +/* * + * @tc.name: InsertWithConflictResolution_001 + * @tc.desc: insert or replace into test(...) values(?) + * @tc.type: FUNC + */ +HWTEST_F(RdbTransDBTest, InsertWithConflictResolution_001, TestSize.Level1) +{ + ValuesBucket row = row_; + auto [errCode, rowId] = transDB_->Insert(TABLE_NAME, row); + ASSERT_EQ(errCode, E_OK); + ASSERT_EQ(rowId, 1); + row.Put("name", "xiaohua"); + errCode = transDB_->InsertWithConflictResolution(rowId, TABLE_NAME, row, ConflictResolution::ON_CONFLICT_REPLACE); + ASSERT_EQ(errCode, E_INVALID_ARGS); + row.Put("attachments", ValueObject()); + errCode = transDB_->InsertWithConflictResolution(rowId, TABLE_NAME, row, ConflictResolution::ON_CONFLICT_REPLACE); + ASSERT_EQ(errCode, E_OK); + auto resultSet = transDB_->QueryByStep("select * from TEST"); + ASSERT_NE(resultSet, nullptr); + errCode = resultSet->GoToNextRow(); + ASSERT_EQ(errCode, E_OK); + RowEntity rowEntity; + errCode = resultSet->GetRow(rowEntity); + ASSERT_EQ(errCode, E_OK); + ASSERT_TRUE(row.values_ == rowEntity.Get()); +} + +/* * + * @tc.name: Replace_001 + * @tc.desc: insert or replace into test(...) values(?) + * @tc.type: FUNC + */ +HWTEST_F(RdbTransDBTest, Replace_001, TestSize.Level1) +{ + ValuesBucket row = row_; + auto [errCode, rowId] = transDB_->Insert(TABLE_NAME, row); + ASSERT_EQ(errCode, E_OK); + ASSERT_EQ(rowId, 1); + row.Put("name", "xiaohua"); + errCode = transDB_->Replace(rowId, TABLE_NAME, row); + ASSERT_EQ(errCode, E_INVALID_ARGS); + row.Put("attachments", ValueObject()); + errCode = transDB_->Replace(rowId, TABLE_NAME, row); + ASSERT_EQ(errCode, E_OK); + auto resultSet = transDB_->QueryByStep("select * from TEST"); + ASSERT_NE(resultSet, nullptr); + errCode = resultSet->GoToNextRow(); + ASSERT_EQ(errCode, E_OK); + RowEntity rowEntity; + errCode = resultSet->GetRow(rowEntity); + ASSERT_EQ(errCode, E_OK); + ASSERT_TRUE(row.values_ == rowEntity.Get()); +} + +/* * + * @tc.name: BatchInsert + * @tc.desc: insert Normal ValuesBucket to db + * @tc.type: FUNC + */ +HWTEST_F(RdbTransDBTest, BatchInsert_001, TestSize.Level1) +{ + int64_t changedNum = -1; + std::vector rows; + for (int i = 0; i < 20; i++) { + ValuesBucket row = row_; + row.Put("id", i); + row.Put("name", "xiaoming_" + std::to_string(i)); + row.Put("years", BigInteger(i % 2, { 128, 225 })); + rows.push_back(std::move(row)); + } + auto errCode = transDB_->BatchInsert(changedNum, TABLE_NAME, rows); + ASSERT_EQ(errCode, E_OK); + ASSERT_EQ(changedNum, 20); + auto resultSet = transDB_->QueryByStep("select * from TEST order by id"); + ASSERT_NE(resultSet, nullptr); + size_t index = 0; + while (resultSet->GoToNextRow() == E_OK && index < rows.size()) { + RowEntity rowEntity; + errCode = resultSet->GetRow(rowEntity); + ASSERT_EQ(errCode, E_OK); + auto row = rowEntity.Steal(); + SqliteSqlBuilder::UpdateAssetStatus(rows[index].values_["attachment"], AssetValue::STATUS_INSERT); + SqliteSqlBuilder::UpdateAssetStatus(rows[index].values_["attachments"], AssetValue::STATUS_INSERT); + ASSERT_TRUE(rows[index].values_ == row); + index++; + } + int32_t rowCount = 0; + errCode = resultSet->GetRowCount(rowCount); + ASSERT_EQ(errCode, E_OK); + ASSERT_EQ(rowCount, rows.size()); +} + +/* * + * @tc.name: BatchInsert + * @tc.desc: insert RefRows to db + * @tc.type: FUNC + */ +HWTEST_F(RdbTransDBTest, BatchInsert_002, TestSize.Level1) +{ + ValuesBuckets rows; + for (int i = 0; i < 20; i++) { + ValuesBucket row = row_; + row.Put("id", i); + row.Put("name", "xiaoming_" + std::to_string(i)); + row.Put("years", BigInteger(i % 2, { 128, 225 })); + rows.Put(row); + } + auto [errCode, changedNum] = transDB_->BatchInsert(TABLE_NAME, rows); + ASSERT_EQ(errCode, E_OK); + ASSERT_EQ(changedNum, 20); + auto resultSet = transDB_->QueryByStep("select * from TEST order by id"); + ASSERT_NE(resultSet, nullptr); + size_t index = 0; + while (resultSet->GoToNextRow() == E_OK) { + RowEntity rowEntity; + errCode = resultSet->GetRow(rowEntity); + ASSERT_EQ(errCode, E_OK); + auto row = rowEntity.Steal(); + for (auto &[key, value] : row) { + auto [ret, val] = rows.Get(index, ValuesBuckets::FieldType(key)); + ASSERT_EQ(ret, E_OK); + ASSERT_TRUE(val.get() == value); + } + index++; + } + int32_t rowCount = 0; + errCode = resultSet->GetRowCount(rowCount); + ASSERT_EQ(errCode, E_OK); + ASSERT_EQ(rows.RowSize(), size_t(rowCount)); +} + +/* * + * @tc.name: Update_001 + * @tc.desc: update test set(id=?,...) + * @tc.type: FUNC + */ +HWTEST_F(RdbTransDBTest, Update_001, TestSize.Level1) +{ + ValuesBucket row = row_; + int32_t changed = -1; + auto [errCode, rowId] = transDB_->Insert(TABLE_NAME, row); + ASSERT_EQ(errCode, E_OK); + ASSERT_EQ(rowId, 1); + row.Put("name", "xiaohua"); + row.Put("attachment", + ValueObject(AssetValue{ .id = "119", .name = "picture1", .hash = "111", .path = "/data/test" })); + std::tie(errCode, changed) = transDB_->Update(TABLE_NAME, row); + ASSERT_EQ(errCode, E_OK); + auto resultSet = transDB_->QueryByStep("select * from TEST"); + ASSERT_NE(resultSet, nullptr); + errCode = resultSet->GoToNextRow(); + ASSERT_EQ(errCode, E_OK); + RowEntity rowEntity; + errCode = resultSet->GetRow(rowEntity); + ASSERT_EQ(errCode, E_OK); + SqliteSqlBuilder::UpdateAssetStatus(row.values_["attachment"], AssetValue::STATUS_UPDATE); + ASSERT_TRUE(row.values_ == rowEntity.Get()); +} + +/* * + * @tc.name: Update_002 + * @tc.desc: update test set(id=?,...) where id > ? and id < ? + * @tc.type: FUNC + */ +HWTEST_F(RdbTransDBTest, Update_002, TestSize.Level1) +{ + int64_t changedNum = -1; + std::vector rows; + for (int i = 0; i < 20; i++) { + ValuesBucket row = row_; + row.Put("id", i); + row.Put("name", "xiaoming_" + std::to_string(i)); + row.Put("years", BigInteger(i % 2, { 128, 225 })); + rows.push_back(std::move(row)); + } + auto errCode = transDB_->BatchInsert(changedNum, TABLE_NAME, rows); + ASSERT_EQ(errCode, E_OK); + ASSERT_EQ(changedNum, 20); + auto updateRow = row_; + updateRow.values_.erase("id"); + updateRow.Put("attachment", + ValueObject(AssetValue{ .id = "119", .name = "picture1", .hash = "111", .path = "/data/test" })); + int32_t updatedNum = -1; + std::tie(errCode, updatedNum) = transDB_->Update(TABLE_NAME, updateRow, "id > ? and id < ?", { 0, 10 }); + ASSERT_EQ(errCode, E_OK); + ASSERT_EQ(updatedNum, 9); + auto resultSet = transDB_->QueryByStep("select * from TEST where id > ? and id < ? order by id", { 0, 10 }); + ASSERT_NE(resultSet, nullptr); + SqliteSqlBuilder::UpdateAssetStatus(updateRow.values_["attachment"], AssetValue::STATUS_UPDATE); + SqliteSqlBuilder::UpdateAssetStatus(updateRow.values_["attachments"], AssetValue::STATUS_INSERT); + size_t index = 0; + while (resultSet->GoToNextRow() == E_OK) { + RowEntity rowEntity; + errCode = resultSet->GetRow(rowEntity); + ASSERT_EQ(errCode, E_OK); + auto row = rowEntity.Steal(); + row.erase("id"); + ASSERT_TRUE(updateRow.values_ == row); + index++; + } + ASSERT_EQ(index, 9); +} + +/* * + * @tc.name: Update_003 + * @tc.desc: update test set(id=?,...) where id > ? and id < ? + * @tc.type: FUNC + */ +HWTEST_F(RdbTransDBTest, Update_003, TestSize.Level1) +{ + int64_t changedNum = -1; + std::vector rows; + for (int i = 0; i < 20; i++) { + ValuesBucket row = row_; + row.Put("id", i); + row.Put("name", "xiaoming_" + std::to_string(i)); + row.Put("years", BigInteger(i % 2, { 128, 225 })); + rows.push_back(std::move(row)); + } + auto errCode = transDB_->BatchInsert(changedNum, TABLE_NAME, rows); + ASSERT_EQ(errCode, E_OK); + ASSERT_EQ(changedNum, 20); + auto updateRow = row_; + updateRow.values_.erase("id"); + updateRow.Put("attachment", + ValueObject(AssetValue{ .id = "119", .name = "picture1", .hash = "111", .path = "/data/test" })); + int32_t updatedNum = -1; + std::tie(errCode, updatedNum) = transDB_->Update(TABLE_NAME, updateRow, "id > ? and id < ?", { 0, 10 }, + ConflictResolution::ON_CONFLICT_ROLLBACK); + ASSERT_EQ(errCode, E_OK); + ASSERT_EQ(updatedNum, 9); + auto resultSet = transDB_->QueryByStep("select * from TEST where id > ? and id < ? order by id", { 0, 10 }); + ASSERT_NE(resultSet, nullptr); + SqliteSqlBuilder::UpdateAssetStatus(updateRow.values_["attachment"], AssetValue::STATUS_UPDATE); + SqliteSqlBuilder::UpdateAssetStatus(updateRow.values_["attachments"], AssetValue::STATUS_INSERT); + size_t index = 0; + while (resultSet->GoToNextRow() == E_OK) { + RowEntity rowEntity; + errCode = resultSet->GetRow(rowEntity); + ASSERT_EQ(errCode, E_OK); + auto row = rowEntity.Steal(); + row.erase("id"); + ASSERT_TRUE(updateRow.values_ == row); + index++; + } + ASSERT_EQ(index, 9); +} + +/* * + * @tc.name: Update_004 + * @tc.desc: update test set(id=?,...) + * @tc.type: FUNC + */ +HWTEST_F(RdbTransDBTest, Update_004, TestSize.Level1) +{ + ValuesBucket row = row_; + int32_t changed = -1; + auto [errCode, rowId] = transDB_->Insert(TABLE_NAME, row); + ASSERT_EQ(errCode, E_OK); + ASSERT_EQ(rowId, 1); + row.Put("name", "xiaohua"); + row.Put("attachment", + ValueObject(AssetValue{ .id = "119", .name = "picture1", .hash = "111", .path = "/data/test" })); + errCode = transDB_->Update(changed, TABLE_NAME, row); + ASSERT_EQ(errCode, E_OK); + auto resultSet = transDB_->QueryByStep("select * from TEST"); + ASSERT_NE(resultSet, nullptr); + errCode = resultSet->GoToNextRow(); + ASSERT_EQ(errCode, E_OK); + RowEntity rowEntity; + errCode = resultSet->GetRow(rowEntity); + ASSERT_EQ(errCode, E_OK); + SqliteSqlBuilder::UpdateAssetStatus(row.values_["attachment"], AssetValue::STATUS_UPDATE); + ASSERT_TRUE(row.values_ == rowEntity.Get()); +} + +/* * + * @tc.name: Update_005 + * @tc.desc: update test set(id=?,...) where id > ? and id < ? + * @tc.type: FUNC + */ +HWTEST_F(RdbTransDBTest, Update_005, TestSize.Level1) +{ + int64_t changedNum = -1; + std::vector rows; + for (int i = 0; i < 20; i++) { + ValuesBucket row = row_; + row.Put("id", i); + row.Put("name", "xiaoming_" + std::to_string(i)); + row.Put("years", BigInteger(i % 2, { 128, 225 })); + rows.push_back(std::move(row)); + } + auto errCode = transDB_->BatchInsert(changedNum, TABLE_NAME, rows); + ASSERT_EQ(errCode, E_OK); + ASSERT_EQ(changedNum, 20); + auto updateRow = row_; + updateRow.values_.erase("id"); + updateRow.Put("attachment", + ValueObject(AssetValue{ .id = "119", .name = "picture1", .hash = "111", .path = "/data/test" })); + int32_t updatedNum = -1; + RdbPredicates rdbPredicates(TABLE_NAME); + rdbPredicates.GreaterThan("id", 0); + rdbPredicates.And(); + rdbPredicates.LessThan("id", 10); + errCode = transDB_->Update(updatedNum, updateRow, rdbPredicates); + ASSERT_EQ(errCode, E_OK); + ASSERT_EQ(updatedNum, 9); + auto resultSet = transDB_->QueryByStep(rdbPredicates); + ASSERT_NE(resultSet, nullptr); + SqliteSqlBuilder::UpdateAssetStatus(updateRow.values_["attachment"], AssetValue::STATUS_UPDATE); + SqliteSqlBuilder::UpdateAssetStatus(updateRow.values_["attachments"], AssetValue::STATUS_INSERT); + size_t index = 0; + while (resultSet->GoToNextRow() == E_OK) { + RowEntity rowEntity; + errCode = resultSet->GetRow(rowEntity); + ASSERT_EQ(errCode, E_OK); + auto row = rowEntity.Steal(); + row.erase("id"); + ASSERT_TRUE(updateRow.values_ == row); + index++; + } + ASSERT_EQ(index, 9); +} + +/* * + * @tc.name: UpdateWithConflictResolution_001 + * @tc.desc: update test set(id=?,...) where id > ? and id < ? + * @tc.type: FUNC + */ +HWTEST_F(RdbTransDBTest, UpdateWithConflictResolution_001, TestSize.Level1) +{ + int64_t changedNum = -1; + std::vector rows; + for (int i = 0; i < 20; i++) { + ValuesBucket row = row_; + row.Put("id", i); + row.Put("name", "xiaoming_" + std::to_string(i)); + row.Put("years", BigInteger(i % 2, { 128, 225 })); + rows.push_back(std::move(row)); + } + auto errCode = transDB_->BatchInsert(changedNum, TABLE_NAME, rows); + ASSERT_EQ(errCode, E_OK); + ASSERT_EQ(changedNum, 20); + auto updateRow = row_; + updateRow.values_.erase("id"); + updateRow.Put("attachment", + ValueObject(AssetValue{ .id = "119", .name = "picture1", .hash = "111", .path = "/data/test" })); + int32_t updatedNum = -1; + errCode = + transDB_->UpdateWithConflictResolution(updatedNum, TABLE_NAME, updateRow, "id > ? and id < ?", { 0, 10 }); + ASSERT_EQ(errCode, E_OK); + ASSERT_EQ(updatedNum, 9); + auto resultSet = transDB_->QueryByStep("select * from TEST where id > ? and id < ? order by id", { 0, 10 }); + ASSERT_NE(resultSet, nullptr); + SqliteSqlBuilder::UpdateAssetStatus(updateRow.values_["attachment"], AssetValue::STATUS_UPDATE); + SqliteSqlBuilder::UpdateAssetStatus(updateRow.values_["attachments"], AssetValue::STATUS_INSERT); + size_t index = 0; + while (resultSet->GoToNextRow() == E_OK) { + RowEntity rowEntity; + errCode = resultSet->GetRow(rowEntity); + ASSERT_EQ(errCode, E_OK); + auto row = rowEntity.Steal(); + row.erase("id"); + ASSERT_TRUE(updateRow.values_ == row); + index++; + } + ASSERT_EQ(index, 9); +} + +/* * + * @tc.name: Delete_001 + * @tc.desc: delete from test where id > ? and id < ? + * @tc.type: FUNC + */ +HWTEST_F(RdbTransDBTest, Delete_001, TestSize.Level1) +{ + int64_t changedNum = -1; + std::vector rows; + for (int i = 0; i < 20; i++) { + ValuesBucket row = row_; + row.Put("id", i); + row.Put("name", "xiaoming_" + std::to_string(i)); + row.Put("years", BigInteger(i % 2, { 128, 225 })); + rows.push_back(std::move(row)); + } + auto errCode = transDB_->BatchInsert(changedNum, TABLE_NAME, rows); + ASSERT_EQ(errCode, E_OK); + ASSERT_EQ(changedNum, 20); + int32_t deleteNum = -1; + RdbPredicates rdbPredicates(TABLE_NAME); + rdbPredicates.GreaterThan("id", 0); + rdbPredicates.And(); + rdbPredicates.LessThan("id", 10); + errCode = transDB_->Delete(deleteNum, rdbPredicates); + ASSERT_EQ(errCode, E_OK); + ASSERT_EQ(deleteNum, 9); + auto resultSet = transDB_->QueryByStep(rdbPredicates); + ASSERT_NE(resultSet, nullptr); + int32_t count = -1; + errCode = resultSet->GetRowCount(count); + ASSERT_EQ(errCode, E_OK); + ASSERT_EQ(count, 0); +} + +/* * + * @tc.name: Delete_002 + * @tc.desc: delete from test where id > ? and id < ? + * @tc.type: FUNC + */ +HWTEST_F(RdbTransDBTest, Delete_002, TestSize.Level1) +{ + int64_t changedNum = -1; + std::vector rows; + for (int i = 0; i < 20; i++) { + ValuesBucket row = row_; + row.Put("id", i); + row.Put("name", "xiaoming_" + std::to_string(i)); + row.Put("years", BigInteger(i % 2, { 128, 225 })); + rows.push_back(std::move(row)); + } + auto errCode = transDB_->BatchInsert(changedNum, TABLE_NAME, rows); + ASSERT_EQ(errCode, E_OK); + ASSERT_EQ(changedNum, 20); + int32_t deleteNum = -1; + errCode = transDB_->Delete(deleteNum, TABLE_NAME, "id > ? and id < ?", { 0, 10 }); + ASSERT_EQ(errCode, E_OK); + ASSERT_EQ(deleteNum, 9); + auto resultSet = transDB_->QueryByStep("select * from TEST where id > ? and id < ? order by id", { 0, 10 }); + ASSERT_NE(resultSet, nullptr); + int32_t count = -1; + errCode = resultSet->GetRowCount(count); + ASSERT_EQ(errCode, E_OK); + ASSERT_EQ(count, 0); +} + +/* * + * @tc.name: QueryByStep_001 + * @tc.desc: select id, name, yeas from test where id > ? and id < ? order by id asc + * @tc.type: FUNC + */ +HWTEST_F(RdbTransDBTest, QueryByStep_001, TestSize.Level1) +{ + int64_t changedNum = -1; + std::vector rows; + for (int i = 0; i < 20; i++) { + ValuesBucket row = row_; + row.Put("id", i); + row.Put("name", "xiaoming_" + std::to_string(i)); + row.Put("years", BigInteger(i % 2, { 128, 225 })); + rows.push_back(std::move(row)); + } + auto errCode = transDB_->BatchInsert(changedNum, TABLE_NAME, rows); + ASSERT_EQ(errCode, E_OK); + ASSERT_EQ(changedNum, 20); + RdbPredicates rdbPredicates(TABLE_NAME); + rdbPredicates.GreaterThan("id", 0); + rdbPredicates.And(); + rdbPredicates.LessThan("id", 10); + rdbPredicates.OrderByAsc("id"); + auto resultSet = transDB_->QueryByStep(rdbPredicates, { "id", "name", "years" }); + ASSERT_NE(resultSet, nullptr); + int64_t index = 1; + while (resultSet->GoToNextRow() == E_OK) { + RowEntity rowEntity; + errCode = resultSet->GetRow(rowEntity); + ASSERT_EQ(errCode, E_OK); + auto row = rowEntity.Steal(); + ASSERT_TRUE(row.size() == 3); + ASSERT_TRUE(row["id"] == ValueObject(index)); + ASSERT_TRUE(row["name"] == ValueObject("xiaoming_" + std::to_string(index))); + ASSERT_TRUE(row["years"] == ValueObject(BigInteger(index % 2, { 128, 225 }))); + index++; + } + int32_t count = -1; + errCode = resultSet->GetRowCount(count); + ASSERT_EQ(errCode, E_OK); + ASSERT_EQ(count, 9); +} + +/* * + * @tc.name: Query_001 + * @tc.desc: select id, name, yeas from test where id > ? and id < ? order by id asc + * @tc.type: FUNC + */ +HWTEST_F(RdbTransDBTest, Query_001, TestSize.Level1) +{ + int64_t changedNum = -1; + std::vector rows; + for (int i = 0; i < 20; i++) { + ValuesBucket row = row_; + row.Put("id", i); + row.Put("name", "xiaoming_" + std::to_string(i)); + row.Put("years", BigInteger(i % 2, { 128, 225 })); + rows.push_back(std::move(row)); + } + auto errCode = transDB_->BatchInsert(changedNum, TABLE_NAME, rows); + ASSERT_EQ(errCode, E_OK); + ASSERT_EQ(changedNum, 20); + RdbPredicates rdbPredicates(TABLE_NAME); + rdbPredicates.GreaterThan("id", 0); + rdbPredicates.And(); + rdbPredicates.LessThan("id", 10); + rdbPredicates.OrderByAsc("id"); + auto resultSet = transDB_->Query(rdbPredicates, { "id", "name", "years" }); + ASSERT_NE(resultSet, nullptr); + int64_t index = 1; + while (resultSet->GoToNextRow() == E_OK) { + RowEntity rowEntity; + errCode = resultSet->GetRow(rowEntity); + ASSERT_EQ(errCode, E_OK); + auto row = rowEntity.Steal(); + ASSERT_TRUE(row.size() == 3); + ASSERT_TRUE(row["id"] == ValueObject(index)); + ASSERT_TRUE(row["name"] == ValueObject("xiaoming_" + std::to_string(index))); + ASSERT_TRUE(row["years"] == ValueObject(BigInteger(index % 2, { 128, 225 }))); + index++; + } + int32_t count = -1; + errCode = resultSet->GetRowCount(count); + ASSERT_EQ(errCode, E_OK); + ASSERT_EQ(count, 9); +} + +/* * + * @tc.name: QuerySql_001 + * @tc.desc: select * from test where id > ? and id < ? order by id asc + * @tc.type: FUNC + */ +HWTEST_F(RdbTransDBTest, QuerySql_001, TestSize.Level1) +{ + int64_t changedNum = -1; + std::vector rows; + for (int i = 0; i < 20; i++) { + ValuesBucket row = row_; + row.Put("id", i); + row.Put("name", "xiaoming_" + std::to_string(i)); + row.Put("years", BigInteger(i % 2, { 128, 225 })); + rows.push_back(std::move(row)); + } + auto errCode = transDB_->BatchInsert(changedNum, TABLE_NAME, rows); + ASSERT_EQ(errCode, E_OK); + ASSERT_EQ(changedNum, 20); + auto resultSet = transDB_->QuerySql("select * from TEST where id > ? and id < ? order by id", { 0, 10 }); + ASSERT_NE(resultSet, nullptr); + int64_t index = 1; + while (resultSet->GoToNextRow() == E_OK) { + RowEntity rowEntity; + errCode = resultSet->GetRow(rowEntity); + ASSERT_EQ(errCode, E_OK); + auto row = rowEntity.Steal(); + ASSERT_TRUE(row["id"] == ValueObject(index)); + ASSERT_TRUE(row["name"] == ValueObject("xiaoming_" + std::to_string(index))); + ASSERT_TRUE(row["years"] == ValueObject(BigInteger(index % 2, { 128, 225 }))); + index++; + } + int32_t count = -1; + errCode = resultSet->GetRowCount(count); + ASSERT_EQ(errCode, E_OK); + ASSERT_EQ(count, 9); +} + +/* * + * @tc.name: Execute_001 + * @tc.desc: PRAGMA user_version + * @tc.type: FUNC + */ +HWTEST_F(RdbTransDBTest, Execute_PRAGMA_001, TestSize.Level1) +{ + auto [errCode, value] = transDB_->Execute("PRAGMA user_version=100"); + ASSERT_EQ(errCode, E_OK); + std::tie(errCode, value) = transDB_->Execute("PRAGMA user_version"); + ASSERT_EQ(errCode, E_OK); + ASSERT_TRUE(value == ValueObject(100)); +} + +/* * + * @tc.name: Execute_DDL_001 + * @tc.desc: PRAGMA user_version + * @tc.type: FUNC + */ +HWTEST_F(RdbTransDBTest, Execute_DDL_001, TestSize.Level1) +{ + auto [errCode, value] = transDB_->Execute("PRAGMA schema_version"); + ASSERT_EQ(errCode, E_OK); + ASSERT_NE(value, ValueObject()); + auto oldVer = value; + std::tie(errCode, value) = transDB_->Execute("CREATE TABLE IF NOT EXISTS TEST1 (id INT PRIMARY KEY, name TEXT)"); + ASSERT_EQ(errCode, E_OK); + ASSERT_TRUE(value == ValueObject()); + std::tie(errCode, value) = transDB_->Execute("DROP TABLE IF EXISTS TEST1"); + ASSERT_EQ(errCode, E_OK); + ASSERT_TRUE(value == ValueObject()); + std::tie(errCode, value) = transDB_->Execute("PRAGMA schema_version"); + ASSERT_EQ(errCode, E_OK); + ASSERT_FALSE(value == ValueObject()); + ASSERT_FALSE(value == oldVer); +} + +/* * + * @tc.name: Execute_Insert_001 + * @tc.desc: INSERT INTO TEST(id, name) VALUES(?,?) + * @tc.type: FUNC + */ +HWTEST_F(RdbTransDBTest, Execute_Insert_001, TestSize.Level1) +{ + auto [errCode, value] = transDB_->Execute("INSERT INTO TEST(id, name) VALUES (?,?)", { 100, "xiaohong" }); + ASSERT_EQ(errCode, E_OK); + ASSERT_EQ(value, ValueObject(1)); + auto resultSet = transDB_->QueryByStep("select * from TEST where id == ?", RdbStore::Values{ 100 }); + ASSERT_NE(resultSet, nullptr); + errCode = resultSet->GoToNextRow(); + ASSERT_EQ(errCode, E_OK); + RowEntity rowEntity; + errCode = resultSet->GetRow(rowEntity); + ASSERT_EQ(errCode, E_OK); + auto row = rowEntity.Steal(); + ASSERT_TRUE(row["id"] == ValueObject(100)); + ASSERT_TRUE(row["name"] == ValueObject("xiaohong")); + ASSERT_TRUE(row["years"] == ValueObject()); + int32_t count = -1; + errCode = resultSet->GetRowCount(count); + ASSERT_EQ(errCode, E_OK); + ASSERT_EQ(count, 1); +} + +/* * + * @tc.name: Execute_Insert_002 + * @tc.desc: INSERT OR IGNORE INTO TEST(id, name) VALUES(?,?) + * @tc.type: FUNC + */ +HWTEST_F(RdbTransDBTest, Execute_Insert_002, TestSize.Level1) +{ + auto [errCode, value] = transDB_->Execute("INSERT INTO TEST(id, name) VALUES (?,?)", { 100, "xiaohong" }); + ASSERT_EQ(errCode, E_OK); + ASSERT_EQ(value, ValueObject(1)); + std::tie(errCode, value) = transDB_->Execute( + "INSERT OR IGNORE INTO TEST(id, name) VALUES (?,?)", { 100, "xiaoming" }); + ASSERT_EQ(errCode, E_OK); + ASSERT_EQ(value, ValueObject(-1)); + auto resultSet = transDB_->QueryByStep("select * from TEST where id == ?", RdbStore::Values{ 100 }); + ASSERT_NE(resultSet, nullptr); + errCode = resultSet->GoToNextRow(); + ASSERT_EQ(errCode, E_OK); + RowEntity rowEntity; + errCode = resultSet->GetRow(rowEntity); + ASSERT_EQ(errCode, E_OK); + auto row = rowEntity.Steal(); + ASSERT_TRUE(row["id"] == ValueObject(100)); + ASSERT_TRUE(row["name"] == ValueObject("xiaohong")); + int32_t count = -1; + errCode = resultSet->GetRowCount(count); + ASSERT_EQ(errCode, E_OK); + ASSERT_EQ(count, 1); +} + +/* * + * @tc.name: Execute_Update_001 + * @tc.desc: UPDATE TEST SET id=?, name=? + * @tc.type: FUNC + */ +HWTEST_F(RdbTransDBTest, Execute_Update_001, TestSize.Level1) +{ + auto [errCode, value] = transDB_->Execute("INSERT INTO TEST(id, name) VALUES (?,?)", { 100, "xiaohong" }); + ASSERT_EQ(errCode, E_OK); + ASSERT_EQ(value, ValueObject(1)); + std::tie(errCode, value) = transDB_->Execute("UPDATE TEST SET id=?, name=?", { 100, "xiaoming" }); + ASSERT_EQ(errCode, E_OK); + ASSERT_EQ(value, ValueObject(1)); + auto resultSet = transDB_->QueryByStep("select * from TEST where id == ?", RdbStore::Values{ 100 }); + ASSERT_NE(resultSet, nullptr); + errCode = resultSet->GoToNextRow(); + ASSERT_EQ(errCode, E_OK); + RowEntity rowEntity; + errCode = resultSet->GetRow(rowEntity); + ASSERT_EQ(errCode, E_OK); + auto row = rowEntity.Steal(); + ASSERT_TRUE(row["id"] == ValueObject(100)); + ASSERT_TRUE(row["name"] == ValueObject("xiaoming")); + int32_t count = -1; + errCode = resultSet->GetRowCount(count); + ASSERT_EQ(errCode, E_OK); + ASSERT_EQ(count, 1); +} + +/* * + * @tc.name: Execute_Transaction_001 + * @tc.desc: UPDATE TEST SET(id=?, name=?) + * @tc.type: FUNC + */ +HWTEST_F(RdbTransDBTest, Execute_Transaction_001, TestSize.Level1) +{ + auto [errCode, value] = transDB_->Execute("BEGIN"); + ASSERT_EQ(errCode, E_OK); + ASSERT_TRUE(value == ValueObject()); + std::tie(errCode, value) = transDB_->Execute("INSERT INTO TEST(id, name) VALUES (?,?)", { 100, "xiaohong" }); + ASSERT_EQ(errCode, E_OK); + ASSERT_TRUE(value == ValueObject(1)); + auto resultSet = transDB_->QueryByStep("select * from TEST where id == ?", RdbStore::Values{ 100 }); + ASSERT_NE(resultSet, nullptr); + int32_t count = -1; + errCode = resultSet->GetRowCount(count); + ASSERT_EQ(errCode, E_OK); + ASSERT_EQ(count, 1); + std::tie(errCode, value) = transDB_->Execute("ROLLBACK"); + ASSERT_EQ(errCode, E_OK); + resultSet = transDB_->QueryByStep("select * from TEST where id == ?", RdbStore::Values{ 100 }); + ASSERT_NE(resultSet, nullptr); + count = -1; + errCode = resultSet->GetRowCount(count); + ASSERT_EQ(errCode, E_OK); + ASSERT_EQ(count, 0); +} + +/* * + * @tc.name: Execute_Transaction_002 + * @tc.desc: BEGIN, COMMIT, ROLLBACK + * @tc.type: FUNC + */ +HWTEST_F(RdbTransDBTest, Execute_Transaction_002, TestSize.Level1) +{ + auto [errCode, value] = transDB_->Execute("BEGIN"); + ASSERT_EQ(errCode, E_OK); + ASSERT_TRUE(value == ValueObject()); + std::tie(errCode, value) = transDB_->Execute("INSERT INTO TEST(id, name) VALUES (?,?)", { 100, "xiaohong" }); + ASSERT_EQ(errCode, E_OK); + ASSERT_TRUE(value == ValueObject(1)); + std::tie(errCode, value) = transDB_->Execute("COMMIT"); + auto resultSet = transDB_->QueryByStep("select * from TEST where id == ?", RdbStore::Values{ 100 }); + ASSERT_NE(resultSet, nullptr); + int32_t count = -1; + errCode = resultSet->GetRowCount(count); + ASSERT_EQ(errCode, E_OK); + ASSERT_EQ(count, 1); + std::tie(errCode, value) = transDB_->Execute("ROLLBACK"); + resultSet = transDB_->QueryByStep("select * from TEST where id == ?", RdbStore::Values{ 100 }); + ASSERT_NE(resultSet, nullptr); + count = -1; + errCode = resultSet->GetRowCount(count); + ASSERT_EQ(errCode, E_OK); + ASSERT_EQ(count, 1); +} + +/* * + * @tc.name: Execute_INVALID_001 + * @tc.desc: attach detach select and etc. + * @tc.type: FUNC + */ +HWTEST_F(RdbTransDBTest, Execute_INVALID_001, TestSize.Level1) +{ + auto [errCode, value] = transDB_->Execute(" ATTACH DATABASE ? AS ? ", { "/data/test/a.db", "a" }); + ASSERT_EQ(errCode, E_INVALID_ARGS); + std::tie(errCode, value) = transDB_->Execute(" DETACH DATABASE ?", { "/data/test/a.db" }); + ASSERT_EQ(errCode, E_INVALID_ARGS); + std::tie(errCode, value) = transDB_->Execute(" select * from TEST where id == ?", RdbStore::Values{ 100 }); + ASSERT_EQ(errCode, E_INVALID_ARGS); +} + +/* * + * @tc.name: QueryByStep_ThreadSafe_001 + * @tc.desc: multi-thread use resultSet and closed etc. + * @tc.type: FUNC + */ +HWTEST_F(RdbTransDBTest, QueryByStep_ThreadSafe_001, TestSize.Level1) +{ + ValuesBucket row = row_; + auto [errCode, rowId] = transDB_->Insert(TABLE_NAME, row); + ASSERT_EQ(errCode, E_OK); + ASSERT_EQ(rowId, 1); + auto resultSet = transDB_->QueryByStep("select * from TEST"); + ASSERT_NE(resultSet, nullptr); + errCode = resultSet->GoToNextRow(); + ASSERT_EQ(errCode, E_OK); + std::shared_ptr threads[4]; + for (int i = 0; i < 4; ++i) { + threads[i] = std::make_shared([resultSet]() { + RowEntity rowEntity; + while (resultSet->GetRow(rowEntity) != E_ALREADY_CLOSED) { + }; + }); + } + usleep(200); + resultSet->Close(); + for (int i = 0; i < 4; ++i) { + if (threads[i] == nullptr) { + continue; + } + threads[i]->join(); + threads[i] = nullptr; + } +} +} // namespace Test diff --git a/relational_store/test/native/rdb/unittest/rdb_update_test.cpp b/relational_store/test/native/rdb/unittest/rdb_update_test.cpp index 83319dffee8127ae0a700e0ff224b61c873b8f1f..f0f581dc615a54c1527887ee3c35fb6d055c366e 100644 --- a/relational_store/test/native/rdb/unittest/rdb_update_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_update_test.cpp @@ -748,8 +748,8 @@ HWTEST_F(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_007, TestSize { std::shared_ptr &store = RdbStoreUpdateTest::store; - int changedRows; - int64_t id; + int changedRows = 0; + int64_t id = -1; ValuesBucket values; int ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); diff --git a/relational_store/test/native/rdb/unittest/sqlite_utils_test.cpp b/relational_store/test/native/rdb/unittest/sqlite_utils_test.cpp index 0cebc8f917e4ce8c9f4c2a66f2866bbe1a4e11b7..d528681c153f4265974b1eccd8962a35301bdc94 100644 --- a/relational_store/test/native/rdb/unittest/sqlite_utils_test.cpp +++ b/relational_store/test/native/rdb/unittest/sqlite_utils_test.cpp @@ -61,7 +61,7 @@ HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_004, TestSize.Level1) HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_005, TestSize.Level1) { - EXPECT_EQ(SqliteUtils::Anonymous("rdb_30005_test.db"), "rdb_***005_test.db"); + EXPECT_EQ(SqliteUtils::Anonymous("rdb_30005_test.db"), "rdb_30005_test.db"); } HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_006, TestSize.Level1) @@ -118,15 +118,46 @@ HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_0014, TestSize.Level1) HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_0015, TestSize.Level1) { - EXPECT_EQ(SqliteUtils::Anonymous("K23edfK.db"), "K***edfK.db"); + EXPECT_EQ(SqliteUtils::Anonymous("K23edfK.db"), "K23edfK.db"); } HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_0016, TestSize.Level1) { - EXPECT_EQ(SqliteUtils::Anonymous("__23edf__.db"), "__***edf__.db"); + EXPECT_EQ(SqliteUtils::Anonymous("__23edf__.db"), "__23edf__.db"); } HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_0017, TestSize.Level1) { EXPECT_EQ(SqliteUtils::Anonymous("K3edfK.db"), "K3edfK.db"); +} + +HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_0018, TestSize.Level1) +{ + EXPECT_EQ(SqliteUtils::Anonymous("K23564edfK.db"), "K***4edfK.db"); +} + +HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_0019, TestSize.Level1) +{ + EXPECT_EQ(SqliteUtils::Anonymous("K235648edfK.db"), "K***8edfK.db"); +} + +HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_0020, TestSize.Level1) +{ + EXPECT_EQ(SqliteUtils::Anonymous("K2356489edfK.db"), "K***9edfK.db"); +} + +HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_0021, TestSize.Level1) +{ + EXPECT_EQ(SqliteUtils::Anonymous("linker_reborn.db-wal"), "linker_reborn.db-wal"); +} + +HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_0022, TestSize.Level1) +{ + EXPECT_EQ(SqliteUtils::Anonymous("linker_grow.db-wal"), "linker_grow.db-wal"); +} + +HWTEST_F(SqliteUtilsTest, SqliteUtils_Test_0023, TestSize.Level1) +{ + EXPECT_EQ(SqliteUtils::Anonymous("file /data/stage/el2/database/rdb/ddddddd/linker_reborn.db-wal"), + "file /***/el2/***/linker_reborn.db-wal"); } \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/transaction_test.cpp b/relational_store/test/native/rdb/unittest/transaction_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c4e325e73e498cb9b1d629c3851edf68ac24115f --- /dev/null +++ b/relational_store/test/native/rdb/unittest/transaction_test.cpp @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2022 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 "common.h" +#include "rdb_errno.h" +#include "rdb_helper.h" +#include "rdb_open_callback.h" + +using namespace testing::ext; +using namespace OHOS::NativeRdb; + +static const std::string DATABASE_NAME = RDB_TEST_PATH + "transaction_test.db"; +static const char CREATE_TABLE_SQL[] = + "CREATE TABLE IF NOT EXISTS test " + "(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, age INTEGER, salary REAL, blobType BLOB)"; + +class TransactionTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; + + static inline std::shared_ptr store_; + + class TransactionTestOpenCallback : public RdbOpenCallback { + public: + int OnCreate(RdbStore &store) override; + int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override; + }; +}; + + +int TransactionTest::TransactionTestOpenCallback::OnCreate(RdbStore &store) +{ + auto [ret, value] = store.Execute(CREATE_TABLE_SQL); + return ret; +} + +int TransactionTest::TransactionTestOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) +{ + return E_OK; +} + +void TransactionTest::SetUpTestCase() +{ + int errCode = E_OK; + RdbHelper::DeleteRdbStore(DATABASE_NAME); + RdbStoreConfig config(DATABASE_NAME); + TransactionTestOpenCallback helper; + TransactionTest::store_ = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(TransactionTest::store_, nullptr); + EXPECT_EQ(errCode, E_OK); +} + +void TransactionTest::TearDownTestCase() +{ + store_ = nullptr; + RdbHelper::DeleteRdbStore(DATABASE_NAME); +} + +void TransactionTest::SetUp() +{ + store_->Execute("DELETE FROM test"); +} + +void TransactionTest::TearDown() +{ +} + +/** + * @tc.name: RdbStore_Transaction_001 + * @tc.desc: createTransaction and commit + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_001, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + auto [ret, transaction] = store->CreateTransaction(Transaction::EXCLUSIVE); + EXPECT_EQ(ret, E_OK); + EXPECT_NE(transaction, nullptr); + + auto result = transaction->Insert("test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + EXPECT_EQ(result.first, E_OK); + EXPECT_EQ(1, result.second); + + result = transaction->Insert("test", UTUtils::SetRowData(UTUtils::g_rowData[1])); + EXPECT_EQ(result.first, E_OK); + EXPECT_EQ(2, result.second); + + result = store->Insert("test", UTUtils::SetRowData(UTUtils::g_rowData[2]), RdbStore::NO_ACTION); + EXPECT_EQ(result.first, E_SQLITE_BUSY); + + auto resultSet = transaction->QueryByStep("SELECT * FROM test"); + EXPECT_NE(resultSet, nullptr); + if (resultSet != nullptr) { + int32_t rowCount{}; + ret = resultSet->GetRowCount(rowCount); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(rowCount, 2); + } + + ret = transaction->Commit(); + EXPECT_EQ(ret, E_OK); + + if (resultSet != nullptr) { + ValueObject value; + ret = resultSet->Get(0, value); + EXPECT_EQ(ret, E_ALREADY_CLOSED); + } + + result = store->Insert("test", UTUtils::SetRowData(UTUtils::g_rowData[2]), RdbStore::NO_ACTION); + EXPECT_EQ(result.first, E_OK); + EXPECT_EQ(3, result.second); + + result = transaction->Insert("test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + EXPECT_EQ(result.first, E_ALREADY_CLOSED); + + resultSet = store->QueryByStep("SELECT * FROM test"); + EXPECT_NE(resultSet, nullptr); + if (resultSet != nullptr) { + int32_t rowCount{}; + resultSet->GetRowCount(rowCount); + EXPECT_EQ(rowCount, 3); + } +} + +/** + * @tc.name: RdbStore_Transaction_002 + * @tc.desc: createTransaction and rollback + * @tc.type: FUNC + */ +HWTEST_F(TransactionTest, RdbStore_Transaction_002, TestSize.Level1) +{ + std::shared_ptr &store = TransactionTest::store_; + + auto [ret, transaction] = store->CreateTransaction(Transaction::EXCLUSIVE); + EXPECT_EQ(ret, E_OK); + EXPECT_NE(transaction, nullptr); + + auto result = transaction->Insert("test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + EXPECT_EQ(result.first, E_OK); + EXPECT_EQ(1, result.second); + + result = transaction->Insert("test", UTUtils::SetRowData(UTUtils::g_rowData[1])); + EXPECT_EQ(result.first, E_OK); + EXPECT_EQ(2, result.second); + + ret = transaction->Rollback(); + EXPECT_EQ(ret, E_OK); + + auto resultSet = store->QueryByStep("SELECT * FROM test"); + EXPECT_NE(resultSet, nullptr); + if (resultSet != nullptr) { + int32_t rowCount{}; + ret = resultSet->GetRowCount(rowCount); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(rowCount, 0); + } + + result = store->Insert("test", UTUtils::SetRowData(UTUtils::g_rowData[2]), RdbStore::NO_ACTION); + EXPECT_EQ(result.first, E_OK); + EXPECT_EQ(3, result.second); + + result = transaction->Insert("test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + EXPECT_EQ(result.first, E_ALREADY_CLOSED); + + resultSet = store->QueryByStep("SELECT * FROM test"); + EXPECT_NE(resultSet, nullptr); + if (resultSet != nullptr) { + int32_t rowCount{}; + ret = resultSet->GetRowCount(rowCount); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(rowCount, 1); + } +} diff --git a/relational_store/test/native/relational_store_test/unittest/rdb_store_test.cpp b/relational_store/test/native/relational_store_test/unittest/rdb_store_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e898d8e9d5127a2f0d8899d7dea89bb2d3c3f666 --- /dev/null +++ b/relational_store/test/native/relational_store_test/unittest/rdb_store_test.cpp @@ -0,0 +1,1987 @@ +/* + * Copyright (c) 2021 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 "rdb_store_impl.h" + +#include + +#include +#include + +#include "common.h" +#include "rdb_errno.h" +#include "rdb_helper.h" +#include "rdb_open_callback.h" +#include "relational_store_delegate.h" +#include "relational_store_manager.h" +#include "sqlite_connection.h" + +using namespace testing::ext; +using namespace OHOS::NativeRdb; + +class RdbTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + + static const std::string DATABASE_NAME; + +protected: + std::shared_ptr store_; +}; + +const std::string RdbTest::DATABASE_NAME = RDB_TEST_PATH + "stepResultSet_impl_test.db"; + +class RdbTestOpenCallback : public RdbOpenCallback { +public: + int OnCreate(RdbStore &store) override; + int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override; +}; + +int RdbTestOpenCallback::OnCreate(RdbStore &store) +{ + return E_OK; +} + +int RdbTestOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) +{ + return E_OK; +} + +void RdbTest::SetUpTestCase(void) +{ +} + +void RdbTest::TearDownTestCase(void) +{ +} + +void RdbTest::SetUp(void) +{ + store_ = nullptr; + int errCode = RdbHelper::DeleteRdbStore(DATABASE_NAME); + EXPECT_EQ(E_OK, errCode); + RdbStoreConfig config(RdbTest::DATABASE_NAME); + RdbTestOpenCallback helper; + store_ = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store_, nullptr); + EXPECT_EQ(errCode, E_OK); +} + +void RdbTest::TearDown(void) +{ + store_ = nullptr; + RdbHelper::ClearCache(); + int errCode = RdbHelper::DeleteRdbStore(DATABASE_NAME); + EXPECT_EQ(E_OK, errCode); +} + +/* * + * @tc.name: GetModifyTimeByRowIdTest_001 + * @tc.desc: Normal testCase for GetModifyTime, get timestamp by id + * @tc.type: FUNC + */ +HWTEST_F(RdbTest, GetModifyTimeByRowIdTest_001, TestSize.Level2) +{ + store_->ExecuteSql("CREATE TABLE naturalbase_rdb_aux_RdbTest_integer_log " + "(id INTEGER PRIMARY KEY AUTOINCREMENT, timestamp INTEGER, data_key INTEGER, " + "data3 FLOAT, data4 BLOB, data5 BOOLEAN);"); + int64_t rowId; + ValuesBucket valuesBucket; + valuesBucket.PutInt("data_key", ValueObject(1)); + valuesBucket.PutInt("timestamp", ValueObject(1000000000)); + int errorCode = store_->Insert(rowId, "naturalbase_rdb_aux_RdbTest_integer_log", valuesBucket); + EXPECT_EQ(E_OK, errorCode); + EXPECT_EQ(1, rowId); + + std::vector PKey = { 1 }; + std::map result = + store_->GetModifyTime("RdbTest_integer", "ROWID", PKey); + int size = result.size(); + EXPECT_EQ(1, size); + EXPECT_EQ(100000, int64_t(result[1])); + + store_->ExecuteSql("DROP TABLE IF EXISTS naturalbase_rdb_aux_RdbTest_integer_log"); +} + +/* * + * @tc.name: GetModifyTimeByRowIdTest_002 + * @tc.desc: Abnormal testCase for GetModifyTime, get timestamp by id, + * resultSet is empty or table name is not exist + * @tc.type: FUNC + */ +HWTEST_F(RdbTest, GetModifyTimeByRowIdTest_002, TestSize.Level2) +{ + store_->ExecuteSql("CREATE TABLE naturalbase_rdb_aux_RdbTest_integer_log " + "(id INTEGER PRIMARY KEY AUTOINCREMENT, timestamp INTEGER, data_key INTEGER, " + "data3 FLOAT, data4 BLOB, data5 BOOLEAN);"); + int64_t rowId; + ValuesBucket valuesBucket; + valuesBucket.PutInt("data_key", ValueObject(2)); + int errorCode = store_->Insert(rowId, "naturalbase_rdb_aux_RdbTest_integer_log", valuesBucket); + EXPECT_EQ(E_OK, errorCode); + EXPECT_EQ(1, rowId); + + // resultSet is empty + std::vector PKey = { 1 }; + std::map result = + store_->GetModifyTime("RdbTest_integer", "ROWID", PKey); + int size = result.size(); + EXPECT_EQ(0, size); + + // table name is not exist , resultSet is null + result = store_->GetModifyTime("test", "ROWID", PKey); + size = result.size(); + EXPECT_EQ(0, size); + + store_->ExecuteSql("DROP TABLE IF EXISTS naturalbase_rdb_aux_RdbTest_integer_log"); +} + +/* * + * @tc.name: GetModifyTimeByRowIdTest_003 + * @tc.desc: Abnormal testCase for GetModifyTime, get timestamp by id, + * resultSet is empty or table name is not exist + * @tc.type: FUNC + */ +HWTEST_F(RdbTest, GetModifyTimeByRowIdTest_003, TestSize.Level2) +{ + store_->ExecuteSql("CREATE TABLE naturalbase_rdb_aux_RdbTest_integer_log " + "(id INTEGER PRIMARY KEY AUTOINCREMENT, timestamp INTEGER, data_key INTEGER, " + "data3 FLOAT, data4 BLOB, data5 BOOLEAN);"); + int64_t rowId; + ValuesBucket valuesBucket; + valuesBucket.PutInt("data_key", ValueObject(1)); + int errorCode = store_->Insert(rowId, "naturalbase_rdb_aux_RdbTest_integer_log", valuesBucket); + EXPECT_EQ(E_OK, errorCode); + EXPECT_EQ(1, rowId); + + std::vector PKey = { 1 }; + RdbStore::ModifyTime resultMapTmp = store_->GetModifyTime("RdbTest_integer", "ROWID", PKey); + std::map resultMap = std::map(resultMapTmp); + EXPECT_EQ(1, resultMap.size()); + + RdbStore::ModifyTime resultPtrTmp = store_->GetModifyTime("RdbTest_integer", "ROWID", PKey); + std::shared_ptr resultPtr = std::shared_ptr(resultPtrTmp); + int count = 0; + resultPtr->GetRowCount(count); + EXPECT_EQ(1, count); + + RdbStore::ModifyTime result = store_->GetModifyTime("RdbTest_integer", "ROWID", PKey); + RdbStore::PRIKey key = result.GetOriginKey(std::vector{}); + RdbStore::PRIKey monostate = std::monostate(); + EXPECT_EQ(monostate, key); + EXPECT_EQ(8, result.GetMaxOriginKeySize()); + + store_->ExecuteSql("DROP TABLE IF EXISTS naturalbase_rdb_aux_RdbTest_integer_log"); +} + +/* * + * @tc.name: GetModifyTime_001 + * @tc.desc: Abnormal testCase for GetModifyTime, tablename columnName, keys is empty, + * and resultSet is null or empty + * @tc.type: FUNC + */ +HWTEST_F(RdbTest, GetModifyTime_001, TestSize.Level2) +{ + store_->ExecuteSql("CREATE TABLE naturalbase_rdb_aux_RdbTest_integer_log " + "(id INTEGER PRIMARY KEY AUTOINCREMENT, timestamp INTEGER, data_key INTEGER, " + "data3 FLOAT, data4 BLOB, data5 BOOLEAN);"); + + // table name is "" + std::vector PKey = { 1 }; + std::map result = store_->GetModifyTime("", "data_key", PKey); + int size = result.size(); + EXPECT_EQ(0, size); + + // table name is not exist , query resultSet is null + result = store_->GetModifyTime("test", "data_key", PKey); + size = result.size(); + EXPECT_EQ(0, size); + + // columnName is "" + result = store_->GetModifyTime("test", "", PKey); + size = result.size(); + EXPECT_EQ(0, size); + + // keys is empty + std::vector emptyPRIKey; + result = store_->GetModifyTime("test", "data_key", emptyPRIKey); + size = result.size(); + EXPECT_EQ(0, size); + + store_->ExecuteSql("DROP TABLE IF EXISTS naturalbase_rdb_aux_RdbTest_integer_log"); +} + +/* * + * @tc.name: GetModifyTime_002 + * @tc.desc: Abnormal testCase for GetModifyTime, get timestamp by data3 ,if query resultSet is empty + * @tc.type: FUNC + */ +HWTEST_F(RdbTest, GetModifyTime_002, TestSize.Level2) +{ + store_->ExecuteSql("CREATE TABLE naturalbase_rdb_aux_RdbTest_integer_log " + "(id INTEGER PRIMARY KEY AUTOINCREMENT, timestamp INTEGER, hash_key INTEGER, " + "data3 FLOAT, data4 BLOB, data5 BOOLEAN);"); + + std::vector PKey = { 1 }; + std::map result = + store_->GetModifyTime("RdbTest_integer", "data3", PKey); + EXPECT_EQ(0, result.size()); + + store_->ExecuteSql("DROP TABLE IF EXISTS naturalbase_rdb_aux_RdbTest_integer_log"); +} + +/* * + * @tc.name: Rdb_BatchInsertTest_001 + * @tc.desc: Abnormal testCase for BatchInsert, if initialBatchValues is empty + * @tc.type: FUNC + */ +HWTEST_F(RdbTest, Rdb_BatchInsertTest_001, TestSize.Level2) +{ + std::vector valuesBuckets; + int64_t insertNum = 1; + int ret = store_->BatchInsert(insertNum, "test", valuesBuckets); + EXPECT_EQ(0, insertNum); + EXPECT_EQ(E_OK, ret); +} + +/* * + * @tc.name: Rdb_QueryTest_001 + * @tc.desc: Abnormal testCase for Query, if table name is empty + * @tc.type: FUNC + */ +HWTEST_F(RdbTest, Rdb_QueryTest_001, TestSize.Level2) +{ + int errCode = E_OK; + store_->Query(errCode, true, "", {}, "", std::vector{}, "", "", "", 1, 0); + EXPECT_NE(E_OK, errCode); +} + +/* * + * @tc.name: Rdb_QueryTest_002 + * @tc.desc: Normal testCase for Query, get * form test + * @tc.type: FUNC + */ +HWTEST_F(RdbTest, Rdb_QueryTest_002, TestSize.Level2) +{ + store_->ExecuteSql("CREATE TABLE test (id INTEGER PRIMARY KEY AUTOINCREMENT, data1 TEXT, " + "data2 INTEGER, data3 FLOAT, data4 BLOB, data5 BOOLEAN);"); + int errCode = E_OK; + store_->Query(errCode, true, "test", {}, "", std::vector{}, "", "", "", 1, 0); + EXPECT_EQ(E_OK, errCode); + + store_->ExecuteSql("DROP TABLE IF EXISTS test"); +} + +/* * + * @tc.name: Rdb_RemoteQueryTest_001 + * @tc.desc: Abnormal testCase for RemoteQuery + * @tc.type: FUNC + */ +HWTEST_F(RdbTest, Rdb_RemoteQueryTest_001, TestSize.Level2) +{ + int errCode = E_OK; + AbsRdbPredicates predicates("test"); + predicates.EqualTo("id", 1); + + // GetRdbService failed if rdbstoreconfig bundlename_ empty + auto ret = store_->RemoteQuery("", predicates, {}, errCode); + EXPECT_EQ(E_INVALID_ARGS, errCode); + EXPECT_EQ(nullptr, ret); + RdbHelper::DeleteRdbStore(RdbTest::DATABASE_NAME); + + RdbStoreConfig config(RdbTest::DATABASE_NAME); + config.SetName("RdbStore_impl_test.db"); + config.SetBundleName("com.example.distributed.rdb"); + RdbTestOpenCallback helper; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_EQ(E_OK, errCode); + + // GetRdbService succeeded if configuration file has already been configured + ret = store->RemoteQuery("", predicates, {}, errCode); + EXPECT_NE(E_OK, errCode); + EXPECT_EQ(nullptr, ret); + + store = nullptr; + RdbHelper::DeleteRdbStore(RdbTest::DATABASE_NAME); +} + +/* * + * @tc.name: Rdb_RollbackTest_001 + * @tc.desc: Abnormal testCase for Rollback + * @tc.type: FUNC + */ +HWTEST_F(RdbTest, Rdb_RollbackTest_001, TestSize.Level2) +{ + int ret = store_->RollBack(); + EXPECT_EQ(OHOS::NativeRdb::E_NO_TRANSACTION_IN_SESSION, ret); +} + +/* * + * @tc.name: Rdb_CommitTest_001 + * @tc.desc: Abnormal testCase for Commit,if not use BeginTransaction + * @tc.type: FUNC + */ +HWTEST_F(RdbTest, Rdb_CommitTest_001, TestSize.Level2) +{ + int ret = store_->Commit(); + EXPECT_EQ(E_OK, ret); +} + +/* * + * @tc.name: Rdb_BackupTest_001 + * @tc.desc: Abnormal testCase for Backup + * @tc.type: FUNC + */ +HWTEST_F(RdbTest, Rdb_BackupTest_001, TestSize.Level2) +{ + int errCode = E_OK; + std::string databasePath = RDB_TEST_PATH + "test.db"; + std::vector destEncryptKey; + // isEncrypt_ is false, and destEncryptKey is emtpy + errCode = store_->Backup(databasePath, destEncryptKey); + EXPECT_EQ(E_OK, errCode); + RdbHelper::DeleteRdbStore(databasePath); + + // isEncrypt_ is false, and destEncryptKey is not emtpy + destEncryptKey.push_back(1); + errCode = store_->Backup(databasePath, destEncryptKey); + EXPECT_EQ(E_OK, errCode); + store_ = nullptr; + RdbHelper::DeleteRdbStore(DATABASE_NAME); + RdbHelper::DeleteRdbStore(databasePath); + + RdbStoreConfig config(RdbTest::DATABASE_NAME); + config.SetEncryptStatus(true); + RdbTestOpenCallback helper; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_EQ(E_OK, errCode); + + // isEncrypt_ is true, and destEncryptKey is not emtpy + errCode = store->Backup(databasePath, destEncryptKey); + EXPECT_EQ(E_OK, errCode); + RdbHelper::DeleteRdbStore(databasePath); + + // isEncrypt_ is true, and destEncryptKey is not emtpy + destEncryptKey.pop_back(); + errCode = store->Backup(databasePath, destEncryptKey); + EXPECT_EQ(E_OK, errCode); + store = nullptr; + RdbHelper::DeleteRdbStore(databasePath); + RdbHelper::DeleteRdbStore(DATABASE_NAME); +} + +/* * + * @tc.name: Rdb_SqlitConnectionTest_001 + * @tc.desc: Abnormal testCase for SetPageSize, + * return ok if open db again and set same page size + * @tc.type: FUNC + */ +HWTEST_F(RdbTest, Rdb_SqlitConnectionTest_001, TestSize.Level2) +{ + const std::string DATABASE_NAME = RDB_TEST_PATH + "SqlitConnectionOpenTest.db"; + RdbStoreConfig config(DATABASE_NAME); + config.SetReadOnly(false); + config.SetPageSize(1024); + auto [errCode, connection] = Connection::Create(config, true); + EXPECT_NE(nullptr, connection); + auto [err, statement] = connection->CreateStatement("PRAGMA page_size", connection); + auto [error, object] = statement->ExecuteForValue(); + EXPECT_EQ(E_OK, error); + EXPECT_EQ(1024, static_cast(object)); + + std::tie(errCode, connection) = Connection::Create(config, true); + EXPECT_NE(nullptr, connection); +} + +/* * + * @tc.name: Rdb_ConnectionPoolTest_001 + * @tc.desc: Abnormal testCase for ConfigLocale + * @tc.type: FUNC + */ +HWTEST_F(RdbTest, Rdb_ConnectionPoolTest_001, TestSize.Level2) +{ + const std::string DATABASE_NAME = RDB_TEST_PATH + "ConnectionOpenTest.db"; + int errCode = E_OK; + RdbStoreConfig config(DATABASE_NAME); + config.SetReadConSize(1); + config.SetStorageMode(StorageMode::MODE_DISK); + + RdbTestOpenCallback helper; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_EQ(E_OK, errCode); + + auto connectionPool = ConnectionPool::Create(config, errCode); + EXPECT_NE(nullptr, connectionPool); + EXPECT_EQ(E_OK, errCode); + + // connecting database + auto connection = connectionPool->AcquireConnection(true); + EXPECT_NE(nullptr, connection); + errCode = connectionPool->ConfigLocale("AbnormalTest"); + EXPECT_EQ(OHOS::NativeRdb::E_DATABASE_BUSY, errCode); + + store = nullptr; + RdbHelper::DeleteRdbStore(DATABASE_NAME); +} + +/* * + * @tc.name: Rdb_ConnectionPoolTest_002 + * @tc.desc: Abnormal testCase for AcquireConnection/AcquireTransaction + * @tc.type: FUNC + */ +HWTEST_F(RdbTest, Rdb_ConnectionPoolTest_002, TestSize.Level2) +{ + const std::string DATABASE_NAME = RDB_TEST_PATH + "ConnectionTest.db"; + int errCode = E_OK; + RdbStoreConfig config(DATABASE_NAME); + config.SetReadConSize(1); + config.SetStorageMode(StorageMode::MODE_DISK); + auto connectionPool = ConnectionPool::Create(config, errCode); + EXPECT_NE(nullptr, connectionPool); + EXPECT_EQ(E_OK, errCode); + + // repeat AcquireReader without release + auto connection = connectionPool->AcquireConnection(true); + EXPECT_NE(nullptr, connection); + connection = connectionPool->AcquireConnection(true); + EXPECT_NE(nullptr, connection); + connection = connectionPool->AcquireConnection(true); + EXPECT_NE(nullptr, connection); + + // repeat AcquireWriter without release + connection = connectionPool->AcquireConnection(false); + EXPECT_NE(nullptr, connection); + connection = connectionPool->AcquireConnection(false); + EXPECT_EQ(nullptr, connection); + connection = connectionPool->AcquireConnection(false); + EXPECT_NE(nullptr, connection); + + // repeat AcquireTransaction without release + errCode = connectionPool->AcquireTransaction(); + EXPECT_EQ(E_OK, errCode); + errCode = connectionPool->AcquireTransaction(); + EXPECT_NE(E_OK, errCode); + connectionPool->ReleaseTransaction(); +} + +/* * + * @tc.name: Rdb_ConnectionPoolTest_003 + * @tc.desc: Abnormal testCase for ChangeDbFileForRestore + * @tc.type: FUNC + */ +HWTEST_F(RdbTest, Rdb_ConnectionPoolTest_0023, TestSize.Level2) +{ + const std::string DATABASE_NAME = RDB_TEST_PATH + "ConnectionTest.db"; + int errCode = E_OK; + RdbStoreConfig config(DATABASE_NAME); + config.SetReadConSize(1); + config.SetStorageMode(StorageMode::MODE_DISK); + auto connectionPool = ConnectionPool::Create(config, errCode); + EXPECT_NE(nullptr, connectionPool); + EXPECT_EQ(E_OK, errCode); + + const std::string newPath = DATABASE_NAME; + const std::string backupPath = DATABASE_NAME; + const std::vector newKey; + + // newPath == currentPath, writeConnectionUsed == true + auto connection = connectionPool->AcquireConnection(false); + SlaveStatus curStatus; + errCode = connectionPool->ChangeDbFileForRestore(newPath, backupPath, newKey, curStatus); + EXPECT_EQ(E_ERROR, errCode); + connection = nullptr; + // newPath == currentPath + errCode = connectionPool->ChangeDbFileForRestore(newPath, backupPath, newKey, curStatus); + EXPECT_NE(E_OK, errCode); + // newPath != currentPath + const std::string newPath2 = RDB_TEST_PATH + "tmp.db"; + errCode = connectionPool->ChangeDbFileForRestore(newPath2, backupPath, newKey, curStatus); + EXPECT_EQ(E_ERROR, errCode); +} + +HWTEST_F(RdbTest, NotifyDataChangeTest_001, TestSize.Level2) +{ + const std::string DATABASE_NAME = RDB_TEST_PATH + "SqlitConnectionOpenTest.db"; + RdbStoreConfig config(DATABASE_NAME); + config.SetReadOnly(false); + config.SetPageSize(1024); + auto [errCode, connection] = SqliteConnection::Create(config, true); + EXPECT_NE(nullptr, connection); + RdbTestOpenCallback helper; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(nullptr, store); +} + +HWTEST_F(RdbTest, NotifyDataChangeTest_002, TestSize.Level2) +{ + int errCode = E_OK; + RdbStoreConfig config(RdbTest::DATABASE_NAME); + config.SetReadOnly(false); + config.SetPageSize(1024); + config.SetBundleName("callback.test2"); + config.SetSearchable(true); + config.SetStorageMode(StorageMode::MODE_DISK); + // register callback + RdbTestOpenCallback helper; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(nullptr, store); + store->ExecuteSql("DROP TABLE IF EXISTS test_callback_t2;"); + store->ExecuteSql("CREATE TABLE if not exists test_callback_t2 " + "(id INTEGER PRIMARY KEY AUTOINCREMENT, timestamp INTEGER, data_key INTEGER, " + "data3 FLOAT, data4 BLOB, data5 BOOLEAN);"); + // set TrackerTable + DistributedDB::TrackerSchema tracker; + tracker.tableName = "test_callback_t2"; + tracker.extendColName = ""; + tracker.trackerColNames = { "id", "timestamp" }; + using Delegate = DistributedDB::RelationalStoreDelegate; + DistributedDB::RelationalStoreManager rStoreManager("test_app", "test_user_id", 0); + Delegate::Option option; + Delegate *g_delegate = nullptr; + EXPECT_EQ(RdbTest::DATABASE_NAME, "/data/test/stepResultSet_impl_test.db"); + int status = rStoreManager.OpenStore(RdbTest::DATABASE_NAME, "test_callback_t2", option, g_delegate); + EXPECT_EQ(E_OK, status); + auto delegatePtr = std::shared_ptr( + g_delegate, [&rStoreManager](Delegate *delegate) { rStoreManager.CloseStore(delegate); }); + int setStatus = delegatePtr->SetTrackerTable(tracker); + EXPECT_EQ(E_OK, setStatus); + + int64_t rowId; + ValuesBucket valuesBucket; + valuesBucket.PutInt("data_key", ValueObject(1)); + valuesBucket.PutInt("timestamp", ValueObject(1000000000)); + int errorCode = store->Insert(rowId, "test_callback_t2", valuesBucket); + EXPECT_EQ(E_OK, errorCode); + EXPECT_EQ(1, rowId); + store->ExecuteSql("DROP TABLE IF EXISTS test_callback_t2;"); +} + +HWTEST_F(RdbTest, NotifyDataChangeTest_003, TestSize.Level2) +{ + int errCode = E_OK; + RdbStoreConfig config(RdbTest::DATABASE_NAME); + config.SetReadOnly(false); + config.SetPageSize(1024); + config.SetBundleName("callback.test3"); + config.SetSearchable(true); + config.SetStorageMode(StorageMode::MODE_DISK); + + RdbTestOpenCallback helper; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + + store->ExecuteSql("DROP TABLE IF EXISTS test_callback_t3;"); + + store->ExecuteSql("CREATE TABLE if not exists test_callback_t3 " + "(id INTEGER PRIMARY KEY AUTOINCREMENT, timestamp INTEGER, data_key INTEGER, " + "data3 FLOAT, data4 BLOB, data5 BOOLEAN);"); + // set TrackerTable + DistributedDB::TrackerSchema tracker; + tracker.tableName = "test_callback_t3"; + tracker.extendColName = ""; + tracker.trackerColNames = { "id", "timestamp" }; + using Delegate = DistributedDB::RelationalStoreDelegate; + DistributedDB::RelationalStoreManager rStoreManager("test_app", "test_user_id", 0); + Delegate::Option option; + Delegate *g_delegate = nullptr; + EXPECT_EQ(RdbTest::DATABASE_NAME, "/data/test/stepResultSet_impl_test.db"); + int status = rStoreManager.OpenStore(RdbTest::DATABASE_NAME, "test_callback_t3", option, g_delegate); + EXPECT_EQ(E_OK, status); + auto delegatePtr = std::shared_ptr( + g_delegate, [&rStoreManager](Delegate *delegate) { rStoreManager.CloseStore(delegate); }); + int setStatus = delegatePtr->SetTrackerTable(tracker); + EXPECT_EQ(E_OK, setStatus); + + int64_t rowId; + ValuesBucket valuesBucket; + valuesBucket.PutInt("data_key", ValueObject(1)); + valuesBucket.PutInt("timestamp", ValueObject(1000000000)); + int errorCode = store->Insert(rowId, "test_callback_t3", valuesBucket); + EXPECT_EQ(E_OK, errorCode); + EXPECT_EQ(1, rowId); + errorCode = store->ExecuteSql("UPDATE test_callback_t3 SET timestamp = 100 WHERE id = 1;"); + EXPECT_EQ(E_OK, errorCode); + + store->ExecuteSql("DROP TABLE IF EXISTS test_callback_t3;"); +} + +/* * + * @tc.name: Rdb_QuerySharingResourceTest_001 + * @tc.desc: QuerySharingResource testCase + * @tc.type: FUNC + */ +HWTEST_F(RdbTest, Rdb_QuerySharingResourceTest_001, TestSize.Level2) +{ + RdbHelper::DeleteRdbStore(RdbTest::DATABASE_NAME); + int errCode = E_OK; + RdbStoreConfig config(RdbTest::DATABASE_NAME); + config.SetName("RdbStore_impl_test.db"); + config.SetBundleName("com.example.distributed.rdb"); + + RdbTestOpenCallback helper; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + EXPECT_EQ(errCode, E_OK); + AbsRdbPredicates predicates("test"); + predicates.EqualTo("id", 1); + + auto ret = store->QuerySharingResource(predicates, {}); + EXPECT_NE(E_OK, ret.first); + EXPECT_EQ(nullptr, ret.second); + RdbHelper::DeleteRdbStore(RdbTest::DATABASE_NAME); +} + +/* * + * @tc.name: Rdb_QuerySharingResourceTest_002 + * @tc.desc: QuerySharingResource testCase + * @tc.type: FUNC + */ +HWTEST_F(RdbTest, Rdb_QuerySharingResourceTest_002, TestSize.Level2) +{ + RdbHelper::DeleteRdbStore(RdbTest::DATABASE_NAME); + int errCode = E_OK; + RdbStoreConfig config(RdbTest::DATABASE_NAME); + config.SetName("RdbStore_impl_test.db"); + config.SetBundleName("com.example.distributed.rdb"); + + RdbTestOpenCallback helper; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + EXPECT_EQ(errCode, E_OK); + store->ExecuteSql("CREATE TABLE test_resource " + "(id INTEGER PRIMARY KEY AUTOINCREMENT, timestamp INTEGER, data_key INTEGER, " + "data3 FLOAT, data4 BLOB, data5 BOOLEAN);"); + int64_t rowId; + ValuesBucket valuesBucket; + valuesBucket.PutInt("data_key", ValueObject(1)); + valuesBucket.PutInt("timestamp", ValueObject(1000000000)); + int errorCode = store->Insert(rowId, "test_resource", valuesBucket); + EXPECT_EQ(E_OK, errorCode); + EXPECT_EQ(1, rowId); + AbsRdbPredicates predicates("test_resource"); + predicates.EqualTo("data_key", 1); + + auto [status, resultSet] = store->QuerySharingResource(predicates, { "id", "data_key" }); + EXPECT_NE(E_OK, status); + ASSERT_EQ(nullptr, resultSet); + + RdbHelper::DeleteRdbStore(RdbTest::DATABASE_NAME); +} + +/* * + * @tc.name: CleanDirtyDataTest_001 + * @tc.desc: Abnormal testCase for CleanDirtyData + * @tc.type: FUNC + */ +HWTEST_F(RdbTest, Abnormal_CleanDirtyDataTest_001, TestSize.Level2) +{ + store_->ExecuteSql("CREATE TABLE test (id INTEGER PRIMARY KEY AUTOINCREMENT, data1 TEXT, " + "data2 INTEGER, data3 FLOAT, data4 BLOB, data5 BOOLEAN);"); + int errCode = E_OK; + + // tabel is empty + std::string table = ""; + uint64_t cursor = UINT64_MAX; + errCode = RdbTest::store_->CleanDirtyData(table, cursor); + EXPECT_EQ(E_INVALID_ARGS, errCode); + + table = "test"; + errCode = RdbTest::store_->CleanDirtyData(table, cursor); + EXPECT_EQ(E_ERROR, errCode); + store_->ExecuteSql("DROP TABLE IF EXISTS test"); +} + +/* * + * @tc.name: ClearCacheTest_001 + * @tc.desc: Normal testCase for ClearCache + * @tc.type: FUNC + */ +HWTEST_F(RdbTest, Normal_ClearCacheTest_001, TestSize.Level2) +{ + store_->ExecuteSql("CREATE TABLE test (id INTEGER PRIMARY KEY AUTOINCREMENT, data1 TEXT, " + "data2 INTEGER, data3 FLOAT, data4 BLOB, data5 BOOLEAN);"); + int errCode = E_OK; + int64_t id; + ValuesBucket valuesBucket; + valuesBucket.PutString("data1", std::string("zhangsan")); + valuesBucket.PutInt("data2", 10); + errCode = store_->Insert(id, "test", valuesBucket); + EXPECT_EQ(errCode, E_OK); + EXPECT_EQ(1, id); + + int rowCount; + std::shared_ptr resultSet = store_->QueryByStep("SELECT * FROM test"); + EXPECT_NE(resultSet, nullptr); + resultSet->GetRowCount(rowCount); + EXPECT_EQ(rowCount, 1); + int64_t currentMemory = sqlite3_memory_used(); + EXPECT_EQ(E_OK, resultSet->Close()); + EXPECT_LT(sqlite3_memory_used(), currentMemory); +} + +/* * + * @tc.name: LockCloudContainerTest + * @tc.desc: lock cloudContainer testCase + * @tc.type: FUNC + */ +HWTEST_F(RdbTest, LockCloudContainerTest, TestSize.Level2) +{ + int errCode = E_OK; + // GetRdbService failed if rdbstoreconfig bundlename_ empty + auto ret = store_->LockCloudContainer(); + EXPECT_EQ(E_INVALID_ARGS, ret.first); + EXPECT_EQ(0, ret.second); + RdbHelper::DeleteRdbStore(RdbTest::DATABASE_NAME); + + RdbStoreConfig config(RdbTest::DATABASE_NAME); + config.SetName("RdbStore_impl_test.db"); + config.SetBundleName("com.example.distributed.rdb"); + RdbTestOpenCallback helper; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_EQ(E_OK, errCode); + // GetRdbService succeeded if configuration file has already been configured + ret = store->LockCloudContainer(); + EXPECT_NE(E_OK, ret.first); + store = nullptr; + RdbHelper::DeleteRdbStore(RdbTest::DATABASE_NAME); +} + +/* * + * @tc.name: UnlockCloudContainerTest + * @tc.desc: unlock cloudContainer testCase + * @tc.type: FUNC + */ +HWTEST_F(RdbTest, UnlockCloudContainerTest, TestSize.Level2) +{ + int errCode = E_OK; + // GetRdbService failed if rdbstoreconfig bundlename_ empty + auto result = store_->UnlockCloudContainer(); + EXPECT_EQ(E_INVALID_ARGS, result); + RdbHelper::DeleteRdbStore(RdbTest::DATABASE_NAME); + + RdbStoreConfig config(RdbTest::DATABASE_NAME); + config.SetName("RdbStore_impl_test.db"); + config.SetBundleName("com.example.distributed.rdb"); + RdbTestOpenCallback helper; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_EQ(E_OK, errCode); + // GetRdbService succeeded if configuration file has already been configured + result = store->UnlockCloudContainer(); + EXPECT_NE(E_OK, result); + store = nullptr; + RdbHelper::DeleteRdbStore(RdbTest::DATABASE_NAME); +} + +/* * + * @tc.name: LockCloudContainerTest001 + * @tc.desc: lock cloudContainer testCase + * @tc.type: FUNC + */ +HWTEST_F(RdbTest, LockCloudContainerTest001, TestSize.Level2) +{ + int errCode = E_OK; + RdbStoreConfig config(RdbTest::DATABASE_NAME); + config.SetName("RdbStore_impl_test.db"); + config.SetBundleName("com.example.distributed.rdb"); + RdbTestOpenCallback helper; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + EXPECT_EQ(E_OK, errCode); + // GetRdbService succeeded if configuration file has already been configured + auto ret = store->RdbStore::LockCloudContainer(); + EXPECT_EQ(E_OK, ret.first); + EXPECT_EQ(0, ret.second); + store = nullptr; + RdbHelper::DeleteRdbStore(RdbTest::DATABASE_NAME); +} + +/* * + * @tc.name: UnlockCloudContainerTest001 + * @tc.desc: unlock cloudContainer testCase + * @tc.type: FUNC + */ +HWTEST_F(RdbTest, UnlockCloudContainerTest001, TestSize.Level2) +{ + int errCode = E_OK; + RdbStoreConfig config(RdbTest::DATABASE_NAME); + config.SetName("RdbStore_impl_test.db"); + config.SetBundleName("com.example.distributed.rdb"); + RdbTestOpenCallback helper; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + ASSERT_NE(store, nullptr); + EXPECT_EQ(E_OK, errCode); + // GetRdbService succeeded if configuration file has already been configured + auto result = store->RdbStore::UnlockCloudContainer(); + EXPECT_EQ(E_OK, result); + store = nullptr; + RdbHelper::DeleteRdbStore(RdbTest::DATABASE_NAME); +} + +/* * + * @tc.name: SetSearchableTest + * @tc.desc: SetSearchable testCase + * @tc.type: FUNC + */ +HWTEST_F(RdbTest, SetSearchableTest, TestSize.Level2) +{ + int errCode = E_OK; + RdbStoreConfig config(RdbTest::DATABASE_NAME); + config.SetBundleName(""); + RdbTestOpenCallback helper; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_EQ(E_OK, errCode); + + int result = store->SetSearchable(true); + EXPECT_EQ(E_INVALID_ARGS, result); + RdbHelper::DeleteRdbStore(RdbTest::DATABASE_NAME); + + config.SetBundleName("com.example.distributed.rdb"); + EXPECT_EQ(E_OK, errCode); + store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_EQ(E_OK, errCode); + result = store->SetSearchable(true); + EXPECT_EQ(E_OK, result); +} + +/* * + * @tc.name: RdbStore_Delete_001 + * @tc.desc: normal testcase of SqliteSharedResultSet for move + * @tc.type: FUNC + * @tc.require: AR000FKD4F + */ +HWTEST_F(RdbTest, Sqlite_Shared_Result_Set_001, TestSize.Level1) +{ + GenerateDefaultTable(); + std::vector selectionArgs; + std::unique_ptr rstSet = + RdbTest::store->QuerySql("SELECT * FROM test", selectionArgs); + EXPECT_NE(rstSet, nullptr); + + int ret = rstSet->GoToRow(1); + EXPECT_EQ(ret, E_OK); + + int rowCnt = -1; + ret = rstSet->GetRowCount(rowCnt); + EXPECT_EQ(rowCnt, 3); + + std::string colName = ""; + rstSet->GetColumnName(1, colName); + EXPECT_EQ(colName, "data1"); + + rstSet->GetColumnName(2, colName); + EXPECT_EQ(colName, "data2"); + + rstSet->GetColumnName(3, colName); + EXPECT_EQ(colName, "data3"); + + rstSet->GetColumnName(4, colName); + EXPECT_EQ(colName, "data4"); + + std::string valueStr = ""; + rstSet->GetString(0, valueStr); + EXPECT_EQ(valueStr, "2"); + + rstSet->GetString(1, valueStr); + EXPECT_EQ(valueStr, "2"); + + int64_t valuelg = 0; + rstSet->GetLong(2, valuelg); + EXPECT_EQ(valuelg, -5); + + double valueDb = 0.0; + rstSet->GetDouble(3, valueDb); + EXPECT_EQ(valueDb, 2.5); + + std::vector blob; + rstSet->GetBlob(4, blob); + int sz = blob.size(); + EXPECT_EQ(sz, 0); + + rstSet->GoTo(1); + rstSet->GetString(0, valueStr); + EXPECT_EQ(valueStr, "3"); + + rstSet->GetString(1, valueStr); + EXPECT_EQ(valueStr, "hello world"); + + rstSet->GetLong(2, valuelg); + EXPECT_EQ(valuelg, 3); + + rstSet->GetDouble(3, valueDb); + EXPECT_EQ(valueDb, 1.8); + + rstSet->GetBlob(4, blob); + sz = blob.size(); + EXPECT_EQ(sz, 0); + + bool isNull = false; + rstSet->IsColumnNull(4, isNull); + EXPECT_EQ(isNull, true); + + ret = -1; + ret = rstSet->GoToPreviousRow(); + EXPECT_EQ(ret, E_OK); + ret = -1; + ret = rstSet->GoToPreviousRow(); + EXPECT_EQ(ret, E_OK); + + rstSet->GetString(0, valueStr); + EXPECT_EQ(valueStr, "1"); + + rstSet->GetString(1, valueStr); + EXPECT_EQ(valueStr, "hello"); + + rstSet->GetLong(2, valuelg); + EXPECT_EQ(valuelg, 10); + + rstSet->GetDouble(3, valueDb); + EXPECT_EQ(valueDb, 1.0); + + rstSet->Close(); + bool isClosedFlag = rstSet->IsClosed(); + EXPECT_EQ(isClosedFlag, true); +} + +/* * + * @tc.name: Sqlite_Shared_Result_Set_002 + * @tc.desc: normal testcase of SqliteSharedResultSet for goToNextRow + * @tc.type: FUNC + * @tc.require: AR000FKD4F + */ +HWTEST_F(RdbTest, Sqlite_Shared_Result_Set_002, TestSize.Level1) +{ + GenerateDefaultTable(); + std::vector selectionArgs; + std::unique_ptr rstSet = + RdbTest::store->QuerySql("SELECT * FROM test", selectionArgs); + EXPECT_NE(rstSet, nullptr); + + int pos = -2; + rstSet->GetRowIndex(pos); + EXPECT_EQ(pos, -1); + bool isStart = true; + rstSet->IsStarted(isStart); + EXPECT_EQ(isStart, false); + bool isAtFirstRow = true; + rstSet->IsAtFirstRow(isAtFirstRow); + EXPECT_EQ(isAtFirstRow, false); + bool isEnded = true; + rstSet->IsEnded(isEnded); + EXPECT_EQ(isEnded, false); + + int retN1 = rstSet->GoToNextRow(); + EXPECT_EQ(retN1, E_OK); + rstSet->GetRowIndex(pos); + EXPECT_EQ(pos, 0); + rstSet->IsStarted(isStart); + EXPECT_EQ(isStart, true); + rstSet->IsAtFirstRow(isAtFirstRow); + EXPECT_EQ(isAtFirstRow, true); + isEnded = true; + rstSet->IsEnded(isEnded); + EXPECT_EQ(isEnded, false); + + int retN2 = rstSet->GoToNextRow(); + EXPECT_EQ(retN2, E_OK); + rstSet->GetRowIndex(pos); + EXPECT_EQ(pos, 1); + isStart = false; + rstSet->IsStarted(isStart); + EXPECT_EQ(isStart, true); + isAtFirstRow = true; + rstSet->IsAtFirstRow(isAtFirstRow); + EXPECT_EQ(isAtFirstRow, false); + isEnded = true; + rstSet->IsEnded(isEnded); + EXPECT_EQ(isEnded, false); + + int retN3 = rstSet->GoToNextRow(); + EXPECT_EQ(retN3, E_OK); + rstSet->GetRowIndex(pos); + EXPECT_EQ(pos, 2); + isStart = false; + rstSet->IsStarted(isStart); + EXPECT_EQ(isStart, true); + isAtFirstRow = true; + rstSet->IsAtFirstRow(isAtFirstRow); + EXPECT_EQ(isAtFirstRow, false); + bool isAtLastRow = false; + rstSet->IsAtLastRow(isAtLastRow); + EXPECT_EQ(isAtLastRow, true); + + int retN = rstSet->GoToNextRow(); + EXPECT_EQ(retN, E_ERROR); + rstSet->GetRowIndex(pos); + EXPECT_EQ(pos, 3); + isStart = false; + rstSet->IsStarted(isStart); + EXPECT_EQ(isStart, true); + isAtFirstRow = true; + rstSet->IsAtFirstRow(isAtFirstRow); + EXPECT_EQ(isAtFirstRow, false); + isEnded = false; + rstSet->IsEnded(isEnded); + EXPECT_EQ(isEnded, true); + + rstSet->Close(); + bool isClosedFlag = rstSet->IsClosed(); + EXPECT_EQ(isClosedFlag, true); +} + +/* * + * @tc.name: Sqlite_Shared_Result_Set_003 + * @tc.desc: normal testcase of SqliteSharedResultSet for moveFirst + * @tc.type: FUNC + * @tc.require: AR000FKD4F + */ +HWTEST_F(RdbTest, Sqlite_Shared_Result_Set_003, TestSize.Level1) +{ + GenerateDefaultTable(); + std::vector selectionArgs; + std::unique_ptr rstSet = + RdbTest::store->QuerySql("SELECT * FROM test", selectionArgs); + EXPECT_NE(rstSet, nullptr); + + int retF = rstSet->GoToFirstRow(); + EXPECT_EQ(retF, E_OK); + int index = -1; + rstSet->GetRowIndex(index); + EXPECT_EQ(index, 0); + bool isAtFirstRow = false; + rstSet->IsAtFirstRow(isAtFirstRow); + EXPECT_EQ(isAtFirstRow, true); + bool isStd = false; + rstSet->IsStarted(isStd); + EXPECT_EQ(isStd, true); + + int retN = rstSet->GoToNextRow(); + EXPECT_EQ(retN, E_OK); + rstSet->GetRowIndex(index); + EXPECT_EQ(index, 1); + isAtFirstRow = true; + rstSet->IsAtFirstRow(isAtFirstRow); + EXPECT_EQ(isAtFirstRow, false); + isStd = false; + rstSet->IsStarted(isStd); + EXPECT_EQ(isStd, true); + + int retGf = rstSet->GoToFirstRow(); + EXPECT_EQ(retGf, E_OK); + rstSet->GetRowIndex(index); + EXPECT_EQ(index, 0); + isAtFirstRow = false; + rstSet->IsAtFirstRow(isAtFirstRow); + EXPECT_EQ(isAtFirstRow, true); + isStd = false; + rstSet->IsStarted(isStd); + EXPECT_EQ(isStd, true); + + rstSet->Close(); + bool isClosedFlag = rstSet->IsClosed(); + EXPECT_EQ(isClosedFlag, true); +} + +/* * + * @tc.name: Sqlite_Shared_Result_Set_004 + * @tc.desc: normal testcase of SqliteSharedResultSet for getInt + * @tc.type: FUNC + * @tc.require: AR000FKD4F + */ +HWTEST_F(RdbTest, Sqlite_Shared_Result_Set_004, TestSize.Level1) +{ + GenerateDefaultTable(); + std::vector selectionArgs; + std::unique_ptr rstSet = + RdbTest::store->QuerySql("SELECT * FROM test", selectionArgs); + EXPECT_NE(rstSet, nullptr); + + int64_t valueInt = 0; + int ret = rstSet->GetLong(0, valueInt); + EXPECT_EQ(ret, E_INVALID_STATEMENT); + + int retF = rstSet->GoToFirstRow(); + EXPECT_EQ(retF, E_OK); + rstSet->GetLong(0, valueInt); + EXPECT_EQ(valueInt, 1); + rstSet->GetLong(2, valueInt); + EXPECT_EQ(valueInt, 10); + rstSet->GetLong(3, valueInt); + EXPECT_EQ(valueInt, 1); + + int retN = rstSet->GoToNextRow(); + EXPECT_EQ(retN, E_OK); + rstSet->GetLong(0, valueInt); + EXPECT_EQ(valueInt, 2); + valueInt = 0; + rstSet->GetLong(0, valueInt); + EXPECT_EQ(valueInt, 2); + valueInt = 0; + rstSet->GetLong(1, valueInt); + EXPECT_EQ(valueInt, 2); + + rstSet->Close(); + bool isClosedFlag = rstSet->IsClosed(); + EXPECT_EQ(isClosedFlag, true); +} + +/* * + * @tc.name: Sqlite_Shared_Result_Set_005 + * @tc.desc: normal testcase of SqliteSharedResultSet for getString + * @tc.type: FUNC + * @tc.require: AR000FKD4F + */ + +HWTEST_F(RdbTest, Sqlite_Shared_Result_Set_005, TestSize.Level1) +{ + GenerateDefaultTable(); + std::vector selectionArgs; + std::unique_ptr rstSet = + RdbTest::store->QuerySql("SELECT * FROM test", selectionArgs); + EXPECT_NE(rstSet, nullptr); + + std::string valueStr = ""; + int ret1 = rstSet->GetString(0, valueStr); + EXPECT_EQ(ret1, E_INVALID_STATEMENT); + + int retF = rstSet->GoToFirstRow(); + EXPECT_EQ(retF, E_OK); + valueStr = ""; + rstSet->GetString(1, valueStr); + EXPECT_EQ(valueStr, "hello"); + rstSet->GetString(2, valueStr); + EXPECT_EQ(valueStr, "10"); + rstSet->GetString(3, valueStr); + EXPECT_EQ(valueStr, "1"); + + int ret2 = rstSet->GetString(4, valueStr); + EXPECT_EQ(ret2, E_OK); + + valueStr = ""; + int colCnt = 0; + rstSet->GetColumnCount(colCnt); + int ret3 = rstSet->GetString(colCnt, valueStr); + EXPECT_EQ(ret3, E_INVALID_COLUMN_INDEX); + + int retN = rstSet->GoToNextRow(); + EXPECT_EQ(retN, E_OK); + rstSet->GetString(0, valueStr); + EXPECT_EQ(valueStr, "2"); + valueStr = ""; + rstSet->GetString(1, valueStr); + EXPECT_EQ(valueStr, "2"); + rstSet->GetString(2, valueStr); + EXPECT_EQ(valueStr, "-5"); + rstSet->GetString(3, valueStr); + EXPECT_EQ(valueStr, "2.5"); + + rstSet->Close(); + bool isClosedFlag = rstSet->IsClosed(); + EXPECT_EQ(isClosedFlag, true); +} + +/* * + * @tc.name: Sqlite_Shared_Result_Set_006 + * @tc.desc: normal testcase of SqliteSharedResultSet for getDouble + * @tc.type: FUNC + * @tc.require: AR000FKD4F + */ +HWTEST_F(RdbTest, Sqlite_Shared_Result_Set_006, TestSize.Level1) +{ + GenerateDefaultTable(); + std::vector selectionArgs; + std::unique_ptr rstSet = + RdbTest::store->QuerySql("SELECT * FROM test", selectionArgs); + EXPECT_NE(rstSet, nullptr); + + double valueDb = 0.0; + int ret = rstSet->GetDouble(0, valueDb); + EXPECT_EQ(ret, E_INVALID_STATEMENT); + + int retF = rstSet->GoToFirstRow(); + EXPECT_EQ(retF, E_OK); + rstSet->GetDouble(0, valueDb); + EXPECT_EQ(valueDb, 1.0); + std::string valueStr = ""; + rstSet->GetString(1, valueStr); + EXPECT_EQ(valueStr, "hello"); + rstSet->GetDouble(2, valueDb); + EXPECT_EQ(valueDb, 10.0); + rstSet->GetDouble(3, valueDb); + EXPECT_EQ(valueDb, 1.0); + + int colCnt = 0; + rstSet->GetColumnCount(colCnt); + int ret1 = rstSet->GetDouble(colCnt, valueDb); + EXPECT_EQ(ret1, E_INVALID_COLUMN_INDEX); + + int retN = rstSet->GoToNextRow(); + EXPECT_EQ(retN, E_OK); + rstSet->GetDouble(0, valueDb); + EXPECT_EQ(valueDb, 2.0); + valueDb = 0.0; + rstSet->GetDouble(1, valueDb); + EXPECT_EQ(valueDb, 2.0); + + rstSet->GetDouble(2, valueDb); + EXPECT_EQ(valueDb, -5.0); + rstSet->GetDouble(3, valueDb); + EXPECT_EQ(valueDb, 2.5); + + rstSet->Close(); + bool isClosedFlag = rstSet->IsClosed(); + EXPECT_EQ(isClosedFlag, true); +} + +/* * + * @tc.name: Sqlite_Shared_Result_Set_007 + * @tc.desc: normal testcase of SqliteSharedResultSet for getBlob + * @tc.type: FUNC + * @tc.require: AR000FKD4F + */ +HWTEST_F(RdbTest, Sqlite_Shared_Result_Set_007, TestSize.Level1) +{ + GenerateDefaultTable(); + std::vector selectionArgs; + std::unique_ptr rstSet = + RdbTest::store->QuerySql("SELECT * FROM test", selectionArgs); + EXPECT_NE(rstSet, nullptr); + + int retF = rstSet->GoToFirstRow(); + EXPECT_EQ(retF, E_OK); + + std::vector blobVec; + rstSet->GetBlob(4, blobVec); + EXPECT_EQ(blobVec[0], 66); + + int retN = rstSet->GoToNextRow(); + EXPECT_EQ(retN, E_OK); + blobVec.clear(); + rstSet->GetBlob(4, blobVec); + int blobSz = blobVec.size(); + EXPECT_EQ(blobSz, 0); + + int retN1 = rstSet->GoToNextRow(); + EXPECT_EQ(retN1, E_OK); + blobVec.clear(); + rstSet->GetBlob(4, blobVec); + EXPECT_EQ(blobSz, 0); + + rstSet->Close(); + bool isClosedFlag = rstSet->IsClosed(); + EXPECT_EQ(isClosedFlag, true); +} + +/* * + * @tc.name: Sqlite_Shared_Result_Set_008 + * @tc.desc: normal testcase of SqliteSharedResultSet for getColumnTypeForIndex + * @tc.type: FUNC + * @tc.require: AR000FKD4F + */ + +HWTEST_F(RdbTest, Sqlite_Shared_Result_Set_008, TestSize.Level1) +{ + GenerateDefaultTable(); + std::vector selectionArgs; + std::unique_ptr rstSet = + RdbTest::store->QuerySql("SELECT * FROM test", selectionArgs); + EXPECT_NE(rstSet, nullptr); + + ColumnType colType; + int ret = rstSet->GetColumnType(0, colType); + EXPECT_EQ(ret, E_INVALID_STATEMENT); + int retF = rstSet->GoToFirstRow(); + EXPECT_EQ(retF, E_OK); + + rstSet->GetColumnType(0, colType); + EXPECT_EQ(colType, ColumnType::TYPE_INTEGER); + + bool isColNull = true; + rstSet->IsColumnNull(0, isColNull); + EXPECT_EQ(isColNull, false); + + rstSet->GetColumnType(1, colType); + EXPECT_EQ(colType, ColumnType::TYPE_STRING); + + isColNull = true; + rstSet->IsColumnNull(0, isColNull); + EXPECT_EQ(isColNull, false); + + rstSet->GetColumnType(2, colType); + EXPECT_EQ(colType, ColumnType::TYPE_INTEGER); + rstSet->GetColumnType(3, colType); + EXPECT_EQ(colType, ColumnType::TYPE_FLOAT); + rstSet->GetColumnType(4, colType); + EXPECT_EQ(colType, ColumnType::TYPE_BLOB); + + int colCnt = 0; + rstSet->GetColumnCount(colCnt); + int ret1 = rstSet->GetColumnType(colCnt, colType); + EXPECT_EQ(ret1, E_INVALID_COLUMN_INDEX); + + rstSet->Close(); + bool isClosedFlag = rstSet->IsClosed(); + EXPECT_EQ(isClosedFlag, true); +} + +/* * + * @tc.name: Sqlite_Shared_Result_Set_009 + * @tc.desc: normal testcase of SqliteSharedResultSet for getColumnIndexForName + * @tc.type: FUNC + * @tc.require: AR000FKD4F + */ +HWTEST_F(RdbTest, Sqlite_Shared_Result_Set_009, TestSize.Level1) +{ + GenerateDefaultTable(); + std::vector selectionArgs; + std::unique_ptr rstSet = + RdbTest::store->QuerySql("SELECT * FROM test", selectionArgs); + EXPECT_NE(rstSet, nullptr); + + int colIndex = 0; + rstSet->GetColumnIndex("data1", colIndex); + EXPECT_EQ(colIndex, 1); + + rstSet->GetColumnIndex("data2", colIndex); + EXPECT_EQ(colIndex, 2); + + rstSet->GetColumnIndex("data3", colIndex); + EXPECT_EQ(colIndex, 3); + + rstSet->GetColumnIndex("data4", colIndex); + EXPECT_EQ(colIndex, 4); + + rstSet->GetColumnIndex("datax", colIndex); + EXPECT_EQ(colIndex, -1); + + rstSet->Close(); + bool isClosedFlag = rstSet->IsClosed(); + EXPECT_EQ(isClosedFlag, true); +} + +/* * + * @tc.name: Sqlite_Shared_Result_Set_010 + * @tc.desc: normal testcase of SqliteSharedResultSet for getColumnNameForIndex + * @tc.type: FUNC + * @tc.require: AR000FKD4F + */ +HWTEST_F(RdbTest, Sqlite_Shared_Result_Set_010, TestSize.Level1) +{ + GenerateDefaultTable(); + std::vector selectionArgs; + std::unique_ptr rstSet = + RdbTest::store->QuerySql("SELECT * FROM test", selectionArgs); + EXPECT_NE(rstSet, nullptr); + + std::vector allColNamesVec; + rstSet->GetAllColumnNames(allColNamesVec); + + std::string colName = ""; + rstSet->GetColumnName(1, colName); + EXPECT_EQ(colName, "data1"); + EXPECT_EQ(allColNamesVec[1], colName); + + rstSet->GetColumnName(2, colName); + EXPECT_EQ(colName, "data2"); + EXPECT_EQ(allColNamesVec[2], colName); + + rstSet->GetColumnName(3, colName); + EXPECT_EQ(colName, "data3"); + rstSet->GetColumnName(4, colName); + EXPECT_EQ(colName, "data4"); + + int colCnt = 0; + rstSet->GetColumnCount(colCnt); + int ret = rstSet->GetColumnName(colCnt, colName); + EXPECT_EQ(ret, E_INVALID_COLUMN_INDEX); + + rstSet->Close(); + bool isClosedFlag = rstSet->IsClosed(); + EXPECT_EQ(isClosedFlag, true); +} + +/* * + * @tc.name: Sqlite_Shared_Result_Set_011 + * @tc.desc: normal testcase of SqliteSharedResultSet + * @tc.type: FUNC + * @tc.require: AR000FKD4F + */ +HWTEST_F(RdbTest, Sqlite_Shared_Result_Set_011, TestSize.Level1) +{ + GenerateDefaultTable(); + std::vector selectionArgs; + std::unique_ptr rstSet = + RdbTest::store->QuerySql("SELECT * FROM test", selectionArgs); + EXPECT_NE(rstSet, nullptr); + + int retF = rstSet->GoToFirstRow(); + EXPECT_EQ(retF, E_OK); + + bool isAtFrtRow = false; + rstSet->IsAtFirstRow(isAtFrtRow); + EXPECT_EQ(isAtFrtRow, true); + + bool isStarted = false; + rstSet->IsStarted(isStarted); + EXPECT_EQ(isStarted, true); + + int64_t valueInt = 0; + rstSet->GetLong(2, valueInt); + EXPECT_EQ(valueInt, 10); + + rstSet->Close(); + bool isClosedFlag = rstSet->IsClosed(); + EXPECT_EQ(isClosedFlag, true); +} + +/* * + * @tc.name: Sqlite_Shared_Result_Set_012 + * @tc.desc: normal testcase of SqliteSharedResultSet for getLong + * @tc.type: FUNC + * @tc.require: AR000FKD4F + */ +HWTEST_F(RdbTest, Sqlite_Shared_Result_Set_012, TestSize.Level1) +{ + GenerateDefaultTable(); + std::vector selectionArgs; + std::unique_ptr rstSet = + RdbTest::store->QuerySql("SELECT * FROM test", selectionArgs); + EXPECT_NE(rstSet, nullptr); + + int64_t valueInt = 0; + int ret = rstSet->GetLong(0, valueInt); + EXPECT_EQ(ret, E_INVALID_STATEMENT); + + int retF = rstSet->GoToFirstRow(); + EXPECT_EQ(retF, E_OK); + rstSet->GetLong(0, valueInt); + EXPECT_EQ(valueInt, 1.0); + std::string valueStr = ""; + rstSet->GetString(1, valueStr); + EXPECT_EQ(valueStr, "hello"); + rstSet->GetLong(2, valueInt); + EXPECT_EQ(valueInt, 10.0); + rstSet->GetLong(3, valueInt); + EXPECT_EQ(valueInt, 1.0); + + int colCnt = 0; + rstSet->GetColumnCount(colCnt); + int ret1 = rstSet->GetLong(colCnt, valueInt); + EXPECT_EQ(ret1, E_INVALID_COLUMN_INDEX); + + int retN = rstSet->GoToNextRow(); + EXPECT_EQ(retN, E_OK); + rstSet->GetLong(0, valueInt); + EXPECT_EQ(valueInt, 2.0); + valueInt = 0; + rstSet->GetLong(1, valueInt); + EXPECT_EQ(valueInt, 2.0); + rstSet->GetLong(2, valueInt); + EXPECT_EQ(valueInt, -5.0); + + rstSet->Close(); + bool isClosedFlag = rstSet->IsClosed(); + EXPECT_EQ(isClosedFlag, true); +} + +/* * + * @tc.name: Sqlite_Shared_Result_Set_013 + * @tc.desc: normal testcase of SqliteSharedResultSet for fillBlock + * @tc.type: FUNC + * @tc.require: AR000FKD4F + */ +HWTEST_F(RdbTest, Sqlite_Shared_Result_Set_013, TestSize.Level1) +{ + GenerateDefaultTable(); + std::vector selectionArgs; + std::unique_ptr rstSet = + RdbTest::store->QuerySql("SELECT * FROM test", selectionArgs); + EXPECT_NE(rstSet, nullptr); + + SqliteSharedResultSet *pSqlSharedRstSet = static_cast(rstSet.get()); + bool isBk = pSqlSharedRstSet->HasBlock(); + EXPECT_EQ(isBk, true); + + rstSet->Close(); + bool isClosedFlag = rstSet->IsClosed(); + EXPECT_EQ(isClosedFlag, true); +} +/* * + * @tc.name: Sqlite_Shared_Result_Set_014 + * @tc.desc: normal testcase of SqliteSharedResultSet for getBlock + * @tc.type: FUNC + * @tc.require: AR000FKD4F + */ +HWTEST_F(RdbTest, Sqlite_Shared_Result_Set_014, TestSize.Level1) +{ + GenerateDefaultTable(); + std::vector selectionArgs; + std::unique_ptr rstSet = + RdbTest::store->QuerySql("SELECT * FROM test", selectionArgs); + EXPECT_NE(rstSet, nullptr); + + SqliteSharedResultSet *pSqlSharedRstSet = static_cast(rstSet.get()); + bool isBk = pSqlSharedRstSet->HasBlock(); + EXPECT_EQ(isBk, true); + + int retF = rstSet->GoToFirstRow(); + EXPECT_EQ(retF, E_OK); + OHOS::AppDataFwk::SharedBlock* pBk = pSqlSharedRstSet->GetBlock(); + EXPECT_NE(pBk, nullptr); + + std::string path = RdbTest::store->GetPath(); + std::string path1 = pBk->Name(); + + EXPECT_EQ(path, "/data/test/shared_test.db"); + EXPECT_EQ(path1, "/data/test/shared_test.db"); + + rstSet->Close(); + bool isClosedFlag = rstSet->IsClosed(); + EXPECT_EQ(isClosedFlag, true); +} +/* * + * @tc.name: Sqlite_Shared_Result_Set_015 + * @tc.desc: normal testcase of SqliteSharedResultSet for setBlock + * @tc.type: FUNC + * @tc.require: AR000FKD4F + */ +HWTEST_F(RdbTest, Sqlite_Shared_Result_Set_015, TestSize.Level1) +{ + GenerateDefaultTable(); + std::vector selectionArgs; + std::unique_ptr rstSet = + RdbTest::store->QuerySql("SELECT * FROM test", selectionArgs); + EXPECT_NE(rstSet, nullptr); + + SqliteSharedResultSet *pSqlSharedRstSet = static_cast(rstSet.get()); + bool isBk = pSqlSharedRstSet->HasBlock(); + EXPECT_EQ(isBk, true); + + int retN = rstSet->GoToNextRow(); + EXPECT_EQ(retN, E_OK); + + std::string path = RdbTest::store->GetPath(); + OHOS::AppDataFwk::SharedBlock* pBk = pSqlSharedRstSet->GetBlock(); + std::string path1 = pBk->Name(); + + EXPECT_EQ(path, "/data/test/shared_test.db"); + EXPECT_EQ(path1, "/data/test/shared_test.db"); + + rstSet->Close(); + bool isClosedFlag = rstSet->IsClosed(); + EXPECT_EQ(isClosedFlag, true); +} + +/* * + * @tc.name: Sqlite_Shared_Result_Set_016 + * @tc.desc: normal testcase of SqliteSharedResultSet for setFillWindowForwardOnly + * @tc.type: FUNC + * @tc.require: AR000FKD4F + */ +HWTEST_F(RdbTest, Sqlite_Shared_Result_Set_016, TestSize.Level1) +{ + GenerateDefaultTable(); + std::vector selectionArgs; + std::unique_ptr rstSet = + RdbTest::store->QuerySql("SELECT * FROM test", selectionArgs); + EXPECT_NE(rstSet, nullptr); + + SqliteSharedResultSet *pSqlSharedRstSet = static_cast(rstSet.get()); + bool isBk = pSqlSharedRstSet->HasBlock(); + EXPECT_EQ(isBk, true); + + pSqlSharedRstSet->PickFillBlockStartPosition(0, 0); + pSqlSharedRstSet->SetFillBlockForwardOnly(true); + pSqlSharedRstSet->GoToFirstRow(); + + OHOS::AppDataFwk::SharedBlock* pBk = pSqlSharedRstSet->GetBlock(); + EXPECT_NE(pBk, nullptr); + std::string path = RdbTest::store->GetPath(); + std::string path1 = pBk->Name(); + + EXPECT_EQ(path, "/data/test/shared_test.db"); + EXPECT_EQ(path1, "/data/test/shared_test.db"); + + int rowCnt = 0; + pSqlSharedRstSet->GetRowCount(rowCnt); + int rowCntBk = pBk->GetRowNum(); + + EXPECT_EQ(rowCnt, rowCntBk); + + rstSet->Close(); + bool isClosedFlag = rstSet->IsClosed(); + EXPECT_EQ(isClosedFlag, true); +} + +/* * + * @tc.name: Sqlite_Shared_Result_Set_017 + * @tc.desc: normal testcase of SqliteSharedResultSet for setExtensions and getExtensions + * @tc.type: FUNC + * @tc.require: AR000FKD4F + */ +HWTEST_F(RdbTest, Sqlite_Shared_Result_Set_017, TestSize.Level1) +{ + GenerateDefaultTable(); + std::vector selectionArgs; + std::unique_ptr rstSet = + RdbTest::store->QuerySql("SELECT * FROM test", selectionArgs); + EXPECT_NE(rstSet, nullptr); + + int rowCnt = 0; + rstSet->GetRowCount(rowCnt); + EXPECT_EQ(rowCnt, 3); + int ret = rstSet->GoToLastRow(); + EXPECT_EQ(ret, E_OK); +} + +/** + * @tc.name: RdbStore_Transaction_001 + * @tc.desc: test RdbStore BaseTransaction + * @tc.type: FUNC + * @tc.require: AR000CU2BO + * @tc.author: chenxi + */ +HWTEST_F(RdbTest, RdbStore_Transaction_001, TestSize.Level1) +{ + std::shared_ptr &store = RdbTest::store; + + int64_t id; + ValuesBucket values; + + int ret = store->BeginTransaction(); + EXPECT_EQ(ret, E_OK); + + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 18); + values.PutDouble("salary", 100.5); + values.PutBlob("blobType", std::vector{ 1, 2, 3 }); + 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")); + values.PutInt("age", 19); + values.PutDouble("salary", 200.5); + values.PutBlob("blobType", std::vector{ 4, 5, 6 }); + 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("wangyjing")); + values.PutInt("age", 20); + values.PutDouble("salary", 300.5); + values.PutBlob("blobType", std::vector{ 7, 8, 9 }); + ret = store->Insert(id, "test", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(3, id); + + ret = store->Commit(); + EXPECT_EQ(ret, E_OK); + + int64_t count; + ret = store->ExecuteAndGetLong(count, "SELECT COUNT(*) FROM test"); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(count, 3); + + int deletedRows; + ret = store->Delete(deletedRows, "test"); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(deletedRows, 3); +} + +/** + * @tc.name: RdbStore_Transaction_002 + * @tc.desc: test RdbStore BaseTransaction + * @tc.type: FUNC + * @tc.require: AR000CU2BO + * @tc.author: chenxi + */ +HWTEST_F(RdbTest, RdbStore_Transaction_002, TestSize.Level1) +{ + std::shared_ptr &store = RdbTest::store; + + int64_t id; + ValuesBucket values; + + int ret = store->BeginTransaction(); + EXPECT_EQ(ret, E_OK); + + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 18); + values.PutDouble("salary", 100.5); + values.PutBlob("blobType", std::vector{ 1, 2, 3 }); + 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")); + values.PutInt("age", 19); + values.PutDouble("salary", 200.5); + values.PutBlob("blobType", std::vector{ 4, 5, 6 }); + 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("wangyjing")); + values.PutInt("age", 20); + values.PutDouble("salary", 300.5); + values.PutBlob("blobType", std::vector{ 7, 8, 9 }); + ret = store->Insert(id, "test", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(3, id); + + ret = store->Commit(); + EXPECT_EQ(ret, E_OK); + + int64_t count; + ret = store->ExecuteAndGetLong(count, "SELECT COUNT(*) FROM test"); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(count, 3); + + std::unique_ptr resultSet = store->QuerySql("SELECT * FROM test"); + EXPECT_NE(resultSet, nullptr); + ret = resultSet->GoToNextRow(); + EXPECT_EQ(ret, E_OK); + ret = resultSet->Close(); + EXPECT_EQ(ret, E_OK); + + int deletedRows; + ret = store->Delete(deletedRows, "test"); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(deletedRows, 3); +} + +/** + * @tc.name: RdbStore_NestedTransaction_001 + * @tc.desc: test RdbStore BaseTransaction + * @tc.type: FUNC + * @tc.require: AR000CU2BO + * @tc.author: chenxi + */ +HWTEST_F(RdbTest, RdbStore_NestedTransaction_001, TestSize.Level1) +{ + std::shared_ptr &store = RdbTest::store; + + int64_t id; + ValuesBucket values; + + int ret = store->BeginTransaction(); + EXPECT_EQ(ret, E_OK); + + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 18); + values.PutDouble("salary", 100.5); + values.PutBlob("blobType", std::vector{ 1, 2, 3 }); + ret = store->Insert(id, "test", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, id); + + ret = store->BeginTransaction(); + EXPECT_EQ(ret, E_OK); + values.Clear(); + values.PutInt("id", 2); + values.PutString("name", std::string("lisi")); + values.PutInt("age", 19); + values.PutDouble("salary", 200.5); + values.PutBlob("blobType", std::vector{ 4, 5, 6 }); + ret = store->Insert(id, "test", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(2, id); + ret = store->Commit(); // not commit + EXPECT_EQ(ret, E_OK); + + values.Clear(); + values.PutInt("id", 3); + values.PutString("name", std::string("wangyjing")); + values.PutInt("age", 20); + values.PutDouble("salary", 300.5); + values.PutBlob("blobType", std::vector{ 7, 8, 9 }); + ret = store->Insert(id, "test", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(3, id); + + ret = store->Commit(); + EXPECT_EQ(ret, E_OK); + + int64_t count; + ret = store->ExecuteAndGetLong(count, "SELECT COUNT(*) FROM test"); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(count, 3); + + std::unique_ptr resultSet = store->QuerySql("SELECT * FROM test"); + EXPECT_NE(resultSet, nullptr); + ret = resultSet->GoToNextRow(); + EXPECT_EQ(ret, E_OK); + ret = resultSet->Close(); + EXPECT_EQ(ret, E_OK); + + int deletedRows; + ret = store->Delete(deletedRows, "test"); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(deletedRows, 3); +} + +/** + * @tc.name: RdbStore_NestedTransaction_002 + * @tc.desc: test RdbStore BaseTransaction + * @tc.type: FUNC + * @tc.require: AR000CU2BO + * @tc.author: chenxi + */ +HWTEST_F(RdbTest, RdbStore_NestedTransaction_002, TestSize.Level1) +{ + std::shared_ptr &store = RdbTest::store; + + int64_t id; + ValuesBucket values; + + int ret = store->BeginTransaction(); + EXPECT_EQ(ret, E_OK); + + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 18); + values.PutDouble("salary", 100.5); + values.PutBlob("blobType", std::vector{ 1, 2, 3 }); + ret = store->Insert(id, "test", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, id); + + ret = store->BeginTransaction(); + EXPECT_EQ(ret, E_OK); + values.Clear(); + values.PutInt("id", 2); + values.PutString("name", std::string("lisi")); + values.PutInt("age", 19); + values.PutDouble("salary", 200.5); + values.PutBlob("blobType", std::vector{ 4, 5, 6 }); + ret = store->Insert(id, "test", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(2, id); + ret = store->Commit(); + EXPECT_EQ(ret, E_OK); + ret = store->Commit(); // commit + EXPECT_EQ(ret, E_OK); + + values.Clear(); + values.PutInt("id", 3); + values.PutString("name", std::string("wangyjing")); + values.PutInt("age", 20); + values.PutDouble("salary", 300.5); + values.PutBlob("blobType", std::vector{ 7, 8, 9 }); + ret = store->Insert(id, "test", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(3, id); + + int64_t count; + ret = store->ExecuteAndGetLong(count, "SELECT COUNT(*) FROM test"); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(count, 3); + + std::unique_ptr resultSet = store->QuerySql("SELECT * FROM test"); + EXPECT_NE(resultSet, nullptr); + ret = resultSet->GoToNextRow(); + EXPECT_EQ(ret, E_OK); + ret = resultSet->Close(); + EXPECT_EQ(ret, E_OK); + + int deletedRows; + ret = store->Delete(deletedRows, "test"); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(deletedRows, 3); +} + +/** + * @tc.name: RdbStore_NestedTransaction_003 + * @tc.desc: test RdbStore BaseTransaction + * @tc.type: FUNC + * @tc.require: AR000CU2BO + * @tc.author: chenxi + */ +HWTEST_F(RdbTest, RdbStore_NestedTransaction_003, TestSize.Level1) +{ + std::shared_ptr &store = RdbTest::store; + + int64_t id; + ValuesBucket values; + + int ret = store->BeginTransaction(); + EXPECT_EQ(ret, E_OK); + + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 18); + values.PutDouble("salary", 100.5); + values.PutBlob("blobType", std::vector{ 1, 2, 3 }); + ret = store->Insert(id, "test", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, id); + + ret = store->BeginTransaction(); + EXPECT_EQ(ret, E_OK); + values.Clear(); + values.PutInt("id", 2); + values.PutString("name", std::string("lisi")); + values.PutInt("age", 19); + values.PutDouble("salary", 200.5); + values.PutBlob("blobType", std::vector{ 4, 5, 6 }); + ret = store->Insert(id, "test", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(2, id); + ret = store->Commit(); // not commit + EXPECT_EQ(ret, E_OK); + + values.Clear(); + values.PutInt("id", 3); + values.PutString("name", std::string("wangyjing")); + values.PutInt("age", 20); + values.PutDouble("salary", 300.5); + values.PutBlob("blobType", std::vector{ 7, 8, 9 }); + ret = store->Insert(id, "test", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(3, id); + + ret = store->Commit(); // not commit + EXPECT_EQ(ret, E_OK); + + int64_t count; + ret = store->ExecuteAndGetLong(count, "SELECT COUNT(*) FROM test"); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(count, 3); + + std::unique_ptr resultSet = store->QuerySql("SELECT * FROM test"); + EXPECT_NE(resultSet, nullptr); + ret = resultSet->GoToNextRow(); + EXPECT_EQ(ret, E_OK); + ret = resultSet->Close(); + EXPECT_EQ(ret, E_OK); + + int deletedRows; + ret = store->Delete(deletedRows, "test"); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(deletedRows, 3); +} \ No newline at end of file diff --git a/relational_store/test/native/relational_store_test/unittest/relational_store_test.cpp b/relational_store/test/native/relational_store_test/unittest/relational_store_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5dd2d3ef76c5c9b9e0a6e5a226108b507c51b4f2 --- /dev/null +++ b/relational_store/test/native/relational_store_test/unittest/relational_store_test.cpp @@ -0,0 +1,1977 @@ +/* + * Copyright (c) 2021 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 "common.h" +#include "logger.h" +#include "rdb_errno.h" +#include "rdb_helper.h" +#include "rdb_open_callback.h" + +using namespace testing::ext; +using namespace OHOS::NativeRdb; + +class RdbTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + void QueryCheck1(std::shared_ptr &store) const; + void QueryCheck2(std::shared_ptr &store) const; + + static const std::string MAIN_DATABASE_NAME; + static const std::string ATTACHED_DATABASE_NAME; + static const std::string DATABASE_NAME; + static std::shared_ptr store; +}; + +const std::string RdbTest::MAIN_DATABASE_NAME = RDB_TEST_PATH + "main.db"; +const std::string RdbTest::DATABASE_NAME = RDB_TEST_PATH + "delete_test.db"; +const std::string RdbTest::DATABASE_NAME = RDB_TEST_PATH + "update_test.db"; +std::shared_ptr RdbTest::store = nullptr; + +class DeleteTestOpenCallback : public RdbOpenCallback { +public: + int OnCreate(RdbStore &rdbStore) override; + int OnUpgrade(RdbStore &rdbStore, int oldVersion, int newVersion) override; + static const std::string CREATE_TABLE_TEST; +}; + +std::string const DeleteTestOpenCallback::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 DeleteTestOpenCallback::OnCreate(RdbStore &store) +{ + return store.ExecuteSql(CREATE_TABLE_TEST); +} + +int DeleteTestOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) +{ + return E_OK; +} + +class MainOpenCallback : public RdbOpenCallback { +public: + int OnCreate(RdbStore &rdbStore) override; + int OnUpgrade(RdbStore &rdbStore, int oldVersion, int newVersion) override; + static const std::string CREATE_TABLE_TEST; +}; + +std::string const MainOpenCallback::CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test1(id INTEGER PRIMARY KEY " + "AUTOINCREMENT, name TEXT NOT NULL)"; + +int MainOpenCallback::OnCreate(RdbStore &store) +{ + return store.ExecuteSql(CREATE_TABLE_TEST); +} + +int MainOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) +{ + return E_OK; +} + +const std::string RdbTest::ATTACHED_DATABASE_NAME = RDB_TEST_PATH + "attached.db"; + +class AttachedOpenCallback : public RdbOpenCallback { +public: + int OnCreate(RdbStore &rdbStore) override; + int OnUpgrade(RdbStore &rdbStore, int oldVersion, int newVersion) override; + static const std::string CREATE_TABLE_TEST; +}; + +std::string const AttachedOpenCallback::CREATE_TABLE_TEST = "CREATE TABLE IF NOT EXISTS test2(id INTEGER PRIMARY KEY " + "AUTOINCREMENT, name TEXT NOT NULL)"; + +int AttachedOpenCallback::OnCreate(RdbStore &store) +{ + return store.ExecuteSql(CREATE_TABLE_TEST); +} + +int AttachedOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) +{ + return E_OK; +} + +void RdbTest::SetUpTestCase(void) +{ + RdbStoreConfig attachedConfig(RdbTest::ATTACHED_DATABASE_NAME); + AttachedOpenCallback attachedHelper; + int errCode = E_OK; + std::shared_ptr attachedStore = RdbHelper::GetRdbStore(attachedConfig, 1, attachedHelper, errCode); + EXPECT_NE(attachedStore, nullptr); +} + +void RdbTest::TearDownTestCase(void) +{ + RdbHelper::DeleteRdbStore(MAIN_DATABASE_NAME); + RdbHelper::DeleteRdbStore(ATTACHED_DATABASE_NAME); +} + +void RdbTest::SetUp(void) +{ +} + +void RdbTest::TearDown(void) +{ + RdbHelper::ClearCache(); +} + +/** + * @tc.name: RdbStore_Attach_001 + * @tc.desc: test attach, attach is not supported in wal mode + * @tc.type: FUNC + * @tc.require: AR000CU2BO + * @tc.author: + */ +HWTEST_F(RdbTest, RdbStore_Attach_001, TestSize.Level1) +{ + RdbStoreConfig config(RdbTest::MAIN_DATABASE_NAME); + MainOpenCallback helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + + int ret = store->ExecuteSql("ATTACH '" + ATTACHED_DATABASE_NAME + "' as attached"); + EXPECT_EQ(ret, E_NOT_SUPPORTED_ATTACH_IN_WAL_MODE); + + ret = store->ExecuteSql("attach '" + ATTACHED_DATABASE_NAME + "' as attached"); + EXPECT_EQ(ret, E_NOT_SUPPORTED_ATTACH_IN_WAL_MODE); +} + +/** + * @tc.name: RdbStore_Attach_002 + * @tc.desc: test RdbStore attach + * @tc.type: FUNC + * @tc.require: AR000CU2BO + * @tc.author: + */ +HWTEST_F(RdbTest, RdbStore_Attach_002, TestSize.Level1) +{ + RdbStoreConfig config(RdbTest::MAIN_DATABASE_NAME); + config.SetJournalMode(JournalMode::MODE_TRUNCATE); + MainOpenCallback helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + + int ret = store->ExecuteSql("ATTACH DATABASE '" + ATTACHED_DATABASE_NAME + "' as 'attached'"); + EXPECT_EQ(ret, E_OK); + + int64_t id; + ValuesBucket values; + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan")); + ret = store->Insert(id, "test1", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(id, 1); + + values.Clear(); + values.PutInt("id", 1); + values.PutString("name", std::string("lisi")); + ret = store->Insert(id, "test2", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(id, 1); + + QueryCheck1(store); + + ret = store->ExecuteSql("DETACH DATABASE 'attached'"); + EXPECT_EQ(ret, E_OK); + + QueryCheck2(store); + + ret = store->ExecuteSql("attach database '" + ATTACHED_DATABASE_NAME + "' as 'attached'"); + EXPECT_EQ(ret, E_OK); + + ret = store->ExecuteSql("detach database 'attached'"); + EXPECT_EQ(ret, E_OK); +} + +void RdbTest::QueryCheck1(std::shared_ptr &store) const +{ + std::unique_ptr resultSet = store->QuerySql("SELECT * FROM test1"); + EXPECT_NE(resultSet, nullptr); + int ret = resultSet->GoToNextRow(); + EXPECT_EQ(ret, E_OK); + int columnIndex; + int intVal; + ret = resultSet->GetColumnIndex("id", columnIndex); + EXPECT_EQ(ret, E_OK); + ret = resultSet->GetInt(columnIndex, intVal); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(intVal, 1); + std::string strVal; + ret = resultSet->GetColumnIndex("name", columnIndex); + EXPECT_EQ(ret, E_OK); + ret = resultSet->GetString(columnIndex, strVal); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(strVal, "zhangsan"); + + resultSet = store->QuerySql("SELECT * FROM test2"); + EXPECT_NE(resultSet, nullptr); + ret = resultSet->GoToNextRow(); + EXPECT_EQ(ret, E_OK); + ret = resultSet->GetColumnIndex("id", columnIndex); + EXPECT_EQ(ret, E_OK); + ret = resultSet->GetInt(columnIndex, intVal); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(intVal, 1); + ret = resultSet->GetColumnIndex("name", columnIndex); + EXPECT_EQ(ret, E_OK); + ret = resultSet->GetString(columnIndex, strVal); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(strVal, "lisi"); +} + +void RdbTest::QueryCheck2(std::shared_ptr &store) const +{ + std::unique_ptr resultSet = store->QuerySql("SELECT * FROM test1"); + EXPECT_NE(resultSet, nullptr); + int ret = resultSet->GoToNextRow(); + EXPECT_EQ(ret, E_OK); + int columnIndex; + int intVal; + ret = resultSet->GetColumnIndex("id", columnIndex); + EXPECT_EQ(ret, E_OK); + ret = resultSet->GetInt(columnIndex, intVal); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(intVal, 1); + std::string strVal; + ret = resultSet->GetColumnIndex("name", columnIndex); + EXPECT_EQ(ret, E_OK); + ret = resultSet->GetString(columnIndex, strVal); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(strVal, "zhangsan"); + + // detached, no table test2 + resultSet = store->QuerySql("SELECT * FROM test2"); + EXPECT_NE(resultSet, nullptr); +} + +/** + * @tc.name: RdbStore_Delete_001 + * @tc.desc: test RdbStore update, select id and update one row + * @tc.type: FUNC + * @tc.require: AR000CU2BO + * @tc.author: + */ +HWTEST_F(RdbTest, RdbStore_Delete_001, TestSize.Level1) +{ + std::shared_ptr &store = RdbTest::store; + + int64_t id; + ValuesBucket values; + int deletedRows; + + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 18); + values.PutDouble("salary", 100.5); + values.PutBlob("blobType", std::vector{ 1, 2, 3 }); + 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")); + values.PutInt("age", 19); + values.PutDouble("salary", 200.5); + values.PutBlob("blobType", std::vector{ 4, 5, 6 }); + 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("wangyjing")); + values.PutInt("age", 20); + values.PutDouble("salary", 300.5); + values.PutBlob("blobType", std::vector{ 7, 8, 9 }); + ret = store->Insert(id, "test", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(3, id); + + ret = store->Delete(deletedRows, "test", "id = 1"); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, deletedRows); + + std::unique_ptr resultSet = + store->QuerySql("SELECT * FROM test WHERE id = ?", std::vector{ "1" }); + EXPECT_NE(resultSet, nullptr); + ret = resultSet->GoToNextRow(); + EXPECT_EQ(ret, E_ERROR); + ret = resultSet->Close(); + EXPECT_EQ(ret, E_OK); + + resultSet = store->QuerySql("SELECT * FROM test WHERE id = ?", std::vector{ "2" }); + EXPECT_NE(resultSet, nullptr); + ret = resultSet->GoToFirstRow(); + EXPECT_EQ(ret, E_OK); + ret = resultSet->GoToNextRow(); + EXPECT_EQ(ret, E_ERROR); + ret = resultSet->Close(); + EXPECT_EQ(ret, E_OK); + + resultSet = store->QuerySql("SELECT * FROM test WHERE id = 3", std::vector()); + EXPECT_NE(resultSet, nullptr); + ret = resultSet->GoToFirstRow(); + EXPECT_EQ(ret, E_OK); + ret = resultSet->GoToNextRow(); + EXPECT_EQ(ret, E_ERROR); + ret = resultSet->Close(); + EXPECT_EQ(ret, E_OK); +} + +/** + * @tc.name: RdbStore_Delete_002 + * @tc.desc: test RdbStore update, select id and update one row + * @tc.type: FUNC + * @tc.require: AR000CU2BO + * @tc.author: + */ +HWTEST_F(RdbTest, RdbStore_Delete_002, TestSize.Level1) +{ + std::shared_ptr &store = RdbTest::store; + + int64_t id; + ValuesBucket values; + int deletedRows; + + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 18); + values.PutDouble("salary", 100.5); + values.PutBlob("blobType", std::vector{ 1, 2, 3 }); + 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")); + values.PutInt("age", 19); + values.PutDouble("salary", 200.5); + values.PutBlob("blobType", std::vector{ 4, 5, 6 }); + 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("wangyjing")); + values.PutInt("age", 20); + values.PutDouble("salary", 300.5); + values.PutBlob("blobType", std::vector{ 7, 8, 9 }); + ret = store->Insert(id, "test", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(3, id); + + ret = store->Delete(deletedRows, "test"); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(3, deletedRows); + + std::unique_ptr resultSet = store->QuerySql("SELECT * FROM test"); + EXPECT_NE(resultSet, nullptr); + ret = resultSet->GoToNextRow(); + EXPECT_EQ(ret, E_ERROR); + ret = resultSet->Close(); + EXPECT_EQ(ret, E_OK); +} + +/** + * @tc.name: RdbStore_Encrypt_Decrypt_Test_001 + * @tc.desc: test RdbStore Get Encrypt Store + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbTest, RdbStore_Encrypt_01, TestSize.Level1) +{ + RdbStoreConfig config(RdbTest::ENCRYPTED_DATABASE_NAME); + config.SetEncryptStatus(true); + config.SetBundleName("com.example.TestEncrypt1"); + EncryptTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); +} + +/** + * @tc.name: RdbStore_Encrypt_Decrypt_Test_002 + * @tc.desc: test RdbStore Get Unencrypted Store + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbTest, RdbStore_Encrypt_02, TestSize.Level1) +{ + RdbStoreConfig config(RdbTest::UNENCRYPTED_DATABASE_NAME); + config.SetEncryptStatus(false); + config.SetBundleName("com.example.TestEncrypt2"); + EncryptTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); +} + +/** + * @tc.name: RdbStore_Encrypt_Decrypt_Test_003 + * @tc.desc: test create encrypted Rdb and insert data ,then query + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbTest, RdbStore_Encrypt_03, TestSize.Level1) +{ + RdbStoreConfig config(RdbTest::ENCRYPTED_DATABASE_NAME); + config.SetEncryptStatus(true); + config.SetBundleName("com.example.TestEncrypt3"); + EncryptTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + + int64_t id; + ValuesBucket values; + + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 18); + values.PutDouble("salary", 100.5); + values.PutBlob("blobType", std::vector{ 1, 2, 3 }); + int ret = store->Insert(id, "test", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, id); + + std::unique_ptr resultSet = store->QuerySql("SELECT * FROM test"); + EXPECT_NE(resultSet, nullptr); + + ret = resultSet->GoToNextRow(); + EXPECT_EQ(ret, E_OK); + + int columnIndex; + int intVal; + std::string strVal; + double dVal; + std::vector blob; + + ret = resultSet->GetColumnIndex("id", columnIndex); + EXPECT_EQ(ret, E_OK); + 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->GetString(columnIndex, strVal); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ("zhangsan", strVal); + + ret = resultSet->GetColumnIndex("age", columnIndex); + EXPECT_EQ(ret, E_OK); + ret = resultSet->GetInt(columnIndex, intVal); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(18, intVal); + + ret = resultSet->GetColumnIndex("salary", columnIndex); + EXPECT_EQ(ret, E_OK); + ret = resultSet->GetDouble(columnIndex, dVal); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(100.5, dVal); + + ret = resultSet->GetColumnIndex("blobType", columnIndex); + EXPECT_EQ(ret, E_OK); + ret = resultSet->GetBlob(columnIndex, blob); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(3, static_cast(blob.size())); + EXPECT_EQ(1, blob[0]); + + ret = resultSet->GoToNextRow(); + EXPECT_EQ(ret, E_ERROR); + + ret = resultSet->Close(); + EXPECT_EQ(ret, E_OK); +} + +/** + * @tc.name: RdbStore_Encrypt_Decrypt_Test_004 + * @tc.desc: test RdbStore key file. + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbTest, RdbStore_Encrypt_04, TestSize.Level1) +{ + RdbStoreConfig config(RdbTest::ENCRYPTED_DATABASE_NAME); + config.SetEncryptStatus(true); + config.SetBundleName("com.example.TestEncrypt4"); + EncryptTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + std::string keyPath = RDB_TEST_PATH + "key/encrypted.pub_key"; + int ret = access(keyPath.c_str(), F_OK); + EXPECT_EQ(ret, 0); + + RdbHelper::DeleteRdbStore(RdbTest::ENCRYPTED_DATABASE_NAME); + ret = access(keyPath.c_str(), F_OK); + EXPECT_EQ(ret, -1); +} + +/** + * @tc.name: RdbStore_Encrypt_Decrypt_Test_005 + * @tc.desc: test RdbStore Get Encrypted Store with empty boundlename + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbTest, RdbStore_Encrypt_05, TestSize.Level1) +{ + RdbStoreConfig config(RdbTest::ENCRYPTED_DATABASE_NAME); + config.SetEncryptStatus(true); + config.SetBundleName(""); + EncryptTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_EQ(store, nullptr); +} + +/** + * @tc.name: RdbStore_Encrypt_Decrypt_Test_006 + * @tc.desc: test SaveSecretKeyToFile when KeyFileType isNot PUB_KEY_FILE + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbTest, RdbStore_Encrypt_06, TestSize.Level1) +{ + RdbStoreConfig config(RdbTest::ENCRYPTED_DATABASE_NAME); + config.SetEncryptStatus(true); + config.SetBundleName("com.example.TestEncrypt6"); + EncryptTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + bool ret = + RdbSecurityManager::GetInstance().CheckKeyDataFileExists(RdbSecurityManager::KeyFileType::PUB_KEY_BAK_FILE); + EXPECT_EQ(ret, false); + std::vector key = RdbSecurityManager::GetInstance().GenerateRandomNum(RdbSecurityManager::RDB_KEY_SIZE); + bool flag = RdbSecurityManager::GetInstance().SaveSecretKeyToFile( + RdbSecurityManager::KeyFileType::PUB_KEY_BAK_FILE, key); + EXPECT_EQ(flag, true); +} + +/** + * @tc.name: RdbStore_Encrypt_Decrypt_Test_007 + * @tc.desc: test GetRdbPassword when KeyFileType isNot PUB_KEY_FILE + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbTest, RdbStore_Encrypt_07, TestSize.Level1) +{ + RdbStoreConfig config(RdbTest::ENCRYPTED_DATABASE_NAME); + config.SetEncryptStatus(true); + config.SetBundleName("com.example.TestEncrypt7"); + EncryptTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + auto key = RdbSecurityManager::GetInstance().GetRdbPassword(RdbSecurityManager::KeyFileType::PUB_KEY_BAK_FILE); + RdbPassword password = {}; + EXPECT_EQ(key, password); +} + +/** + * @tc.name: RdbStore_Encrypt_Decrypt_Test_008 + * @tc.desc: test RemoveSuffix when pos == std::string::npos + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbTest, RdbStore_Encrypt_08, TestSize.Level1) +{ + std::string path = RDB_TEST_PATH + "test"; + RdbStoreConfig config(path); + config.SetEncryptStatus(true); + config.SetBundleName("com.example.TestEncrypt8"); + EncryptTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); +} + +/** + * @tc.name: RdbStore_Encrypt_Decrypt_Test_009 + * @tc.desc: test GetKeyDistributedStatus and SetKeyDistributedStatus + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(RdbTest, RdbStore_Encrypt_09, TestSize.Level1) +{ + RdbStoreConfig config(RdbTest::ENCRYPTED_DATABASE_NAME); + config.SetEncryptStatus(true); + config.SetBundleName("com.example.TestEncrypt9"); + EncryptTestOpenCallback helper; + int errCode; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + + bool distributedStatus = false; + int ret = RdbSecurityManager::GetInstance().GetKeyDistributedStatus( + RdbSecurityManager::KeyFileType::PUB_KEY_FILE, distributedStatus); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(distributedStatus, false); + ret = RdbSecurityManager::GetInstance().GetKeyDistributedStatus( + RdbSecurityManager::KeyFileType::PUB_KEY_BAK_FILE, distributedStatus); + EXPECT_EQ(ret, E_ERROR); + EXPECT_EQ(distributedStatus, false); + ret = RdbSecurityManager::GetInstance().SetKeyDistributedStatus( + RdbSecurityManager::KeyFileType::PUB_KEY_FILE, true); + EXPECT_EQ(ret, E_OK); + ret = RdbSecurityManager::GetInstance().GetKeyDistributedStatus( + RdbSecurityManager::KeyFileType::PUB_KEY_FILE, distributedStatus); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(distributedStatus, true); + ret = RdbSecurityManager::GetInstance().SetKeyDistributedStatus( + RdbSecurityManager::KeyFileType::PUB_KEY_BAK_FILE, distributedStatus); + EXPECT_EQ(ret, E_ERROR); +} + +/** + * @tc.name: RdbStore_Execute_001 + * @tc.desc: test RdbStore Execute + * @tc.type: FUNC + * @tc.require: AR000CU2BO + * @tc.author: + */ +HWTEST_F(RdbTest, RdbStore_Execute_001, TestSize.Level1) +{ + std::shared_ptr &store = RdbTest::store; + + int64_t id; + ValuesBucket values; + + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 18); + values.PutDouble("salary", 100.5); + values.PutBlob("blobType", std::vector{ 1, 2, 3 }); + 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")); + values.PutInt("age", 19); + values.PutDouble("salary", 200.5); + values.PutBlob("blobType", std::vector{ 4, 5, 6 }); + 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("wangyjing")); + values.PutInt("age", 20); + values.PutDouble("salary", 300.5); + values.PutBlob("blobType", std::vector{ 7, 8, 9 }); + ret = store->Insert(id, "test", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(3, id); + + int64_t count; + ret = store->ExecuteAndGetLong(count, "SELECT COUNT(*) FROM test"); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(count, 3); + + ret = store->ExecuteSql("DELETE FROM test WHERE age = ? OR age = ?", + std::vector{ ValueObject(std::string("18")), ValueObject(std ::string("20")) }); + EXPECT_EQ(ret, E_OK); + + ret = store->ExecuteAndGetLong(count, "SELECT COUNT(*) FROM test where age = 19"); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(count, 1); + + ret = store->ExecuteSql("DELETE FROM test WHERE age = 19"); + EXPECT_EQ(ret, E_OK); + + ret = store->ExecuteAndGetLong(count, "SELECT COUNT(*) FROM test"); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(count, 0); +} + +/** + * @tc.name: RdbStore_Execute_002 + * @tc.desc: test RdbStore Execute + * @tc.type: FUNC + * @tc.require: AR000CU2BO + * @tc.author: + */ +HWTEST_F(RdbTest, RdbStore_Execute_002, TestSize.Level1) +{ + std::shared_ptr &store = RdbTest::store; + + int64_t id; + ValuesBucket values; + + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 18); + values.PutDouble("salary", 100.5); + values.PutBlob("blobType", std::vector{ 1, 2, 3 }); + 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")); + values.PutInt("age", 19); + values.PutDouble("salary", 200.5); + values.PutBlob("blobType", std::vector{ 4, 5, 6 }); + ret = store->Insert(id, "test", values); + EXPECT_EQ(2, id); + + values.Clear(); + values.PutInt("id", 3); + values.PutString("name", std::string("wangyjing")); + values.PutInt("age", 20); + values.PutDouble("salary", 300.5); + values.PutBlob("blobType", std::vector{ 7, 8, 9 }); + ret = store->Insert(id, "test", values); + EXPECT_EQ(3, id); + + int64_t count; + ret = store->ExecuteAndGetLong(count, "SELECT COUNT(*) FROM test", std::vector()); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(count, 3); + + ret = store->ExecuteSql("DELETE FROM test WHERE age = ? OR age = ?", + std::vector{ ValueObject(std::string("18")), ValueObject(std ::string("20")) }); + EXPECT_EQ(ret, E_OK); + + ret = store->ExecuteAndGetLong( + count, "SELECT COUNT(*) FROM test where age = ?", std::vector{ ValueObject(std::string("19")) }); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(count, 1); + + ret = store->ExecuteSql("DELETE FROM test WHERE age = 19"); + EXPECT_EQ(ret, E_OK); + + ret = store->ExecuteAndGetLong(count, "SELECT COUNT(*) FROM test", std::vector()); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(count, 0); + + ret = store->ExecuteSql("DROP TABLE IF EXISTS test"); + EXPECT_EQ(ret, E_OK); + + ret = store->ExecuteAndGetLong(count, "SELECT COUNT(*) FROM test"); + EXPECT_EQ(ret, -1); +} + +/** + * @tc.name: RdbStore_Execute_003 + * @tc.desc: test RdbStore Execute + * @tc.type: FUNC + * @tc.require: AR000CU2BO + * @tc.author: + */ +HWTEST_F(RdbTest, RdbStore_Execute_003, TestSize.Level1) +{ + std::shared_ptr &store = RdbTest::store; + + int64_t pageSize; + int ret = store->ExecuteAndGetLong(pageSize, "PRAGMA page_size"); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(pageSize, 4096); + + std::string journalMode; + ret = store->ExecuteAndGetString(journalMode, "PRAGMA journal_mode"); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(journalMode, "wal"); +} + +/** + * @tc.name: RdbStore_Insert_001 + * @tc.desc: test RdbStore insert + * @tc.type: FUNC + * @tc.require: AR000CU2BO + * @tc.author: + */ +HWTEST_F(RdbTest, RdbStore_Insert_001, TestSize.Level1) +{ + std::shared_ptr &store = RdbTest::store; + + int64_t id; + ValuesBucket values; + + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 18); + values.PutDouble("salary", 100.5); + values.PutBlob("blobType", std::vector{ 1, 2, 3 }); + 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")); + values.PutInt("age", 18); + values.PutDouble("salary", 100.5); + values.PutBlob("blobType", std::vector{ 1, 2, 3 }); + 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")); + values.PutInt("age", 20L); + values.PutDouble("salary", 100.5f); + values.PutBlob("blobType", std::vector{ 1, 2, 3 }); + ret = store->Insert(id, "test", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(3, id); + + RdbTest::CheckResultSet(store); +} + +void RdbTest::CheckResultSet(std::shared_ptr &store) +{ + std::unique_ptr resultSet = + store->QuerySql("SELECT * FROM test WHERE name = ?", std::vector{ "zhangsan" }); + EXPECT_NE(resultSet, nullptr); + + int columnIndex; + int intVal; + std::string strVal; + ColumnType columnType; + int position; + int ret = resultSet->GetRowIndex(position); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(position, -1); + + ret = resultSet->GetColumnType(0, columnType); + EXPECT_EQ(ret, E_INVALID_STATEMENT); + + ret = resultSet->GoToFirstRow(); + EXPECT_EQ(ret, E_OK); + + ret = resultSet->GetColumnIndex("id", columnIndex); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(columnIndex, 0); + ret = resultSet->GetColumnType(columnIndex, columnType); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(columnType, ColumnType::TYPE_INTEGER); + 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); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(columnType, ColumnType::TYPE_STRING); + ret = resultSet->GetString(columnIndex, strVal); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ("zhangsan", strVal); + + RdbTest::CheckAge(resultSet); + RdbTest::CheckSalary(resultSet); + RdbTest::CheckBlob(resultSet); + + ret = resultSet->GoToNextRow(); + EXPECT_EQ(ret, E_ERROR); + + ret = resultSet->GetColumnType(columnIndex, columnType); + EXPECT_EQ(ret, E_INVALID_STATEMENT); + + ret = resultSet->Close(); + EXPECT_EQ(ret, E_OK); +} + +void RdbTest::CheckAge(std::unique_ptr &resultSet) +{ + int columnIndex; + int intVal; + ColumnType columnType; + int ret = resultSet->GetColumnIndex("age", columnIndex); + EXPECT_EQ(ret, E_OK); + ret = resultSet->GetColumnType(columnIndex, columnType); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(columnType, ColumnType::TYPE_INTEGER); + ret = resultSet->GetInt(columnIndex, intVal); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(18, intVal); +} + +void RdbTest::CheckSalary(std::unique_ptr &resultSet) +{ + int columnIndex; + double dVal; + ColumnType columnType; + int ret = resultSet->GetColumnIndex("salary", columnIndex); + EXPECT_EQ(ret, E_OK); + ret = resultSet->GetColumnType(columnIndex, columnType); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(columnType, ColumnType::TYPE_FLOAT); + ret = resultSet->GetDouble(columnIndex, dVal); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(100.5, dVal); +} + +void RdbTest::CheckBlob(std::unique_ptr &resultSet) +{ + int columnIndex; + std::vector blob; + ColumnType columnType; + int ret = resultSet->GetColumnIndex("blobType", columnIndex); + EXPECT_EQ(ret, E_OK); + ret = resultSet->GetColumnType(columnIndex, columnType); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(columnType, ColumnType::TYPE_BLOB); + ret = resultSet->GetBlob(columnIndex, blob); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(3, static_cast(blob.size())); + EXPECT_EQ(1, blob[0]); + EXPECT_EQ(2, blob[1]); + EXPECT_EQ(3, blob[2]); +} + +/** + * @tc.name: RdbStore_Replace_001 + * @tc.desc: test RdbStore replace + * @tc.type: FUNC + * @tc.require: AR000CU2BO + * @tc.author: + */ +HWTEST_F(RdbTest, RdbStore_Replace_001, TestSize.Level1) +{ + std::shared_ptr &store = RdbTest::store; + + int64_t id; + ValuesBucket values; + + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 18); + values.PutDouble("salary", 100.5); + values.PutBlob("blobType", std::vector{ 1, 2, 3 }); + int ret = store->Replace(id, "test", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, id); + + std::unique_ptr resultSet = store->QuerySql("SELECT * FROM test"); + EXPECT_NE(resultSet, nullptr); + + ret = resultSet->GoToNextRow(); + EXPECT_EQ(ret, E_OK); + + int columnIndex; + int intVal; + std::string strVal; + double dVal; + std::vector blob; + + ret = resultSet->GetColumnIndex("id", columnIndex); + EXPECT_EQ(ret, E_OK); + 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->GetString(columnIndex, strVal); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ("zhangsan", strVal); + + ret = resultSet->GetColumnIndex("age", columnIndex); + EXPECT_EQ(ret, E_OK); + ret = resultSet->GetInt(columnIndex, intVal); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(18, intVal); + + ret = resultSet->GetColumnIndex("salary", columnIndex); + EXPECT_EQ(ret, E_OK); + ret = resultSet->GetDouble(columnIndex, dVal); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(100.5, dVal); + + ret = resultSet->GetColumnIndex("blobType", columnIndex); + EXPECT_EQ(ret, E_OK); + ret = resultSet->GetBlob(columnIndex, blob); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(3, static_cast(blob.size())); + EXPECT_EQ(1, blob[0]); + EXPECT_EQ(2, blob[1]); + EXPECT_EQ(3, blob[2]); + + ret = resultSet->GoToNextRow(); + EXPECT_EQ(ret, E_ERROR); + + ret = resultSet->Close(); + EXPECT_EQ(ret, E_OK); +} + +/** + * @tc.name: RdbStore_Replace_002 + * @tc.desc: test RdbStore replace + * @tc.type: FUNC + * @tc.require: AR000CU2BO + * @tc.author: + */ +HWTEST_F(RdbTest, RdbStore_Replace_002, TestSize.Level1) +{ + std::shared_ptr &store = RdbTest::store; + + int64_t id; + ValuesBucket values; + + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 18); + values.PutDouble("salary", 100.5); + values.PutBlob("blobType", std::vector{ 1, 2, 3 }); + int ret = store->Insert(id, "test", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, id); + + values.Clear(); + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 18); + values.PutDouble("salary", 200.5); + values.PutBlob("blobType", std::vector{ 1, 2, 3 }); + ret = store->Replace(id, "test", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, id); + + std::unique_ptr resultSet = store->QuerySql("SELECT * FROM test"); + EXPECT_NE(resultSet, nullptr); + + ret = resultSet->GoToNextRow(); + EXPECT_EQ(ret, E_OK); + + int columnIndex; + int intVal; + std::string strVal; + double dVal; + std::vector blob; + + ret = resultSet->GetColumnIndex("id", columnIndex); + EXPECT_EQ(ret, E_OK); + 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->GetString(columnIndex, strVal); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ("zhangsan", strVal); + + ret = resultSet->GetColumnIndex("age", columnIndex); + EXPECT_EQ(ret, E_OK); + ret = resultSet->GetInt(columnIndex, intVal); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(18, intVal); + + ret = resultSet->GetColumnIndex("salary", columnIndex); + EXPECT_EQ(ret, E_OK); + ret = resultSet->GetDouble(columnIndex, dVal); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(200.5, dVal); + + ret = resultSet->GetColumnIndex("blobType", columnIndex); + EXPECT_EQ(ret, E_OK); + ret = resultSet->GetBlob(columnIndex, blob); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(3, static_cast(blob.size())); + EXPECT_EQ(1, blob[0]); + EXPECT_EQ(2, blob[1]); + EXPECT_EQ(3, blob[2]); + + ret = resultSet->GoToNextRow(); + EXPECT_EQ(ret, E_ERROR); + + ret = resultSet->Close(); + EXPECT_EQ(ret, E_OK); +} + +/** + * @tc.name: RdbStore_InsertWithConflictResolution_001_002 + * @tc.desc: test RdbStore InsertWithConflictResolution + * @tc.type: FUNC + * @tc.require: AR000CU2BO + * @tc.author: + */ +HWTEST_F(RdbTest, RdbStore_InsertWithConflictResolution_001_002, TestSize.Level1) +{ + std::shared_ptr &store = RdbTest::store; + + int64_t id; + ValuesBucket values; + + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 18); + values.PutDouble("salary", 100.5); + values.PutBlob("blobType", std::vector{ 1, 2, 3 }); + + // default is ConflictResolution::ON_CONFLICT_NONE + int ret = store->InsertWithConflictResolution(id, "test", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, id); + + values.Clear(); + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 18); + values.PutDouble("salary", 200.5); + values.PutBlob("blobType", std::vector{ 1, 2, 3 }); + ret = store->InsertWithConflictResolution(id, "test", values); + EXPECT_EQ(ret, RdbTest::E_SQLITE_CONSTRAINT); +} + +/** + * @tc.name: RdbStore_InsertWithConflictResolution_003_004 + * @tc.desc: test RdbStore InsertWithConflictResolution + * @tc.type: FUNC + * @tc.require: AR000CU2BO + * @tc.author: + */ +HWTEST_F(RdbTest, RdbStore_InsertWithConflictResolution_003_004, TestSize.Level1) +{ + std::shared_ptr &store = RdbTest::store; + + int64_t id; + ValuesBucket values; + + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 18); + values.PutDouble("salary", 100.5); + values.PutBlob("blobType", std::vector{ 1, 2, 3 }); + int ret = store->InsertWithConflictResolution(id, "test", values, ConflictResolution::ON_CONFLICT_ROLLBACK); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, id); + + values.Clear(); + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 18); + values.PutDouble("salary", 200.5); + values.PutBlob("blobType", std::vector{ 1, 2, 3 }); + ret = store->InsertWithConflictResolution(id, "test", values, ConflictResolution::ON_CONFLICT_ROLLBACK); + EXPECT_EQ(ret, RdbTest::E_SQLITE_CONSTRAINT); +} + +/** + * @tc.name: RdbStore_InsertWithConflictResolution_005 + * @tc.desc: test RdbStore InsertWithConflictResolution + * @tc.type: FUNC + * @tc.require: AR000CU2BO + * @tc.author: + */ +HWTEST_F(RdbTest, RdbStore_InsertWithConflictResolution_005, TestSize.Level1) +{ + std::shared_ptr &store = RdbTest::store; + + int64_t id; + ValuesBucket values; + + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 18); + values.PutDouble("salary", 100.5); + values.PutBlob("blobType", std::vector{ 1, 2, 3 }); + int ret = store->InsertWithConflictResolution(id, "test", values, ConflictResolution::ON_CONFLICT_IGNORE); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, id); + + values.Clear(); + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 18); + values.PutDouble("salary", 200.5); + values.PutBlob("blobType", std::vector{ 1, 2, 3 }); + ret = store->InsertWithConflictResolution(id, "test", values, ConflictResolution::ON_CONFLICT_IGNORE); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(id, -1); +} + +/** + * @tc.name: RdbStore_InsertWithConflictResolution_006_007 + * @tc.desc: test RdbStore InsertWithConflictResolution + * @tc.type: FUNC + * @tc.require: AR000CU2BO + * @tc.author: + */ +HWTEST_F(RdbTest, RdbStore_InsertWithConflictResolution_006_007, TestSize.Level1) +{ + std::shared_ptr &store = RdbTest::store; + + int64_t id; + ValuesBucket values; + + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 18); + values.PutDouble("salary", 100.5); + values.PutBlob("blobType", std::vector{ 1, 2, 3 }); + int ret = store->InsertWithConflictResolution(id, "test", values, ConflictResolution::ON_CONFLICT_REPLACE); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, id); + + values.Clear(); + values.PutInt("id", 1); + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 18); + values.PutDouble("salary", 200.5); + values.PutBlob("blobType", std::vector{ 4, 5, 6 }); + ret = store->InsertWithConflictResolution(id, "test", values, ConflictResolution::ON_CONFLICT_REPLACE); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(id, 1); + + std::unique_ptr resultSet = store->QuerySql("SELECT * FROM test"); + EXPECT_NE(resultSet, nullptr); + + ret = resultSet->GoToNextRow(); + EXPECT_EQ(ret, E_OK); + + int columnIndex; + int intVal; + std::string strVal; + double dVal; + std::vector blob; + + ret = resultSet->GetColumnIndex("id", columnIndex); + EXPECT_EQ(ret, E_OK); + 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->GetString(columnIndex, strVal); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ("zhangsan", strVal); + + ret = resultSet->GetColumnIndex("age", columnIndex); + EXPECT_EQ(ret, E_OK); + ret = resultSet->GetInt(columnIndex, intVal); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(18, intVal); + + ret = resultSet->GetColumnIndex("salary", columnIndex); + EXPECT_EQ(ret, E_OK); + ret = resultSet->GetDouble(columnIndex, dVal); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(200.5, dVal); + + ret = resultSet->GetColumnIndex("blobType", columnIndex); + EXPECT_EQ(ret, E_OK); + ret = resultSet->GetBlob(columnIndex, blob); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(3, static_cast(blob.size())); + EXPECT_EQ(4, blob[0]); + EXPECT_EQ(5, blob[1]); + EXPECT_EQ(6, blob[2]); + + ret = resultSet->GoToNextRow(); + EXPECT_EQ(ret, E_ERROR); + + ret = resultSet->Close(); + EXPECT_EQ(ret, E_OK); +} + +/** + * @tc.name: RdbStore_BatchInsert_001 + * @tc.desc: test RdbStore BatchInsert + * @tc.type: FUNC + * @tc.require: issueI5GZGX + */ +HWTEST_F(RdbTest, RdbStore_BatchInsert_001, TestSize.Level1) +{ + std::shared_ptr &store = RdbTest::store; + + ValuesBucket values; + + values.PutString("name", "zhangsan"); + values.PutInt("age", 18); + values.PutDouble("salary", 100.5); + values.PutBlob("blobType", std::vector{ 1, 2, 3 }); + + std::vector valuesBuckets; + for (int i = 0; i < 100; i++) { + valuesBuckets.push_back(values); + } + int64_t insertNum = 0; + int ret = store->BatchInsert(insertNum, "test", valuesBuckets); + EXPECT_EQ(E_OK, ret); + EXPECT_EQ(100, insertNum); + std::unique_ptr resultSet = store->QuerySql("SELECT * FROM test"); + int rowCount = 0; + resultSet->GetRowCount(rowCount); + EXPECT_EQ(100, rowCount); +} + +/** + * @tc.name: ValueObject_TEST_001 + * @tc.desc: test ValueObject + * @tc.type: FUNC + * @tc.require: AR000CU2BO + * @tc.author: + */ +HWTEST_F(RdbTest, ValueObject_TEST_001, TestSize.Level1) +{ + ValueObject obj = ValueObject(); + ValueObjectType type = obj.GetType(); + EXPECT_EQ(type, ValueObjectType::TYPE_NULL); +} + +/** + * @tc.name: ValueObject_TEST_002 + * @tc.desc: test ValueObject + * @tc.type: FUNC + * @tc.require: AR000CU2BO + * @tc.author: + */ +HWTEST_F(RdbTest, ValueObject_TEST_002, TestSize.Level1) +{ + int inputVal = 5; + int outputVal = 0; + ValueObject obj = ValueObject(inputVal); + ValueObjectType type = obj.GetType(); + EXPECT_EQ(type, ValueObjectType::TYPE_INT); + int ret = obj.GetInt(outputVal); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(outputVal, 5); +} + +/** + * @tc.name: ValueObject_TEST_003 + * @tc.desc: test ValueObject + * @tc.type: FUNC + * @tc.require: AR000CU2BO + * @tc.author: + */ +HWTEST_F(RdbTest, ValueObject_TEST_003, TestSize.Level1) +{ + bool inputVal = true; + bool outputVal = false; + ValueObject obj = ValueObject(inputVal); + ValueObjectType type = obj.GetType(); + EXPECT_EQ(type, ValueObjectType::TYPE_BOOL); + int ret = obj.GetBool(outputVal); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(outputVal, true); +} + +/** + * @tc.name: ValueObject_TEST_004 + * @tc.desc: test ValueObject + * @tc.type: FUNC + * @tc.require: AR000CU2BO + * @tc.author: + */ +HWTEST_F(RdbTest, ValueObject_TEST_004, TestSize.Level1) +{ + std::string inputVal = "hello"; + std::string outputVal = ""; + ValueObject obj = ValueObject(inputVal); + ValueObjectType type = obj.GetType(); + EXPECT_EQ(type, ValueObjectType::TYPE_STRING); + int ret = obj.GetString(outputVal); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(outputVal, "hello"); +} + +/** + * @tc.name: ValueObject_TEST_005 + * @tc.desc: test ValueObject + * @tc.type: FUNC + * @tc.require: AR000CU2BO + * @tc.author: + */ +HWTEST_F(RdbTest, ValueObject_TEST_005, TestSize.Level1) +{ + std::vector inputVal = { 'h', 'e', 'l', 'l', 'o' }; + std::vector outputVal; + ValueObject obj = ValueObject(inputVal); + ValueObjectType type = obj.GetType(); + EXPECT_EQ(type, ValueObjectType::TYPE_BLOB); + int ret = obj.GetBlob(outputVal); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(static_cast(outputVal.size()), 5); + EXPECT_EQ(outputVal[0], 'h'); + EXPECT_EQ(outputVal[1], 'e'); + EXPECT_EQ(outputVal[2], 'l'); + EXPECT_EQ(outputVal[3], 'l'); + EXPECT_EQ(outputVal[4], 'o'); +} + +/** + * @tc.name: ValueObject_TEST_006 + * @tc.desc: test ValueObject + * @tc.type: FUNC + * @tc.require: AR000CU2BO + * @tc.author: + */ +HWTEST_F(RdbTest, ValueObject_TEST_006, TestSize.Level1) +{ + int inputVal = 5; + ValueObject obj = ValueObject(inputVal); + ValueObject obj1 = ValueObject(); + obj1 = obj; + ValueObjectType type = obj1.GetType(); + EXPECT_EQ(type, ValueObjectType::TYPE_INT); +} + +/** + * @tc.name: ValuesBucket_001 + * @tc.desc: test ValuesBucket + * @tc.type: FUNC + * @tc.require: AR000CU2BO + * @tc.author: + */ +HWTEST_F(RdbTest, ValuesBucket_001, TestSize.Level1) +{ + ValuesBucket values; + values.PutInt("id", 1); + values.PutNull("name"); + values.PutInt("age", 18); + values.PutDouble("salary", 100.5); + values.PutBlob("blobType", std::vector{ 1, 2, 3 }); + + int size = values.Size(); + EXPECT_EQ(size, 5); + bool contains = values.HasColumn("name"); + EXPECT_EQ(contains, true); + ValueObject obj; + contains = values.GetObject("salary", obj); + double val = 0.0; + ValueObjectType type = obj.GetType(); + EXPECT_EQ(type, ValueObjectType::TYPE_DOUBLE); + int ret = obj.GetDouble(val); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(val, 100.5); + + values.Delete("name"); + size = values.Size(); + EXPECT_EQ(size, 4); + contains = values.HasColumn("name"); + EXPECT_EQ(contains, false); + + values.Clear(); + size = values.Size(); + EXPECT_EQ(size, 0); + contains = values.HasColumn("salary"); + EXPECT_EQ(contains, false); +} + +/** + * @tc.name: ValuesBucket_002 + * @tc.desc: test ValuesBucket + * @tc.type: FUNC + * @tc.require: AR000CU2BO + * @tc.author: + */ +HWTEST_F(RdbTest, ValuesBucket_002, TestSize.Level1) +{ + int errCode = E_OK; + const std::string dbPath = RDB_TEST_PATH + "InterfaceTest.db"; + RdbStoreConfig config(dbPath); + MyOpenCallback helper; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + EXPECT_EQ(errCode, E_OK); + + int64_t id; + ValuesBucket values; + values.PutInt("id", 1); + values.PutNull("name"); + values.PutInt("age", 18); + values.PutDouble("salary", 100.5); + values.PutBlob("blobType", std::vector{ 1, 2, 3 }); + int ret = store->Insert(id, "test", values); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, id); + + std::unique_ptr resultSet = store->QuerySql("SELECT * FROM test"); + EXPECT_NE(resultSet, nullptr); + + int columnIndex; + std::string strVal; + + ret = resultSet->GoToFirstRow(); + EXPECT_EQ(ret, E_OK); + + ret = resultSet->GetColumnIndex("name", columnIndex); + EXPECT_EQ(ret, E_OK); + ret = resultSet->GetString(columnIndex, strVal); + EXPECT_EQ(ret, E_OK); + + resultSet->Close(); + resultSet = nullptr; + store = nullptr; + ret = RdbHelper::DeleteRdbStore(dbPath); + EXPECT_EQ(ret, E_OK); +} + +/** + * @tc.name: ValuesBucket_003 + * @tc.desc: test ValuesBucket + * @tc.type: FUNC + * @tc.require: AR000CU2BO + * @tc.author: + */ +HWTEST_F(RdbTest, ValuesBucket_003, TestSize.Level1) +{ + ValuesBucket values; + values.PutBool("boolType", true); + values.PutLong("longType", 1); + + int size = values.Size(); + EXPECT_EQ(size, 2); + bool contains = values.HasColumn("boolType"); + EXPECT_EQ(contains, true); + ValueObject obj; + contains = values.GetObject("boolType", obj); + ValueObjectType type = obj.GetType(); + EXPECT_EQ(type, ValueObjectType::TYPE_BOOL); + bool val1 = false; + int ret = obj.GetBool(val1); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(val1, true); + + contains = values.HasColumn("longType"); + EXPECT_EQ(contains, true); + contains = values.GetObject("longType", obj); + type = obj.GetType(); + EXPECT_EQ(type, ValueObjectType::TYPE_INT64); + int64_t val2 = 0; + ret = obj.GetLong(val2); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(val2, 1); +} + +/** + * @tc.name: RdbStore_UpdateWithConflictResolution_001 + * @tc.desc: test RdbStore UpdateWithConflictResolution + * @tc.type: FUNC + */ +HWTEST_F(RdbTest, RdbStore_UpdateWithConflictResolution_001, TestSize.Level1) +{ + std::shared_ptr &store = RdbTest::store; + + ValuesBucket values; + int changedRows; + int64_t id; + + int ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, id); + + ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1])); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(2, id); + + // update lisi age=19 to wangjing age=20 + values.PutInt("id", 3); + values.PutString("name", std::string("wangjing")); + values.PutInt("age", 20); + values.PutDouble("salary", 300.5); + values.PutBlob("blobType", std::vector{ 7, 8, 9 }); + ret = store->UpdateWithConflictResolution(changedRows, "test", values, "age = 19"); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, changedRows); + + std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test"); + EXPECT_NE(resultSet, nullptr); + + ret = resultSet->GoToNextRow(); + EXPECT_EQ(ret, E_OK); + RdbTest::ExpectValue(resultSet, RowData{ 1, "zhangsan", 18, 100.5, std::vector{ 1, 2, 3 } }); + + ret = resultSet->GoToNextRow(); + EXPECT_EQ(ret, E_OK); + RdbTest::ExpectValue(resultSet, RowData{ 3, "wangjing", 20, 300.5, std::vector{ 7, 8, 9 } }); + + ret = resultSet->GoToNextRow(); + EXPECT_EQ(ret, E_ROW_OUT_RANGE); + + ret = resultSet->Close(); + EXPECT_EQ(ret, E_OK); +} + +/** + * @tc.name: RdbStore_UpdateWithConflictResolution_002 + * @tc.desc: test RdbStore UpdateWithConflictResolution + * @tc.type: FUNC + */ +HWTEST_F(RdbTest, RdbStore_UpdateWithConflictResolution_002, TestSize.Level1) +{ + std::shared_ptr &store = RdbTest::store; + + ValuesBucket values; + int changedRows; + int64_t id; + + int ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, id); + + ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1])); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(2, id); + + // update lisi age=19 to zhangsan age=20 + values.PutInt("id", 3); + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 20); + values.PutDouble("salary", 300.5); + values.PutBlob("blobType", std::vector{ 7, 8, 9 }); + ret = store->UpdateWithConflictResolution(changedRows, "test", values, "age = ?", std::vector{ "19" }, + ConflictResolution::ON_CONFLICT_NONE); + EXPECT_EQ(ret, E_SQLITE_CONSTRAINT); + + std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test"); + EXPECT_NE(resultSet, nullptr); + + ret = resultSet->GoToNextRow(); + EXPECT_EQ(ret, E_OK); + RdbTest::ExpectValue(resultSet, RowData{ 1, "zhangsan", 18, 100.5, std::vector{ 1, 2, 3 } }); + + ret = resultSet->GoToNextRow(); + EXPECT_EQ(ret, E_OK); + RdbTest::ExpectValue(resultSet, RowData{ 2, "lisi", 19, 200.5, std::vector{ 4, 5, 6 } }); + + ret = resultSet->GoToNextRow(); + EXPECT_EQ(ret, E_ROW_OUT_RANGE); + + ret = resultSet->Close(); + EXPECT_EQ(ret, E_OK); +} + +/** + * @tc.name: RdbStore_UpdateWithConflictResolution_003 + * @tc.desc: test RdbStore UpdateWithConflictResolution + * @tc.type: FUNC + */ +HWTEST_F(RdbTest, RdbStore_UpdateWithConflictResolution_003, TestSize.Level1) +{ + std::shared_ptr &store = RdbTest::store; + + ValuesBucket values; + int changedRows; + int64_t id; + + int ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, id); + + ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1])); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(2, id); + + // update lisi age=19 to wangjing age=20 + values.PutInt("id", 3); + values.PutString("name", std::string("wangjing")); + values.PutInt("age", 20); + values.PutDouble("salary", 300.5); + values.PutBlob("blobType", std::vector{ 7, 8, 9 }); + ret = store->UpdateWithConflictResolution(changedRows, "test", values, "age = ?", std::vector{ "19" }, + ConflictResolution::ON_CONFLICT_ROLLBACK); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, changedRows); + + std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test"); + EXPECT_NE(resultSet, nullptr); + + ret = resultSet->GoToNextRow(); + EXPECT_EQ(ret, E_OK); + RdbTest::ExpectValue(resultSet, RowData{ 1, "zhangsan", 18, 100.5, std::vector{ 1, 2, 3 } }); + + ret = resultSet->GoToNextRow(); + EXPECT_EQ(ret, E_OK); + RdbTest::ExpectValue(resultSet, RowData{ 3, "wangjing", 20, 300.5, std::vector{ 7, 8, 9 } }); + + ret = resultSet->GoToNextRow(); + EXPECT_EQ(ret, E_ROW_OUT_RANGE); + + ret = resultSet->Close(); + EXPECT_EQ(ret, E_OK); +} + +/** + * @tc.name: RdbStore_UpdateWithConflictResolution_004 + * @tc.desc: test RdbStore UpdateWithConflictResolution + * @tc.type: FUNC + */ +HWTEST_F(RdbTest, RdbStore_UpdateWithConflictResolution_004, TestSize.Level1) +{ + std::shared_ptr &store = RdbTest::store; + + ValuesBucket values; + int changedRows; + int64_t id; + + int ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, id); + + ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1])); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(2, id); + + // update lisi age=19 to zhangsan age=20 + values.PutInt("id", 3); + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 20); + values.PutDouble("salary", 300.5); + values.PutBlob("blobType", std::vector{ 7, 8, 9 }); + ret = store->UpdateWithConflictResolution(changedRows, "test", values, "age = ?", std::vector{ "19" }, + ConflictResolution::ON_CONFLICT_ROLLBACK); + EXPECT_EQ(ret, E_SQLITE_CONSTRAINT); + + std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test"); + EXPECT_NE(resultSet, nullptr); + + ret = resultSet->GoToNextRow(); + EXPECT_EQ(ret, E_OK); + RdbTest::ExpectValue(resultSet, RowData{ 1, "zhangsan", 18, 100.5, std::vector{ 1, 2, 3 } }); + + ret = resultSet->GoToNextRow(); + EXPECT_EQ(ret, E_OK); + RdbTest::ExpectValue(resultSet, RowData{ 2, "lisi", 19, 200.5, std::vector{ 4, 5, 6 } }); + + ret = resultSet->GoToNextRow(); + EXPECT_EQ(ret, E_ROW_OUT_RANGE); + + ret = resultSet->Close(); + EXPECT_EQ(ret, E_OK); +} + +/** + * @tc.name: RdbStore_UpdateWithConflictResolution_005 + * @tc.desc: test RdbStore UpdateWithConflictResolution + * @tc.type: FUNC + */ +HWTEST_F(RdbTest, RdbStore_UpdateWithConflictResolution_005, TestSize.Level1) +{ + std::shared_ptr &store = RdbTest::store; + + ValuesBucket values; + int changedRows; + int64_t id; + + int ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, id); + + ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1])); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(2, id); + + // update lisi age=19 to wangjing age=20 + values.PutInt("id", 3); + values.PutString("name", std::string("wangjing")); + values.PutInt("age", 20); + values.PutDouble("salary", 300.5); + values.PutBlob("blobType", std::vector{ 7, 8, 9 }); + ret = store->UpdateWithConflictResolution(changedRows, "test", values, "age = ?", std::vector{ "19" }, + ConflictResolution::ON_CONFLICT_REPLACE); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, changedRows); + + std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test"); + EXPECT_NE(resultSet, nullptr); + + ret = resultSet->GoToNextRow(); + EXPECT_EQ(ret, E_OK); + RdbTest::ExpectValue(resultSet, RowData{ 1, "zhangsan", 18, 100.5, std::vector{ 1, 2, 3 } }); + + ret = resultSet->GoToNextRow(); + EXPECT_EQ(ret, E_OK); + RdbTest::ExpectValue(resultSet, RowData{ 3, "wangjing", 20, 300.5, std::vector{ 7, 8, 9 } }); + + ret = resultSet->GoToNextRow(); + EXPECT_EQ(ret, E_ROW_OUT_RANGE); + + ret = resultSet->Close(); + EXPECT_EQ(ret, E_OK); +} + +/** + * @tc.name: RdbStore_UpdateWithConflictResolution_006 + * @tc.desc: test RdbStore UpdateWithConflictResolution + * @tc.type: FUNC + */ +HWTEST_F(RdbTest, RdbStore_UpdateWithConflictResolution_006, TestSize.Level1) +{ + std::shared_ptr &store = RdbTest::store; + + ValuesBucket values; + int changedRows; + int64_t id; + + int ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, id); + + ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1])); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(2, id); + + // update lisi age=19 to zhangsan age=20 + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 20); + values.PutDouble("salary", 300.5); + ret = store->UpdateWithConflictResolution(changedRows, "test", values, "age = ?", std::vector{ "19" }, + ConflictResolution::ON_CONFLICT_REPLACE); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(changedRows, 1); + + std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test"); + EXPECT_NE(resultSet, nullptr); + + ret = resultSet->GoToNextRow(); + EXPECT_EQ(ret, E_OK); + + RdbTest::ExpectValue(resultSet, RowData{ 2, "zhangsan", 20, 300.5, std::vector{ 4, 5, 6 } }); + + ret = resultSet->GoToNextRow(); + EXPECT_EQ(ret, E_ROW_OUT_RANGE); + + ret = resultSet->Close(); + EXPECT_EQ(ret, E_OK); +} + +/** + * @tc.name: RdbStore_UpdateWithConflictResolution_007 + * @tc.desc: test RdbStore UpdateWithConflictResolution + * @tc.type: FUNC + */ +HWTEST_F(RdbTest, RdbStore_UpdateWithConflictResolution_007, TestSize.Level1) +{ + std::shared_ptr &store = RdbTest::store; + + int changedRows; + int64_t id; + ValuesBucket values; + + int ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(1, id); + + values.PutInt("id", 2); + values.PutInt("age", 19); + ret = store->UpdateWithConflictResolution(changedRows, "test", values, "age = ?", std::vector{ "18" }, + static_cast(6)); + EXPECT_EQ(E_INVALID_CONFLICT_FLAG, ret); + EXPECT_EQ(0, changedRows); + + values.Clear(); + values.PutInt("id", 2); + values.PutInt("age", 19); + ret = store->UpdateWithConflictResolution(changedRows, "test", values, "age = ?", std::vector{ "18" }, + static_cast(-1)); + EXPECT_EQ(E_INVALID_CONFLICT_FLAG, ret); + EXPECT_EQ(0, changedRows); +} + +/** + * @tc.name: RdbStore_UpdateSqlBuilder_001 + * @tc.desc: test RdbStore UpdateSqlBuilder + * @tc.type: FUNC + */ +HWTEST_F(RdbTest, RdbStore_UpdateSqlBuilder_001, TestSize.Level1) +{ + ValuesBucket values; + values.PutString("name", std::string("zhangsan")); + values.PutInt("age", 20); + values.PutDouble("salary", 300.5); + + std::vector bindArgs; + std::string updateSql = SqliteSqlBuilder::BuildUpdateString(values, "test", std::vector{ "19" }, "", + "age = ?", "", "", INT_MIN, INT_MIN, bindArgs, ConflictResolution::ON_CONFLICT_NONE); + EXPECT_EQ(updateSql, "UPDATE test SET age=?,name=?,salary=? WHERE age = ?"); + + updateSql = SqliteSqlBuilder::BuildUpdateString(values, "test", std::vector{}, "", "", "", "", + INT_MIN, INT_MIN, bindArgs, ConflictResolution::ON_CONFLICT_NONE); + EXPECT_EQ(updateSql, "UPDATE test SET age=?,name=?,salary=?"); +} + +void RdbTest::ExpectValue( + const std::shared_ptr &resultSet, const RowData &expect) +{ + EXPECT_NE(nullptr, resultSet); + int columnIndex; + int intVal; + int ret; + + if (expect.id != -1) { + ret = resultSet->GetColumnIndex("id", columnIndex); + EXPECT_EQ(ret, E_OK); + ret = resultSet->GetInt(columnIndex, intVal); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(expect.id, intVal); + } + if (expect.name != "") { + std::string strVal; + ret = resultSet->GetColumnIndex("name", columnIndex); + EXPECT_EQ(ret, E_OK); + ret = resultSet->GetString(columnIndex, strVal); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(expect.name, strVal); + } + if (expect.age != -1) { + ret = resultSet->GetColumnIndex("age", columnIndex); + EXPECT_EQ(ret, E_OK); + ret = resultSet->GetInt(columnIndex, intVal); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(expect.age, intVal); + } + if (expect.salary != -1) { + double dVal; + ret = resultSet->GetColumnIndex("salary", columnIndex); + EXPECT_EQ(ret, E_OK); + ret = resultSet->GetDouble(columnIndex, dVal); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(expect.salary, dVal); + } + if (expect.blobType.size() != 0) { + std::vector blob; + ret = resultSet->GetColumnIndex("blobType", columnIndex); + EXPECT_EQ(ret, E_OK); + ret = resultSet->GetBlob(columnIndex, blob); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(expect.blobType.size(), static_cast(blob.size())); + for (int i = 0; i < expect.blobType.size(); i++) { + EXPECT_EQ(expect.blobType[i], blob[i]); + } + } +} diff --git a/relational_store/test/ndk/BUILD.gn b/relational_store/test/ndk/BUILD.gn index b68ae477b1b6ef46cab22e3517e80e4a5f030af2..eba7c49d3c5ce8c42bb0fb251808a7f8c0a898bd 100644 --- a/relational_store/test/ndk/BUILD.gn +++ b/relational_store/test/ndk/BUILD.gn @@ -45,6 +45,7 @@ ohos_unittest("NativeRdbNdkTest") { "unittest/rdb_asset_test.cpp", "unittest/rdb_cursor_test.cpp", "unittest/rdb_predicates_test.cpp", + "unittest/rdb_store_configv2_test.cpp", "unittest/rdb_store_test.cpp", ] diff --git a/relational_store/test/ndk/unittest/rdb_store_configv2_test.cpp b/relational_store/test/ndk/unittest/rdb_store_configv2_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..27e2f3219804a1d47b5ab8b5426e335d30107afb --- /dev/null +++ b/relational_store/test/ndk/unittest/rdb_store_configv2_test.cpp @@ -0,0 +1,199 @@ +/* + * 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 + +#include + +#include "accesstoken_kit.h" +#include "common.h" +#include "grd_api_manager.h" +#include "rdb_errno.h" +#include "relational_store.h" +#include "relational_store_error_code.h" +#include "relational_store_impl.h" +#include "token_setproc.h" + +using namespace testing::ext; +using namespace OHOS::NativeRdb; +using namespace OHOS::Security::AccessToken; +using namespace OHOS::RdbNdk; + +class RdbNativeStoreConfigV2Test : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + static OH_Rdb_ConfigV2 *InitRdbConfig() + { + OH_Rdb_ConfigV2 *config = OH_Rdb_CreateConfig(); + EXPECT_NE(config, nullptr); + OH_Rdb_SetDatabaseDir(config, RDB_TEST_PATH); + OH_Rdb_SetStoreName(config, "rdb_store_test.db"); + OH_Rdb_SetBundleName(config, "com.ohos.example.distributedndk"); + OH_Rdb_SetEncrypted(config, false); + OH_Rdb_SetSecurityLevel(config, OH_Rdb_SecurityLevel::S1); + OH_Rdb_SetArea(config, RDB_SECURITY_AREA_EL1); + + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, OH_Rdb_SetDbType(config, RDB_SQLITE)); + return config; + } +}; + +void RdbNativeStoreConfigV2Test::SetUpTestCase(void) +{ +} + +void RdbNativeStoreConfigV2Test::TearDownTestCase(void) +{ +} + +void RdbNativeStoreConfigV2Test::SetUp(void) +{ +} + +void RdbNativeStoreConfigV2Test::TearDown(void) +{ +} + +/** + * @tc.name: RDB_Native_store_test_001 + * @tc.desc: Normal testCase of store for Update、Query. + * @tc.type: FUNC + */ +HWTEST_F(RdbNativeStoreConfigV2Test, RDB_Native_store_test_001, TestSize.Level1) +{ + mkdir(RDB_TEST_PATH, 0770); + int errCode = 0; + auto config = InitRdbConfig(); + auto storeConfigV2TestRdbStore = OH_Rdb_CreateOrOpen(config, &errCode); + EXPECT_NE(storeConfigV2TestRdbStore, NULL); + char createTableSql[] = "CREATE TABLE store_test (id INTEGER PRIMARY KEY AUTOINCREMENT, data1 TEXT, data2 INTEGER, " + "data3 FLOAT, data4 BLOB, data5 TEXT);"; + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, OH_Rdb_Execute(storeConfigV2TestRdbStore, createTableSql)); + char dropTableSql[] = "DROP TABLE IF EXISTS store_test"; + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, OH_Rdb_Execute(storeConfigV2TestRdbStore, dropTableSql)); + + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, OH_Rdb_CloseStore(storeConfigV2TestRdbStore)); + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, OH_Rdb_DeleteStoreV2(config)); + OH_Rdb_DestroyConfig(config); +} + + +void VdbTest002(const OH_Rdb_ConfigV2 *config) +{ + int errCode = OH_Rdb_ErrCode::RDB_OK; + auto store = OH_Rdb_CreateOrOpen(config, &errCode); + EXPECT_NE(store, nullptr); + + char createTableSql[] = "CREATE TABLE t1(id INT PRIMARY KEY, repr floatvector(4));"; + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, OH_Rdb_ExecuteByTrxId(store, 0, createTableSql)); + + int64_t trxId = 0; + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, OH_Rdb_BeginTransWithTrxId(store, &trxId)); + char insertSql[] = "INSERT INTO t1 VALUES(2, '[1, 2, 3, 4]');"; + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, OH_Rdb_ExecuteByTrxId(store, trxId, insertSql)); + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, OH_Rdb_CommitByTrxId(store, trxId)); + + char querySql[] = "SELECT * FROM t1;"; + OH_Cursor *cursor = OH_Rdb_ExecuteQuery(store, querySql); + EXPECT_NE(cursor, nullptr); + int rowCount = 0; + cursor->getRowCount(cursor, &rowCount); + EXPECT_EQ(1, rowCount); + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, cursor->goToNextRow(cursor)); + int64_t intVal = 0; + cursor->getInt64(cursor, 0, &intVal); + EXPECT_EQ(2, intVal); // Expect to get 2 as the result + cursor->destroy(cursor); + + char dropSql[] = "DROP TABLE IF EXISTS t1;"; + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, OH_Rdb_ExecuteByTrxId(store, 0, dropSql)); + + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, OH_Rdb_DeleteStoreV2(config)); +} + +HWTEST_F(RdbNativeStoreConfigV2Test, RDB_Native_store_test_002, TestSize.Level1) +{ + auto config = InitRdbConfig(); + int errCode = OH_Rdb_SetDbType(config, RDB_CAYLEY); + EXPECT_TRUE(((!OHOS::NativeRdb::IsUsingArkData()) && errCode == OH_Rdb_ErrCode::RDB_E_NOT_SUPPORTED) || + (OHOS::NativeRdb::IsUsingArkData() && errCode == OH_Rdb_ErrCode::RDB_OK)); + if (OHOS::NativeRdb::IsUsingArkData()) { + VdbTest002(config); + } + OH_Rdb_DestroyConfig(config); +} + +HWTEST_F(RdbNativeStoreConfigV2Test, RDB_Native_store_test_003, TestSize.Level1) +{ + int numType = 0; + const int *supportTypeList = OH_Rdb_GetSupportedDbType(&numType); + EXPECT_NE(supportTypeList, nullptr); + EXPECT_TRUE(((!OHOS::NativeRdb::IsUsingArkData()) && numType == 1) || // 1 means only contain RDB_SQLITE + ((OHOS::NativeRdb::IsUsingArkData()) && numType == 2)); // 2 means both contain RDB_SQLITE and RDB_CAYLEY + EXPECT_EQ(RDB_SQLITE, supportTypeList[0]); + if (OHOS::NativeRdb::IsUsingArkData()) { + EXPECT_EQ(RDB_CAYLEY, supportTypeList[1]); // 1st element must be RDB_CAYLEY + } +} + +HWTEST_F(RdbNativeStoreConfigV2Test, RDB_Native_store_test_004, TestSize.Level1) +{ + auto config = InitRdbConfig(); + EXPECT_EQ(OH_Rdb_ErrCode::RDB_E_INVALID_ARGS, OH_Rdb_SetDatabaseDir(config, nullptr)); + EXPECT_EQ(OH_Rdb_ErrCode::RDB_E_INVALID_ARGS, OH_Rdb_SetStoreName(config, nullptr)); + EXPECT_EQ(OH_Rdb_ErrCode::RDB_E_INVALID_ARGS, OH_Rdb_SetBundleName(config, nullptr)); + EXPECT_EQ(OH_Rdb_ErrCode::RDB_E_INVALID_ARGS, OH_Rdb_SetModuleName(config, nullptr)); + + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, OH_Rdb_SetDatabaseDir(config, "")); + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, OH_Rdb_SetStoreName(config, "")); + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, OH_Rdb_SetBundleName(config, "")); + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, OH_Rdb_SetModuleName(config, "")); + + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, OH_Rdb_SetEncrypted(config, false)); + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, OH_Rdb_SetEncrypted(config, true)); + + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, OH_Rdb_SetSecurityLevel(config, S1)); + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, OH_Rdb_SetSecurityLevel(config, S2)); + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, OH_Rdb_SetSecurityLevel(config, S3)); + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, OH_Rdb_SetSecurityLevel(config, S4)); + EXPECT_EQ(OH_Rdb_ErrCode::RDB_E_INVALID_ARGS, OH_Rdb_SetSecurityLevel(config, 0)); // 0 is invalid secure level + EXPECT_EQ(OH_Rdb_ErrCode::RDB_E_INVALID_ARGS, OH_Rdb_SetSecurityLevel(config, -1)); // -1 is invalid secure level + EXPECT_EQ(OH_Rdb_ErrCode::RDB_E_INVALID_ARGS, OH_Rdb_SetSecurityLevel(config, 5)); // 5 is invalid secure level + + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, OH_Rdb_SetArea(config, RDB_SECURITY_AREA_EL1)); + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, OH_Rdb_SetArea(config, RDB_SECURITY_AREA_EL2)); + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, OH_Rdb_SetArea(config, RDB_SECURITY_AREA_EL3)); + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, OH_Rdb_SetArea(config, RDB_SECURITY_AREA_EL4)); + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, OH_Rdb_SetArea(config, RDB_SECURITY_AREA_EL5)); + + EXPECT_EQ(OH_Rdb_ErrCode::RDB_E_INVALID_ARGS, OH_Rdb_SetArea(config, -1)); // -1 is invalid area level + EXPECT_EQ(OH_Rdb_ErrCode::RDB_E_INVALID_ARGS, OH_Rdb_SetArea(config, 0)); // 0 is invalid area level + EXPECT_EQ(OH_Rdb_ErrCode::RDB_E_INVALID_ARGS, OH_Rdb_SetArea(config, 8)); // 8 is invalid area level + + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, OH_Rdb_SetDbType(config, RDB_SQLITE)); + EXPECT_EQ(OH_Rdb_ErrCode::RDB_E_INVALID_ARGS, OH_Rdb_SetDbType(config, 0)); // 0 is invalid db type level + EXPECT_EQ(OH_Rdb_ErrCode::RDB_E_INVALID_ARGS, OH_Rdb_SetDbType(config, 6)); // 6 is invalid db type level + EXPECT_EQ(OH_Rdb_ErrCode::RDB_E_INVALID_ARGS, OH_Rdb_SetDbType(config, -1)); // -1 is invalid db type level + + const int *supportList = OH_Rdb_GetSupportedDbType(nullptr); + EXPECT_EQ(nullptr, supportList); + + EXPECT_EQ(OH_Rdb_ErrCode::RDB_E_INVALID_ARGS, OH_Rdb_DestroyConfig(nullptr)); + EXPECT_EQ(OH_Rdb_ErrCode::RDB_OK, OH_Rdb_DestroyConfig(config)); +} diff --git a/udmf/adapter/BUILD.gn b/udmf/adapter/BUILD.gn index 42963c5f41e80ea8bc7661d6dbb8a92af949feae..32d4ff893f5762f49c7cdf1f535fd27a14a3ee8b 100644 --- a/udmf/adapter/BUILD.gn +++ b/udmf/adapter/BUILD.gn @@ -73,6 +73,7 @@ config("arkui_x_udmf_config") { } arkui_x_public_source = [ + "${udmf_framework_path}/innerkitsimpl/client/getter_system.cpp", "${udmf_framework_path}/innerkitsimpl/common/unified_key.cpp", "${udmf_framework_path}/innerkitsimpl/common/unified_meta.cpp", "${udmf_framework_path}/innerkitsimpl/data/application_defined_record.cpp", @@ -102,9 +103,9 @@ ohos_source_set("arkui_x_udmf_data") { "${udmf_framework_path}/common/custom_utd_json_parser.cpp", "${udmf_framework_path}/common/custom_utd_store.cpp", "${udmf_framework_path}/common/graph.cpp", - "${udmf_framework_path}/common/udmf_utils.cpp", "${udmf_framework_path}/common/utd_cfgs_checker.cpp", "${udmf_framework_path}/common/utd_graph.cpp", + "${udmf_root_path}/adapter/framework/common/udmf_utils.cpp", ] sources += arkui_x_public_source diff --git a/udmf/adapter/framework/common/udmf_utils.cpp b/udmf/adapter/framework/common/udmf_utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2c0c1b1756a7a32f37dc8e6a0333d6529f319fb9 --- /dev/null +++ b/udmf/adapter/framework/common/udmf_utils.cpp @@ -0,0 +1,65 @@ +/* + * 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 "udmf_utils.h" +#include +#include + +namespace OHOS { +namespace UDMF { +namespace UTILS { +static constexpr int ID_LEN = 32; +static constexpr int MINIMUM = 48; +static constexpr int MAXIMUM = 121; +constexpr char SPECIAL = '^'; + +std::vector StrSplit(const std::string &str, const std::string &delimiter) +{ + std::vector result; + size_t start = 0; + size_t end = str.find(delimiter); + while (end != std::string::npos) { + result.push_back(str.substr(start, end - start)); + start = end + delimiter.length(); + end = str.find(delimiter, start); + } + result.push_back(str.substr(start)); + return result; +} + +std::vector Random(int32_t len, int32_t minimum, int32_t maximum) +{ + std::random_device randomDevice; + std::uniform_int_distribution distribution(minimum, maximum); + std::vector key(len); + for (int32_t i = 0; i < len; i++) { + key[i] = static_cast(distribution(randomDevice)); + } + return key; +} + +std::string GenerateId() +{ + std::vector randomDevices = Random(ID_LEN, MINIMUM, MAXIMUM); + std::stringstream idStr; + for (auto &randomDevice : randomDevices) { + auto asc = randomDevice; + asc = asc >= SPECIAL ? asc + 1 : asc; + idStr << static_cast(asc); + } + return idStr.str(); +} +} // namespace UTILS +} // namespace UDMF +} // namespace OHOS \ No newline at end of file diff --git a/data_share/frameworks/native/proxy/include/data_share_errno.h b/udmf/adapter/framework/common/udmf_utils.h similarity index 55% rename from data_share/frameworks/native/proxy/include/data_share_errno.h rename to udmf/adapter/framework/common/udmf_utils.h index a511fc3ba42f652fa106f3e1b869872d9f22bfa9..d64e4dde2666e0ab9b0655bf79c8d27283f4f2b8 100644 --- a/data_share/frameworks/native/proxy/include/data_share_errno.h +++ b/udmf/adapter/framework/common/udmf_utils.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * 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 @@ -13,19 +13,21 @@ * limitations under the License. */ -#ifndef DISTRIBUTEDDATAFWK_DATA_SHARE_TYPES_H -#define DISTRIBUTEDDATAFWK_DATA_SHARE_TYPES_H +#ifndef UDMF_UTILS_H +#define UDMF_UTILS_H -#include -#include #include #include +namespace OHOS { +namespace UDMF { +namespace UTILS { +std::vector StrSplit(const std::string &str, const std::string &delimiter); +std::vector Random(int32_t len, int32_t minimum = 0, + int32_t maximum = std::numeric_limits::max()); +std::string GenerateId(); -namespace OHOS::DataShare { -enum class DataShareStatus { - DATA_SHARE_ERROR = -1, - DATA_SHARE_OK = 0, -}; +} // namespace UTILS +} // namespace UDMF +} // namespace OHOS -} // namespace OHOS::DataShare -#endif +#endif /* UDMF_UTILS_H */ diff --git a/datamgr_service/services/distributeddataservice/service/udmf/utd/custom_utd_installer.h b/udmf/adapter/framework/innerkitsimpl/client/udmf_client.h similarity index 32% rename from datamgr_service/services/distributeddataservice/service/udmf/utd/custom_utd_installer.h rename to udmf/adapter/framework/innerkitsimpl/client/udmf_client.h index 2b3d20f3b2a08bb854c89e58d118925cc3fa12e0..4398f83f8090116aadb214ee36230d84bb31d031 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/utd/custom_utd_installer.h +++ b/udmf/adapter/framework/innerkitsimpl/client/udmf_client.h @@ -13,36 +13,48 @@ * limitations under the License. */ -#ifndef DATAMGR_SERVICE_UTD_MANAGER_H -#define DATAMGR_SERVICE_UTD_MANAGER_H +#ifndef UDMF_CLIENT_H +#define UDMF_CLIENT_H -#include #include +#include +#include +#include -#include "bundlemgr/bundle_mgr_proxy.h" -#include "utd_common.h" -#include "utd_cfgs_checker.h" -#include "system_ability.h" - +#include "concurrent_map.h" +#include "error_code.h" +#include "unified_data.h" +#include "unified_meta.h" +#include "unified_types.h" +#include "visibility.h" namespace OHOS { namespace UDMF { -class CustomUtdInstaller { +class API_EXPORT UdmfClient { public: - static CustomUtdInstaller &GetInstance(); - int32_t InstallUtd(const std::string &bundleName, int32_t user); - int32_t UninstallUtd(const std::string &bundleName, int32_t user); + static UdmfClient &GetInstance(); + + Status SetData(CustomOption &option, UnifiedData &unifiedData, std::string &key); + Status GetData(const QueryOption &query, UnifiedData &unifiedData); + Status GetBatchData(const QueryOption &query, std::vector &unifiedDataSet); + Status UpdateData(const QueryOption &query, UnifiedData &unifiedData); + Status DeleteData(const QueryOption &query, std::vector &unifiedDataSet); + Status GetSummary(const QueryOption &query, Summary& summary); + Status AddPrivilege(const QueryOption &query, Privilege &privilege); + Status Sync(const QueryOption &query, const std::vector &devices); + Status IsRemoteData(const QueryOption &query, bool &result); + Status SetAppShareOption(const std::string &intention, enum ShareOptions shareOption); + Status RemoveAppShareOption(const std::string &intention); + Status GetAppShareOption(const std::string &intention, enum ShareOptions &shareOption); private: - CustomUtdInstaller(); - ~CustomUtdInstaller(); - CustomUtdInstaller(const CustomUtdInstaller &obj) = delete; - CustomUtdInstaller &operator=(const CustomUtdInstaller &obj) = delete; - sptr GetBundleManager(); - std::vector GetHapModules(const std::string &bundleName, int32_t user); - CustomUtdCfgs GetModuleCustomUtdTypes(const std::string &bundleName, const std::string &moduleName, int32_t user); - int32_t SaveCustomUtds(const CustomUtdCfgs &utdTypes, std::vector customTyepCfgs, - const std::string &bundleName, const std::string &path); + UdmfClient() = default; + ~UdmfClient() = default; + UdmfClient(const UdmfClient &obj) = delete; + UdmfClient &operator=(const UdmfClient &obj) = delete; + std::string GetSelfBundleName(); + + ConcurrentMap dataCache_; }; } // namespace UDMF } // namespace OHOS -#endif // DATAMGR_SERVICE_UTD_MANAGER_H +#endif // UDMF_CLIENT_H \ No newline at end of file diff --git a/udmf/adapter/framework/innerkitsimpl/client/utd_client.cpp b/udmf/adapter/framework/innerkitsimpl/client/utd_client.cpp index ec365eed0abfceffc8d500eb26593533edd3dbe8..5f40226516f9ce94d7fdf6399d30812cd7a2c722 100644 --- a/udmf/adapter/framework/innerkitsimpl/client/utd_client.cpp +++ b/udmf/adapter/framework/innerkitsimpl/client/utd_client.cpp @@ -70,5 +70,32 @@ Status UtdClient::IsUtd(std::string typeId, bool &result) { return Status::E_OK; } + +Status UtdClient::GetUniformDataTypesByFilenameExtension(const std::string &fileExtension, + std::vector &typeIds, const std::string &belongsTo) +{ + return Status::E_OK; +} + +std::string UtdClient::GetTypeIdFromCfg(const std::string &mimeType) +{ + return ""; +} + +std::vector UtdClient::GetTypeIdsFromCfg(const std::string &mimeType) +{ + std::vector typeIdsInCfg; + return typeIdsInCfg; +} + +void UtdClient::SubscribeUtdChange() +{ +} + +Status UtdClient::GetUniformDataTypesByMIMEType(const std::string &mimeType, std::vector &typeIds, + const std::string &belongsTo) +{ + return Status::E_OK; +} } // namespace UDMF } // namespace OHOS diff --git a/udmf/adapter/framework/innerkitsimpl/client/utd_client.h b/udmf/adapter/framework/innerkitsimpl/client/utd_client.h new file mode 100644 index 0000000000000000000000000000000000000000..64563853fdff1321b7fc2e6362d1a8593dcbff62 --- /dev/null +++ b/udmf/adapter/framework/innerkitsimpl/client/utd_client.h @@ -0,0 +1,71 @@ +/* + * 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 UTD_CLIENT_H +#define UTD_CLIENT_H + +#include +#include +#include +#include + +#include "error_code.h" +#include "flexible_type.h" +#include "preset_type_descriptors.h" +#include "preset_type_descriptors.h" +#include "type_descriptor.h" +#include "utd_common.h" +#include "visibility.h" +namespace OHOS { +namespace UDMF { +class TypeDescriptor; +class UtdChangeSubscriber; +class API_EXPORT UtdClient { +public: + static UtdClient &GetInstance(); + Status GetTypeDescriptor(const std::string &typeId, std::shared_ptr &descriptor); + Status GetUniformDataTypeByFilenameExtension(const std::string &fileExtension, std::string &typeId, + std::string belongsTo = DEFAULT_TYPE_ID); + Status GetUniformDataTypesByFilenameExtension(const std::string &fileExtension, + std::vector &typeIds, const std::string &belongsTo = DEFAULT_TYPE_ID); + Status GetUniformDataTypeByMIMEType(const std::string &mimeType, std::string &typeId, + std::string belongsTo = DEFAULT_TYPE_ID); + Status GetUniformDataTypesByMIMEType(const std::string &mimeType, std::vector &typeIds, + const std::string &belongsTo = DEFAULT_TYPE_ID); + Status IsUtd(std::string typeId, bool &result); + +private: + UtdClient(); + ~UtdClient(); + UtdClient(const UtdClient &obj) = delete; + UtdClient &operator=(const UtdClient &obj) = delete; + void Init(); + bool IsHapTokenType(); + std::string GetCustomUtdPath(); + Status GetCurrentActiveUserId(int32_t& userId); + bool IsValidFileExtension(const std::string &fileExtension); + bool IsValidMimeType(const std::string &mimeType); + Status GetFlexibleTypeDescriptor(const std::string &typeId, std::shared_ptr &descriptor); + std::string GetTypeIdFromCfg(const std::string &mimeType); + std::vector GetTypeIdsFromCfg(const std::string &mimeType); + void SubscribeUtdChange(); + + std::vector descriptorCfgs_; + std::shared_ptr subscriber_; + std::shared_mutex utdMutex_; +}; +} // namespace UDMF +} // namespace OHOS +#endif // UTD_CLIENT_H \ No newline at end of file diff --git a/udmf/bundle.json b/udmf/bundle.json index 11cd88051aef503ca15d7e5d7a2face736e8df42..5ce0aa323df92417d3921432efdf0746d86a18f6 100644 --- a/udmf/bundle.json +++ b/udmf/bundle.json @@ -30,7 +30,6 @@ "bundle_framework", "cJSON", "c_utils", - "common_event_service", "hilog", "hisysevent", "hitrace", diff --git a/udmf/framework/common/custom_utd_json_parser.cpp b/udmf/framework/common/custom_utd_json_parser.cpp index 91285e4c26e3ea01b85a908d024becbb4053fa5c..7a8be281d023d58d8ab3b51c410c66d69a33af41 100644 --- a/udmf/framework/common/custom_utd_json_parser.cpp +++ b/udmf/framework/common/custom_utd_json_parser.cpp @@ -64,6 +64,8 @@ bool CustomUtdJsonParser::ParseUserCustomUtdJson(const std::string &jsonData, GetTypeDescriptors(*jsonRoot, UTD_CUSTOM_REFERENCE, typesReference); } cJSON_Delete(jsonRoot); + LOG_DEBUG(UDMF_CLIENT, "DeclarationsSize:%{public}zu, ReferenceSize:%{public}zu", + typesDeclarations.size(), typesReference.size()); return true; } diff --git a/udmf/framework/common/custom_utd_store.cpp b/udmf/framework/common/custom_utd_store.cpp index f44868b0ecc4e493cba7fa0135c0debc86be2669..e7e11dbb9d077fafb565a28f18f2acc14a4956b0 100644 --- a/udmf/framework/common/custom_utd_store.cpp +++ b/udmf/framework/common/custom_utd_store.cpp @@ -16,15 +16,21 @@ #include "custom_utd_store.h" #include #include -#include "unistd.h" -#include "error_code.h" #include "logger.h" +#include "preset_type_descriptors.h" +#include "unistd.h" +#include "utd_cfgs_checker.h" +#include "utd_graph.h" #ifdef WITH_SELINUX #include #endif namespace OHOS { namespace UDMF { constexpr const char* UTD_CFG_FILE = "utd-adt.json"; +constexpr const char* CUSTOM_UTD_HAP_DIR = "/data/utd/utd-adt.json"; +constexpr const char* CUSTOM_UTD_SA_DIR = "/data/service/el1/"; +constexpr const char* OLD_CUSTOM_UTD_SA_SUB_DIR = "/distributeddata/utd/"; +constexpr const char* CUSTOM_UTD_SA_SUB_DIR = "/utdtypes/utd/"; CustomUtdStore::CustomUtdStore() { @@ -40,8 +46,31 @@ CustomUtdStore &CustomUtdStore::GetInstance() return utdCustomPersistence; } -std::vector CustomUtdStore::GetTypeCfgs(const std::string &cfgFilePath) +std::vector CustomUtdStore::GetHapTypeCfgs() +{ + LOG_DEBUG(UDMF_CLIENT, "get utdcustom from cfg, Path:%{public}s.", CUSTOM_UTD_HAP_DIR); + std::string jsonStr; + std::ifstream fin(CUSTOM_UTD_HAP_DIR); + while (fin.good()) { + std::string line; + std::getline(fin, line); + jsonStr += line; + } + std::vector customUtdTypes; + utdJsonParser_.ParseStoredCustomUtdJson(jsonStr, customUtdTypes); + LOG_DEBUG(UDMF_CLIENT, "GetTypeCfgs, customUtdTypes total:%{public}zu.", customUtdTypes.size()); + return customUtdTypes; +} + +std::vector CustomUtdStore::GetTypeCfgs(int32_t userId) { + std::string path = CUSTOM_UTD_SA_DIR + std::to_string(userId) + CUSTOM_UTD_SA_SUB_DIR; + std::string old_path = CUSTOM_UTD_SA_DIR + std::to_string(userId) + OLD_CUSTOM_UTD_SA_SUB_DIR; + std::string cfgFilePath = path; + if (access(path.c_str(), F_OK) != 0 && access(old_path.c_str(), F_OK) == 0) { + cfgFilePath = old_path; + } + cfgFilePath.append(UTD_CFG_FILE); LOG_DEBUG(UDMF_CLIENT, "get utdcustom from cfg, Path:%{public}s.", cfgFilePath.c_str()); std::string jsonStr; std::ifstream fin(cfgFilePath); @@ -56,14 +85,13 @@ std::vector CustomUtdStore::GetTypeCfgs(const std::string &cf return customUtdTypes; } -int32_t CustomUtdStore::SaveTypeCfgs(const std::vector &customUtdTypes, - const std::string &cfgFilePath) +int32_t CustomUtdStore::SaveTypeCfgs(const std::vector &customUtdTypes, int32_t user) { + LOG_DEBUG(UDMF_CLIENT, "customUtdTypes total:%{public}zu.", customUtdTypes.size()); std::string jsonData; - std::string cfgFileName = UTD_CFG_FILE; - std::string cfgFileDir = cfgFilePath.substr(0, cfgFilePath.length() - cfgFileName.length()); + std::string cfgFileDir = CUSTOM_UTD_SA_DIR + std::to_string(user) + CUSTOM_UTD_SA_SUB_DIR; if (utdJsonParser_.ConvertUtdCfgsToJson(customUtdTypes, jsonData) && CreateDirectory(cfgFileDir)) { - SavaCfgFile(jsonData, cfgFilePath); + SavaCfgFile(jsonData, cfgFileDir.append(UTD_CFG_FILE)); } return 0; } @@ -73,7 +101,9 @@ int32_t CustomUtdStore::SavaCfgFile(const std::string &jsonData, const std::stri std::ofstream ofs; LOG_DEBUG(UDMF_CLIENT, "set cfg start, path:%{public}s ", cfgFilePath.c_str()); ofs.open(cfgFilePath, std::ios_base::ate); - LOG_DEBUG(UDMF_CLIENT, "set cfg, is_open= %{public}d", ofs.is_open()); + if (!ofs.is_open()) { + LOG_ERROR(UDMF_CLIENT, "open cfg failed, path:%{public}s", cfgFilePath.c_str()); + } ofs << jsonData << std::endl; ofs.close(); LOG_DEBUG(UDMF_CLIENT, "set cfg end."); @@ -115,5 +145,87 @@ bool CustomUtdStore::CreateDirectory(const std::string &path) const return false; } + +bool CustomUtdStore::InstallCustomUtds(const std::string &bundleName, const std::string &jsonStr, + int32_t user, std::vector &customTyepCfgs) +{ + CustomUtdCfgs typeCfgs; + if (!utdJsonParser_.ParseUserCustomUtdJson(jsonStr, typeCfgs.first, typeCfgs.second)) { + LOG_ERROR(UDMF_CLIENT, "Parse json failed. bundleName:%{public}s", bundleName.c_str()); + return false; + } + std::vector presetTypes = PresetTypeDescriptors::GetInstance().GetPresetTypes(); + + if (!UtdCfgsChecker::GetInstance().CheckTypeDescriptors( + typeCfgs, presetTypes, customTyepCfgs, bundleName)) { + LOG_ERROR(UDMF_CLIENT, "check type descriptors failed, bundleName:%{public}s", bundleName.c_str()); + return false; + } + + ProcessUtdForSave(typeCfgs, customTyepCfgs, bundleName); + if (CustomUtdStore::GetInstance().SaveTypeCfgs(customTyepCfgs, user) != E_OK) { + LOG_ERROR(UDMF_CLIENT, "Save failed, bundleName: %{public}s", bundleName.c_str()); + return false; + } + return true; +} + +bool CustomUtdStore::UninstallCustomUtds(const std::string &bundleName, int32_t user, + std::vector &customTyepCfgs) +{ + for (auto iter = customTyepCfgs.begin(); iter != customTyepCfgs.end();) { + auto it = find(iter->installerBundles.begin(), iter->installerBundles.end(), bundleName); + if (it != iter->installerBundles.end()) { + iter->installerBundles.erase(it); + } + if (iter->installerBundles.empty()) { + iter = customTyepCfgs.erase(iter); + } else { + iter++; + } + } + std::vector presetTypes = PresetTypeDescriptors::GetInstance().GetPresetTypes(); + if (!UtdCfgsChecker::GetInstance().CheckBelongingToTypes(customTyepCfgs, presetTypes)) { + LOG_ERROR(UDMF_CLIENT, "belongingToTypes check failed. bundleName:%{public}s", bundleName.c_str()); + return false; + } + if (CustomUtdStore::GetInstance().SaveTypeCfgs(customTyepCfgs, user) != E_OK) { + LOG_ERROR(UDMF_CLIENT, "Save type cfgs failed, bundleName: %{public}s", bundleName.c_str()); + return false; + } + return true; +} + +void CustomUtdStore::ProcessUtdForSave(const CustomUtdCfgs &utdTypes, std::vector &customTyepCfgs, + const std::string &bundleName) +{ + for (TypeDescriptorCfg declarationType : utdTypes.first) { + for (auto iter = customTyepCfgs.begin(); iter != customTyepCfgs.end();) { + if (iter->typeId == declarationType.typeId) { + declarationType.installerBundles = iter->installerBundles; + iter = customTyepCfgs.erase(iter); + } else { + iter++; + } + } + declarationType.installerBundles.emplace(bundleName); + declarationType.ownerBundle = bundleName; + customTyepCfgs.push_back(declarationType); + } + for (TypeDescriptorCfg referenceType : utdTypes.second) { + bool found = false; + for (auto &typeCfg : customTyepCfgs) { + if (typeCfg.typeId == referenceType.typeId) { + typeCfg.installerBundles.emplace(bundleName); + found = true; + break; + } + } + if (!found) { + referenceType.installerBundles.emplace(bundleName); + customTyepCfgs.push_back(referenceType); + } + } +} } // namespace UDMF } // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/common/custom_utd_store.h b/udmf/framework/common/custom_utd_store.h index 105ed62340d63624cf4ac7619c2d3c3eafedaa73..2934b152dcd7384e4336fd0b2619dd773cd588e8 100644 --- a/udmf/framework/common/custom_utd_store.h +++ b/udmf/framework/common/custom_utd_store.h @@ -28,15 +28,20 @@ namespace UDMF { class API_EXPORT CustomUtdStore { public: static CustomUtdStore &GetInstance(); - std::vector GetTypeCfgs(const std::string &cfgFilePath); - int32_t SaveTypeCfgs(const std::vector &customUtdTypes, const std::string &cfgFilePath); - + std::vector GetTypeCfgs(int32_t userId); + std::vector GetHapTypeCfgs(); + int32_t SaveTypeCfgs(const std::vector &customUtdTypes, int32_t user); + bool InstallCustomUtds(const std::string &bundleName, const std::string &jsonStr, int32_t user, + std::vector &customTyepCfgs); + bool UninstallCustomUtds(const std::string &bundleName, int32_t user, + std::vector &customTyepCfgs); private: CustomUtdStore(); ~CustomUtdStore(); int32_t SavaCfgFile(const std::string &jsonData, const std::string &cfgFilePath); bool CreateDirectory(const std::string &path) const; - + void ProcessUtdForSave(const CustomUtdCfgs &utdTypes, std::vector &customTyepCfgs, + const std::string &bundleName); CustomUtdJsonParser utdJsonParser_; }; } // namespace UDMF diff --git a/udmf/framework/common/graph.cpp b/udmf/framework/common/graph.cpp index 3cc46db74bbd40af2e7aa6d8d0d02d1c46366b7e..ccc44b707c9c72b2381f8a86e32bef5977842084 100644 --- a/udmf/framework/common/graph.cpp +++ b/udmf/framework/common/graph.cpp @@ -12,10 +12,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#define LOG_TAG "Graph" #include "graph.h" +#include "logger.h" namespace OHOS { namespace UDMF { -Graph::Graph(uint32_t vertexNum):vertexNum_(vertexNum) +Graph::Graph(uint32_t vertexNum, const std::map &typeIdIndex) + : vertexNum_(vertexNum), typeIdIndex_(typeIdIndex) { for (uint32_t node = 0; node < vertexNum_; node++) { adjList_.push_back({node, nullptr}); @@ -36,6 +39,18 @@ Graph::~Graph() } } +void Graph::AddEdge(const std::string &startNode, const std::string &endNode) +{ + int32_t start = GetIndex(startNode); + int32_t end = GetIndex(endNode); + if (start < 0 || end < 0) { + LOG_WARN(UDMF_CLIENT, "abnormal edge, startNode:%{public}s, endNode:%{public}s. ", + startNode.c_str(), endNode.c_str()); + return; + } + AddEdge(start, end); +} + void Graph::AddEdge(uint32_t start, uint32_t end) { EdgeNode *edge = new EdgeNode; // add new edge @@ -92,5 +107,28 @@ bool Graph::DfsUnconnectedGraph(Action action) } return true; } + +bool Graph::IsValidType(const std::string &node) +{ + if (typeIdIndex_.find(node) == typeIdIndex_.end()) { + LOG_ERROR(UDMF_CLIENT, "invalid typeId. typeId:%{public}s ", node.c_str()); + return false; + } + return true; +} + +int32_t Graph::GetIndex(const std::string &node) +{ + auto idx = typeIdIndex_.find(node); + if (idx == typeIdIndex_.end()) { + return -1; + } + return idx->second; +} + +bool Graph::IsDAG() +{ + return DfsUnconnectedGraph([&](uint32_t currNode) -> bool { return false; }); +} } // namespace UDMF } // namespace OHOS diff --git a/udmf/framework/common/graph.h b/udmf/framework/common/graph.h index f6b9e2b9b3d02bbb887527c58e43f8d4b0f16541..7b2dc006847dd69ae079d25f0eba55387e418560 100644 --- a/udmf/framework/common/graph.h +++ b/udmf/framework/common/graph.h @@ -17,6 +17,7 @@ #define UDMF_GRAPH_H #include +#include #include #include #include @@ -35,16 +36,21 @@ struct VertexNode { }; class Graph { public: - explicit Graph(uint32_t vertexNum); + explicit Graph(uint32_t vertexNum, const std::map &typeIdIndex); ~Graph(); using Action = std::function; + void AddEdge(const std::string &startNode, const std::string &endNode); void AddEdge(uint32_t start, uint32_t end); bool Dfs(uint32_t startNode, Action action, bool isInit = true); bool DfsUnconnectedGraph(Action action); + bool IsValidType(const std::string &node); + int32_t GetIndex(const std::string &node); + bool IsDAG(); private: uint32_t vertexNum_; std::vector adjList_; // Adjacency List std::vector visited_; // Determine whether the vertex has been accessed, index=vertex value + std::map typeIdIndex_; }; } // namespace UDMF } // namespace OHOS diff --git a/udmf/framework/common/utd_cfgs_checker.cpp b/udmf/framework/common/utd_cfgs_checker.cpp index baecb3e5eb2effaae10cabf368215aa07094cea6..187b505f69069aa66d7bb674707eb752466adca1 100644 --- a/udmf/framework/common/utd_cfgs_checker.cpp +++ b/udmf/framework/common/utd_cfgs_checker.cpp @@ -78,7 +78,7 @@ bool UtdCfgsChecker::CheckTypesFormat(CustomUtdCfgs &typeCfgs, const std::string } for (TypeDescriptorCfg &typeCfg : inputTypeCfgs) { for (std::string filenames : typeCfg.filenameExtensions) { - if (!(filenames[0] == FILE_EXTENSION_PREFIX)) { + if (filenames.size() <= 1 || filenames[0] != FILE_EXTENSION_PREFIX) { LOG_ERROR(UDMF_CLIENT, "Extension not valid, extension: %{public}s, bundleName: %{public}s.", filenames.c_str(), bundleName.c_str()); return false; @@ -200,8 +200,8 @@ bool UtdCfgsChecker::CanConstructDAG(CustomUtdCfgs &typeCfgs, const std::vector< allTypeCfgs.insert(allTypeCfgs.end(), presetCfgs.begin(), presetCfgs.end()); } if (!allTypeCfgs.empty()) { - UtdGraph::GetInstance().InitUtdGraph(allTypeCfgs); - if (UtdGraph::GetInstance().IsDAG()) { + auto graph = UtdGraph::GetInstance().ConstructNewGraph(allTypeCfgs); + if (graph->IsDAG()) { return true; } } diff --git a/udmf/framework/common/utd_graph.cpp b/udmf/framework/common/utd_graph.cpp index 525fe3b40c42a90cef7fed5b70106ad209de4fbc..2fa09f75fe9b7239db1546b33789e7647c53c70c 100644 --- a/udmf/framework/common/utd_graph.cpp +++ b/udmf/framework/common/utd_graph.cpp @@ -35,63 +35,39 @@ UtdGraph &UtdGraph::GetInstance() bool UtdGraph::IsValidType(const std::string &node) { - if (typeIdIndex_.find(node) == typeIdIndex_.end()) { - LOG_ERROR(UDMF_CLIENT, "invalid typeId. typeId:%{public}s ", node.c_str()); - return false; - } - return true; -} - -int32_t UtdGraph::GetIndex(const std::string &node) -{ - auto idx = typeIdIndex_.find(node); - if (idx == typeIdIndex_.end()) { - return -1; - } - return idx->second; + std::unique_lock lock(graphMutex_); + return graph_->IsValidType(node); } void UtdGraph::InitUtdGraph(const std::vector &descriptorCfgs) { - typeIdIndex_.clear(); + std::map typeIdIndex; uint32_t descriptorsNum = static_cast(descriptorCfgs.size()); - std::unique_lock lock(graphMutex_); - graph_ = std::make_unique(descriptorsNum); for (uint32_t i = 0; i < descriptorsNum; i++) { - typeIdIndex_.insert(std::make_pair(descriptorCfgs[i].typeId, i)); + typeIdIndex.insert(std::make_pair(descriptorCfgs[i].typeId, i)); } + std::unique_lock lock(graphMutex_); + graph_ = std::make_unique(descriptorsNum, typeIdIndex); for (const auto &descriptorCfg : descriptorCfgs) { std::vector belongsTo = descriptorCfg.belongingToTypes; for (auto belongsToType : belongsTo) { - AddEdge(belongsToType, descriptorCfg.typeId); + graph_->AddEdge(belongsToType, descriptorCfg.typeId); } } LOG_INFO(UDMF_CLIENT, "InitUtdGraph success, descriptorsNum:%{public}u. ", descriptorsNum); } -void UtdGraph::AddEdge(const std::string &startNode, const std::string &endNode) -{ - int32_t start = GetIndex(startNode); - int32_t end = GetIndex(endNode); - if (start < 0 || end < 0) { - LOG_WARN(UDMF_CLIENT, "abnormal edge, startNode:%{public}s, endNode:%{public}s. ", - startNode.c_str(), endNode.c_str()); - return; - } - graph_->AddEdge(start, end); -} - bool UtdGraph::IsLowerLevelType(const std::string &lowerLevelType, const std::string &heigitLevelType) { + std::unique_lock lock(graphMutex_); bool isFind = false; - int32_t start = GetIndex(lowerLevelType); - int32_t end = GetIndex(heigitLevelType); + int32_t start = graph_->GetIndex(lowerLevelType); + int32_t end = graph_->GetIndex(heigitLevelType); if (start < 0 || end < 0) { return false; } uint32_t uStart = static_cast(start); uint32_t uEnd = static_cast(end); - std::unique_lock lock(graphMutex_); graph_->Dfs(uStart, [&isFind, &uEnd](uint32_t currNode)-> bool { if (uEnd == currNode) { isFind = true; @@ -102,10 +78,28 @@ bool UtdGraph::IsLowerLevelType(const std::string &lowerLevelType, const std::st return isFind; } -bool UtdGraph::IsDAG() +std::unique_ptr UtdGraph::ConstructNewGraph(const std::vector &descriptorCfgs) +{ + std::map typeIdIndex; + uint32_t descriptorsNum = static_cast(descriptorCfgs.size()); + for (uint32_t i = 0; i < descriptorsNum; i++) { + typeIdIndex.insert(std::make_pair(descriptorCfgs[i].typeId, i)); + } + auto graph = std::make_unique(descriptorsNum, typeIdIndex); + + for (const auto &descriptorCfg : descriptorCfgs) { + std::vector belongsTo = descriptorCfg.belongingToTypes; + for (auto belongsToType : belongsTo) { + graph->AddEdge(belongsToType, descriptorCfg.typeId); + } + } + return graph; +} + +void UtdGraph::Update(std::unique_ptr graph) { std::unique_lock lock(graphMutex_); - return graph_->DfsUnconnectedGraph([&](uint32_t currNode) -> bool {return false; }); + graph_ = std::move(graph); } } // namespace UDMF } // namespace OHOS diff --git a/udmf/framework/common/utd_graph.h b/udmf/framework/common/utd_graph.h index a4861b6ec8d548f8334364b6f5bcdae1c610bde3..20586661e5be25f9dcec2b279ca631573a62f051 100644 --- a/udmf/framework/common/utd_graph.h +++ b/udmf/framework/common/utd_graph.h @@ -34,17 +34,15 @@ public: bool IsValidType(const std::string &node); void InitUtdGraph(const std::vector &descriptorCfgs); bool IsLowerLevelType(const std::string &lowerLevelType, const std::string &heigitLevelType); - bool IsDAG(); + std::unique_ptr ConstructNewGraph(const std::vector &descriptorCfgs); + void Update(std::unique_ptr graph); private: UtdGraph(); ~UtdGraph(); UtdGraph(const UtdGraph &obj) = delete; UtdGraph &operator=(const UtdGraph &obj) = delete; - int32_t GetIndex(const std::string &node); - void AddEdge(const std::string &startNode, const std::string &endNode); std::mutex graphMutex_; std::unique_ptr graph_; - std::map typeIdIndex_; }; } // namespace UDMF } // namespace OHOS diff --git a/udmf/framework/innerkitsimpl/client/utd_client.cpp b/udmf/framework/innerkitsimpl/client/utd_client.cpp index 51926b9f2baec7d28e00b427a7c5705c570f0375..cb33d8dd30fddd9fb73fab1a69960297a32b5fee 100644 --- a/udmf/framework/innerkitsimpl/client/utd_client.cpp +++ b/udmf/framework/innerkitsimpl/client/utd_client.cpp @@ -18,10 +18,6 @@ #include #include #include -#include "common_event_manager.h" -#include "common_event_subscriber.h" -#include "common_event_support.h" -#include "utd_client.h" #include "logger.h" #include "utd_graph.h" #include "custom_utd_store.h" @@ -30,24 +26,18 @@ #include "os_account_manager.h" namespace OHOS { namespace UDMF { -constexpr const char* CUSTOM_UTD_HAP_DIR = "/data/utd/utd-adt.json"; -constexpr const char* CUSTOM_UTD_SA_DIR = "/data/service/el1/"; -constexpr const char* CUSTOM_UTD_SA_SUB_DIR = "/distributeddata/utd/utd-adt.json"; - -class UtdChangeSubscriber final : public EventFwk::CommonEventSubscriber { -public: - explicit UtdChangeSubscriber(const EventFwk::CommonEventSubscribeInfo &subscribeInfo, - const std::function &callback); - virtual ~UtdChangeSubscriber() = default; - void OnReceiveEvent(const EventFwk::CommonEventData &data) override; -private: - std::function callback_; -}; +constexpr const int MAX_UTD_LENGTH = 256; UtdClient::UtdClient() { - Init(); - SubscribeUtdChange(); + if (!Init()) { + LOG_WARN(UDMF_CLIENT, "construct UtdClient failed, try again."); + auto updateTask = []() { + std::this_thread::sleep_for(std::chrono::seconds(3)); + UtdClient::GetInstance().Init(); + }; + std::thread(updateTask).detach(); + } LOG_INFO(UDMF_CLIENT, "construct UtdClient sucess."); } @@ -61,21 +51,27 @@ UtdClient &UtdClient::GetInstance() return *instance; } -void UtdClient::Init() +bool UtdClient::Init() { + bool result = true; std::unique_lock lock(utdMutex_); descriptorCfgs_ = PresetTypeDescriptors::GetInstance().GetPresetTypes(); - std::string customUtdPath = GetCustomUtdPath(); - if (!customUtdPath.empty()) { - std::vector customTypes = - CustomUtdStore::GetInstance().GetTypeCfgs(customUtdPath); - LOG_INFO(UDMF_CLIENT, "get customUtd. path:%{public}s, size:%{public}zu", - customUtdPath.c_str(), customTypes.size()); - if (!customTypes.empty()) { - descriptorCfgs_.insert(descriptorCfgs_.end(), customTypes.begin(), customTypes.end()); + std::vector customTypes; + if (IsHapTokenType()) { + customTypes = CustomUtdStore::GetInstance().GetHapTypeCfgs(); + } else { + int32_t userId = DEFAULT_USER_ID; + if (GetCurrentActiveUserId(userId) != Status::E_OK) { + result = false; } + customTypes = CustomUtdStore::GetInstance().GetTypeCfgs(userId); + } + LOG_INFO(UDMF_CLIENT, "get customUtd, size:%{public}zu", customTypes.size()); + if (!customTypes.empty()) { + descriptorCfgs_.insert(descriptorCfgs_.end(), customTypes.begin(), customTypes.end()); } UtdGraph::GetInstance().InitUtdGraph(descriptorCfgs_); + return result; } Status UtdClient::GetTypeDescriptor(const std::string &typeId, std::shared_ptr &descriptor) @@ -146,11 +142,17 @@ Status UtdClient::GetUniformDataTypeByFilenameExtension(const std::string &fileE } { std::shared_lock guard(utdMutex_); + bool found = false; for (const auto &utdTypeCfg : descriptorCfgs_) { - std::vector fileExtensions = utdTypeCfg.filenameExtensions; - if (find(fileExtensions.begin(), fileExtensions.end(), lowerFileExtension) != fileExtensions.end() || - find(fileExtensions.begin(), fileExtensions.end(), fileExtension) != fileExtensions.end()) { - typeId = utdTypeCfg.typeId; + for (auto fileEx : utdTypeCfg.filenameExtensions) { + std::transform(fileEx.begin(), fileEx.end(), fileEx.begin(), ::tolower); + if (fileEx == lowerFileExtension) { + typeId = utdTypeCfg.typeId; + found = true; + break; + } + } + if (found) { break; } } @@ -192,9 +194,12 @@ Status UtdClient::GetUniformDataTypesByFilenameExtension(const std::string &file { std::shared_lock guard(utdMutex_); for (const auto &utdTypeCfg : descriptorCfgs_) { - std::vector fileExtensions = utdTypeCfg.filenameExtensions; - if (find(fileExtensions.begin(), fileExtensions.end(), lowerFileExtension) != fileExtensions.end()) { - typeIdsInCfg.push_back(utdTypeCfg.typeId); + for (auto fileEx : utdTypeCfg.filenameExtensions) { + std::transform(fileEx.begin(), fileEx.end(), fileEx.begin(), ::tolower); + if (fileEx == lowerFileExtension) { + typeIdsInCfg.push_back(utdTypeCfg.typeId); + break; + } } } } @@ -324,7 +329,7 @@ std::vector UtdClient::GetTypeIdsFromCfg(const std::string &mimeTyp Status UtdClient::IsUtd(std::string typeId, bool &result) { try { - if (typeId.empty()) { + if (typeId.empty() || typeId.size() > MAX_UTD_LENGTH) { result = false; return Status::E_INVALID_PARAMETERS; } @@ -338,8 +343,7 @@ Status UtdClient::IsUtd(std::string typeId, bool &result) result = true; return Status::E_OK; } - constexpr const char *customUtdRegexRule = - R"(^([A-Za-z][\w]*[A-Za-z\d])(\.([A-Za-z\d]+_?)+[A-Za-z\d]+){2,}(\.[A-Za-z\d]+[-|\.]?[A-Za-z\d]+)+)"; + constexpr const char *customUtdRegexRule = R"(^([A-Za-z]\w*)(\.\w+)+(\.[A-Za-z\d-]+)+)"; if (std::regex_match(typeId, std::regex(customUtdRegexRule))) { result = true; return Status::E_OK; @@ -365,20 +369,6 @@ bool UtdClient::IsHapTokenType() return false; } -std::string UtdClient::GetCustomUtdPath() -{ - if (IsHapTokenType()) { - return std::string(CUSTOM_UTD_HAP_DIR); - } - int32_t userId = DEFAULT_USER_ID; - if (GetCurrentActiveUserId(userId) != Status::E_OK) { - return ""; - } - std::string customUtdSaPath = std::string(CUSTOM_UTD_SA_DIR) + - std::to_string(userId) + std::string(CUSTOM_UTD_SA_SUB_DIR); - return customUtdSaPath; -} - Status UtdClient::GetCurrentActiveUserId(int32_t& userId) { std::vector localIds; @@ -391,35 +381,54 @@ Status UtdClient::GetCurrentActiveUserId(int32_t& userId) return Status::E_OK; } -void UtdClient::SubscribeUtdChange() +void UtdClient::InstallCustomUtds(const std::string &bundleName, const std::string &jsonStr, int32_t user) { if (IsHapTokenType()) { return; } - LOG_INFO(UDMF_CLIENT, "subscribe utd change callback."); - EventFwk::MatchingSkills matchingSkills; - matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_ADDED); - matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_CHANGED); - matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_PACKAGE_REMOVED); - EventFwk::CommonEventSubscribeInfo subscribeInfo(matchingSkills); - auto updateTask = []() { - std::this_thread::sleep_for(std::chrono::milliseconds(3000)); - UtdClient::GetInstance().Init(); - }; - subscriber_ = std::make_shared(subscribeInfo, updateTask); - (void)EventFwk::CommonEventManager::SubscribeCommonEvent(subscriber_); + LOG_INFO(UDMF_CLIENT, "start, bundleName:%{public}s, user:%{public}d", bundleName.c_str(), user); + std::vector customTyepCfgs = CustomUtdStore::GetInstance().GetTypeCfgs(user); + if (!CustomUtdStore::GetInstance().UninstallCustomUtds(bundleName, user, customTyepCfgs)) { + LOG_ERROR(UDMF_CLIENT, "custom utd installed failed. bundleName:%{public}s, user:%{public}d", + bundleName.c_str(), user); + return; + } + UpdateGraph(customTyepCfgs); + if (!jsonStr.empty()) { + if (!CustomUtdStore::GetInstance().InstallCustomUtds(bundleName, jsonStr, user, customTyepCfgs)) { + LOG_ERROR(UDMF_CLIENT, "no custom utd installed. bundleName:%{public}s, user:%{public}d", + bundleName.c_str(), user); + return; + } + UpdateGraph(customTyepCfgs); + } } -UtdChangeSubscriber::UtdChangeSubscriber(const EventFwk::CommonEventSubscribeInfo &subscribeInfo, - const std::function &callback) - : EventFwk::CommonEventSubscriber(subscribeInfo), callback_(callback) +void UtdClient::UninstallCustomUtds(const std::string &bundleName, int32_t user) { + if (IsHapTokenType()) { + return; + } + LOG_INFO(UDMF_CLIENT, "start, bundleName:%{public}s, user:%{public}d", bundleName.c_str(), user); + std::vector customTyepCfgs = CustomUtdStore::GetInstance().GetTypeCfgs(user); + if (!CustomUtdStore::GetInstance().UninstallCustomUtds(bundleName, user, customTyepCfgs)) { + LOG_ERROR(UDMF_CLIENT, "custom utd installed failed. bundleName:%{public}s, user:%{public}d", + bundleName.c_str(), user); + return; + } + UpdateGraph(customTyepCfgs); } -void UtdChangeSubscriber::OnReceiveEvent(const EventFwk::CommonEventData &data) +void UtdClient::UpdateGraph(const std::vector &customTyepCfgs) { - LOG_INFO(UDMF_CLIENT, "start."); - std::thread(callback_).detach(); + std::vector allTypeCfgs = PresetTypeDescriptors::GetInstance().GetPresetTypes(); + allTypeCfgs.insert(allTypeCfgs.end(), customTyepCfgs.begin(), customTyepCfgs.end()); + LOG_INFO(UDMF_CLIENT, "customTyepSize:%{public}zu, allTypeSize:%{public}zu", + customTyepCfgs.size(), allTypeCfgs.size()); + auto graph = UtdGraph::GetInstance().ConstructNewGraph(allTypeCfgs); + std::unique_lock lock(utdMutex_); + UtdGraph::GetInstance().Update(std::move(graph)); + descriptorCfgs_ = allTypeCfgs; } } // namespace UDMF } // namespace OHOS diff --git a/udmf/framework/innerkitsimpl/common/unified_meta.cpp b/udmf/framework/innerkitsimpl/common/unified_meta.cpp index 5df2fd9c0f90ff1c1f26a2a4c0e0ab80e475985a..51f5641c71d64e73df3de3017a813331fe1c86d1 100644 --- a/udmf/framework/innerkitsimpl/common/unified_meta.cpp +++ b/udmf/framework/innerkitsimpl/common/unified_meta.cpp @@ -458,7 +458,49 @@ static constexpr UtdType UTD_TYPES[] = { { HMOS_WIFI, "HMOS_WIFI", "com.huawei.hmos.settings.wifi" }, { TEL, "TEL", "general.tel" }, { ETS, "ETS", "general.ets" }, - { JSON5, "JSON5", "general.json5" } + { JSON5, "JSON5", "general.json5" }, + { APE_AUDIO, "APE_AUDIO", "com.monkeysaudio.ape-audio" }, + { OPUS_AUDIO, "OPUS_AUDIO", "org.xiph.opus-audio"}, + { CONF, "CONF", "general.conf" }, + { MICROSOFT_DOS_BATCH, "MICROSOFT_DOS_BATCH", "com.microsoft.dos-batch" }, + { MICROSOFT_VBSCRIPT, "MICROSOFT_VBSCRIPT", "com.microsoft.vbscript" }, + { ION, "ION", "general.ion" }, + { MICROSOFT_REGISTRY, "MICROSOFT_REGISTRY", "com.microsoft.registry" }, + { MICROSOFT_CATALOG, "MICROSOFT_CATALOG", "com.microsoft.catalog" }, + { MICROSOFT_POWERSHELL_SCRIPT, "MICROSOFT_POWERSHELL_SCRIPT", "com.microsoft.powershell-script" }, + { W3_WOFF, "W3_WOFF", "org.w3.woff" }, + { SQLITE_DATABASE, "SQLITE_DATABASE", "org.sqlite.database" }, + { MICROSOFT_SYS, "MICROSOFT_SYS", "com.microsoft.sys" }, + { MICROSOFT_INF, "MICROSOFT_INF", "com.microsoft.inf" }, + { MICROSOFT_PDB, "MICROSOFT_PDB", "com.microsoft.pdb" }, + { MICROSOFT_TLB, "MICROSOFT_TLB", "com.microsoft.tlb" }, + { MICROSOFT_SCCD, "MICROSOFT_SCCD", "com.microsoft.sccd" }, + { ADOBE_F4V, "ADOBE_F4V", "com.adobe.f4v" }, + { MP2T, "MP2T", "general.mp2t" }, + { YOUTUBE_VIDEO, "YOUTUBE_VIDEO", "com.youtube.video" }, + { WEBEX_VIDEO, "WEBEX_VIDEO", "com.cisco.webex-video" }, + { MPEG2, "MPEG2", "general.mpeg-2" }, + { MPEG1, "MPEG1", "general.mpeg-1" }, + { REALMEDIA_VBR, "REALMEDIA_VBR", "com.real.realmedia-vbr" }, + { REAL_REALVIDEO, "REAL_REALVIDEO", "com.real.realvideo" }, + { DIVX_VIDEO, "DIVX_VIDEO", "general.divx-video" }, + { CSIRO_ANNODEX, "CSIRO_ANNODEX", "org.csiro.annodex" }, + { OGV, "OGV", "general.ogv" }, + { LSF_VIDEO, "LSF_VIDEO", "com.microsoft.lsf-video" }, + { H264_VIDEO, "H264_VIDEO", "general.h264-video" }, + { JPEG2000, "JPEG2000", "general.jpeg-2000" }, + { RAF_RAW_IMAGE, "RAF_RAW_IMAGE", "com.fujifilm.raf-raw-image" }, + { NRW_RAW_IMAGE, "NRW_RAW_IMAGE", "com.nikon.nrw-raw-image" }, + { RW2_RAW_IMAGE, "RW2_RAW_IMAGE", "com.panasonic.rw2-raw-image" }, + { PEF_RAW_IMAGE, "PEF_RAW_IMAGE", "com.pentax.pef-raw-image" }, + { SRW_RAW_IMAGE, "SRW_RAW_IMAGE", "com.sumsung.srw-raw-image" }, + { ERF_RAW_IMAGE, "ERF_RAW_IMAGE", "com.epson.erf-raw-image" }, + { ORF_RAW_IMAGE, "ORF_RAW_IMAGE", "com.olympus.orf-raw-image" }, + { IEF_IMAGE, "IEF_IMAGE", "general.ief-image" }, + { ART_IMAGE, "ART_IMAGE", "com.aol.art-image" }, + { CONTENT_FORM, "CONTENT_FORM", "general.content-form" }, + { M4P_AUDIO, "M4P_AUDIO", "com.apple.m4p-audio" }, + { AC3_AUDIO, "AC3_AUDIO", "general.ac3-audio" } }; namespace UtdUtils { diff --git a/udmf/framework/innerkitsimpl/convert/ndk_data_conversion.cpp b/udmf/framework/innerkitsimpl/convert/ndk_data_conversion.cpp index f29312d903cbc952f8da7cc471e59c5d8de2d095..00a105de0d14dc625337ef7a9dac5e0d09e2e29d 100644 --- a/udmf/framework/innerkitsimpl/convert/ndk_data_conversion.cpp +++ b/udmf/framework/innerkitsimpl/convert/ndk_data_conversion.cpp @@ -15,23 +15,22 @@ #include "ndk_data_conversion.h" -#include "udmf_capi_common.h" namespace OHOS::UDMF { -Status NdkDataConversion::GetNativeUnifiedData(OH_UdmfData *ndkData, std::shared_ptr &data) -{ - if (ndkData == nullptr || data == nullptr || ndkData->cid != NdkStructId::UDMF_UNIFIED_DATA_STRUCT_ID) { - return Status::E_INVALID_PARAMETERS; + Status NdkDataConversion::GetNativeUnifiedData(OH_UdmfData* ndkData, std::shared_ptr& data) + { + if (ndkData == nullptr || data == nullptr || ndkData->cid != NdkStructId::UDMF_UNIFIED_DATA_STRUCT_ID) { + return Status::E_INVALID_PARAMETERS; + } + data = ndkData->unifiedData_; + return Status::E_OK; } - data = ndkData->unifiedData_; - return Status::E_OK; -} -Status NdkDataConversion::GetNdkUnifiedData(std::shared_ptr data, OH_UdmfData *ndkData) -{ - if (data == nullptr || ndkData == nullptr || ndkData->cid != NdkStructId::UDMF_UNIFIED_DATA_STRUCT_ID) { - return Status::E_INVALID_PARAMETERS; + Status NdkDataConversion::GetNdkUnifiedData(std::shared_ptr data, OH_UdmfData* ndkData) + { + if (data == nullptr || ndkData == nullptr || ndkData->cid != NdkStructId::UDMF_UNIFIED_DATA_STRUCT_ID) { + return Status::E_INVALID_PARAMETERS; + } + ndkData->unifiedData_ = data; + return Status::E_OK; } - ndkData->unifiedData_ = data; - return Status::E_OK; -} -} // namespace OHOS::UDMF \ No newline at end of file +} \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/convert/udmf_conversion.cpp b/udmf/framework/innerkitsimpl/convert/udmf_conversion.cpp index ad831f34b98a34e09fd280d55187cb78244ed29c..ff3fce704a645debba891d60d25fd191c6b0b340 100644 --- a/udmf/framework/innerkitsimpl/convert/udmf_conversion.cpp +++ b/udmf/framework/innerkitsimpl/convert/udmf_conversion.cpp @@ -41,7 +41,7 @@ void UdmfConversion::SetValueWhenNotUds(std::shared_ptr record) return; } auto object = std::get>(record->GetValue()); - auto it = object->value_.find("VALUE_TYPE"); + auto it = object->value_.find(VALUE_TYPE); if (it == object->value_.end()) { return; } diff --git a/udmf/framework/innerkitsimpl/data/application_defined_record.cpp b/udmf/framework/innerkitsimpl/data/application_defined_record.cpp index 7336e901916e53c8c0938d7d51ce958838e51aff..350a3446980c2f29ecd108ccee8882f208a93ef4 100644 --- a/udmf/framework/innerkitsimpl/data/application_defined_record.cpp +++ b/udmf/framework/innerkitsimpl/data/application_defined_record.cpp @@ -24,6 +24,7 @@ ApplicationDefinedRecord::ApplicationDefinedRecord() : UnifiedRecord(APPLICATION ApplicationDefinedRecord::ApplicationDefinedRecord(std::string type) : UnifiedRecord(APPLICATION_DEFINED_RECORD) { this->applicationDefinedType = std::move(type); + SetUtdId(this->applicationDefinedType); } ApplicationDefinedRecord::ApplicationDefinedRecord(std::string type, std::vector &data) @@ -31,6 +32,7 @@ ApplicationDefinedRecord::ApplicationDefinedRecord(std::string type, std::vector { this->applicationDefinedType = std::move(type); this->rawData_ = std::move(data); + SetUtdId(this->applicationDefinedType); } ApplicationDefinedRecord::ApplicationDefinedRecord(UDType type, ValueType value) @@ -41,10 +43,14 @@ ApplicationDefinedRecord::ApplicationDefinedRecord(UDType type, ValueType value) rawData_ = std::get>(value); } else if (std::holds_alternative>(value)) { auto object = std::get>(value); - object->GetValue(APPLICATION_DEFINED_TYPE, applicationDefinedType); - object->GetValue(RAW_DATA, rawData_); + object->GetValue(UNIFORM_DATA_TYPE, applicationDefinedType); + object->GetValue(ARRAY_BUFFER, rawData_); hasObject_ = true; } + if (applicationDefinedType.empty()) { + applicationDefinedType = UtdUtils::GetUtdIdFromUtdEnum(type); + } + SetUtdId(this->applicationDefinedType); } int64_t ApplicationDefinedRecord::GetSize() @@ -60,9 +66,10 @@ std::string ApplicationDefinedRecord::GetApplicationDefinedType() const void ApplicationDefinedRecord::SetApplicationDefinedType(const std::string &type) { this->applicationDefinedType = type; + SetUtdId(this->applicationDefinedType); if (std::holds_alternative>(value_)) { auto object = std::get>(value_); - object->value_[APPLICATION_DEFINED_TYPE] = applicationDefinedType; + object->value_[UNIFORM_DATA_TYPE] = applicationDefinedType; } } @@ -76,7 +83,8 @@ void ApplicationDefinedRecord::SetRawData(const std::vector &rawData) this->rawData_ = rawData; if (std::holds_alternative>(value_)) { auto object = std::get>(value_); - object->value_[RAW_DATA] = rawData_; + object->value_[ARRAY_BUFFER] = rawData_; + object->value_[ARRAY_BUFFER_LENGTH] = static_cast(rawData_.size()); } } @@ -86,10 +94,10 @@ void ApplicationDefinedRecord::InitObject() auto value = value_; value_ = std::make_shared(); auto object = std::get>(value_); - object->value_[UNIFORM_DATA_TYPE] = UtdUtils::GetUtdIdFromUtdEnum(dataType_); - object->value_[APPLICATION_DEFINED_TYPE] = applicationDefinedType; - object->value_[RAW_DATA] = rawData_; - object->value_["VALUE_TYPE"] = value; + object->value_[UNIFORM_DATA_TYPE] = applicationDefinedType; + object->value_[ARRAY_BUFFER] = rawData_; + object->value_[ARRAY_BUFFER_LENGTH] = static_cast(rawData_.size()); + object->value_[VALUE_TYPE] = value; } } diff --git a/udmf/framework/innerkitsimpl/data/file.cpp b/udmf/framework/innerkitsimpl/data/file.cpp index 9ac6c1ca6f6b272ff445d19951fa41feb885ef96..43beaed6db3b4669b502d43ba5630cbf21279fa0 100644 --- a/udmf/framework/innerkitsimpl/data/file.cpp +++ b/udmf/framework/innerkitsimpl/data/file.cpp @@ -100,7 +100,7 @@ void File::InitObject() object->value_[ORI_URI] = oriUri_; object->value_[REMOTE_URI] = remoteUri_; object->value_[DETAILS] = ObjectUtils::ConvertToObject(details_); - object->value_["VALUE_TYPE"] = value; + object->value_[VALUE_TYPE] = value; } } diff --git a/udmf/framework/innerkitsimpl/data/html.cpp b/udmf/framework/innerkitsimpl/data/html.cpp index 1b4fe76767c9e1a156344b0577638c081a5f23a9..3aebd8d0babbf8860aee05615e2f281aae3aa153 100644 --- a/udmf/framework/innerkitsimpl/data/html.cpp +++ b/udmf/framework/innerkitsimpl/data/html.cpp @@ -40,7 +40,7 @@ Html::Html(UDType type, ValueType value) : Text(type, value) } else if (std::holds_alternative>(value)) { auto object = std::get>(value); object->GetValue(HTML_CONTENT, htmlContent_); - object->GetValue(PLAINT_CONTENT, plainContent_); + object->GetValue(PLAIN_CONTENT, plainContent_); std::shared_ptr detailObj = nullptr; if (object->GetValue(DETAILS, detailObj)) { details_ = ObjectUtils::ConvertToUDDetails(detailObj); @@ -83,7 +83,7 @@ void Html::SetPlainContent(const std::string &plainContent) this->plainContent_ = plainContent; if (std::holds_alternative>(value_)) { auto object = std::get>(value_); - object->value_[PLAINT_CONTENT] = plainContent_; + object->value_[PLAIN_CONTENT] = plainContent_; } } @@ -95,9 +95,9 @@ void Html::InitObject() auto object = std::get>(value_); object->value_[UNIFORM_DATA_TYPE] = UtdUtils::GetUtdIdFromUtdEnum(dataType_); object->value_[HTML_CONTENT] = htmlContent_; - object->value_[PLAINT_CONTENT] = plainContent_; + object->value_[PLAIN_CONTENT] = plainContent_; object->value_[DETAILS] = ObjectUtils::ConvertToObject(details_); - object->value_["VALUE_TYPE"] = value; + object->value_[VALUE_TYPE] = value; } } } // namespace UDMF diff --git a/udmf/framework/innerkitsimpl/data/link.cpp b/udmf/framework/innerkitsimpl/data/link.cpp index 6861bf829d2d35173911c3f16aed8571896ff2a0..ebfe38ea633c8dd852e5fee31248c0c1422c63bd 100644 --- a/udmf/framework/innerkitsimpl/data/link.cpp +++ b/udmf/framework/innerkitsimpl/data/link.cpp @@ -99,7 +99,7 @@ void Link::InitObject() object->value_[URL] = url_; object->value_[DESCRIPTION] = description_; object->value_[DETAILS] = ObjectUtils::ConvertToObject(details_); - object->value_["VALUE_TYPE"] = value; + object->value_[VALUE_TYPE] = value; } } } // namespace UDMF diff --git a/udmf/framework/innerkitsimpl/data/plain_text.cpp b/udmf/framework/innerkitsimpl/data/plain_text.cpp index e16191893cce96a7aa7b846dc83935f45a08d832..da7d2a8b1249e064f730776900cdf092d4787409 100644 --- a/udmf/framework/innerkitsimpl/data/plain_text.cpp +++ b/udmf/framework/innerkitsimpl/data/plain_text.cpp @@ -38,7 +38,7 @@ PlainText::PlainText(UDType type, ValueType value) : Text(type, value) content_ = std::get(value); } else if (std::holds_alternative>(value)) { auto object = std::get>(value); - object->GetValue(TEXT_CONTENT, content_); + object->GetValue(CONTENT, content_); object->GetValue(ABSTRACT, abstract_); std::shared_ptr detailObj = nullptr; if (object->GetValue(DETAILS, detailObj)) { @@ -66,7 +66,7 @@ void PlainText::SetContent(const std::string &text) this->content_ = text; if (std::holds_alternative>(value_)) { auto object = std::get>(value_); - object->value_[TEXT_CONTENT] = content_; + object->value_[CONTENT] = content_; } } @@ -94,10 +94,10 @@ void PlainText::InitObject() value_ = std::make_shared(); auto object = std::get>(value_); object->value_[UNIFORM_DATA_TYPE] = UtdUtils::GetUtdIdFromUtdEnum(dataType_); - object->value_[TEXT_CONTENT] = content_; + object->value_[CONTENT] = content_; object->value_[ABSTRACT] = abstract_; object->value_[DETAILS] = ObjectUtils::ConvertToObject(details_); - object->value_["VALUE_TYPE"] = value; + object->value_[VALUE_TYPE] = value; } } } // namespace UDMF diff --git a/udmf/framework/innerkitsimpl/data/preset_type_descriptors.cpp b/udmf/framework/innerkitsimpl/data/preset_type_descriptors.cpp index ac239d416939245786d4241cf8ed4a207098971b..7c9006be205f085ad2bcd4000276d107eb3e5663 100644 --- a/udmf/framework/innerkitsimpl/data/preset_type_descriptors.cpp +++ b/udmf/framework/innerkitsimpl/data/preset_type_descriptors.cpp @@ -20,7 +20,6 @@ constexpr const char *REFERENCE_URL = "https://gitee.com/openharmony/docs/blob/m PresetTypeDescriptors::PresetTypeDescriptors() { - InitDescriptors(); } PresetTypeDescriptors::~PresetTypeDescriptors() @@ -38,2964 +37,3255 @@ std::vector &PresetTypeDescriptors::GetPresetTypes() return typeDescriptors_; } -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"}, - {"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"}, - {"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"}, - {"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"}, - {"image/heif"}, - "High efficiency image format", - REFERENCE_URL, - ""}, - {"general.heic", - {"general.image"}, - {".heic"}, - {"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, - ""}, - }; -} +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, + ""} +}; } // 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 6278bef2eb77658a1b8aaa9e5c8ef5ca9d5ad013..6412ed112bedc1fc218d6286207ec2ad15dfc873 100644 --- a/udmf/framework/innerkitsimpl/data/preset_type_descriptors.h +++ b/udmf/framework/innerkitsimpl/data/preset_type_descriptors.h @@ -30,8 +30,7 @@ private: PresetTypeDescriptors(const PresetTypeDescriptors &obj) = delete; PresetTypeDescriptors &operator=(const PresetTypeDescriptors &obj) = delete; - void InitDescriptors(); - std::vector typeDescriptors_; + static std::vector typeDescriptors_; }; } // namespace UDMF } // namespace OHOS diff --git a/udmf/framework/innerkitsimpl/data/system_defined_appitem.cpp b/udmf/framework/innerkitsimpl/data/system_defined_appitem.cpp index 59ed1cd874e09a5660bbc8e084e9d52f8d1ee2e5..9cfc622c926782b3d02703afac4de8aa481d17cc 100644 --- a/udmf/framework/innerkitsimpl/data/system_defined_appitem.cpp +++ b/udmf/framework/innerkitsimpl/data/system_defined_appitem.cpp @@ -27,12 +27,12 @@ SystemDefinedAppItem::SystemDefinedAppItem(UDType type, ValueType value) : Syste SetType(SYSTEM_DEFINED_APP_ITEM); if (std::holds_alternative>(value)) { auto object = std::get>(value); - object->GetValue(APPID, appId_); - object->GetValue(APPNAME, appName_); - object->GetValue(APPICONID, appIconId_); - object->GetValue(APPLABELID, appLabelId_); - object->GetValue(BUNDLENAME, bundleName_); - object->GetValue(ABILITYNAME, abilityName_); + object->GetValue(APP_ID, appId_); + object->GetValue(APP_NAME, appName_); + object->GetValue(APP_ICON_ID, appIconId_); + object->GetValue(APP_LABEL_ID, appLabelId_); + object->GetValue(BUNDLE_NAME, bundleName_); + object->GetValue(ABILITY_NAME, abilityName_); std::shared_ptr detailObj = nullptr; if (object->GetValue(DETAILS, detailObj)) { details_ = ObjectUtils::ConvertToUDDetails(detailObj); @@ -56,7 +56,7 @@ void SystemDefinedAppItem::SetAppId(const std::string &appId) { this->appId_ = appId; if (std::holds_alternative>(value_)) { - std::get>(value_)->value_[APPID] = appId_; + std::get>(value_)->value_[APP_ID] = appId_; } } @@ -69,7 +69,7 @@ void SystemDefinedAppItem::SetAppName(const std::string &appName) { this->appName_ = appName; if (std::holds_alternative>(value_)) { - std::get>(value_)->value_[APPNAME] = appName_; + std::get>(value_)->value_[APP_NAME] = appName_; } } @@ -82,7 +82,7 @@ void SystemDefinedAppItem::SetAppIconId(const std::string &appIconId) { this->appIconId_ = appIconId; if (std::holds_alternative>(value_)) { - std::get>(value_)->value_[APPICONID] = appIconId_; + std::get>(value_)->value_[APP_ICON_ID] = appIconId_; } } @@ -95,7 +95,7 @@ void SystemDefinedAppItem::SetAppLabelId(const std::string &appLabelId) { this->appLabelId_ = appLabelId; if (std::holds_alternative>(value_)) { - std::get>(value_)->value_[APPLABELID] = appLabelId_; + std::get>(value_)->value_[APP_LABEL_ID] = appLabelId_; } } @@ -108,7 +108,7 @@ void SystemDefinedAppItem::SetBundleName(const std::string &bundleName) { this->bundleName_ = bundleName; if (std::holds_alternative>(value_)) { - std::get>(value_)->value_[BUNDLENAME] = bundleName_; + std::get>(value_)->value_[BUNDLE_NAME] = bundleName_; } } @@ -121,7 +121,7 @@ void SystemDefinedAppItem::SetAbilityName(const std::string &abilityName) { this->abilityName_ = abilityName; if (std::holds_alternative>(value_)) { - std::get>(value_)->value_[ABILITYNAME] = abilityName_; + std::get>(value_)->value_[ABILITY_NAME] = abilityName_; } } @@ -132,22 +132,22 @@ void SystemDefinedAppItem::SetItems(UDDetails &details) if (value == nullptr) { continue; } - if (item.first == APPID) { + if (item.first == APP_ID) { SetAppId(*value); } - if (item.first == APPNAME) { + if (item.first == APP_NAME) { SetAppName(*value); } - if (item.first == APPICONID) { + if (item.first == APP_ICON_ID) { SetAppIconId(*value); } - if (item.first == APPLABELID) { + if (item.first == APP_LABEL_ID) { SetAppLabelId(*value); } - if (item.first == BUNDLENAME) { + if (item.first == BUNDLE_NAME) { SetBundleName(*value); } - if (item.first == ABILITYNAME) { + if (item.first == ABILITY_NAME) { SetAbilityName(*value); } } @@ -156,12 +156,12 @@ void SystemDefinedAppItem::SetItems(UDDetails &details) UDDetails SystemDefinedAppItem::GetItems() { UDDetails items; - items[APPID] = GetAppId(); - items[APPNAME] = GetAppName(); - items[APPICONID] = GetAppIconId(); - items[APPLABELID] = GetAppLabelId(); - items[BUNDLENAME] = GetBundleName(); - items[ABILITYNAME] = GetAbilityName(); + items[APP_ID] = GetAppId(); + items[APP_NAME] = GetAppName(); + items[APP_ICON_ID] = GetAppIconId(); + items[APP_LABEL_ID] = GetAppLabelId(); + items[BUNDLE_NAME] = GetBundleName(); + items[ABILITY_NAME] = GetAbilityName(); return items; } @@ -172,14 +172,14 @@ void SystemDefinedAppItem::InitObject() value_ = std::make_shared(); auto object = std::get>(value_); object->value_[UNIFORM_DATA_TYPE] = UtdUtils::GetUtdIdFromUtdEnum(dataType_); - object->value_[APPID] = appId_; - object->value_[APPNAME] = appName_; - object->value_[APPICONID] = appIconId_; - object->value_[APPLABELID] = appLabelId_; - object->value_[BUNDLENAME] = bundleName_; - object->value_[ABILITYNAME] = abilityName_; + object->value_[APP_ID] = appId_; + object->value_[APP_NAME] = appName_; + object->value_[APP_ICON_ID] = appIconId_; + object->value_[APP_LABEL_ID] = appLabelId_; + object->value_[BUNDLE_NAME] = bundleName_; + object->value_[ABILITY_NAME] = abilityName_; object->value_[DETAILS] = ObjectUtils::ConvertToObject(details_); - object->value_["VALUE_TYPE"] = value; + object->value_[VALUE_TYPE] = value; } } } // namespace UDMF diff --git a/udmf/framework/innerkitsimpl/data/system_defined_form.cpp b/udmf/framework/innerkitsimpl/data/system_defined_form.cpp index 2d305bcbd930cf5831423986ca6502e373e8bfe3..1bfcbc34a6f19a1bebf68d42a92ae38b0ae871b1 100644 --- a/udmf/framework/innerkitsimpl/data/system_defined_form.cpp +++ b/udmf/framework/innerkitsimpl/data/system_defined_form.cpp @@ -29,8 +29,8 @@ SystemDefinedForm::SystemDefinedForm(UDType type, ValueType value) : SystemDefin auto object = std::get>(value); object->GetValue(FORMID, formId_); object->GetValue(FORMNAME, formName_); - object->GetValue(BUNDLENAME, bundleName_); - object->GetValue(ABILITYNAME, abilityName_); + object->GetValue(BUNDLE_NAME, bundleName_); + object->GetValue(ABILITY_NAME, abilityName_); object->GetValue(MODULE, module_); std::shared_ptr detailObj = nullptr; if (object->GetValue(DETAILS, detailObj)) { @@ -81,7 +81,7 @@ void SystemDefinedForm::SetBundleName(const std::string &bundleName) { this->bundleName_ = bundleName; if (std::holds_alternative>(value_)) { - std::get>(value_)->value_[BUNDLENAME] = bundleName_; + std::get>(value_)->value_[BUNDLE_NAME] = bundleName_; } } @@ -94,7 +94,7 @@ void SystemDefinedForm::SetAbilityName(const std::string &abilityName) { this->abilityName_ = abilityName; if (std::holds_alternative>(value_)) { - std::get>(value_)->value_[ABILITYNAME] = abilityName_; + std::get>(value_)->value_[ABILITY_NAME] = abilityName_; } } @@ -132,10 +132,10 @@ void SystemDefinedForm::SetItems(UDDetails& details) if (item.first == MODULE) { SetModule(*value); } - if (item.first == BUNDLENAME) { + if (item.first == BUNDLE_NAME) { SetBundleName(*value); } - if (item.first == ABILITYNAME) { + if (item.first == ABILITY_NAME) { SetAbilityName(*value); } } @@ -147,8 +147,8 @@ UDDetails SystemDefinedForm::GetItems() items[FORMID] = GetFormId(); items[FORMNAME] = GetFormName(); items[MODULE] = GetModule(); - items[BUNDLENAME] = GetBundleName(); - items[ABILITYNAME] = GetAbilityName(); + items[BUNDLE_NAME] = GetBundleName(); + items[ABILITY_NAME] = GetAbilityName(); return items; } @@ -161,11 +161,11 @@ void SystemDefinedForm::InitObject() object->value_[UNIFORM_DATA_TYPE] = UtdUtils::GetUtdIdFromUtdEnum(dataType_); object->value_[FORMID] = formId_; object->value_[FORMNAME] = formName_; - object->value_[BUNDLENAME] = bundleName_; - object->value_[ABILITYNAME] = abilityName_; + object->value_[BUNDLE_NAME] = bundleName_; + object->value_[ABILITY_NAME] = abilityName_; object->value_[MODULE] = module_; object->value_[DETAILS] = ObjectUtils::ConvertToObject(details_); - object->value_["VALUE_TYPE"] = value; + object->value_[VALUE_TYPE] = value; } } diff --git a/udmf/framework/innerkitsimpl/data/system_defined_pixelmap.cpp b/udmf/framework/innerkitsimpl/data/system_defined_pixelmap.cpp index 06848ca0e861d2e7d599c62bb038ae77b50a7042..94d6b3992533e8e593ddfc9670ff7c337fa83347 100644 --- a/udmf/framework/innerkitsimpl/data/system_defined_pixelmap.cpp +++ b/udmf/framework/innerkitsimpl/data/system_defined_pixelmap.cpp @@ -19,7 +19,6 @@ namespace OHOS { namespace UDMF { - SystemDefinedPixelMap::SystemDefinedPixelMap() { SetType(SYSTEM_DEFINED_PIXEL_MAP); @@ -37,8 +36,12 @@ SystemDefinedPixelMap::SystemDefinedPixelMap(UDType type, ValueType value) : Sys if (std::holds_alternative>(value)) { rawData_ = std::get>(value); return; - } - if (std::holds_alternative>(value)) { + } else if (std::holds_alternative>(value)) { + auto pixelMap = std::get>(value); + if (!pixelMap->EncodeTlv(rawData_)) { + LOG_ERROR(UDMF_KITS_INNER, "pixelMap encode fail!"); + } + } else if (std::holds_alternative>(value)) { auto object = std::get>(value); auto it = object->value_.find(PIXEL_MAP); hasObject_ = true; @@ -94,10 +97,10 @@ void SystemDefinedPixelMap::InitObject() } else { object->value_[PIXEL_MAP] = pixelMap; } + object->value_[UNIFORM_DATA_TYPE] = UtdUtils::GetUtdIdFromUtdEnum(dataType_); object->value_[DETAILS] = ObjectUtils::ConvertToObject(details_); - object->value_["VALUE_TYPE"] = value; + object->value_[VALUE_TYPE] = value; } } - } // namespace UDMF } // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/data/system_defined_record.cpp b/udmf/framework/innerkitsimpl/data/system_defined_record.cpp index e10b09d057ecfb26e34473847e9ca239f678c265..e4dc3e26a84db6c2d61b968f819b1fb3ab38472e 100644 --- a/udmf/framework/innerkitsimpl/data/system_defined_record.cpp +++ b/udmf/framework/innerkitsimpl/data/system_defined_record.cpp @@ -81,7 +81,7 @@ void SystemDefinedRecord::InitObject() value_ = std::make_shared(); auto object = std::get>(value_); object->value_[DETAILS] = ObjectUtils::ConvertToObject(details_); - object->value_["VALUE_TYPE"] = value; + object->value_[VALUE_TYPE] = value; } } } // namespace UDMF diff --git a/udmf/framework/innerkitsimpl/data/text.cpp b/udmf/framework/innerkitsimpl/data/text.cpp index 7bb42a2a7ede7c4f3cb37a0ae3ee9ed6caaa2644..9d473c8578e818ca1eff3254b0610884540d626f 100644 --- a/udmf/framework/innerkitsimpl/data/text.cpp +++ b/udmf/framework/innerkitsimpl/data/text.cpp @@ -64,7 +64,7 @@ void Text::InitObject() value_ = std::make_shared(); auto object = std::get>(value_); object->value_[DETAILS] = ObjectUtils::ConvertToObject(details_); - object->value_["VALUE_TYPE"] = value; + object->value_[VALUE_TYPE] = value; } } } // namespace UDMF diff --git a/udmf/framework/innerkitsimpl/data/unified_data_helper.cpp b/udmf/framework/innerkitsimpl/data/unified_data_helper.cpp index 9c4156235623d92f9af24baf13b520e735d67e02..340885a7f65897087fda4353b91cacb33569c86f 100644 --- a/udmf/framework/innerkitsimpl/data/unified_data_helper.cpp +++ b/udmf/framework/innerkitsimpl/data/unified_data_helper.cpp @@ -19,12 +19,12 @@ #include #include "common_func.h" #include "directory_ex.h" -#include "file.h" #include "file_ex.h" #include "file_uri.h" #include "logger.h" #include "tlv_util.h" #include "udmf_conversion.h" +#include "file.h" namespace OHOS { namespace UDMF { diff --git a/udmf/framework/innerkitsimpl/data/unified_record.cpp b/udmf/framework/innerkitsimpl/data/unified_record.cpp index 44408a2c8204130a5c5eed2ac429a929be1ad5a8..0afab7f22dee1c7c1602abdd299c54260dbd56b9 100644 --- a/udmf/framework/innerkitsimpl/data/unified_record.cpp +++ b/udmf/framework/innerkitsimpl/data/unified_record.cpp @@ -16,6 +16,7 @@ #include "unified_record.h" #include "getter_system.h" +#include "logger.h" namespace OHOS { namespace UDMF { @@ -174,12 +175,18 @@ uint32_t UnifiedRecord::GetRecordId() const return recordId_; } -void UnifiedRecord::SetEntryGetter(const std::set &utdIds, const std::shared_ptr entryGetter) +void UnifiedRecord::SetEntryGetter( + const std::vector &utdIds, + const std::shared_ptr &entryGetter) { - for (auto utdId : utdIds) { + for (auto const &utdId : utdIds) { + if (HasType(utdId)) { + LOG_WARN(UDMF_FRAMEWORK, "already has the utdId: %{public}s", utdId.c_str()); + continue; + } AddEntry(utdId, ValueType()); } - entryGetter_ = std::move(entryGetter); + entryGetter_ = entryGetter; } std::shared_ptr UnifiedRecord::GetEntryGetter() @@ -198,7 +205,7 @@ void UnifiedRecord::InitObject() auto value = value_; value_ = std::make_shared(); auto object = std::get>(value_); - object->value_["VALUE_TYPE"] = value; + object->value_[VALUE_TYPE] = value; } } diff --git a/udmf/framework/innerkitsimpl/test/unittest/BUILD.gn b/udmf/framework/innerkitsimpl/test/unittest/BUILD.gn index 69b16c259d0f557c3836e06d484c158caa8cfe89..d46bea24d77dbc403c62ce46ab6afe3df5748614 100644 --- a/udmf/framework/innerkitsimpl/test/unittest/BUILD.gn +++ b/udmf/framework/innerkitsimpl/test/unittest/BUILD.gn @@ -35,9 +35,11 @@ config("module_private_config") { common_deps = [ "${udmf_interfaces_path}/innerkits:udmf_client", "${udmf_interfaces_path}/innerkits:utd_client", + "${udmf_interfaces_path}/ndk:libudmf", ] common_external_deps = [ + "ability_base:base", "ability_base:want", "access_token:libaccesstoken_sdk", "access_token:libnativetoken", diff --git a/udmf/framework/innerkitsimpl/test/unittest/custom_utd_store_test.cpp b/udmf/framework/innerkitsimpl/test/unittest/custom_utd_store_test.cpp index 820443addcc67cbfbfef7850b80e68f13b8bf957..9cd67523b15c5a2cbe8b168f97d30b6a4a9ff52a 100644 --- a/udmf/framework/innerkitsimpl/test/unittest/custom_utd_store_test.cpp +++ b/udmf/framework/innerkitsimpl/test/unittest/custom_utd_store_test.cpp @@ -27,8 +27,9 @@ using namespace testing::ext; using namespace OHOS::UDMF; using namespace OHOS; namespace OHOS::Test { -constexpr const char* TEST_CFG_FILE = "/data/100-test/utd-adt.json"; -constexpr const char* TEST_CFG_DIR = "/data/100-test/"; +constexpr const int32_t USERID = 1000000; +constexpr const char* TEST_CFG_FILE = "/data/1000000/utd-adt.json"; +constexpr const char* TEST_CFG_DIR = "/data/1000000/"; constexpr const char* TEST_DATA2 = "{\ \"CustomUTDs\": [{\ @@ -94,11 +95,11 @@ HWTEST_F(CustomUtdStoreTest, SaveTypeCfgs001, TestSize.Level1) std::vector typesCfg; CustomUtdJsonParser parser; parser.ParseStoredCustomUtdJson(TEST_DATA2, typesCfg); - auto status = CustomUtdStore::GetInstance().SaveTypeCfgs(typesCfg, TEST_CFG_FILE); + auto status = CustomUtdStore::GetInstance().SaveTypeCfgs(typesCfg, USERID); EXPECT_EQ(status, E_OK); typesCfg.clear(); - typesCfg = CustomUtdStore::GetInstance().GetTypeCfgs(TEST_CFG_FILE); + typesCfg = CustomUtdStore::GetInstance().GetTypeCfgs(USERID); TypeDescriptorCfg type1 = *(typesCfg.begin()); EXPECT_EQ(type1.typeId, "com.example.utdtest.document"); EXPECT_EQ(*(type1.belongingToTypes.begin()), "com.example.utdtest2.document"); diff --git a/udmf/framework/innerkitsimpl/test/unittest/graph_test.cpp b/udmf/framework/innerkitsimpl/test/unittest/graph_test.cpp index 9db905ba6e0bbc5e73249be811786d305da12c2b..b453d4635db14a1abbe162358beb44f915a56233 100644 --- a/udmf/framework/innerkitsimpl/test/unittest/graph_test.cpp +++ b/udmf/framework/innerkitsimpl/test/unittest/graph_test.cpp @@ -70,7 +70,7 @@ HWTEST_F(GraphTest, DfsUnconnectedGraph001, TestSize.Level1) uint32_t vextexNum = 1; vector> edges={{TestNodes::POINT_A, TestNodes::POINT_A}, }; - Graph graph(vextexNum); + Graph graph(vextexNum, {}); for (uint32_t i = 0; i < edges.size(); i++) { graph.AddEdge(edges[i][0], edges[i][1]); } @@ -92,7 +92,7 @@ HWTEST_F(GraphTest, DfsUnconnectedGraph002, TestSize.Level1) vector> edges={{TestNodes::POINT_A, TestNodes::POINT_B}, {TestNodes::POINT_B, TestNodes::POINT_A}, }; - Graph graph(vextexNum); + Graph graph(vextexNum, {}); for (uint32_t i = 0; i < edges.size(); i++) { graph.AddEdge(edges[i][0], edges[i][1]); } @@ -115,7 +115,7 @@ HWTEST_F(GraphTest, DfsUnconnectedGraph003, TestSize.Level1) {TestNodes::POINT_B, TestNodes::POINT_C}, {TestNodes::POINT_C, TestNodes::POINT_A} }; - Graph graph(vextexNum); + Graph graph(vextexNum, {}); for (uint32_t i = 0; i < edges.size(); i++) { graph.AddEdge(edges[i][0], edges[i][1]); } @@ -138,7 +138,7 @@ HWTEST_F(GraphTest, DfsUnconnectedGraph004, TestSize.Level1) {TestNodes::POINT_B, TestNodes::POINT_C}, {TestNodes::POINT_C, TestNodes::POINT_B}, }; - Graph graph(vextexNum); + Graph graph(vextexNum, {}); for (uint32_t i = 0; i < edges.size(); i++) { graph.AddEdge(edges[i][0], edges[i][1]); } @@ -168,7 +168,7 @@ HWTEST_F(GraphTest, DfsUnconnectedGraph005, TestSize.Level1) {TestNodes::POINT_G, TestNodes::POINT_H}, {TestNodes::POINT_H, TestNodes::POINT_E}, }; - Graph graph(vextexNum); + Graph graph(vextexNum, {}); for (uint32_t i = 0; i < edges.size(); i++) { graph.AddEdge(edges[i][0], edges[i][1]); } @@ -197,7 +197,7 @@ HWTEST_F(GraphTest, DfsUnconnectedGraph006, TestSize.Level1) {TestNodes::POINT_E, TestNodes::POINT_G}, {TestNodes::POINT_G, TestNodes::POINT_H}, }; - Graph graph(vextexNum); + Graph graph(vextexNum, {}); for (uint32_t i = 0; i < edges.size(); i++) { graph.AddEdge(edges[i][0], edges[i][1]); } @@ -223,7 +223,7 @@ HWTEST_F(GraphTest, DfsUnconnectedGraph007, TestSize.Level1) {TestNodes::POINT_C, TestNodes::POINT_D}, {TestNodes::POINT_B, TestNodes::POINT_C}, }; - Graph graph(vextexNum); + Graph graph(vextexNum, {}); for (uint32_t i = 0; i < edges.size(); i++) { graph.AddEdge(edges[i][0], edges[i][1]); } @@ -249,7 +249,7 @@ HWTEST_F(GraphTest, DfsUnconnectedGraph008, TestSize.Level1) {TestNodes::POINT_F, TestNodes::POINT_G}, {TestNodes::POINT_G, TestNodes::POINT_H}, }; - Graph graph(vextexNum); + Graph graph(vextexNum, {}); for (uint32_t i = 0; i < edges.size(); i++) { graph.AddEdge(edges[i][0], edges[i][1]); } @@ -278,7 +278,7 @@ HWTEST_F(GraphTest, DfsHasData001, TestSize.Level1) {TestNodes::POINT_E, TestNodes::POINT_G}, {TestNodes::POINT_G, TestNodes::POINT_H}, }; - Graph graph(vextexNum); + Graph graph(vextexNum, {}); for (uint32_t i = 0; i < edges.size(); i++) { graph.AddEdge(edges[i][0], edges[i][1]); } @@ -331,7 +331,7 @@ HWTEST_F(GraphTest, DfsHasData002, TestSize.Level1) {TestNodes::POINT_F, TestNodes::POINT_G}, {TestNodes::POINT_G, TestNodes::POINT_H}, }; - Graph graph(vextexNum); + Graph graph(vextexNum, {}); for (uint32_t i = 0; i < edges.size(); i++) { graph.AddEdge(edges[i][0], edges[i][1]); } diff --git a/udmf/framework/innerkitsimpl/test/unittest/mock/include/udmf_service_client_mock.h b/udmf/framework/innerkitsimpl/test/unittest/mock/include/udmf_service_client_mock.h index 4a7795f08d7720bd808ada42be654d7260290bfb..4ee008d7d5a0d20cc6f92f4ce3d901f66e0d4b98 100644 --- a/udmf/framework/innerkitsimpl/test/unittest/mock/include/udmf_service_client_mock.h +++ b/udmf/framework/innerkitsimpl/test/unittest/mock/include/udmf_service_client_mock.h @@ -49,21 +49,21 @@ public: class UdmfServiceClientMock : public MUdmfServiceClient { public: - MOCK_METHOD0(GetInstance, std::shared_ptr()); - MOCK_METHOD3(SetData, int32_t(CustomOption &, UnifiedData &, std::string &)); - MOCK_METHOD2(GetData, int32_t(const QueryOption &, UnifiedData &)); - MOCK_METHOD2(GetBatchData, int32_t(const QueryOption &, std::vector &)); - MOCK_METHOD2(UpdateData, int32_t(const QueryOption &, UnifiedData &)); - MOCK_METHOD2(DeleteData, int32_t(const QueryOption &, std::vector &)); - MOCK_METHOD2(GetSummary, int32_t(const QueryOption &, Summary &)); - MOCK_METHOD2(AddPrivilege, int32_t(const QueryOption &, Privilege &)); - MOCK_METHOD2(Sync, int32_t(const QueryOption &, const std::vector &)); - MOCK_METHOD2(IsRemoteData, int32_t(const QueryOption &, bool &)); - MOCK_METHOD2(SetAppShareOption, int32_t(const std::string &, int32_t shareOption)); - MOCK_METHOD2(GetAppShareOption, int32_t(const std::string &, int32_t &)); - MOCK_METHOD1(RemoveAppShareOption, int32_t(const std::string &)); - MOCK_METHOD1(ObtainAsynProcess, int32_t(AsyncProcessInfo&)); - MOCK_METHOD0(ClearAsynProcess, int32_t()); + MOCK_METHOD(std::shared_ptr, GetInstance, ()); + MOCK_METHOD(int32_t, SetData, (CustomOption &, UnifiedData &, std::string &)); + MOCK_METHOD(int32_t, GetData, (const QueryOption &, UnifiedData &)); + MOCK_METHOD(int32_t, GetBatchData, (const QueryOption &, std::vector &)); + MOCK_METHOD(int32_t, UpdateData, (const QueryOption &, UnifiedData &)); + MOCK_METHOD(int32_t, DeleteData, (const QueryOption &, std::vector &)); + MOCK_METHOD(int32_t, GetSummary, (const QueryOption &, Summary &)); + MOCK_METHOD(int32_t, AddPrivilege, (const QueryOption &, Privilege &)); + MOCK_METHOD(int32_t, Sync, (const QueryOption &, const std::vector &)); + MOCK_METHOD(int32_t, IsRemoteData, (const QueryOption &, bool &)); + MOCK_METHOD(int32_t, SetAppShareOption, (const std::string &, int32_t shareOption)); + MOCK_METHOD(int32_t, GetAppShareOption, (const std::string &, int32_t &)); + MOCK_METHOD(int32_t, RemoveAppShareOption, (const std::string &)); + MOCK_METHOD(int32_t, ObtainAsynProcess, (AsyncProcessInfo&)); + MOCK_METHOD(int32_t, ClearAsynProcess, ()); }; } // namespace UDMF } // namespace OHOS 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 7d8dc45592d7257d496d073331f1cfff3e101f27..e05ee39fb39dabe34eec6fa313ba74943022102e 100644 --- a/udmf/framework/innerkitsimpl/test/unittest/ndk_data_conversion_test.cpp +++ b/udmf/framework/innerkitsimpl/test/unittest/ndk_data_conversion_test.cpp @@ -22,10 +22,17 @@ #include "accesstoken_kit.h" #include "nativetoken_kit.h" #include "logger.h" +#include "application_defined_record.h" #include "error_code.h" +#include "html.h" #include "udmf.h" #include "udmf_capi_common.h" +#include "udmf_client.h" +#include "udmf_meta.h" #include "uds.h" +#include "unified_data.h" +#include "pixelmap_native_impl.h" +#include "system_defined_pixelmap.h" using namespace testing::ext; using namespace OHOS::Security::AccessToken; @@ -33,113 +40,650 @@ 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 +class NdkDataConversionTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + static void AllocHapToken1(); + static void AllocHapToken2(); + void SetHapToken1(); + static constexpr int USER_ID = 100; + static constexpr int INST_INDEX = 0; +}; + +void NdkDataConversionTest::SetUpTestCase() +{ + AllocHapToken1(); + AllocHapToken2(); +} + +void NdkDataConversionTest::TearDownTestCase() +{ + auto tokenId = AccessTokenKit::GetHapTokenID(USER_ID, "ohos.test.demo1", INST_INDEX); + AccessTokenKit::DeleteToken(tokenId); + tokenId = AccessTokenKit::GetHapTokenID(USER_ID, "ohos.test.demo2", INST_INDEX); + AccessTokenKit::DeleteToken(tokenId); +} + +void NdkDataConversionTest::SetUp() +{ + SetHapToken1(); +} + +void NdkDataConversionTest::TearDown() {} + +void NdkDataConversionTest::AllocHapToken1() +{ + HapInfoParams info = { + .userID = USER_ID, + .bundleName = "ohos.test.demo1", + .instIndex = INST_INDEX, + .appIDDesc = "ohos.test.demo1" + }; + + HapPolicyParams policy = { + .apl = APL_NORMAL, + .domain = "test.domain", + .permList = { { + .permissionName = "ohos.permission.test", + .bundleName = "ohos.test.demo1", + .grantMode = 1, + .availableLevel = APL_NORMAL, + .label = "label", + .labelId = 1, + .description = "test1", + .descriptionId = 1 } }, + .permStateList = { { + .permissionName = "ohos.permission.test", + .isGeneral = true, + .resDeviceID = { "local" }, + .grantStatus = { PermissionState::PERMISSION_GRANTED }, + .grantFlags = { 1 } } } + }; + auto tokenID = AccessTokenKit::AllocHapToken(info, policy); + SetSelfTokenID(tokenID.tokenIDEx); +} + +void NdkDataConversionTest::AllocHapToken2() +{ + HapInfoParams info = { + .userID = USER_ID, + .bundleName = "ohos.test.demo2", + .instIndex = INST_INDEX, + .appIDDesc = "ohos.test.demo2" + }; + + HapPolicyParams policy = { + .apl = APL_NORMAL, + .domain = "test.domain", + .permList = { { + .permissionName = "ohos.permission.test", + .bundleName = "ohos.test.demo2", + .grantMode = 1, + .availableLevel = APL_NORMAL, + .label = "label", + .labelId = 1, + .description = "test2", + .descriptionId = 1 } }, + .permStateList = { { + .permissionName = "ohos.permission.test", + .isGeneral = true, + .resDeviceID = { "local" }, + .grantStatus = { PermissionState::PERMISSION_GRANTED }, + .grantFlags = { 1 } } } + }; + auto tokenID = AccessTokenKit::AllocHapToken(info, policy); + SetSelfTokenID(tokenID.tokenIDEx); +} + +void NdkDataConversionTest::SetHapToken1() +{ + auto tokenId = AccessTokenKit::GetHapTokenID(USER_ID, "ohos.test.demo1", INST_INDEX); + SetSelfTokenID(tokenId); +} + +/* * + * @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."); +} + +/* * + * @tc.name: ConvertPixelMap_001 + * @tc.desc: test pixel-map conversion between JS and C-API + * @tc.type: FUNC + */ +HWTEST_F(NdkDataConversionTest, ConvertPixelMap_001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "ConvertPixelMap_001 begin."); + uint32_t color[100] = { 3, 7, 9, 9, 7, 6 }; + OHOS::Media::InitializationOptions opts = { { 5, 7 }, + Media::PixelFormat::ARGB_8888, + Media::PixelFormat::ARGB_8888 }; + std::unique_ptr pixelMap = + OHOS::Media::PixelMap::Create(color, sizeof(color) / sizeof(color[0]), opts); + std::shared_ptr pixelMapIn = move(pixelMap); + + auto pixelMapUds = OH_UdsPixelMap_Create(); + OH_PixelmapNative *ohPixelmapNative = new OH_PixelmapNative(pixelMapIn); + OH_UdsPixelMap_SetPixelMap(pixelMapUds, ohPixelmapNative); + auto record = OH_UdmfRecord_Create(); + OH_UdmfRecord_AddPixelMap(record, pixelMapUds); + auto data = OH_UdmfData_Create(); + OH_UdmfData_AddRecord(data, record); + std::shared_ptr unifiedData = std::make_shared(); + auto conversionStatus = NdkDataConversion::GetNativeUnifiedData(data, unifiedData); + EXPECT_EQ(conversionStatus, E_OK); + std::string key; + 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 + }; + auto getRet = UdmfClient::GetInstance().GetData(query, *readData); + EXPECT_EQ(getRet, E_OK); + + auto readRecord = readData->GetRecordAt(0); + auto systemDefinedPixelMap = std::static_pointer_cast(readRecord); + auto rawData = systemDefinedPixelMap->GetRawData(); + EXPECT_GT(rawData.size(), 0); + + OH_UdsPixelMap_Destroy(pixelMapUds); + OH_UdmfRecord_Destroy(record); + OH_UdmfData_Destroy(data); + delete ohPixelmapNative; + LOG_INFO(UDMF_TEST, "ConvertPixelMap_001 end."); +} + +/* * + * @tc.name: ConvertPixelMap_002 + * @tc.desc: test pixel-map conversion between JS and C-API + * @tc.type: FUNC + */ +HWTEST_F(NdkDataConversionTest, ConvertPixelMap_002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "ConvertPixelMap_002 begin."); + uint32_t color[100] = { 3, 7, 9, 9, 7, 6 }; + OHOS::Media::InitializationOptions opts = { { 5, 7 }, + Media::PixelFormat::ARGB_8888, Media::PixelFormat::ARGB_8888 }; + std::unique_ptr pixelMap = + OHOS::Media::PixelMap::Create(color, sizeof(color) / sizeof(color[0]), opts); + std::shared_ptr pixelMapIn = move(pixelMap); + + std::shared_ptr systemDefinedPixelMap = + std::make_shared(UDType::SYSTEM_DEFINED_PIXEL_MAP, pixelMapIn); + UnifiedData data; + std::vector> records = { systemDefinedPixelMap }; + data.SetRecords(records); + + std::string key; + 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 }; + auto getRet = UdmfClient::GetInstance().GetData(query, *readData); + EXPECT_EQ(getRet, E_OK); + + auto ndkData = OH_UdmfData_Create(); + NdkDataConversion::GetNdkUnifiedData(readData, ndkData); + unsigned int count; + OH_UdmfData_GetRecords(ndkData, &count); + EXPECT_EQ(1, count); + auto record = OH_UdmfData_GetRecord(ndkData, 0); + auto pixelMapUds = OH_UdsPixelMap_Create(); + OH_UdmfRecord_GetPixelMap(record, pixelMapUds); + auto type = OH_UdsPixelMap_GetType(pixelMapUds); + EXPECT_EQ(std::string(type), std::string(UDMF_META_OPENHARMONY_PIXEL_MAP)); + + OHOS::Media::InitializationOptions opts2 = { { 10, 10 }, + Media::PixelFormat::ARGB_8888, Media::PixelFormat::ARGB_8888 }; + std::unique_ptr pixelMap2 = + OHOS::Media::PixelMap::Create(color, sizeof(color) / sizeof(color[0]), opts2); + + OH_PixelmapNative *ohPixelmapNative = new OH_PixelmapNative(std::move(pixelMap2)); + OH_UdsPixelMap_GetPixelMap(pixelMapUds, ohPixelmapNative); + auto resultPixelMap = ohPixelmapNative->GetInnerPixelmap(); + auto height = resultPixelMap->GetHeight(); + EXPECT_EQ(height, 7); + + OH_UdsPixelMap_Destroy(pixelMapUds); + OH_UdmfData_Destroy(ndkData); + delete ohPixelmapNative; + LOG_INFO(UDMF_TEST, "ConvertPixelMap_002 end."); +} + +/* * + * @tc.name: ConvertPixelMap_003 + * @tc.desc: test pixel-map conversion between JS and C-API + * @tc.type: FUNC + */ +HWTEST_F(NdkDataConversionTest, ConvertPixelMap_003, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "ConvertPixelMap_003 begin."); + uint32_t color[100] = { 3, 7, 9, 9, 7, 6 }; + OHOS::Media::InitializationOptions opts = { { 5, 7 }, + Media::PixelFormat::ARGB_8888, Media::PixelFormat::ARGB_8888 }; + std::unique_ptr pixelMap = + OHOS::Media::PixelMap::Create(color, sizeof(color) / sizeof(color[0]), opts); + std::shared_ptr pixelMapIn = move(pixelMap); + std::vector buff; + pixelMapIn->EncodeTlv(buff); + + std::shared_ptr systemDefinedPixelMap = + std::make_shared(UDType::SYSTEM_DEFINED_PIXEL_MAP, buff); + UnifiedData data; + std::vector> records = { systemDefinedPixelMap }; + data.SetRecords(records); + + std::string key; + 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 }; + auto getRet = UdmfClient::GetInstance().GetData(query, *readData); + EXPECT_EQ(getRet, E_OK); + + auto ndkData = OH_UdmfData_Create(); + NdkDataConversion::GetNdkUnifiedData(readData, ndkData); + unsigned int count; + OH_UdmfData_GetRecords(ndkData, &count); + EXPECT_EQ(1, count); + auto record = OH_UdmfData_GetRecord(ndkData, 0); + auto pixelMapUds = OH_UdsPixelMap_Create(); + OH_UdmfRecord_GetPixelMap(record, pixelMapUds); + auto type = OH_UdsPixelMap_GetType(pixelMapUds); + EXPECT_EQ(std::string(type), std::string(UDMF_META_OPENHARMONY_PIXEL_MAP)); + + OHOS::Media::InitializationOptions opts2 = { { 10, 10 }, + Media::PixelFormat::ARGB_8888, Media::PixelFormat::ARGB_8888 }; + std::unique_ptr pixelMap2 = + OHOS::Media::PixelMap::Create(color, sizeof(color) / sizeof(color[0]), opts2); + + OH_PixelmapNative *ohPixelmapNative = new OH_PixelmapNative(std::move(pixelMap2)); + OH_UdsPixelMap_GetPixelMap(pixelMapUds, ohPixelmapNative); + auto resultPixelMap = ohPixelmapNative->GetInnerPixelmap(); + auto height = resultPixelMap->GetHeight(); + EXPECT_EQ(height, 7); + + OH_UdsPixelMap_Destroy(pixelMapUds); + OH_UdmfData_Destroy(ndkData); + delete ohPixelmapNative; + LOG_INFO(UDMF_TEST, "ConvertPixelMap_003 end."); +} + +/* * + * @tc.name: ConvertApplicationDefined_001 + * @tc.desc: test application defined record conversion between JS and C-API + * @tc.type: FUNC + */ +HWTEST_F(NdkDataConversionTest, ConvertApplicationDefined_001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "ConvertApplicationDefined_001 begin."); + std::vector dataBytes = { '1', '2', '3', '4', '5', '6' }; + std::string definedTypeId = "person_app_demo"; + std::shared_ptr systemDefinedPixelMap = + std::make_shared(definedTypeId, dataBytes); + UnifiedData data; + std::vector> records = { systemDefinedPixelMap }; + data.SetRecords(records); + + std::string key; + 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 + }; + auto getRet = UdmfClient::GetInstance().GetData(query, *readData); + EXPECT_EQ(getRet, E_OK); + + auto ndkData = OH_UdmfData_Create(); + NdkDataConversion::GetNdkUnifiedData(readData, ndkData); + unsigned int count; + OH_UdmfData_GetRecords(ndkData, &count); + EXPECT_EQ(1, count); + auto record = OH_UdmfData_GetRecord(ndkData, 0); + unsigned int getCount = 0; + unsigned char *getEntry; + auto result = OH_UdmfRecord_GetGeneralEntry(record, definedTypeId.c_str(), &getEntry, &getCount); + EXPECT_EQ(0, result); + EXPECT_EQ(6, getCount); + dataBytes = { '1', '2', '3', '4', '5', '6' }; + EXPECT_EQ(std::string(dataBytes.begin(), dataBytes.end()), std::string(reinterpret_cast(getEntry))); + + OH_UdmfData_Destroy(ndkData); + LOG_INFO(UDMF_TEST, "ConvertApplicationDefined_001 end."); +} + +/* * + * @tc.name: ConvertApplicationDefined_002 + * @tc.desc: test application defined record conversion between JS and C-API + * @tc.type: FUNC + */ +HWTEST_F(NdkDataConversionTest, ConvertApplicationDefined_002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "ConvertApplicationDefined_002 begin."); + std::vector dataBytes = { '1', '2', '3', '4', '5', '6' }; + std::string definedTypeId = "person_app_demo"; + std::shared_ptr systemDefinedPixelMap = + std::make_shared(definedTypeId, dataBytes); + UnifiedData data; + std::vector> records = { systemDefinedPixelMap }; + data.SetRecords(records); + + std::string key; + 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 + }; + auto getRet = UdmfClient::GetInstance().GetData(query, *readData); + EXPECT_EQ(getRet, E_OK); + + auto ndkData = OH_UdmfData_Create(); + NdkDataConversion::GetNdkUnifiedData(readData, ndkData); + unsigned int count; + OH_UdmfData_GetRecords(ndkData, &count); + EXPECT_EQ(1, count); + auto record = OH_UdmfData_GetRecord(ndkData, 0); + auto arrayBuffer = OH_UdsArrayBuffer_Create(); + auto result = OH_UdmfRecord_GetArrayBuffer(record, definedTypeId.c_str(), arrayBuffer); + EXPECT_EQ(0, result); + unsigned int getCount = 0; + unsigned char *getEntry; + OH_UdsArrayBuffer_GetData(arrayBuffer, &getEntry, &getCount); + EXPECT_EQ(6, getCount); + dataBytes = { '1', '2', '3', '4', '5', '6' }; + EXPECT_EQ(std::string(dataBytes.begin(), dataBytes.end()), std::string(reinterpret_cast(getEntry))); + + OH_UdsArrayBuffer_Destroy(arrayBuffer); + OH_UdmfData_Destroy(ndkData); + LOG_INFO(UDMF_TEST, "ConvertApplicationDefined_002 end."); +} + +/* * + * @tc.name: ConvertApplicationDefined_003 + * @tc.desc: test application defined record conversion between JS and C-API + * @tc.type: FUNC + */ +HWTEST_F(NdkDataConversionTest, ConvertApplicationDefined_003, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "ConvertApplicationDefined_003 begin."); + auto arrayBuffer = OH_UdsArrayBuffer_Create(); + unsigned char data[] = {'1', '2', '3', '4', '5', '6'}; + OH_UdsArrayBuffer_SetData(arrayBuffer, data, 6); + auto record = OH_UdmfRecord_Create(); + OH_UdmfRecord_AddArrayBuffer(record, "person_demo", arrayBuffer); + auto ndkData = OH_UdmfData_Create(); + OH_UdmfData_AddRecord(ndkData, record); + 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 + }; + auto setRet = UdmfClient::GetInstance().SetData(option, *unifiedData, key); + EXPECT_EQ(setRet, E_OK); + + std::shared_ptr readData = std::make_shared(); + QueryOption query = { + .key = key + }; + auto getRet = UdmfClient::GetInstance().GetData(query, *readData); + EXPECT_EQ(getRet, E_OK); + + auto readRecord = readData->GetRecordAt(0); + auto definedRecord = std::static_pointer_cast(readRecord); + auto type = definedRecord->GetApplicationDefinedType(); + EXPECT_EQ("person_demo", type); + auto rawData = definedRecord->GetRawData(); + std::vector dataBytes = { '1', '2', '3', '4', '5', '6' }; + EXPECT_EQ(std::string(dataBytes.begin(), dataBytes.end()), std::string(rawData.begin(), rawData.end())); + + OH_UdsArrayBuffer_Destroy(arrayBuffer); + OH_UdmfRecord_Destroy(record); + OH_UdmfData_Destroy(ndkData); + LOG_INFO(UDMF_TEST, "ConvertApplicationDefined_003 end."); +} + +/* * + * @tc.name: ConvertApplicationDefined_004 + * @tc.desc: test application defined record conversion between JS and C-API + * @tc.type: FUNC + */ +HWTEST_F(NdkDataConversionTest, ConvertApplicationDefined_004, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "ConvertApplicationDefined_004 begin."); + unsigned char data[] = {'1', '2', '3', '4', '5', '6'}; + auto record = OH_UdmfRecord_Create(); + OH_UdmfRecord_AddGeneralEntry(record, "person_demo", data, 6); + auto ndkData = OH_UdmfData_Create(); + OH_UdmfData_AddRecord(ndkData, record); + 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 + }; + auto setRet = UdmfClient::GetInstance().SetData(option, *unifiedData, key); + EXPECT_EQ(setRet, E_OK); + + std::shared_ptr readData = std::make_shared(); + QueryOption query = { + .key = key + }; + auto getRet = UdmfClient::GetInstance().GetData(query, *readData); + EXPECT_EQ(getRet, E_OK); + + auto readRecord = readData->GetRecordAt(0); + auto definedRecord = std::static_pointer_cast(readRecord); + auto type = definedRecord->GetApplicationDefinedType(); + EXPECT_EQ("person_demo", type); + auto rawData = definedRecord->GetRawData(); + std::vector dataBytes = { '1', '2', '3', '4', '5', '6' }; + EXPECT_EQ(std::string(dataBytes.begin(), dataBytes.end()), std::string(rawData.begin(), rawData.end())); + + OH_UdmfRecord_Destroy(record); + OH_UdmfData_Destroy(ndkData); + LOG_INFO(UDMF_TEST, "ConvertApplicationDefined_004 end."); +} + +/* * + * @tc.name: ConvertHtml_001 + * @tc.desc: test html conversion between JS and C-API + * @tc.type: FUNC + */ +HWTEST_F(NdkDataConversionTest, ConvertHtml_001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "ConvertHtml_001 begin."); + std::string definedTypeId = "person_app_demo"; + std::shared_ptr html = std::make_shared("htmlContent", "plainContent"); + UnifiedData data; + std::vector> records = { html }; + data.SetRecords(records); + + std::string key; + 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 + }; + auto getRet = UdmfClient::GetInstance().GetData(query, *readData); + EXPECT_EQ(getRet, E_OK); + + auto ndkData = OH_UdmfData_Create(); + NdkDataConversion::GetNdkUnifiedData(readData, ndkData); + unsigned int count; + OH_UdmfData_GetRecords(ndkData, &count); + EXPECT_EQ(1, 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("htmlContent", std::string(OH_UdsHtml_GetContent(htmlNdk))); + EXPECT_EQ("plainContent", std::string(OH_UdsHtml_GetPlainContent(htmlNdk))); + + OH_UdsHtml_Destroy(htmlNdk); + OH_UdmfData_Destroy(ndkData); + LOG_INFO(UDMF_TEST, "ConvertHtml_001 end."); +} + +/* * + * @tc.name: ConvertHtml_002 + * @tc.desc: test html conversion between JS and C-API + * @tc.type: FUNC + */ +HWTEST_F(NdkDataConversionTest, ConvertHtml_002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "ConvertHtml_002 begin."); + auto htmlNdk = OH_UdsHtml_Create(); + OH_UdsHtml_SetContent(htmlNdk, "htmlContent"); + OH_UdsHtml_SetPlainContent(htmlNdk, "plainContent"); + auto record = OH_UdmfRecord_Create(); + OH_UdmfRecord_AddHtml(record, htmlNdk); + auto ndkData = OH_UdmfData_Create(); + OH_UdmfData_AddRecord(ndkData, record); + 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 + }; + auto setRet = UdmfClient::GetInstance().SetData(option, *unifiedData, key); + EXPECT_EQ(setRet, E_OK); + + std::shared_ptr readData = std::make_shared(); + QueryOption query = { + .key = key + }; + auto getRet = UdmfClient::GetInstance().GetData(query, *readData); + EXPECT_EQ(getRet, E_OK); + + auto readRecord = readData->GetRecordAt(0); + auto html = std::static_pointer_cast(readRecord); + EXPECT_EQ("htmlContent", html->GetHtmlContent()); + EXPECT_EQ("plainContent", html->GetPlainContent()); + + OH_UdsHtml_Destroy(htmlNdk); + OH_UdmfRecord_Destroy(record); + OH_UdmfData_Destroy(ndkData); + LOG_INFO(UDMF_TEST, "ConvertHtml_002 end."); +} +} diff --git a/udmf/framework/innerkitsimpl/test/unittest/system_defined_appitem_test.cpp b/udmf/framework/innerkitsimpl/test/unittest/system_defined_appitem_test.cpp index 9155a366db5959f36cfc5fe1f9bf21da2b98e139..8c6b65d1a26bf1d9330059ff2a7269ac4eb497ca 100644 --- a/udmf/framework/innerkitsimpl/test/unittest/system_defined_appitem_test.cpp +++ b/udmf/framework/innerkitsimpl/test/unittest/system_defined_appitem_test.cpp @@ -79,7 +79,7 @@ HWTEST_F(SystemDefinedAppitemTest, SetItems002, TestSize.Level1) { LOG_INFO(UDMF_TEST, "SetItems002 begin."); UDDetails details; - details.insert({ SystemDefinedAppItem::APPID, "SetItems002" }); + details.insert({ APP_ID, "SetItems002" }); SystemDefinedAppItem systemDefinedAppItem; systemDefinedAppItem.SetItems(details); EXPECT_EQ(systemDefinedAppItem.appId_, "SetItems002"); @@ -95,7 +95,7 @@ HWTEST_F(SystemDefinedAppitemTest, SetItems003, TestSize.Level1) { LOG_INFO(UDMF_TEST, "SetItems003 begin."); UDDetails details; - details.insert({ SystemDefinedAppItem::APPNAME, "SetItems003" }); + details.insert({ APP_NAME, "SetItems003" }); SystemDefinedAppItem systemDefinedAppItem; systemDefinedAppItem.SetItems(details); EXPECT_EQ(systemDefinedAppItem.appName_, "SetItems003"); @@ -111,7 +111,7 @@ HWTEST_F(SystemDefinedAppitemTest, SetItems004, TestSize.Level1) { LOG_INFO(UDMF_TEST, "SetItems004 begin."); UDDetails details; - details.insert({ SystemDefinedAppItem::APPICONID, "SetItems004" }); + details.insert({ APP_ICON_ID, "SetItems004" }); SystemDefinedAppItem systemDefinedAppItem; systemDefinedAppItem.SetItems(details); EXPECT_EQ(systemDefinedAppItem.appIconId_, "SetItems004"); @@ -127,7 +127,7 @@ HWTEST_F(SystemDefinedAppitemTest, SetItems005, TestSize.Level1) { LOG_INFO(UDMF_TEST, "SetItems005 begin."); UDDetails details; - details.insert({ SystemDefinedAppItem::APPLABELID, "SetItems005" }); + details.insert({APP_LABEL_ID, "SetItems005" }); SystemDefinedAppItem systemDefinedAppItem; systemDefinedAppItem.SetItems(details); EXPECT_EQ(systemDefinedAppItem.appLabelId_, "SetItems005"); @@ -143,7 +143,7 @@ HWTEST_F(SystemDefinedAppitemTest, SetItems006, TestSize.Level1) { LOG_INFO(UDMF_TEST, "SetItems006 begin."); UDDetails details; - details.insert({ SystemDefinedAppItem::BUNDLENAME, "SetItems006" }); + details.insert({ BUNDLE_NAME, "SetItems006" }); SystemDefinedAppItem systemDefinedAppItem; systemDefinedAppItem.SetItems(details); EXPECT_EQ(systemDefinedAppItem.bundleName_, "SetItems006"); @@ -159,7 +159,7 @@ HWTEST_F(SystemDefinedAppitemTest, SetItems007, TestSize.Level1) { LOG_INFO(UDMF_TEST, "SetItems007 begin."); UDDetails details; - details.insert({ SystemDefinedAppItem::ABILITYNAME, "SetItems007" }); + details.insert({ ABILITY_NAME, "SetItems007" }); SystemDefinedAppItem systemDefinedAppItem; systemDefinedAppItem.SetItems(details); EXPECT_EQ(systemDefinedAppItem.abilityName_, "SetItems007"); @@ -182,12 +182,12 @@ HWTEST_F(SystemDefinedAppitemTest, GetItems001, TestSize.Level1) valueType.bundleName_ = "bundleName"; valueType.abilityName_ = "abilityName"; UDDetails items = valueType.GetItems(); - EXPECT_EQ(std::get(items[SystemDefinedAppItem::APPID]), valueType.appId_); - EXPECT_EQ(std::get(items[SystemDefinedAppItem::APPNAME]), valueType.appName_); - EXPECT_EQ(std::get(items[SystemDefinedAppItem::APPICONID]), valueType.appIconId_); - EXPECT_EQ(std::get(items[SystemDefinedAppItem::APPLABELID]), valueType.appLabelId_); - EXPECT_EQ(std::get(items[SystemDefinedAppItem::BUNDLENAME]), valueType.bundleName_); - EXPECT_EQ(std::get(items[SystemDefinedAppItem::ABILITYNAME]), valueType.abilityName_); + EXPECT_EQ(std::get(items[APP_ID]), valueType.appId_); + EXPECT_EQ(std::get(items[APP_NAME]), valueType.appName_); + EXPECT_EQ(std::get(items[APP_ICON_ID]), valueType.appIconId_); + EXPECT_EQ(std::get(items[APP_LABEL_ID]), valueType.appLabelId_); + EXPECT_EQ(std::get(items[BUNDLE_NAME]), valueType.bundleName_); + EXPECT_EQ(std::get(items[ABILITY_NAME]), valueType.abilityName_); LOG_INFO(UDMF_TEST, "GetItems001 end."); } @@ -209,14 +209,14 @@ HWTEST_F(SystemDefinedAppitemTest, GetValue001, TestSize.Level1) valueType.abilityName_ = "abilityName"; valueType.InitObject(); auto object = std::get>(valueType.value_); - auto details = std::get>(object->value_[SystemDefinedAppItem::DETAILS]); + auto details = std::get>(object->value_[DETAILS]); EXPECT_EQ(std::get(object->value_[UNIFORM_DATA_TYPE]), "openharmony.app-item"); - EXPECT_EQ(std::get(object->value_[SystemDefinedAppItem::APPID]), valueType.appId_); - EXPECT_EQ(std::get(object->value_[SystemDefinedAppItem::APPNAME]), valueType.appName_); - EXPECT_EQ(std::get(object->value_[SystemDefinedAppItem::APPICONID]), valueType.appIconId_); - EXPECT_EQ(std::get(object->value_[SystemDefinedAppItem::APPLABELID]), valueType.appLabelId_); - EXPECT_EQ(std::get(object->value_[SystemDefinedAppItem::BUNDLENAME]), valueType.bundleName_); - EXPECT_EQ(std::get(object->value_[SystemDefinedAppItem::ABILITYNAME]), valueType.abilityName_); + EXPECT_EQ(std::get(object->value_[APP_ID]), valueType.appId_); + EXPECT_EQ(std::get(object->value_[APP_NAME]), valueType.appName_); + EXPECT_EQ(std::get(object->value_[APP_ICON_ID]), valueType.appIconId_); + EXPECT_EQ(std::get(object->value_[APP_LABEL_ID]), valueType.appLabelId_); + EXPECT_EQ(std::get(object->value_[BUNDLE_NAME]), valueType.bundleName_); + EXPECT_EQ(std::get(object->value_[ABILITY_NAME]), valueType.abilityName_); EXPECT_EQ(details->value_.size(), 0); LOG_INFO(UDMF_TEST, "GetValue001 end."); } diff --git a/udmf/framework/innerkitsimpl/test/unittest/system_defined_record_test.cpp b/udmf/framework/innerkitsimpl/test/unittest/system_defined_record_test.cpp index 74f664bd34432f16f48192f7c038161521918f68..0d59039bc1187ed3ffd78b960bd58958c094fbb4 100644 --- a/udmf/framework/innerkitsimpl/test/unittest/system_defined_record_test.cpp +++ b/udmf/framework/innerkitsimpl/test/unittest/system_defined_record_test.cpp @@ -65,7 +65,7 @@ HWTEST_F(SystemDefinedRecordTest, AddProperty001, TestSize.Level1) systemDefinedRecord.value_ = std::make_shared(); systemDefinedRecord.AddProperty(property, value); auto object = std::get>(systemDefinedRecord.value_); - auto details = std::get>(object->value_[SystemDefinedRecord::DETAILS]); + auto details = std::get>(object->value_[DETAILS]); systemDefinedRecord.InitObject(); EXPECT_EQ(systemDefinedRecord.details_.size(), 1); EXPECT_NE(details->value_.size(), 0); @@ -87,7 +87,7 @@ HWTEST_F(SystemDefinedRecordTest, AddProperty002, TestSize.Level1) systemDefinedRecord.value_ = std::make_shared(); systemDefinedRecord.AddProperty(property, value); auto object = std::get>(systemDefinedRecord.value_); - auto details = std::get>(object->value_[SystemDefinedRecord::DETAILS]); + auto details = std::get>(object->value_[DETAILS]); EXPECT_EQ(systemDefinedRecord.details_[property], value); EXPECT_NE(details->value_.size(), 0); LOG_INFO(UDMF_TEST, "AddProperty002 end."); @@ -121,7 +121,7 @@ HWTEST_F(SystemDefinedRecordTest, InitObject001, TestSize.Level1) systemDefinedRecord.details_.insert({ "first", "second" }); systemDefinedRecord.InitObject(); auto object = std::get>(systemDefinedRecord.value_); - auto details = std::get>(object->value_[SystemDefinedRecord::DETAILS]); + auto details = std::get>(object->value_[DETAILS]); EXPECT_NE(details->value_.size(), 0); LOG_INFO(UDMF_TEST, "InitObject001 end."); } diff --git a/udmf/framework/innerkitsimpl/test/unittest/text_test.cpp b/udmf/framework/innerkitsimpl/test/unittest/text_test.cpp index 75dceb9fd7213afb5e209b246014b3fc50d2a983..22c2f58bfe2a3af31e7f25f8e5a8e949c11265b8 100644 --- a/udmf/framework/innerkitsimpl/test/unittest/text_test.cpp +++ b/udmf/framework/innerkitsimpl/test/unittest/text_test.cpp @@ -76,11 +76,10 @@ HWTEST_F(TextTest, InitObject001, TestSize.Level1) { LOG_INFO(UDMF_TEST, "InitObject001 begin."); Text text; - text.value_ = std::make_shared(); text.details_.insert({ "first", "second" }); text.InitObject(); auto object = std::get>(text.value_); - auto details = std::get>(object->value_[Text::DETAILS]); + auto details = std::get>(object->value_[DETAILS]); EXPECT_NE(details->value_.size(), 0); LOG_INFO(UDMF_TEST, "InitObject001 end."); } diff --git a/udmf/framework/innerkitsimpl/test/unittest/udmf_client_abnormal_test.cpp b/udmf/framework/innerkitsimpl/test/unittest/udmf_client_abnormal_test.cpp index cb6011a4ee15222b37ba94a48f368307798e95aa..36459f7ffc87583dfeb649cde8871c3fd9d218a7 100644 --- a/udmf/framework/innerkitsimpl/test/unittest/udmf_client_abnormal_test.cpp +++ b/udmf/framework/innerkitsimpl/test/unittest/udmf_client_abnormal_test.cpp @@ -20,7 +20,7 @@ #include #include "logger.h" -//#include "udmf_capi_common.h" +#include "udmf_capi_common.h" #include "udmf_client.h" #include "udmf_service_client_mock.h" diff --git a/udmf/framework/innerkitsimpl/test/unittest/utd_client_test.cpp b/udmf/framework/innerkitsimpl/test/unittest/utd_client_test.cpp index bd64b784fa9b364fbabed6b5843478e89d746756..ba7b4caf96ce4d119159d483cbd88e27362e3218 100644 --- a/udmf/framework/innerkitsimpl/test/unittest/utd_client_test.cpp +++ b/udmf/framework/innerkitsimpl/test/unittest/utd_client_test.cpp @@ -32,8 +32,6 @@ using namespace OHOS::Security::AccessToken; using namespace OHOS::UDMF; using namespace OHOS; -constexpr const char* CUSTOM_UTD_HAP_DIR = "/data/utd/utd-adt.json"; - namespace OHOS::Test { class UtdClientTest : public testing::Test { public: @@ -1863,100 +1861,4 @@ HWTEST_F(UtdClientTest, IsHapTokenType001, TestSize.Level1) EXPECT_TRUE(ret); LOG_INFO(UDMF_TEST, "IsHapTokenType001 end."); } - -/** -* @tc.name: GetCustomUtdPath001 -* @tc.desc: Normal testcase of GetCustomUtdPath -* @tc.type: FUNC -*/ -HWTEST_F(UtdClientTest, GetCustomUtdPath001, TestSize.Level1) -{ - LOG_INFO(UDMF_TEST, "GetCustomUtdPath001 begin."); - HapInfoParams info = { - .userID = 100, - .bundleName = "ohos.test.demo", - .instIndex = 0, - .appIDDesc = "ohos.test.demo" - }; - - HapPolicyParams policy = { - .apl = APL_NORMAL, - .domain = "test.domain", - .permList = { - { - .permissionName = "ohos.permission.test", - .bundleName = "ohos.test.demo", - .grantMode = 1, - .availableLevel = APL_NORMAL, - .label = "label", - .labelId = 1, - .description = "test", - .descriptionId = 1 - } - }, - .permStateList = { - { - .permissionName = "ohos.permission.test", - .isGeneral = true, - .resDeviceID = {"local"}, - .grantStatus = {PermissionState::PERMISSION_GRANTED}, - .grantFlags = {1} - } - } - }; - auto tokenID = AccessTokenKit::AllocHapToken(info, policy); - SetSelfTokenID(tokenID.tokenIDEx); - UtdClient utdClient; - std::string ret = utdClient.GetCustomUtdPath(); - EXPECT_EQ(ret, std::string(CUSTOM_UTD_HAP_DIR)); - LOG_INFO(UDMF_TEST, "GetCustomUtdPath001 end."); -} - -/** -* @tc.name: SubscribeUtdChange001 -* @tc.desc: Normal testcase of SubscribeUtdChange -* @tc.type: FUNC -*/ -HWTEST_F(UtdClientTest, SubscribeUtdChange001, TestSize.Level1) -{ - LOG_INFO(UDMF_TEST, "SubscribeUtdChange001 begin."); - HapInfoParams info = { - .userID = 100, - .bundleName = "ohos.test.demo", - .instIndex = 0, - .appIDDesc = "ohos.test.demo" - }; - - HapPolicyParams policy = { - .apl = APL_NORMAL, - .domain = "test.domain", - .permList = { - { - .permissionName = "ohos.permission.test", - .bundleName = "ohos.test.demo", - .grantMode = 1, - .availableLevel = APL_NORMAL, - .label = "label", - .labelId = 1, - .description = "test", - .descriptionId = 1 - } - }, - .permStateList = { - { - .permissionName = "ohos.permission.test", - .isGeneral = true, - .resDeviceID = {"local"}, - .grantStatus = {PermissionState::PERMISSION_GRANTED}, - .grantFlags = {1} - } - } - }; - auto tokenID = AccessTokenKit::AllocHapToken(info, policy); - SetSelfTokenID(tokenID.tokenIDEx); - UtdClient utdClient; - utdClient.SubscribeUtdChange(); - EXPECT_EQ(utdClient.subscriber_, nullptr); - LOG_INFO(UDMF_TEST, "SubscribeUtdChange001 end."); -} } // OHOS::Test \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/common/napi_error_utils.cpp b/udmf/framework/jskitsimpl/common/napi_error_utils.cpp index 23d7445a9d4f2e5c9cb494f0e75c48f469fec32a..f71939b842417d4f99588c472a9a80f64ebe9b4a 100644 --- a/udmf/framework/jskitsimpl/common/napi_error_utils.cpp +++ b/udmf/framework/jskitsimpl/common/napi_error_utils.cpp @@ -26,7 +26,7 @@ static constexpr NapiErrorCode JS_ERROR_CODE_MSGS[] = { { Status::E_INVALID_PARAMETERS, 401, "Parameter error." }, { Status::E_SETTINGS_EXISTED, 20400001, "Settings already exist." }, { Status::E_NO_SYSTEM_PERMISSION, 202, - "Permission denied, application which is not a system application uses system API." }, + "Permission denied, application which is not a system application uses system API." }, }; const std::optional GetErrorCode(int32_t errorCode) diff --git a/udmf/framework/jskitsimpl/common/napi_queue.cpp b/udmf/framework/jskitsimpl/common/napi_queue.cpp index cad9556fc655ae8eebf774a0c5ebfe14646f6c85..898ba6d80823f95bdb850c54cd94969528d9e5a9 100644 --- a/udmf/framework/jskitsimpl/common/napi_queue.cpp +++ b/udmf/framework/jskitsimpl/common/napi_queue.cpp @@ -21,12 +21,6 @@ ContextBase::~ContextBase() { LOG_DEBUG(UDMF_KITS_NAPI, "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; } @@ -69,13 +63,16 @@ 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(UDMF_KITS_NAPI, "NapiQueue::AsyncWork name = %{public}s", name.c_str()); - ctxt->execute = std::move(execute); - ctxt->complete = std::move(complete); + AsyncContext *aCtx = new AsyncContext; + aCtx->ctxt = std::move(contextBase); + aCtx->execute = std::move(execute); + aCtx->complete = std::move(complete); LOG_DEBUG(UDMF_KITS_NAPI, "NapiQueue::AsyncWork move func finish"); + auto ctxt = aCtx->ctxt; napi_value promise = nullptr; if (ctxt->callbackRef == nullptr) { LOG_DEBUG(UDMF_KITS_NAPI, "NapiQueue::AsyncWork has promise"); @@ -89,38 +86,14 @@ napi_value NapiQueue::AsyncWork(napi_env env, std::shared_ptr ctxt, LOG_DEBUG(UDMF_KITS_NAPI, "NapiQueue::AsyncWork create string start"); napi_create_string_utf8(ctxt->env, name.c_str(), NAPI_AUTO_LENGTH, &resource); LOG_DEBUG(UDMF_KITS_NAPI, "NapiQueue::AsyncWork create string finish"); - napi_create_async_work(ctxt->env, nullptr, resource, - [](napi_env env, void *data) { - LOG_DEBUG(UDMF_KITS_NAPI, "NapiQueue::AsyncWork start execute"); - ASSERT_VOID(data != nullptr, "no data"); - auto ctxt = reinterpret_cast(data); - LOG_DEBUG(UDMF_KITS_NAPI, "napi_async_execute_callback ctxt->status = %{public}d", ctxt->status); - if (ctxt->execute && ctxt->status == napi_ok) { - LOG_DEBUG(UDMF_KITS_NAPI, "NapiQueue::AsyncWork do user design execute"); - ctxt->execute(); - } - LOG_DEBUG(UDMF_KITS_NAPI, "NapiQueue::AsyncWork finish execute"); - }, - [](napi_env env, napi_status status, void *data) { - LOG_DEBUG(UDMF_KITS_NAPI, "NapiQueue::AsyncWork start output"); - ASSERT_VOID(data != nullptr, "no data"); - auto ctxt = reinterpret_cast(data); - LOG_DEBUG(UDMF_KITS_NAPI, "napi_async_complete_callback status = %{public}d, ctxt->status = %{public}d", - status, ctxt->status); - if ((status != napi_ok) && (ctxt->status == napi_ok)) { - LOG_DEBUG(UDMF_KITS_NAPI, "NapiQueue::AsyncWork check status"); - ctxt->status = status; - } - if ((ctxt->complete) && (status == napi_ok) && (ctxt->status == napi_ok)) { - LOG_DEBUG(UDMF_KITS_NAPI, "NapiQueue::AsyncWork do user design output"); - ctxt->complete(ctxt->output); - } - GenerateOutput(ctxt); - LOG_DEBUG(UDMF_KITS_NAPI, "NapiQueue::AsyncWork finish output"); - }, - reinterpret_cast(ctxt.get()), &ctxt->work); - napi_queue_async_work(ctxt->env, ctxt->work); - ctxt->hold = ctxt; // save crossing-thread ctxt. + napi_create_async_work(ctxt->env, nullptr, resource, onExecute, onComplete, reinterpret_cast(aCtx), + &aCtx->work); + auto status = napi_queue_async_work(ctxt->env, aCtx->work); + if (status != napi_ok) { + LOG_ERROR(UDMF_KITS_NAPI, "async work failed: %{public}d", status); + napi_get_undefined(env, &promise); + delete aCtx; + } return promise; } @@ -166,8 +139,42 @@ void NapiQueue::GenerateOutput(ContextBase *ctxt) LOG_DEBUG(UDMF_KITS_NAPI, "call callback function"); napi_call_function(ctxt->env, nullptr, callback, RESULT_ALL, result, &callbackResult); } - ctxt->hold.reset(); // release ctxt. LOG_DEBUG(UDMF_KITS_NAPI, "GenerateOutput stop"); } + +void NapiQueue::onExecute(napi_env env, void *data) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "NapiQueue::AsyncWork start execute"); + ASSERT_VOID(data != nullptr, "no data"); + auto actxt = reinterpret_cast(data); + LOG_DEBUG(UDMF_KITS_NAPI, "napi_async_execute_callback ctxt->status = %{public}d", actxt->ctxt->status); + if (actxt->execute && actxt->ctxt->status == napi_ok) { + LOG_DEBUG(UDMF_KITS_NAPI, "NapiQueue::AsyncWork do user design execute"); + actxt->execute(); + } + LOG_DEBUG(UDMF_KITS_NAPI, "NapiQueue::AsyncWork finish execute"); +} + +void NapiQueue::onComplete(napi_env env, napi_status status, void *data) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "NapiQueue::AsyncWork start output"); + ASSERT_VOID(data != nullptr, "no data"); + auto actxt = reinterpret_cast(data); + LOG_DEBUG(UDMF_KITS_NAPI, "napi_async_complete_callback status = %{public}d, ctxt->status = %{public}d", status, + actxt->ctxt->status); + if ((status != napi_ok) && (actxt->ctxt->status == napi_ok)) { + LOG_DEBUG(UDMF_KITS_NAPI, "NapiQueue::AsyncWork check status"); + actxt->ctxt->status = status; + } + if ((actxt->complete) && (status == napi_ok) && (actxt->ctxt->status == napi_ok)) { + LOG_DEBUG(UDMF_KITS_NAPI, "NapiQueue::AsyncWork do user design output"); + actxt->complete(actxt->ctxt->output); + } + GenerateOutput(actxt->ctxt.get()); + LOG_DEBUG(UDMF_KITS_NAPI, "NapiQueue::AsyncWork finish output"); + napi_delete_reference(env, actxt->ctxt->callbackRef); + napi_delete_async_work(env, actxt->work); + delete actxt; +} } // namespace UDMF } // namespace OHOS diff --git a/udmf/framework/jskitsimpl/data/unified_data_napi.cpp b/udmf/framework/jskitsimpl/data/unified_data_napi.cpp index 72da7cb974f5f00ce8c9f4d0013149786b1aa743..4c9b7b4f16f8b950f0dbca1d0260df7a19c97c30 100644 --- a/udmf/framework/jskitsimpl/data/unified_data_napi.cpp +++ b/udmf/framework/jskitsimpl/data/unified_data_napi.cpp @@ -89,6 +89,9 @@ void UnifiedDataNapi::Destructor(napi_env env, void *data, void *hint) LOG_DEBUG(UDMF_KITS_NAPI, "UnifiedDataNapi finalize."); auto *uData = static_cast(data); ASSERT_VOID(uData != nullptr, "finalize null!"); + if (uData->propertyRef_ != nullptr) { + napi_delete_reference(env, uData->propertyRef_); + } delete uData; } diff --git a/udmf/framework/jskitsimpl/data/unified_data_properties_napi.cpp b/udmf/framework/jskitsimpl/data/unified_data_properties_napi.cpp index 995309f5aa135989a688a86881ba62055117ec3e..4927fed55da0544d42db8ebdfd5630fed95bdca1 100644 --- a/udmf/framework/jskitsimpl/data/unified_data_properties_napi.cpp +++ b/udmf/framework/jskitsimpl/data/unified_data_properties_napi.cpp @@ -54,6 +54,9 @@ void UnifiedDataPropertiesNapi::Destructor(napi_env env, void *data, void *hint) LOG_DEBUG(UDMF_KITS_NAPI, "UnifiedDataPropertiesNapi finalize."); auto *properties = static_cast(data); ASSERT_VOID(properties != nullptr, "finalize null!"); + if (properties->delayDataRef_ != nullptr) { + napi_delete_reference(env, properties->delayDataRef_); + } delete properties; } @@ -208,6 +211,9 @@ napi_value UnifiedDataPropertiesNapi::SetDelayData(napi_env env, napi_callback_i auto properties = static_cast(ctxt->native); ASSERT_ERR(ctxt->env, (properties != nullptr && properties->value_ != nullptr), Status::E_ERROR, "invalid object!"); + if (properties->delayDataRef_ != nullptr) { + napi_delete_reference(env, properties->delayDataRef_); + } ctxt->status = napi_create_reference(env, handler, 1, &ref); ASSERT_ERR(ctxt->env, ctxt->status == napi_ok, Status::E_ERROR, "napi_create_reference failed"); properties->delayDataRef_ = ref; diff --git a/udmf/framework/jskitsimpl/unittest/UdmfUtdJsTest.js b/udmf/framework/jskitsimpl/unittest/UdmfUtdJsTest.js index 9862329c1b4e5b10f52132712689a1dc789f7cd3..1e098acf883bdf013e8ef161813d8aa61a6a2c2b 100644 --- a/udmf/framework/jskitsimpl/unittest/UdmfUtdJsTest.js +++ b/udmf/framework/jskitsimpl/unittest/UdmfUtdJsTest.js @@ -29,7 +29,7 @@ describe('UdmfUtdJSTest', function () { * @tc.type: FUNC * @tc.require: issueNumber */ - it ('UdmfTestTypeDescriptor001', 0, function () { + it('UdmfTestTypeDescriptor001', 0, function () { const TAG = 'UdmfTestTypeDescriptor001:'; console.info(TAG, 'start'); let typeObj = UTD.getTypeDescriptor('general.invalidType'); @@ -47,7 +47,7 @@ describe('UdmfUtdJSTest', function () { * @tc.type: FUNC * @tc.require: issueNumber */ - it ('UdmfTestTypeDescriptor002', 0, function () { + it('UdmfTestTypeDescriptor002', 0, function () { const TAG = 'UdmfTestTypeDescriptor002:'; console.info(TAG, 'start'); let typeObj = UTD.getTypeDescriptor('com.adobe.photoshop-image'); @@ -81,7 +81,7 @@ describe('UdmfUtdJSTest', function () { * @tc.type: FUNC * @tc.require: issueNumber */ - it ('UdmfTestTypeDescriptor003', 0, function () { + it('UdmfTestTypeDescriptor003', 0, function () { const TAG = 'UdmfTestTypeDescriptor003:'; console.info(TAG, 'start'); let typeObj = UTD.getTypeDescriptor('general.type-script'); @@ -104,7 +104,7 @@ describe('UdmfUtdJSTest', function () { * @tc.type: FUNC * @tc.require: issueNumber */ - it ('UdmfTestTypeDescriptor004', 0, function () { + it('UdmfTestTypeDescriptor004', 0, function () { const TAG = 'UdmfTestTypeDescriptor004:'; console.info(TAG, 'start'); try { @@ -123,7 +123,7 @@ describe('UdmfUtdJSTest', function () { * @tc.type: FUNC * @tc.require: issueNumber */ - it ('UdmfTestTypeDescriptor005', 0, function () { + it('UdmfTestTypeDescriptor005', 0, function () { const TAG = 'UdmfTestTypeDescriptor005:'; console.info(TAG, 'start'); let typeObj = UTD.getTypeDescriptor('com.adobe.photoshop-image', INVALID_TYPE1, INVALID_TYPE2); @@ -153,7 +153,7 @@ describe('UdmfUtdJSTest', function () { * @tc.type: FUNC * @tc.require: issueNumber */ - it ('UdmfTestTypeDescriptor006', 0, function () { + it('UdmfTestTypeDescriptor006', 0, function () { const TAG = 'UdmfTestTypeDescriptor006:'; console.info(TAG, 'start'); for (let utdType in UTD.UniformDataType) { @@ -171,7 +171,7 @@ describe('UdmfUtdJSTest', function () { * @tc.type: FUNC * @tc.require: issueNumber */ - it ('UdmfTestTypeDescriptor007', 0, function () { + it('UdmfTestTypeDescriptor007', 0, function () { const TAG = 'UdmfTestTypeDescriptor007:'; console.info(TAG, 'start'); try { @@ -190,7 +190,7 @@ describe('UdmfUtdJSTest', function () { * @tc.type: FUNC * @tc.require: issueNumber */ - it ('UdmfTestTypeDescriptor008', 0, function () { + it('UdmfTestTypeDescriptor008', 0, function () { const TAG = 'UdmfTestTypeDescriptor008:'; console.info(TAG, 'start'); let typeObj = UTD.getTypeDescriptor('general.type-script'); @@ -211,7 +211,7 @@ describe('UdmfUtdJSTest', function () { * @tc.type: FUNC * @tc.require: issueNumber */ - it ('UdmfTestTypeDescriptor009', 0, function () { + it('UdmfTestTypeDescriptor009', 0, function () { const TAG = 'UdmfTestTypeDescriptor009:'; console.info(TAG, 'start'); expect(UTD.UniformDataType.TEXT).assertEqual('general.text'); @@ -252,7 +252,7 @@ describe('UdmfUtdJSTest', function () { * @tc.type: FUNC * @tc.require: issueNumber */ - it ('UdmfTestTypeDescriptor010', 0, function () { + it('UdmfTestTypeDescriptor010', 0, function () { const TAG = 'UdmfTestTypeDescriptor010:'; console.info(TAG, 'start'); expect(UTD.UniformDataType.PNG).assertEqual('general.png'); @@ -294,7 +294,7 @@ describe('UdmfUtdJSTest', function () { * @tc.type: FUNC * @tc.require: issueNumber */ - it ('UdmfTestTypeDescriptor011', 0, function () { + it('UdmfTestTypeDescriptor011', 0, function () { const TAG = 'UdmfTestTypeDescriptor011:'; console.info(TAG, 'start'); expect(UTD.UniformDataType.WINDOWS_MEDIA_WMA).assertEqual('com.microsoft.windows-media-wma'); @@ -335,7 +335,7 @@ describe('UdmfUtdJSTest', function () { * @tc.type: FUNC * @tc.require: issueNumber */ - it ('UdmfTestTypeDescriptor012', 0, function () { + it('UdmfTestTypeDescriptor012', 0, function () { const TAG = 'UdmfTestTypeDescriptor012:'; console.info(TAG, 'start'); let typeObj = UTD.getTypeDescriptor('general.type-script'); @@ -351,7 +351,7 @@ describe('UdmfUtdJSTest', function () { * @tc.type: FUNC * @tc.require: issueNumber */ - it ('UdmfTestTypeDescriptor013', 0, function () { + it('UdmfTestTypeDescriptor013', 0, function () { const TAG = 'UdmfTestTypeDescriptor013:'; console.info(TAG, 'start'); let typeObj = UTD.getTypeDescriptor('general.type-script'); @@ -367,7 +367,7 @@ describe('UdmfUtdJSTest', function () { * @tc.type: FUNC * @tc.require: issueNumber */ - it ('UdmfTestTypeDescriptor014', 0, function () { + it('UdmfTestTypeDescriptor014', 0, function () { const TAG = 'UdmfTestTypeDescriptor014:'; console.info(TAG, 'start'); let typeObj = UTD.getTypeDescriptor('general.text'); @@ -383,7 +383,7 @@ describe('UdmfUtdJSTest', function () { * @tc.type: FUNC * @tc.require: issueNumber */ - it ('UdmfTestTypeDescriptor015', 0, function () { + it('UdmfTestTypeDescriptor015', 0, function () { const TAG = 'UdmfTestTypeDescriptor015:'; console.info(TAG, 'start'); let typeId = UTD.getUniformDataTypeByFilenameExtension('.ts', 'general.text'); @@ -398,7 +398,7 @@ describe('UdmfUtdJSTest', function () { * @tc.type: FUNC * @tc.require: issueNumber */ - it ('UdmfTestTypeDescriptor016', 0, function () { + it('UdmfTestTypeDescriptor016', 0, function () { const TAG = 'UdmfTestTypeDescriptor016:'; console.info(TAG, 'start'); let typeId = UTD.getUniformDataTypeByMIMEType('application/vnd.ms-excel', 'general.object'); diff --git a/udmf/framework/ndkimpl/data/udmf.cpp b/udmf/framework/ndkimpl/data/udmf.cpp index e45aa73e6d5622cc337e57d8ee72f4649acfce9a..fd50926015dbcb4e652bf82fab1278f5e2105dfc 100644 --- a/udmf/framework/ndkimpl/data/udmf.cpp +++ b/udmf/framework/ndkimpl/data/udmf.cpp @@ -39,7 +39,6 @@ using namespace OHOS::UDMF; static constexpr uint64_t MAX_RECORDS_COUNT = 4 * 1024 * 1024; -static constexpr uint64_t MAX_RECORDS_SIZE = 4 * 1024 * 1024; static constexpr uint64_t MAX_KEY_STRING_LEN = 1 * 1024 * 1024; static const std::map FILE_TYPES = { { UDMF_META_GENERAL_FILE, UDType::FILE }, @@ -398,7 +397,7 @@ int OH_Udmf_SetUnifiedData(Udmf_Intention intention, OH_UdmfData* unifiedData, c return UDMF_ERR; } if (strcpy_s(key, keyLen, keyStr.c_str()) != EOK) { - LOG_INFO(UDMF_CAPI, "string copy failed"); + LOG_ERROR(UDMF_CAPI, "string copy failed"); return UDMF_ERR; } return UDMF_E_OK; @@ -423,6 +422,7 @@ void OH_UdmfRecord_Destroy(OH_UdmfRecord* record) delete[] record->recordData; record->recordData = nullptr; } + DestroyStringArray(record->typesArray, record->typesCount); delete record; } @@ -434,38 +434,37 @@ int OH_UdmfRecord_AddGeneralEntry(OH_UdmfRecord* record, const char* typeId, return UDMF_E_INVALID_PARAM; } std::vector recordValue(entry, entry + count); + auto obj = std::make_shared(); + obj->value_[UNIFORM_DATA_TYPE] = typeId; + obj->value_[ARRAY_BUFFER] = recordValue; + obj->value_[ARRAY_BUFFER_LENGTH] = static_cast(recordValue.size()); if (record->record_->GetType() == UD_BUTT) { - record->record_ = std::make_shared(APPLICATION_DEFINED_RECORD, recordValue); + record->record_ = std::make_shared(APPLICATION_DEFINED_RECORD, obj); record->record_->SetUtdId(typeId); } else { - record->record_->AddEntry(typeId, std::move(recordValue)); + record->record_->AddEntry(typeId, obj); } record->recordDataLen = count; return UDMF_E_OK; } -static int GetValueFromUdsArrayBuffer(OH_UdmfRecord *record, const char *typeId, ValueType value) -{ - OH_UdsArrayBuffer *buffer = OH_UdsArrayBuffer_Create(); - buffer->obj = std::get>(value); - - int ret = OH_UdsArrayBuffer_GetData(buffer, &record->recordData, &record->recordDataLen); - if (ret != UDMF_E_OK) { - LOG_ERROR(UDMF_CAPI, "get data from buffer failed. ret: %{public}d", ret); - return ret; - } - record->lastType = const_cast(typeId); - return UDMF_E_OK; -} - static int GetValueFromUint8Array(OH_UdmfRecord *record, const char *typeId, ValueType value) { - auto recordValue = std::get_if>(&value); - if (recordValue == nullptr) { + if (!std::holds_alternative>(value)) { + LOG_ERROR(UDMF_CAPI, "valueType is not object sptr!"); return UDMF_ERR; } - record->recordDataLen = recordValue->size(); - if (record->recordDataLen > MAX_RECORDS_SIZE) { + auto obj = std::get>(value); + if (obj == nullptr) { + LOG_ERROR(UDMF_CAPI, "object is nullptr!"); + return UDMF_ERR; + } + std::vector recordValue; + int recordDataLen; + obj->GetValue(ARRAY_BUFFER, recordValue); + obj->GetValue(ARRAY_BUFFER_LENGTH, recordDataLen); + record->recordDataLen = recordValue.size(); + if (record->recordDataLen > MAX_GENERAL_ENTRY_SIZE) { LOG_INFO(UDMF_CAPI, "data size exceeds maximum size"); return UDMF_ERR; } @@ -473,7 +472,7 @@ static int GetValueFromUint8Array(OH_UdmfRecord *record, const char *typeId, Val if (record->recordData == nullptr) { return UDMF_ERR; } - auto err = memcpy_s(record->recordData, record->recordDataLen, recordValue->data(), record->recordDataLen); + auto err = memcpy_s(record->recordData, record->recordDataLen, recordValue.data(), record->recordDataLen); if (err != EOK) { LOG_ERROR(UDMF_CAPI, "memcpy error! type:%{public}s", typeId); return UDMF_ERR; @@ -487,7 +486,6 @@ int OH_UdmfRecord_GetGeneralEntry(OH_UdmfRecord* record, const char* typeId, uns if (!IsUnifiedRecordValid(record) || typeId == nullptr || entry == nullptr || count == nullptr) { return UDMF_E_INVALID_PARAM; } - std::lock_guard lock(record->mutex); if (!record->record_->HasType(typeId)) { LOG_ERROR(UDMF_CAPI, "no type:%{public}s", typeId); @@ -499,20 +497,13 @@ int OH_UdmfRecord_GetGeneralEntry(OH_UdmfRecord* record, const char* typeId, uns *count = record->recordDataLen; return UDMF_E_OK; } - if (record->recordData != nullptr) { - delete[] record->recordData; - record->recordData = nullptr; - } + record->record_->InitObject(); auto value = record->record_->GetEntry(typeId); - - int result = UDMF_ERR; - if (std::holds_alternative>(value)) { - result = GetValueFromUdsArrayBuffer(record, typeId, value); - } else if (std::holds_alternative>(value)) { - result = GetValueFromUint8Array(record, typeId, value); - } else { + if (!std::holds_alternative>(value)) { LOG_ERROR(UDMF_CAPI, "Not contains right data type."); + return UDMF_ERR; } + auto result = GetValueFromUint8Array(record, typeId, value); if (result != UDMF_E_OK) { LOG_ERROR(UDMF_CAPI, "Get value from valueType failed. typeId: %{public}s, result: %{public}d", typeId, result); return result; @@ -586,7 +577,7 @@ int OH_UdmfRecord_AddFileUri(OH_UdmfRecord* record, OH_UdsFileUri* fileUri) AddUds