diff --git a/data_object/frameworks/jskitsimpl/src/common/napi_queue.cpp b/data_object/frameworks/jskitsimpl/src/common/napi_queue.cpp index 83035f83f560cea5c036bad0074a70d4d45dae51..b5d330d369e5e46edec355341a41e67ade7ae9cd 100644 --- a/data_object/frameworks/jskitsimpl/src/common/napi_queue.cpp +++ b/data_object/frameworks/jskitsimpl/src/common/napi_queue.cpp @@ -112,7 +112,10 @@ napi_value NapiQueue::AsyncWork(napi_env env, std::shared_ptr ctxt, ctxt->execute = std::move(execute); ctxt->complete = std::move(complete); ctxt->hold = ctxt; // save crossing-thread ctxt. - napi_queue_async_work(ctxt->env, ctxt->work); + auto status = napi_queue_async_work_with_qos(ctxt->env, ctxt->work, napi_qos_user_initiated); + if (status != napi_ok) { + napi_get_undefined(ctxt->env, &promise); + } return promise; } diff --git a/data_share/frameworks/js/napi/common/include/datashare_js_utils.h b/data_share/frameworks/js/napi/common/include/datashare_js_utils.h index 3e096353ddeef1f61295255c8939aeee1f7ccb75..198dc5cab968e784e3bb068891b17574464dff96 100644 --- a/data_share/frameworks/js/napi/common/include/datashare_js_utils.h +++ b/data_share/frameworks/js/napi/common/include/datashare_js_utils.h @@ -22,6 +22,7 @@ #include #include +#include "datashare_operation_statement.h" #include "datashare_template.h" #include "datashare_value_object.h" #include "napi/native_api.h" @@ -59,6 +60,21 @@ public: static constexpr int32_t ASYNC_RST_SIZE = 2; static constexpr int32_t SYNC_RESULT_ELEMNT_NUM = 2; + template + static int32_t Convert2Value(napi_env env, napi_value input, T &output); + + template + static int32_t Convert2Value(napi_env env, napi_value input, std::vector &output); + + template + static int32_t Convert2Value(napi_env env, napi_value input, std::map &output); + + template + static int32_t Convert2Value(napi_env env, napi_value input, const char* propertyName, T &output); + + static int32_t Convert2Value(napi_env env, napi_value input, DataSharePredicates &predicates); + static int32_t Convert2Value(napi_env env, napi_value input, DataShareValuesBucket &valueBucket); + static int32_t Convert2Value(napi_env env, napi_value input, UpdateOperation &operation); static std::string Convert2String(napi_env env, napi_value jsStr, size_t max = DEFAULT_BUF_SIZE); static std::vector Convert2StrVector(napi_env env, napi_value value, size_t strMax); static std::vector Convert2U8Vector(napi_env env, napi_value jsValue); @@ -88,9 +104,10 @@ public: static napi_value Convert2JSValue(napi_env env, const OperationResult &results); static napi_value Convert2JSValue(napi_env env, const std::vector &results); static std::vector ConvertU8Vector(napi_env env, napi_value jsValue); + static napi_value Convert2JSValue(napi_env env, const std::vector &result); + static bool UnwrapDataSharePredicates(napi_env env, napi_value value, DataSharePredicates &dataSharePredicates); static bool Equals(napi_env env, napi_value value, napi_ref copy); - static bool UnwrapPublishedDataItem(napi_env env, napi_value value, PublishedDataItem &publishedDataItem); static bool UnwrapPublishedDataItemVector(napi_env env, napi_value value, std::vector &publishedDataItems); @@ -128,6 +145,82 @@ napi_value DataShareJSUtils::Convert2JSValue(napi_env env, const std::variant(env, 0, value.index(), value); } + +template +int32_t DataShareJSUtils::Convert2Value(napi_env env, napi_value input, const char* propertyName, T& output) +{ + napi_value jsObject = nullptr; + if (napi_get_named_property(env, input, propertyName, &jsObject) != napi_ok) { + return napi_invalid_arg; + } + if (Convert2Value(env, jsObject, output) != napi_ok) { + return napi_invalid_arg; + } + return napi_ok; +} + +template +int32_t DataShareJSUtils::Convert2Value(napi_env env, napi_value input, std::vector &output) +{ + bool isArray = false; + napi_is_array(env, input, &isArray); + if (!isArray) { + return napi_invalid_arg; + } + + uint32_t arrLen = 0; + napi_get_array_length(env, input, &arrLen); + if (arrLen <= 0) { + return napi_invalid_arg; + } + + for (size_t i = 0; i < arrLen; ++i) { + napi_value element; + napi_get_element(env, input, i, &element); + T item; + auto status = Convert2Value(env, element, item); + if (status != napi_ok) { + return napi_invalid_arg; + } + output.push_back(std::move(item)); + } + return napi_ok; +} + +template +int32_t DataShareJSUtils::Convert2Value(napi_env env, napi_value input, std::map &output) +{ + napi_value map = nullptr; + uint32_t count = 0; + napi_status status = napi_get_property_names(env, input, &map); + if (status != napi_ok) { + return napi_invalid_arg; + } + status = napi_get_array_length(env, map, &count); + if (status != napi_ok || count <= 0) { + return napi_invalid_arg; + } + napi_value jsKey = nullptr; + napi_value jsVal = nullptr; + for (uint32_t index = 0; index < count; index++) { + status = napi_get_element(env, map, index, &jsKey); + if (status != napi_ok) { + return napi_invalid_arg; + } + std::string key = Convert2String(env, jsKey); + status = napi_get_property(env, input, jsKey, &jsVal); + if (status != napi_ok || jsVal == nullptr) { + return napi_invalid_arg; + } + T val; + int32_t ret = Convert2Value(env, jsVal, val); + if (ret != napi_ok) { + return napi_invalid_arg; + } + output.insert(std::pair(key, val)); + } + return napi_ok; +} } // namespace DataShare } // namespace OHOS diff --git a/data_share/frameworks/js/napi/common/src/datashare_js_utils.cpp b/data_share/frameworks/js/napi/common/src/datashare_js_utils.cpp index c94d037c147dc166fa4205559bc0daa5cca79415..cb5851fbaf2bb828ed4522c9810a3fa5bbca4a14 100644 --- a/data_share/frameworks/js/napi/common/src/datashare_js_utils.cpp +++ b/data_share/frameworks/js/napi/common/src/datashare_js_utils.cpp @@ -16,6 +16,8 @@ #include "datashare_js_utils.h" #include "datashare_log.h" +#include "datashare_predicates_proxy.h" +#include "napi_datashare_values_bucket.h" #include "napi/native_common.h" #include "securec.h" @@ -675,5 +677,82 @@ bool DataShareJSUtils::UnwrapStringByPropertyName( value = DataShareJSUtils::Convert2String(env, jsResult); return true; } + +napi_value DataShareJSUtils::Convert2JSValue(napi_env env, const std::vector &result) +{ + napi_value resultMap = nullptr; + napi_status status = napi_create_object(env, &resultMap); + if (status != napi_ok) { + LOG_ERROR("napi_create_object : %{public}d", status); + return nullptr; + } + for (const auto &valueArray : result) { + napi_value values; + if (napi_create_object(env, &values) != napi_ok) { + LOG_ERROR("napi_create_object falied"); + return nullptr; + } + uint32_t index = 0; + for (const auto &value : valueArray.codes) { + napi_value jsValue = Convert2JSValue(env, value); + if (napi_set_element(env, values, index++, jsValue) != napi_ok) { + LOG_ERROR("napi_set_element falied"); + return nullptr; + } + } + if (napi_set_named_property(env, resultMap, valueArray.uri.c_str(), values)) { + LOG_ERROR("napi_set_named_property falied"); + return nullptr; + } + } + return resultMap; +} + +int32_t DataShareJSUtils::Convert2Value(napi_env env, napi_value input, UpdateOperation& operation) +{ + napi_valuetype valueType = napi_undefined; + napi_typeof(env, input, &valueType); + if (valueType != napi_object) { + LOG_ERROR("value is not object"); + return napi_invalid_arg; + } + if (Convert2Value(env, input, "predicates", operation.predicates) != napi_ok) { + return napi_invalid_arg; + } + if (Convert2Value(env, input, "values", operation.valuesBucket) != napi_ok) { + return napi_invalid_arg; + } + return napi_ok; +} + +bool DataShareJSUtils::UnwrapDataSharePredicates(napi_env env, napi_value value, + DataSharePredicates &dataSharePredicates) +{ + auto predicates = DataSharePredicatesProxy::GetNativePredicates(env, value); + if (predicates == nullptr) { + LOG_ERROR("GetNativePredicates is nullptr."); + return false; + } + dataSharePredicates = DataSharePredicates(predicates->GetOperationList()); + return true; +} + +int32_t DataShareJSUtils::Convert2Value(napi_env env, napi_value input, DataSharePredicates &predicates) +{ + if (!UnwrapDataSharePredicates(env, input, predicates)) { + LOG_ERROR("get predicates from js failed"); + return napi_invalid_arg; + } + return napi_ok; +} + +int32_t DataShareJSUtils::Convert2Value(napi_env env, napi_value input, DataShareValuesBucket &valueBucket) +{ + if (!GetValueBucketObject(valueBucket, env, input)) { + LOG_ERROR("get valueBucketObject from js failed"); + return napi_invalid_arg; + } + return napi_ok; +} } // namespace DataShare } // namespace OHOS \ No newline at end of file diff --git a/data_share/frameworks/js/napi/common/src/napi_datashare_values_bucket.cpp b/data_share/frameworks/js/napi/common/src/napi_datashare_values_bucket.cpp index b2fa731b4aba45e1c991d26b43fb889a37b711bb..669955740e567626aa5eb3ef57816316945cc049 100644 --- a/data_share/frameworks/js/napi/common/src/napi_datashare_values_bucket.cpp +++ b/data_share/frameworks/js/napi/common/src/napi_datashare_values_bucket.cpp @@ -47,7 +47,7 @@ bool UnWrapValuesBucket(DataShareValuesBucket &valuesBucket, const napi_env &env napi_get_property_names(env, arg, &keys); uint32_t arrLen = 0; napi_status status = napi_get_array_length(env, keys, &arrLen); - if (status != napi_ok) { + if (status != napi_ok || arrLen <= 0) { LOG_ERROR("ValuesBucket err"); return false; } diff --git a/data_share/frameworks/js/napi/dataShare/BUILD.gn b/data_share/frameworks/js/napi/dataShare/BUILD.gn index bda33175bfab560027cbe15eaf07e9cff7ecfdbd..6da16eb65b4f212481f0e4e6a851168b812fb50b 100644 --- a/data_share/frameworks/js/napi/dataShare/BUILD.gn +++ b/data_share/frameworks/js/napi/dataShare/BUILD.gn @@ -97,6 +97,8 @@ ohos_shared_library("datashare") { "c_utils:utils", "common_event_service:cesfwk_innerkits", "hilog:libhilog", + "hitrace:hitrace_meter", + "hitrace:libhitracechain", "ipc:ipc_single", "napi:ace_napi", ] diff --git a/data_share/frameworks/js/napi/dataShare/include/napi_datashare_helper.h b/data_share/frameworks/js/napi/dataShare/include/napi_datashare_helper.h index 2208bcf5e5102bb95af15b50b33896f632a88e85..3efda1872d75e5199211c284a6c7e19eb3487db4 100644 --- a/data_share/frameworks/js/napi/dataShare/include/napi_datashare_helper.h +++ b/data_share/frameworks/js/napi/dataShare/include/napi_datashare_helper.h @@ -36,6 +36,7 @@ public: static napi_value Napi_Delete(napi_env env, napi_callback_info info); static napi_value Napi_Query(napi_env env, napi_callback_info info); static napi_value Napi_Update(napi_env env, napi_callback_info info); + static napi_value Napi_BatchUpdate(napi_env env, napi_callback_info info); static napi_value Napi_BatchInsert(napi_env env, napi_callback_info info); static napi_value Napi_GetType(napi_env env, napi_callback_info info); static napi_value Napi_GetFileTypes(napi_env env, napi_callback_info info); @@ -107,6 +108,8 @@ private: Data publishData; std::string bundleName; std::vector results; + UpdateOperations updateOperations; + std::vector batchUpdateResult; ContextInfo() : Context(nullptr, nullptr) {}; ContextInfo(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)) {}; diff --git a/data_share/frameworks/js/napi/dataShare/src/napi_datashare_helper.cpp b/data_share/frameworks/js/napi/dataShare/src/napi_datashare_helper.cpp index f4d3ca9b897dd7753e58b6d91ee020d9dee58e88..4af3af12637a6620933136cd7c58cafd9c5ea448 100644 --- a/data_share/frameworks/js/napi/dataShare/src/napi_datashare_helper.cpp +++ b/data_share/frameworks/js/napi/dataShare/src/napi_datashare_helper.cpp @@ -44,16 +44,6 @@ static bool GetSilentUri(napi_env env, napi_value jsValue, std::string &uri) return false; } -static DataSharePredicates UnwrapDataSharePredicates(napi_env env, napi_value value) -{ - auto predicates = DataSharePredicatesProxy::GetNativePredicates(env, value); - if (predicates == nullptr) { - LOG_ERROR("GetNativePredicates is nullptr."); - return {}; - } - return DataSharePredicates(predicates->GetOperationList()); -} - static bool UnwrapValuesBucketArrayFromJS(napi_env env, napi_value param, std::vector &value) { uint32_t arraySize = 0; @@ -194,6 +184,7 @@ napi_value NapiDataShareHelper::GetConstructor(napi_env env) DECLARE_NAPI_FUNCTION("query", Napi_Query), DECLARE_NAPI_FUNCTION("update", Napi_Update), DECLARE_NAPI_FUNCTION("batchInsert", Napi_BatchInsert), + DECLARE_NAPI_FUNCTION("batchUpdate", Napi_BatchUpdate), DECLARE_NAPI_FUNCTION("normalizeUri", Napi_NormalizeUri), DECLARE_NAPI_FUNCTION("denormalizeUri", Napi_DenormalizeUri), DECLARE_NAPI_FUNCTION("notifyChange", Napi_NotifyChange), @@ -330,7 +321,10 @@ napi_value NapiDataShareHelper::Napi_Delete(napi_env env, napi_callback_info inf return napi_invalid_arg; } - context->predicates = UnwrapDataSharePredicates(env, argv[1]); + if (!DataShareJSUtils::UnwrapDataSharePredicates(env, argv[1], context->predicates)) { + context->error = std::make_shared("predicates", "DataSharePredicates"); + return napi_invalid_arg; + } return napi_ok; }; auto output = [context](napi_env env, napi_value *result) -> napi_status { @@ -370,7 +364,10 @@ napi_value NapiDataShareHelper::Napi_Query(napi_env env, napi_callback_info info return napi_invalid_arg; } - context->predicates = UnwrapDataSharePredicates(env, argv[1]); + if (!DataShareJSUtils::UnwrapDataSharePredicates(env, argv[1], context->predicates)) { + context->error = std::make_shared("predicates", "DataSharePredicates"); + return napi_invalid_arg; + } context->columns = DataShareJSUtils::Convert2StrVector(env, argv[2], DataShareJSUtils::DEFAULT_BUF_SIZE); return napi_ok; @@ -421,7 +418,10 @@ napi_value NapiDataShareHelper::Napi_Update(napi_env env, napi_callback_info inf return napi_invalid_arg; } - context->predicates = UnwrapDataSharePredicates(env, argv[1]); + if (!DataShareJSUtils::UnwrapDataSharePredicates(env, argv[1], context->predicates)) { + context->error = std::make_shared("predicates", "DataSharePredicates"); + return napi_invalid_arg; + } context->valueBucket.Clear(); if (!GetValueBucketObject(context->valueBucket, env, argv[2])) { @@ -455,6 +455,45 @@ napi_value NapiDataShareHelper::Napi_Update(napi_env env, napi_callback_info inf return asyncCall.Call(env, exec); } +napi_value NapiDataShareHelper::Napi_BatchUpdate(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) -> napi_status { + if (argc != 1) { + context->error = std::make_shared("1"); + return napi_invalid_arg; + } + if (DataShareJSUtils::Convert2Value(env, argv[0], context->updateOperations) != napi_ok) { + context->error = std::make_shared("operations", + "Record>"); + return napi_invalid_arg; + } + return napi_ok; + }; + auto output = [context](napi_env env, napi_value *result) -> napi_status { + if (context->resultNumber < 0) { + context->error = std::make_shared(); + return napi_generic_failure; + } + *result = DataShareJSUtils::Convert2JSValue(env, context->batchUpdateResult); + return napi_ok; + }; + auto exec = [context](AsyncCall::Context *ctx) { + if (context->proxy->datashareHelper_ != nullptr && !context->updateOperations.empty()) { + context->resultNumber = context->proxy->datashareHelper_->BatchUpdate(context->updateOperations, + context->batchUpdateResult); + context->status = napi_ok; + } else { + LOG_ERROR("dataShareHelper_ is nullptr : %{public}d, context->updateOperations is empty : %{public}d", + context->proxy->datashareHelper_ == nullptr, context->updateOperations.empty()); + context->error = std::make_shared(); + } + }; + context->SetAction(std::move(input), std::move(output)); + AsyncCall asyncCall(env, info, context); + return asyncCall.Call(env, exec); +} + napi_value NapiDataShareHelper::Napi_BatchInsert(napi_env env, napi_callback_info info) { auto context = std::make_shared(); diff --git a/data_share/frameworks/js/napi/dataShare/src/napi_datashare_observer.cpp b/data_share/frameworks/js/napi/dataShare/src/napi_datashare_observer.cpp index 997cf479a2fd70662ea235010b66c5a627ed4a5f..287cf6b241f733240086c274136c02d5fc204179 100644 --- a/data_share/frameworks/js/napi/dataShare/src/napi_datashare_observer.cpp +++ b/data_share/frameworks/js/napi/dataShare/src/napi_datashare_observer.cpp @@ -12,8 +12,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#define LOG_TAG "NAPIDataShareObserver" + #include "napi_datashare_observer.h" +#include "adaptor.h" #include #include "datashare_log.h" @@ -23,7 +26,7 @@ NAPIDataShareObserver::~NAPIDataShareObserver() {} void NAPIDataShareObserver::OnChange() { - LOG_DEBUG("NAPIDataShareObserver Start"); + DISTRIBUTED_DATA_HITRACE(std::string(LOG_TAG) + "::" + std::string(__FUNCTION__)); observer_->OnChange(); } } // namespace DataShare diff --git a/data_share/frameworks/js/napi/datashare_ext_ability/datashare_ext_ability.js b/data_share/frameworks/js/napi/datashare_ext_ability/datashare_ext_ability.js index 7e4f2aff936d45f74d221e8703912bf6001918ca..c58357dcac12cb269f68ee3c187c7fb9be9487c7 100644 --- a/data_share/frameworks/js/napi/datashare_ext_ability/datashare_ext_ability.js +++ b/data_share/frameworks/js/napi/datashare_ext_ability/datashare_ext_ability.js @@ -38,6 +38,10 @@ class DataShareExtensionAbility { console.log('update, uri:' + uri); } + batchUpdate(operations, callback) { + console.log('batchUpdate'); + } + delete(uri, predicates, callback) { console.log('delete, uri:' + uri); } diff --git a/data_share/frameworks/native/common/include/adaptor.h b/data_share/frameworks/native/common/include/adaptor.h index 8f9b2290b53ef1c37ec95a78eae0de23f7c3ac03..074ac634a8f71507e29c9680c58c6be69e1206ab 100644 --- a/data_share/frameworks/native/common/include/adaptor.h +++ b/data_share/frameworks/native/common/include/adaptor.h @@ -25,7 +25,7 @@ #else #include "hitrace.h" -#define DISTRIBUTED_DATA_HITRACE(trace) DO_NOTHING +#define DISTRIBUTED_DATA_HITRACE(trace) HiTrace hitrace(trace) #endif diff --git a/data_share/frameworks/native/common/include/datashare_itypes_utils.h b/data_share/frameworks/native/common/include/datashare_itypes_utils.h index 3bbeb0f0bef9792682d2c42d54e52d41fff508f3..7dd6895ef227952e069fc4e6b1102d1dd35f81b4 100644 --- a/data_share/frameworks/native/common/include/datashare_itypes_utils.h +++ b/data_share/frameworks/native/common/include/datashare_itypes_utils.h @@ -38,6 +38,20 @@ using AshmemNode = DataShare::AshmemNode; using OperationStatement = DataShare::OperationStatement; using ExecResult = DataShare::ExecResult; using ExecResultSet = DataShare::ExecResultSet; +using UpdateOperation = DataShare::UpdateOperation; +using BatchUpdateResult = DataShare::BatchUpdateResult; + +template<> +bool Marshalling(const BatchUpdateResult &result, MessageParcel &parcel); + +template<> +bool Unmarshalling(BatchUpdateResult &result, MessageParcel &parcel); + +template<> +bool Marshalling(const UpdateOperation &operation, MessageParcel &parcel); + +template<> +bool Unmarshalling(UpdateOperation &operation, MessageParcel &parcel); template<> bool Marshalling(const Predicates &bucket, MessageParcel &parcel); diff --git a/data_share/frameworks/native/common/include/distributeddata_data_share_ipc_interface_code.h b/data_share/frameworks/native/common/include/distributeddata_data_share_ipc_interface_code.h index fe64078ec8367c0ba67ec23e69d37f3f044ae4a5..5d91f344c76d8d86d19f0883e76c92ae60d9d7f3 100644 --- a/data_share/frameworks/native/common/include/distributeddata_data_share_ipc_interface_code.h +++ b/data_share/frameworks/native/common/include/distributeddata_data_share_ipc_interface_code.h @@ -37,6 +37,7 @@ enum class IDataShareInterfaceCode { CMD_DENORMALIZE_URI, CMD_EXECUTE_BATCH, CMD_INSERT_EXT, + CMD_BATCH_UPDATE, }; enum class ISharedResultInterfaceCode { @@ -90,6 +91,8 @@ enum class DataShareServiceInterfaceCode { DATA_SHARE_SERVICE_CMD_NOTIFY_OBSERVERS, DATA_SHARE_SERVICE_CMD_SET_SILENT_SWITCH, DATA_SHARE_SERVICE_CMD_IS_SILENT_PROXY_ENABLE, + DATA_SHARE_SERVICE_CMD_REGISTER_OBSERVER, + DATA_SHARE_SERVICE_CMD_UNREGISTER_OBSERVER, DATA_SHARE_SERVICE_CMD_MAX }; diff --git a/data_share/frameworks/native/common/include/idata_share_service.h b/data_share/frameworks/native/common/include/idata_share_service.h index 176c43c653b496f9beed07177aa21c5166cae4d1..51818b979e728e3c915059e9a86d845ae8905cc4 100644 --- a/data_share/frameworks/native/common/include/idata_share_service.h +++ b/data_share/frameworks/native/common/include/idata_share_service.h @@ -85,6 +85,12 @@ public: virtual int SetSilentSwitch(const Uri &uri, bool enable) = 0; virtual bool IsSilentProxyEnable(const std::string &uri) = 0; + + virtual int RegisterObserver(const Uri &uri, + const sptr &dataObserver) = 0; + + virtual int UnRegisterObserver(const Uri &uri, + const sptr &dataObserver) = 0; }; } // namespace OHOS::DataShare #endif diff --git a/data_share/frameworks/native/common/include/idatashare.h b/data_share/frameworks/native/common/include/idatashare.h index 7a76650e045cfffeaafb595c8d9c78f3fd78c269..eba1512869c2c51a2bee0d4390b49623727fb12d 100644 --- a/data_share/frameworks/native/common/include/idatashare.h +++ b/data_share/frameworks/native/common/include/idatashare.h @@ -45,6 +45,8 @@ public: virtual int InsertExt(const Uri &uri, const DataShareValuesBucket &value, std::string &result) = 0; virtual int Update(const Uri &uri, const DataSharePredicates &predicates, const DataShareValuesBucket &value) = 0; + + virtual int BatchUpdate(const UpdateOperations &operations, std::vector &results) = 0; virtual int Delete(const Uri &uri, const DataSharePredicates &predicates) = 0; diff --git a/data_share/frameworks/native/common/src/datashare_abs_result_set.cpp b/data_share/frameworks/native/common/src/datashare_abs_result_set.cpp index d4f98e714ba71706a25a6be5add0e60307ecd0bb..5b4c0868922a216f3f9e3e1e0b0a8db2fb863a2e 100644 --- a/data_share/frameworks/native/common/src/datashare_abs_result_set.cpp +++ b/data_share/frameworks/native/common/src/datashare_abs_result_set.cpp @@ -96,7 +96,6 @@ int DataShareAbsResultSet::GoTo(int offset) int DataShareAbsResultSet::GoToFirstRow() { - DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); return GoToRow(0); } diff --git a/data_share/frameworks/native/common/src/datashare_itypes_utils.cpp b/data_share/frameworks/native/common/src/datashare_itypes_utils.cpp index 80a32474f4b6d807fb2bd4bde2658f50c205e9c2..a26d1bf5679facf97e1f0851106f7a1f9381b0ea 100644 --- a/data_share/frameworks/native/common/src/datashare_itypes_utils.cpp +++ b/data_share/frameworks/native/common/src/datashare_itypes_utils.cpp @@ -47,6 +47,30 @@ bool Unmarshalling(Predicates &predicates, MessageParcel &parcel) return true; } +template<> +bool Marshalling(const BatchUpdateResult &result, MessageParcel &parcel) +{ + return ITypesUtil::Marshal(parcel, result.uri, result.codes); +} + +template<> +bool Unmarshalling(BatchUpdateResult &result, MessageParcel &parcel) +{ + return ITypesUtil::Unmarshal(parcel, result.uri, result.codes); +} + +template<> +bool Marshalling(const UpdateOperation &operation, MessageParcel &parcel) +{ + return ITypesUtil::Marshal(parcel, operation.valuesBucket, operation.predicates); +} + +template<> +bool Unmarshalling(UpdateOperation &operation, MessageParcel &parcel) +{ + return ITypesUtil::Unmarshal(parcel, operation.valuesBucket, operation.predicates); +} + template<> bool Marshalling(const Operation &operation, MessageParcel &parcel) { diff --git a/data_share/frameworks/native/common/src/datashare_string_utils.cpp b/data_share/frameworks/native/common/src/datashare_string_utils.cpp index 9dc847b5bf1c91712c72000714c7a755098a640c..f6f74a8e50c743963e32bf0cca40c18dc793db3c 100644 --- a/data_share/frameworks/native/common/src/datashare_string_utils.cpp +++ b/data_share/frameworks/native/common/src/datashare_string_utils.cpp @@ -17,7 +17,7 @@ namespace OHOS { namespace DataShare { -constexpr int32_t END_SIZE = 6; +constexpr int32_t END_SIZE = 10; constexpr const char *DEFAULT_ANONYMOUS = "******"; std::string DataShareStringUtils::Anonymous(const std::string &name) { diff --git a/data_share/frameworks/native/consumer/controller/provider/include/ext_special_controller.h b/data_share/frameworks/native/consumer/controller/provider/include/ext_special_controller.h index 586cf90802c7bfea6a057379b8fcfafeae0c952c..81745c223dc16ff158b0bf01da2cc3ab5cf7a1d7 100644 --- a/data_share/frameworks/native/consumer/controller/provider/include/ext_special_controller.h +++ b/data_share/frameworks/native/consumer/controller/provider/include/ext_special_controller.h @@ -33,6 +33,8 @@ public: int OpenRawFile(const Uri &uri, const std::string &mode); + int BatchUpdate(const UpdateOperations &operations, std::vector &results); + std::string GetType(const Uri &uri); int BatchInsert(const Uri &uri, const std::vector &values); diff --git a/data_share/frameworks/native/consumer/controller/provider/src/ext_special_controller.cpp b/data_share/frameworks/native/consumer/controller/provider/src/ext_special_controller.cpp index d38437045d987dacda66ce2887e64b70f6d2ce75..8228fcedafe106363f8f9ffb739e3b5e965eec85 100644 --- a/data_share/frameworks/native/consumer/controller/provider/src/ext_special_controller.cpp +++ b/data_share/frameworks/native/consumer/controller/provider/src/ext_special_controller.cpp @@ -79,6 +79,22 @@ int ExtSpecialController::BatchInsert(const Uri &uri, const std::vectorBatchInsert(uri, values); } +int ExtSpecialController::BatchUpdate(const UpdateOperations &operations, + std::vector &results) +{ + auto connection = connection_; + if (connection == nullptr) { + LOG_ERROR("connection is nullptr"); + return INVALID_VALUE; + } + auto proxy = connection->GetDataShareProxy(uri_, token_); + if (proxy == nullptr) { + LOG_ERROR("proxy is nullptr"); + return INVALID_VALUE; + } + return proxy->BatchUpdate(operations, results); +} + int ExtSpecialController::InsertExt(Uri &uri, const DataShareValuesBucket &value, std::string &result) { auto connection = connection_; diff --git a/data_share/frameworks/native/consumer/controller/service/include/general_controller_service_impl.h b/data_share/frameworks/native/consumer/controller/service/include/general_controller_service_impl.h index c1b65efb2b98b4f56c1696f05e3b69abef66dc01..6d3ac96934263d9fd693fe2c2988e62156d4e3b0 100644 --- a/data_share/frameworks/native/consumer/controller/service/include/general_controller_service_impl.h +++ b/data_share/frameworks/native/consumer/controller/service/include/general_controller_service_impl.h @@ -16,8 +16,12 @@ #ifndef GENERAL_CONTROLLER_SERVICE_IMPL_H #define GENERAL_CONTROLLER_SERVICE_IMPL_H +#include + +#include "concurrent_map.h" #include "data_share_manager_impl.h" #include "general_controller.h" +#include "uri.h" namespace OHOS { namespace AAFwk { @@ -29,7 +33,7 @@ class GeneralControllerServiceImpl : public GeneralController { public: GeneralControllerServiceImpl() = default; - virtual ~GeneralControllerServiceImpl() = default; + virtual ~GeneralControllerServiceImpl(); int Insert(const Uri &uri, const DataShareValuesBucket &value) override; @@ -45,6 +49,12 @@ public: void UnregisterObserver(const Uri &uri, const sptr &dataObserver) override; void NotifyChange(const Uri &uri) override; +private: + void ReRegisterObserver(); + + void SetRegisterCallback(); + + ConcurrentMap, std::list> observers_; }; } // namespace DataShare } // namespace OHOS diff --git a/data_share/frameworks/native/consumer/controller/service/src/general_controller_service_impl.cpp b/data_share/frameworks/native/consumer/controller/service/src/general_controller_service_impl.cpp index d03ff73fde8b3f9591559181929ae39230226843..e86e16106bd1c74c19c9da9c01e79de122c08841 100644 --- a/data_share/frameworks/native/consumer/controller/service/src/general_controller_service_impl.cpp +++ b/data_share/frameworks/native/consumer/controller/service/src/general_controller_service_impl.cpp @@ -16,12 +16,19 @@ #include "general_controller_service_impl.h" #include "dataobs_mgr_client.h" +#include "dataobs_mgr_errors.h" #include "datashare_log.h" #include "datashare_string_utils.h" namespace OHOS { namespace DataShare { constexpr int INVALID_VALUE = -1; +GeneralControllerServiceImpl::~GeneralControllerServiceImpl() +{ + auto manager = DataShareManagerImpl::GetInstance(); + manager->RemoveRegisterCallback(this); +} + int GeneralControllerServiceImpl::Insert(const Uri &uri, const DataShareValuesBucket &value) { auto proxy = DataShareManagerImpl::GetServiceProxy(); @@ -67,27 +74,48 @@ std::shared_ptr GeneralControllerServiceImpl::Query(const Ur void GeneralControllerServiceImpl::RegisterObserver(const Uri &uri, const sptr &dataObserver) { - auto obsMgrClient = OHOS::AAFwk::DataObsMgrClient::GetInstance(); - if (obsMgrClient == nullptr) { - LOG_ERROR("get DataObsMgrClient failed"); + SetRegisterCallback(); + auto proxy = DataShareManagerImpl::GetServiceProxy(); + if (proxy == nullptr) { + LOG_ERROR("Proxy is nullptr, uri: %{public}s", DataShareStringUtils::Anonymous(uri.ToString()).c_str()); + observers_.Compute(dataObserver, [&uri](const auto &, auto &value) { + value.emplace_back(uri); + return true; + }); return; } - ErrCode ret = obsMgrClient->RegisterObserver(uri, dataObserver); + auto ret = proxy->RegisterObserver(uri, dataObserver->AsObject()); LOG_INFO("Register observer ret: %{public}d, uri: %{public}s", ret, DataShareStringUtils::Anonymous(uri.ToString()).c_str()); + if (ret == E_OK || ret == AAFwk::OBS_EXIST) { + observers_.Compute(dataObserver, [&uri](const auto &, auto &value) { + value.emplace_back(uri); + return true; + }); + } + return; } void GeneralControllerServiceImpl::UnregisterObserver(const Uri &uri, const sptr &dataObserver) { - auto obsMgrClient = OHOS::AAFwk::DataObsMgrClient::GetInstance(); - if (obsMgrClient == nullptr) { - LOG_ERROR("get DataObsMgrClient failed"); + auto proxy = DataShareManagerImpl::GetServiceProxy(); + if (proxy == nullptr) { + LOG_ERROR("Proxy is nullptr"); return; } - ErrCode ret = obsMgrClient->UnregisterObserver(uri, dataObserver); - LOG_INFO("Unregister observer ret: %{public}d, uri: %{public}s", ret, + auto ret = proxy->UnRegisterObserver(uri, dataObserver->AsObject()); + LOG_INFO("UnRegister observer ret: %{public}d, uri: %{public}s", ret, DataShareStringUtils::Anonymous(uri.ToString()).c_str()); + if (ret == E_OK) { + observers_.Compute(dataObserver, [&uri](const auto &, auto &value) { + value.remove_if([&uri](const auto &val) { + return uri == val; + }); + return !value.empty(); + }); + } + return; } void GeneralControllerServiceImpl::NotifyChange(const Uri &uri) @@ -99,5 +127,31 @@ void GeneralControllerServiceImpl::NotifyChange(const Uri &uri) } proxy->Notify(uri.ToString()); } + +void GeneralControllerServiceImpl::SetRegisterCallback() +{ + auto manager = DataShareManagerImpl::GetInstance(); + if (manager == nullptr) { + LOG_ERROR("Manager is nullptr"); + return; + } + auto registerCallback = [this]() { + ReRegisterObserver(); + }; + manager->SetRegisterCallback(this, registerCallback); +} + +void GeneralControllerServiceImpl::ReRegisterObserver() +{ + LOG_INFO("Distributeddata service on start, reRegister observer."); + decltype(observers_) observers(std::move(observers_)); + observers_.Clear(); + observers.ForEach([this](const auto &key, const auto &value) { + for (const auto &uri : value) { + RegisterObserver(uri, key); + } + return false; + }); +} } // namespace DataShare } // namespace OHOS \ No newline at end of file diff --git a/data_share/frameworks/native/consumer/include/datashare_helper_impl.h b/data_share/frameworks/native/consumer/include/datashare_helper_impl.h index c20272928f19df7faa56b25bfa77ab4b6e759430..6bd3aac2bc376f992d4588f531b115fa4d33e632 100644 --- a/data_share/frameworks/native/consumer/include/datashare_helper_impl.h +++ b/data_share/frameworks/native/consumer/include/datashare_helper_impl.h @@ -44,6 +44,8 @@ public: int InsertExt(Uri &uri, const DataShareValuesBucket &value, std::string &result) override; int Update(Uri &uri, const DataSharePredicates &predicates, const DataShareValuesBucket &value) override; + + int BatchUpdate(const UpdateOperations &operations, std::vector &results) override; int Delete(Uri &uri, const DataSharePredicates &predicates) override; diff --git a/data_share/frameworks/native/consumer/include/datashare_proxy.h b/data_share/frameworks/native/consumer/include/datashare_proxy.h index 8da85279a14ff4391705dcc66a171ed345cb0688..a172c798e5a40b82754bc3c1e6b68e86b46e91da 100644 --- a/data_share/frameworks/native/consumer/include/datashare_proxy.h +++ b/data_share/frameworks/native/consumer/include/datashare_proxy.h @@ -42,6 +42,8 @@ public: virtual int Update(const Uri &uri, const DataSharePredicates &predicates, const DataShareValuesBucket &value) override; + virtual int BatchUpdate(const UpdateOperations &operations, std::vector &results) override; + virtual int Delete(const Uri &uri, const DataSharePredicates &predicates) override; virtual std::shared_ptr Query(const Uri &uri, const DataSharePredicates &predicates, @@ -64,8 +66,10 @@ public: virtual Uri DenormalizeUri(const Uri &uri) override; private: + bool CheckSize(const UpdateOperations &operations); static inline BrokerDelegator delegator_; static const size_t MTU_SIZE = 912600; // 900k + static const size_t MAX_SIZE = 4000; }; } // namespace DataShare } // namespace OHOS diff --git a/data_share/frameworks/native/consumer/src/datashare_helper.cpp b/data_share/frameworks/native/consumer/src/datashare_helper.cpp index e820e543419125959506c740e7620a32465f1623..37505a0e3c83ad8c348cda942cf7cfce6afefa3a 100644 --- a/data_share/frameworks/native/consumer/src/datashare_helper.cpp +++ b/data_share/frameworks/native/consumer/src/datashare_helper.cpp @@ -12,15 +12,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#define LOG_TAG "DataShareHelper" #include "datashare_helper.h" #include "datashare_helper_impl.h" +#include "adaptor.h" #include "concurrent_map.h" #include "data_ability_observer_interface.h" #include "data_ability_observer_stub.h" #include "dataobs_mgr_client.h" #include "datashare_log.h" +#include "datashare_string_utils.h" namespace OHOS { namespace DataShare { @@ -74,6 +77,7 @@ std::string DataShareHelper::TransferUriPrefix(const std::string &originPrefix, std::shared_ptr DataShareHelper::Creator( const sptr &token, const std::string &strUri, const std::string &extUri) { + DISTRIBUTED_DATA_HITRACE(std::string(LOG_TAG) + "::" + std::string(__FUNCTION__)); if (token == nullptr) { LOG_ERROR("token == nullptr"); return nullptr; @@ -99,6 +103,7 @@ std::shared_ptr DataShareHelper::Creator( std::shared_ptr DataShareHelper::Creator(const string &strUri, const CreateOptions &options, const std::string &bundleName) { + DISTRIBUTED_DATA_HITRACE(std::string(LOG_TAG) + "::" + std::string(__FUNCTION__)); Uri uri(strUri); if (!options.isProxy_ && options.token_ == nullptr) { LOG_ERROR("token is nullptr"); @@ -163,7 +168,6 @@ std::shared_ptr DataShareHelper::CreateExtHelper(Uri &uri, cons void DataShareHelper::RegisterObserverExt(const Uri &uri, std::shared_ptr dataObserver, bool isDescendants) { - LOG_DEBUG("Start"); if (dataObserver == nullptr) { LOG_ERROR("dataObserver is nullptr"); return; @@ -181,8 +185,9 @@ void DataShareHelper::RegisterObserverExt(const Uri &uri, std::shared_ptrRegisterObserverExt(uri, obs, isDescendants); if (ret != ERR_OK) { ObserverImpl::DeleteObserver(uri, dataObserver); - LOG_ERROR("RegisterObserverExt failed"); } + LOG_INFO("Register observerExt, ret:%{public}d, uri:%{public}s", + ret, DataShareStringUtils::Anonymous(uri.ToString()).c_str()); } /** @@ -193,7 +198,6 @@ void DataShareHelper::RegisterObserverExt(const Uri &uri, std::shared_ptr dataObserver) { - LOG_DEBUG("Start"); if (dataObserver == nullptr) { LOG_ERROR("dataObserver is nullptr"); return; @@ -215,8 +219,9 @@ void DataShareHelper::UnregisterObserverExt(const Uri &uri, std::shared_ptrUnregisterObserverExt(uri, obs); + LOG_INFO("Unregister observerExt, ret:%{public}d, uri:%{public}s", + ret, DataShareStringUtils::Anonymous(uri.ToString()).c_str()); if (ret != ERR_OK) { - LOG_ERROR("UnregisterObserverExt failed"); return; } ObserverImpl::DeleteObserver(uri, dataObserver); @@ -229,8 +234,6 @@ void DataShareHelper::UnregisterObserverExt(const Uri &uri, std::shared_ptrNotifyChangeExt(ObserverImpl::ConvertInfo(changeInfo)); - if (ret != ERR_OK) { - LOG_ERROR("NotifyChangeExt failed"); - } + LOG_INFO("Notify changeExt, ret:%{public}d", ret); } void ObserverImpl::OnChange() {} diff --git a/data_share/frameworks/native/consumer/src/datashare_helper_impl.cpp b/data_share/frameworks/native/consumer/src/datashare_helper_impl.cpp index 4c7d5253b718b2e56ea249451aaf602760f24bac..052938b40f6de75dcf6123f3d14802e34c2b4762 100644 --- a/data_share/frameworks/native/consumer/src/datashare_helper_impl.cpp +++ b/data_share/frameworks/native/consumer/src/datashare_helper_impl.cpp @@ -12,9 +12,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#define LOG_TAG "DataShareHelperImpl" #include "datashare_helper_impl.h" +#include "adaptor.h" #include "concurrent_map.h" #include "data_ability_observer_interface.h" #include "dataobs_mgr_client.h" @@ -91,6 +93,7 @@ int DataShareHelperImpl::OpenRawFile(Uri &uri, const std::string &mode) int DataShareHelperImpl::Insert(Uri &uri, const DataShareValuesBucket &value) { + DISTRIBUTED_DATA_HITRACE(std::string(LOG_TAG) + "::" + std::string(__FUNCTION__)); auto generalCtl = generalCtl_; if (generalCtl == nullptr) { LOG_ERROR("generalCtl_ is nullptr"); @@ -101,6 +104,7 @@ int DataShareHelperImpl::Insert(Uri &uri, const DataShareValuesBucket &value) int DataShareHelperImpl::InsertExt(Uri &uri, const DataShareValuesBucket &value, std::string &result) { + DISTRIBUTED_DATA_HITRACE(std::string(LOG_TAG) + "::" + std::string(__FUNCTION__)); auto extSpCtl = extSpCtl_; if (extSpCtl == nullptr) { LOG_ERROR("providerSpCtl is nullptr"); @@ -111,6 +115,7 @@ int DataShareHelperImpl::InsertExt(Uri &uri, const DataShareValuesBucket &value, int DataShareHelperImpl::Update(Uri &uri, const DataSharePredicates &predicates, const DataShareValuesBucket &value) { + DISTRIBUTED_DATA_HITRACE(std::string(LOG_TAG) + "::" + std::string(__FUNCTION__)); auto generalCtl = generalCtl_; if (generalCtl == nullptr) { LOG_ERROR("generalCtl is nullptr"); @@ -119,8 +124,19 @@ int DataShareHelperImpl::Update(Uri &uri, const DataSharePredicates &predicates, return generalCtl->Update(uri, predicates, value); } +int DataShareHelperImpl::BatchUpdate(const UpdateOperations &operations, std::vector &results) +{ + auto extSpCtl = extSpCtl_; + if (extSpCtl == nullptr) { + LOG_ERROR("extSpCtl is nullptr"); + return INVALID_VALUE; + } + return extSpCtl->BatchUpdate(operations, results); +} + int DataShareHelperImpl::Delete(Uri &uri, const DataSharePredicates &predicates) { + DISTRIBUTED_DATA_HITRACE(std::string(LOG_TAG) + "::" + std::string(__FUNCTION__)); auto generalCtl = generalCtl_; if (generalCtl == nullptr) { LOG_ERROR("generalCtl is nullptr"); @@ -132,6 +148,7 @@ int DataShareHelperImpl::Delete(Uri &uri, const DataSharePredicates &predicates) std::shared_ptr DataShareHelperImpl::Query(Uri &uri, const DataSharePredicates &predicates, std::vector &columns, DatashareBusinessError *businessError) { + DISTRIBUTED_DATA_HITRACE(std::string(LOG_TAG) + "::" + std::string(__FUNCTION__)); auto generalCtl = generalCtl_; if (generalCtl == nullptr) { LOG_ERROR("generalCtl is nullptr"); @@ -157,6 +174,7 @@ std::string DataShareHelperImpl::GetType(Uri &uri) int DataShareHelperImpl::BatchInsert(Uri &uri, const std::vector &values) { + DISTRIBUTED_DATA_HITRACE(std::string(LOG_TAG) + "::" + std::string(__FUNCTION__)); auto extSpCtl = extSpCtl_; if (extSpCtl == nullptr) { LOG_ERROR("providerSepOperator is nullptr"); @@ -205,6 +223,7 @@ void DataShareHelperImpl::UnregisterObserver(const Uri &uri, const sptr DataShareHelperImpl::Publish(const Data &data, const std::string &bundleName) { + DISTRIBUTED_DATA_HITRACE(std::string(LOG_TAG) + "::" + std::string(__FUNCTION__)); auto publishedDataCtl = publishedDataCtl_; if (publishedDataCtl == nullptr) { LOG_ERROR("publishedDataCtl is nullptr"); @@ -265,6 +287,7 @@ std::vector DataShareHelperImpl::Publish(const Data &data, cons Data DataShareHelperImpl::GetPublishedData(const std::string &bundleName, int &resultCode) { + DISTRIBUTED_DATA_HITRACE(std::string(LOG_TAG) + "::" + std::string(__FUNCTION__)); auto publishedDataCtl = publishedDataCtl_; if (publishedDataCtl == nullptr) { LOG_ERROR("publishedDataCtl is nullptr"); @@ -348,7 +371,7 @@ std::vector DataShareHelperImpl::UnsubscribePublishedData(const std::vector DataShareHelperImpl::EnablePubSubs(const std::vector &uris, int64_t subscriberId) { - LOG_DEBUG("Start UnSubscribePublishedData"); + LOG_DEBUG("Start enablePubSubs"); auto publishedDataCtl = publishedDataCtl_; if (publishedDataCtl == nullptr) { LOG_ERROR("publishedDataCtl is nullptr"); @@ -360,7 +383,7 @@ std::vector DataShareHelperImpl::EnablePubSubs(const std::vecto std::vector DataShareHelperImpl::DisablePubSubs(const std::vector &uris, int64_t subscriberId) { - LOG_DEBUG("Start UnSubscribePublishedData"); + LOG_DEBUG("Start disablePubSubs"); auto publishedDataCtl = publishedDataCtl_; if (publishedDataCtl == nullptr) { LOG_ERROR("publishedDataCtl is nullptr"); diff --git a/data_share/frameworks/native/consumer/src/datashare_proxy.cpp b/data_share/frameworks/native/consumer/src/datashare_proxy.cpp index 9dd419e524e5fe293d8444a9e55c0da2ad75da94..29bba953cd037b1a634989f1f70c0823e7f227ce 100644 --- a/data_share/frameworks/native/consumer/src/datashare_proxy.cpp +++ b/data_share/frameworks/native/consumer/src/datashare_proxy.cpp @@ -225,6 +225,37 @@ int DataShareProxy::Update(const Uri &uri, const DataSharePredicates &predicates return index; } +int DataShareProxy::BatchUpdate(const UpdateOperations &operations, std::vector &results) +{ + int ret = -1; + MessageParcel data; + data.SetMaxCapacity(MTU_SIZE); + if (!data.WriteInterfaceToken(DataShareProxy::GetDescriptor())) { + LOG_ERROR("WriteInterfaceToken failed"); + return ret; + } + if (!CheckSize(operations)) { + return ret; + } + if (!ITypesUtil::Marshal(data, operations)) { + LOG_ERROR("fail to Marshalling"); + return ret; + } + MessageParcel reply; + MessageOption option; + int32_t err = Remote()->SendRequest( + static_cast(IDataShareInterfaceCode::CMD_BATCH_UPDATE), data, reply, option); + if (err != DATA_SHARE_NO_ERROR) { + LOG_ERROR("fail to SendRequest. err: %{public}d", err); + return err; + } + if (!ITypesUtil::Unmarshal(reply, results)) { + LOG_ERROR("fail to Unmarshal result"); + return ret; + } + return 0; +} + int DataShareProxy::Delete(const Uri &uri, const DataSharePredicates &predicates) { int index = -1; @@ -498,5 +529,18 @@ Uri DataShareProxy::DenormalizeUri(const Uri &uri) } return info; } + +bool DataShareProxy::CheckSize(const UpdateOperations &operations) +{ + size_t size = 0; + for (const auto &it : operations) { + size += it.second.size(); + } + if (size > MAX_SIZE) { + LOG_ERROR("operations size greater than limit"); + return false; + } + return true; +} } // namespace DataShare } // namespace OHOS diff --git a/data_share/frameworks/native/provider/include/datashare_ext_ability.h b/data_share/frameworks/native/provider/include/datashare_ext_ability.h index 066d5133049cd2a3a1af08e569d6f3a7f0580c28..46528426f6f2636384deb467dfa681385f14515e 100644 --- a/data_share/frameworks/native/provider/include/datashare_ext_ability.h +++ b/data_share/frameworks/native/provider/include/datashare_ext_ability.h @@ -135,6 +135,16 @@ public: virtual int Update(const Uri &uri, const DataSharePredicates &predicates, const DataShareValuesBucket &value); + /** + * @brief Batch updates data records in the database. + * + * @param updateOperations Indicates the param of data to update. + * @param results Indicates the number of data records updated. + * + * @return Return the execution results of batch updates. + */ + virtual int BatchUpdate(const UpdateOperations &operations, std::vector &results); + /** * @brief Deletes one or more data records from the database. * diff --git a/data_share/frameworks/native/provider/include/datashare_stub.h b/data_share/frameworks/native/provider/include/datashare_stub.h index 4e489ad44c0f4c6a8d9b0a1f39ca816c6878d10d..44e195f7af9f2c555fa789993a54caa255ba63a0 100644 --- a/data_share/frameworks/native/provider/include/datashare_stub.h +++ b/data_share/frameworks/native/provider/include/datashare_stub.h @@ -47,9 +47,11 @@ private: ErrCode CmdDenormalizeUri(MessageParcel &data, MessageParcel &reply); ErrCode CmdExecuteBatch(MessageParcel &data, MessageParcel &reply); ErrCode CmdInsertExt(MessageParcel &data, MessageParcel &reply); + ErrCode CmdBatchUpdate(MessageParcel &data, MessageParcel &reply); virtual int ExecuteBatch(const std::vector &statements, ExecResultSet &result) override; virtual int InsertExt(const Uri &uri, const DataShareValuesBucket &value, std::string &result) override; + virtual int BatchUpdate(const UpdateOperations &operations, std::vector &results) override; using RequestFuncType = int (DataShareStub::*)(MessageParcel &data, MessageParcel &reply); std::map stubFuncMap_; diff --git a/data_share/frameworks/native/provider/include/datashare_stub_impl.h b/data_share/frameworks/native/provider/include/datashare_stub_impl.h index 620b1e2659f7c07931e00dde32e80ce61cf4ba49..f0c3e358f562ab9a7af41a3ee3e3afc586cdae63 100644 --- a/data_share/frameworks/native/provider/include/datashare_stub_impl.h +++ b/data_share/frameworks/native/provider/include/datashare_stub_impl.h @@ -46,6 +46,8 @@ public: int Update(const Uri &uri, const DataSharePredicates &predicates, const DataShareValuesBucket &value) override; + int BatchUpdate(const UpdateOperations &operations, std::vector &results) override; + int Delete(const Uri &uri, const DataSharePredicates &predicates) override; std::shared_ptr Query(const Uri &uri, const DataSharePredicates &predicates, diff --git a/data_share/frameworks/native/provider/include/js_datashare_ext_ability.h b/data_share/frameworks/native/provider/include/js_datashare_ext_ability.h index e82150836d02e8a77ebc0fcfe86d88fd5057c114..8bc0871a02e9b9a00a376221fb0c2f0cda7a6692 100644 --- a/data_share/frameworks/native/provider/include/js_datashare_ext_ability.h +++ b/data_share/frameworks/native/provider/include/js_datashare_ext_ability.h @@ -138,6 +138,16 @@ public: int Update(const Uri &uri, const DataSharePredicates &predicates, const DataShareValuesBucket &value) override; + /** + * @brief Batch updates data records in the database. + * + * @param updateOperations Indicates the param of data to update. + * @param results Indicates the number of data records updated. + * + * @return Return the execution results of batch updates. + */ + virtual int BatchUpdate(const UpdateOperations &operations, std::vector &results) override; + /** * @brief Deletes one or more data records from the database. * @@ -276,6 +286,16 @@ public: value = callbackResultStringArr_; } + void SetResult(const std::vector &results) + { + updateResults_ = results; + } + + void GetResult(std::vector &results) + { + results = updateResults_; + } + void SetResult(const std::vector value) { callbackResultStringArr_ = value; @@ -319,6 +339,7 @@ private: void SaveNewCallingInfo(napi_env &env); void GetSrcPath(std::string &srcPath); napi_value MakePredicates(napi_env env, const DataSharePredicates &predicates); + napi_value MakeUpdateOperation(napi_env env, const UpdateOperation &updateOperation); static napi_value AsyncCallback(napi_env env, napi_callback_info info); static napi_value AsyncCallbackWithContext(napi_env env, napi_callback_info info); void CheckAndSetAsyncResult(napi_env env); @@ -326,6 +347,7 @@ private: static void UnWrapBusinessError(napi_env env, napi_value info, DatashareBusinessError &businessError); static napi_valuetype UnWrapPropertyType(napi_env env, napi_value info, const std::string &key); + static bool UnwrapBatchUpdateResult(napi_env env, napi_value &info, std::vector &results); static std::string UnWrapProperty(napi_env env, napi_value info, const std::string &key); int32_t InitAsyncCallParams(size_t argc, napi_env &env, napi_value *args); @@ -340,6 +362,7 @@ private: std::mutex resultSetLock_; std::shared_ptr callbackResultObject_ = nullptr; DatashareBusinessError businessError_; + std::vector updateResults_ = {}; }; } // namespace DataShare } // namespace OHOS diff --git a/data_share/frameworks/native/provider/src/datashare_ext_ability.cpp b/data_share/frameworks/native/provider/src/datashare_ext_ability.cpp index c78aa36267757682f8eebc5e31568ba7bb576cd5..284d49bea388390778b194f1e628f96aad30ae83 100644 --- a/data_share/frameworks/native/provider/src/datashare_ext_ability.cpp +++ b/data_share/frameworks/native/provider/src/datashare_ext_ability.cpp @@ -94,6 +94,11 @@ int DataShareExtAbility::Update(const Uri &uri, const DataSharePredicates &predi return -1; } +int DataShareExtAbility::BatchUpdate(const UpdateOperations &operations, std::vector &results) +{ + return 0; +} + int DataShareExtAbility::Delete(const Uri &uri, const DataSharePredicates &predicates) { return -1; diff --git a/data_share/frameworks/native/provider/src/datashare_stub.cpp b/data_share/frameworks/native/provider/src/datashare_stub.cpp index cc667447ea8ad84ed3c602dbf11fb311bb7c7e1c..b8cd32977c17aabcd45f31a557e913f4927ab4ab 100644 --- a/data_share/frameworks/native/provider/src/datashare_stub.cpp +++ b/data_share/frameworks/native/provider/src/datashare_stub.cpp @@ -51,6 +51,7 @@ DataShareStub::DataShareStub() &DataShareStub::CmdDenormalizeUri; stubFuncMap_[static_cast(IDataShareInterfaceCode::CMD_EXECUTE_BATCH)] = &DataShareStub::CmdExecuteBatch; stubFuncMap_[static_cast(IDataShareInterfaceCode::CMD_INSERT_EXT)] = &DataShareStub::CmdInsertExt; + stubFuncMap_[static_cast(IDataShareInterfaceCode::CMD_BATCH_UPDATE)] = &DataShareStub::CmdBatchUpdate; } DataShareStub::~DataShareStub() @@ -186,6 +187,26 @@ ErrCode DataShareStub::CmdUpdate(MessageParcel &data, MessageParcel &reply) return DATA_SHARE_NO_ERROR; } +ErrCode DataShareStub::CmdBatchUpdate(OHOS::MessageParcel &data, OHOS::MessageParcel &reply) +{ + UpdateOperations updateOperations; + if (!ITypesUtil::Unmarshal(data, updateOperations)) { + LOG_ERROR("Unmarshalling updateOperations is nullptr"); + return ERR_INVALID_VALUE; + } + std::vector results; + int ret = BatchUpdate(updateOperations, results); + if (ret != E_OK) { + LOG_ERROR("BatchUpdate inner error, ret is %{public}d.", ret); + return ret; + } + if (!ITypesUtil::Marshal(reply, results)) { + LOG_ERROR("marshalling updateOperations is failed"); + return ERR_INVALID_VALUE; + } + return DATA_SHARE_NO_ERROR; +} + ErrCode DataShareStub::CmdDelete(MessageParcel &data, MessageParcel &reply) { Uri uri(""); @@ -410,5 +431,10 @@ int DataShareStub::InsertExt(const Uri &uri, const DataShareValuesBucket &value, { return 0; } + +int DataShareStub::BatchUpdate(const UpdateOperations &operations, std::vector &results) +{ + return 0; +} } // namespace DataShare } // namespace OHOS \ No newline at end of file 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 3cf33416da99287762517ff15d8173d0a4021d10..5a57de14bf72b15b4f2890c908e8a7766d10116a 100644 --- a/data_share/frameworks/native/provider/src/datashare_stub_impl.cpp +++ b/data_share/frameworks/native/provider/src/datashare_stub_impl.cpp @@ -17,6 +17,7 @@ #include "accesstoken_kit.h" #include "datashare_log.h" +#include "datashare_string_utils.h" #include "ipc_skeleton.h" namespace OHOS { @@ -179,6 +180,37 @@ int DataShareStubImpl::Update(const Uri &uri, const DataSharePredicates &predica return ret; } +int DataShareStubImpl::BatchUpdate(const UpdateOperations &operations, std::vector &results) +{ + CallingInfo info; + GetCallingInfo(info); + auto client = sptr(this); + auto extension = client->GetOwner(); + if (extension == nullptr) { + return DEFAULT_NUMBER; + } + if (!CheckCallingPermission(extension->abilityInfo_->writePermission)) { + LOG_ERROR("Check calling permission failed."); + return PERMISSION_ERROR_NUMBER; + } + std::shared_ptr ret = std::make_shared(0); + std::function syncTaskFunc = [extension, ret, operations, info]() { + extension->SetCallingInfo(info); + std::vector tmp; + *ret = extension->BatchUpdate(operations, tmp); + }; + std::function getRetFunc = [&results, extension]() -> bool { + if (extension == nullptr) { + return false; + } + extension->GetResult(results); + return extension->GetRecvReply(); + }; + std::lock_guard lock(mutex_); + uvQueue_->SyncCall(syncTaskFunc, getRetFunc); + return *ret; +} + int DataShareStubImpl::Delete(const Uri &uri, const DataSharePredicates &predicates) { CallingInfo info; @@ -317,6 +349,11 @@ bool DataShareStubImpl::RegisterObserver(const Uri &uri, const sptrabilityInfo_->readPermission)) { + LOG_ERROR("Register observer check permission failed. uri: %{public}s", + DataShareStringUtils::Anonymous(uri.ToString()).c_str()); + return PERMISSION_ERROR_NUMBER; + } return extension->RegisterObserver(uri, dataObserver); } @@ -326,6 +363,11 @@ bool DataShareStubImpl::UnregisterObserver(const Uri &uri, const sptrabilityInfo_->readPermission)) { + LOG_ERROR("UnRegister observer check permission failed. uri: %{public}s", + DataShareStringUtils::Anonymous(uri.ToString()).c_str()); + return PERMISSION_ERROR_NUMBER; + } return extension->UnregisterObserver(uri, dataObserver); } 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 0d22f6cf3c80b2c64b93022d15e2c71fe139abff..c43489a8248466860d68835b81ddcb7f43e9c2ae 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 @@ -142,6 +142,42 @@ sptr JsDataShareExtAbility::OnConnect(const AAFwk::Want &want) return remoteObject->AsObject(); } +bool JsDataShareExtAbility::UnwrapBatchUpdateResult(napi_env env, napi_value &info, + std::vector &results) +{ + napi_value keys = 0; + if (napi_get_property_names(env, info, &keys) != napi_ok) { + LOG_ERROR("napi_get_property_names failed"); + return false; + } + + uint32_t arrLen = 0; + if (napi_get_array_length(env, keys, &arrLen) != napi_ok) { + LOG_ERROR("napi_get_array_length failed"); + return false; + } + for (size_t i = 0; i < arrLen; i++) { + napi_value key = 0; + if (napi_get_element(env, keys, i, &key) != napi_ok) { + LOG_ERROR("napi_get_element failed"); + return false; + } + BatchUpdateResult batchUpdateResult; + batchUpdateResult.uri = DataShareJSUtils::UnwrapStringFromJS(env, key); + napi_value value = 0; + if (napi_get_property(env, info, key, &value) != napi_ok) { + LOG_ERROR("napi_get_property failed"); + return false; + } + if (!UnwrapArrayInt32FromJS(env, value, batchUpdateResult.codes)) { + LOG_ERROR("UnwrapArrayInt32FromJS failed"); + return false; + } + results.push_back(std::move(batchUpdateResult)); + } + return true; +} + void JsDataShareExtAbility::CheckAndSetAsyncResult(napi_env env) { napi_valuetype type = napi_undefined; @@ -157,6 +193,11 @@ void JsDataShareExtAbility::CheckAndSetAsyncResult(napi_env env) JSProxy::JSCreator *proxy = nullptr; napi_unwrap(env, result, reinterpret_cast(&proxy)); if (proxy == nullptr) { + std::vector results; + if (UnwrapBatchUpdateResult(env, result, results)) { + SetResult(results); + return; + } std::vector value; OHOS::AppExecFwk::UnwrapArrayStringFromJS(env, result, value); SetResult(value); @@ -570,6 +611,50 @@ int JsDataShareExtAbility::Update(const Uri &uri, const DataSharePredicates &pre return ret; } +int JsDataShareExtAbility::BatchUpdate(const UpdateOperations &operations, + std::vector &results) +{ + int ret = DataShareExtAbility::BatchUpdate(operations, results); + HandleScope handleScope(jsRuntime_); + napi_env env = jsRuntime_.GetNapiEnv(); + napi_handle_scope scope = nullptr; + napi_open_handle_scope(env, &scope); + if (scope == nullptr) { + return ret; + } + napi_value jsMap = nullptr; + napi_status status = napi_create_object(env, &jsMap); + if (status != napi_ok) { + LOG_ERROR("napi_create_object : %{public}d", status); + napi_close_handle_scope(env, scope); + return ret; + } + for (const auto &valueArray : operations) { + napi_value napiValues = nullptr; + status = napi_create_array(env, &napiValues); + if (status != napi_ok) { + LOG_ERROR("napi_create_array status : %{public}d", status); + napi_close_handle_scope(env, scope); + return ret; + } + int32_t index = 0; + for (const auto &value : valueArray.second) { + napi_value jsUpdateOperation = MakeUpdateOperation(env, value); + if (jsUpdateOperation == nullptr) { + LOG_ERROR("MakeUpdateOperation failed"); + napi_close_handle_scope(env, scope); + return ret; + } + napi_set_element(env, napiValues, index++, jsUpdateOperation); + } + napi_set_named_property(env, jsMap, valueArray.first.c_str(), napiValues); + } + napi_value argv[] = { jsMap }; + CallObjectMethod("batchUpdate", argv, 1); + napi_close_handle_scope(env, scope); + return ret; +} + int JsDataShareExtAbility::Delete(const Uri &uri, const DataSharePredicates &predicates) { int ret = INVALID_VALUE; @@ -920,6 +1005,29 @@ void JsDataShareExtAbility::NotifyToDataShareService() static_cast(DataShareServiceInterfaceCode::DATA_SHARE_SERVICE_CMD_NOTIFY), data, reply, option); } +napi_value JsDataShareExtAbility::MakeUpdateOperation(napi_env env, const UpdateOperation &updateOperation) +{ + napi_value jsValueBucket = NewInstance(env, const_cast(updateOperation.valuesBucket)); + napi_value jsPredicates = MakePredicates(env, updateOperation.predicates); + if (jsValueBucket == nullptr || jsPredicates == nullptr) { + LOG_ERROR("failed to make new instance of UpdateOperation."); + return nullptr; + } + napi_value jsUpdateOperation = nullptr; + napi_status status = napi_create_object(env, &jsUpdateOperation); + if (status != napi_ok) { + LOG_ERROR("JsDataShareExtAbility create object failed"); + return nullptr; + } + std::string valuesKey = "values"; + std::string presKey = "predicates"; + napi_value jsValueKey = DataShareJSUtils::Convert2JSValue(env, valuesKey); + napi_value jsPresKey = DataShareJSUtils::Convert2JSValue(env, presKey); + napi_set_property(env, jsUpdateOperation, jsValueKey, jsValueBucket); + napi_set_property(env, jsUpdateOperation, jsPresKey, jsPredicates); + return jsUpdateOperation; +} + bool MakeNapiColumn(napi_env env, napi_value &napiColumns, const std::vector &columns) { napi_status status = napi_create_array(env, &napiColumns); diff --git a/data_share/frameworks/native/proxy/include/data_share_manager_impl.h b/data_share/frameworks/native/proxy/include/data_share_manager_impl.h index 7f80397712b61d09a73c750612f46905dd161465..8b22e8f79815bfa78be32a136b1be0959c84dc20 100644 --- a/data_share/frameworks/native/proxy/include/data_share_manager_impl.h +++ b/data_share/frameworks/native/proxy/include/data_share_manager_impl.h @@ -20,16 +20,19 @@ #include #include +#include "concurrent_map.h" #include "data_share_service_proxy.h" #include "data_share_errno.h" #include "idata_share_client_death_observer.h" #include "iremote_object.h" #include "refbase.h" +#include "system_ability_status_change_stub.h" namespace OHOS { class ExecutorPool; namespace DataShare { class DataShareKvServiceProxy; +class GeneralControllerServiceImpl; class DataShareManagerImpl { public: static DataShareManagerImpl* GetInstance(); @@ -58,6 +61,30 @@ public: DataShareManagerImpl *owner_; }; + class DataShareClientStatusChangeStub : public SystemAbilityStatusChangeStub { + public: + explicit DataShareClientStatusChangeStub(DataShareManagerImpl *owner) : owner_(owner) + { + } + void OnAddSystemAbility(int32_t systemAbilityId, const std::string& deviceId) override + { + if (owner_ != nullptr) { + owner_->OnAddSystemAbility(systemAbilityId, deviceId); + } + } + + void OnRemoveSystemAbility(int32_t systemAbilityId, const std::string& deviceId) override + { + } + private: + DataShareManagerImpl *owner_; + }; + + void SetRegisterCallback(GeneralControllerServiceImpl* ptr, std::function registerCallback); + + void RemoveRegisterCallback(GeneralControllerServiceImpl* ptr); + + void OnAddSystemAbility(int32_t systemAbilityId, const std::string& deviceId); private: DataShareManagerImpl(); @@ -86,6 +113,7 @@ private: std::shared_ptr pool_; std::function)> deathCallback_ = {}; sptr clientDeathObserverPtr_; + ConcurrentMap> observers_; }; } } // namespace OHOS::DataShare diff --git a/data_share/frameworks/native/proxy/include/data_share_service_proxy.h b/data_share/frameworks/native/proxy/include/data_share_service_proxy.h index ded0ea8a2fc4e2c6d4ac56e958acdc50374437d4..06cce528477326f4f0f8cfa9ac9588b27808791b 100644 --- a/data_share/frameworks/native/proxy/include/data_share_service_proxy.h +++ b/data_share/frameworks/native/proxy/include/data_share_service_proxy.h @@ -72,6 +72,12 @@ public: int SetSilentSwitch(const Uri &uri, bool enable) override; bool IsSilentProxyEnable(const std::string &uri) override; + + int RegisterObserver(const Uri &uri, + const sptr &dataObserver) override; + + int UnRegisterObserver(const Uri &uri, + const sptr &dataObserver) override; private: static inline BrokerDelegator delegator_; diff --git a/data_share/frameworks/native/proxy/src/data_share_manager_impl.cpp b/data_share/frameworks/native/proxy/src/data_share_manager_impl.cpp index b9d4ff2ecf67a8bb985df498313fc15358169573..994df0ebe2affc972afa0d0e6d3ca4faa6220a0b 100644 --- a/data_share/frameworks/native/proxy/src/data_share_manager_impl.cpp +++ b/data_share/frameworks/native/proxy/src/data_share_manager_impl.cpp @@ -45,6 +45,13 @@ DataShareManagerImpl* DataShareManagerImpl::GetInstance() if (manager_ == nullptr) { LOG_ERROR("DataShareManagerImpl: GetInstance failed"); } + auto saManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (saManager == nullptr) { + LOG_ERROR("Failed to get saMgrProxy."); + return manager_; + } + sptr callback(new DataShareClientStatusChangeStub(manager_)); + saManager->SubscribeSystemAbility(DISTRIBUTED_KV_DATA_SERVICE_ABILITY_ID, callback); return manager_; } @@ -200,5 +207,31 @@ void DataShareManagerImpl::OnRemoteDied() } LOG_DEBUG("create scheduler success"); } + +void DataShareManagerImpl::SetRegisterCallback(GeneralControllerServiceImpl* ptr, + std::function registerCallback) +{ + observers_.ComputeIfAbsent(ptr, [®isterCallback](const GeneralControllerServiceImpl*) { + return std::move(registerCallback); + }); +} + +void DataShareManagerImpl::RemoveRegisterCallback(GeneralControllerServiceImpl* ptr) +{ + observers_.Erase(ptr); +} + +void DataShareManagerImpl::OnAddSystemAbility(int32_t systemAbilityId, const std::string& deviceId) +{ + if (systemAbilityId != DISTRIBUTED_KV_DATA_SERVICE_ABILITY_ID) { + LOG_ERROR("SystemAbilityId must be DISTRIBUTED_KV_DATA_SERVICE_ABILITY_ID, but it is %{public}d", + systemAbilityId); + return; + } + observers_.ForEach([](const auto &, auto &callback) { + callback(); + return false; + }); +} } } \ No newline at end of file diff --git a/data_share/frameworks/native/proxy/src/data_share_service_proxy.cpp b/data_share/frameworks/native/proxy/src/data_share_service_proxy.cpp index 360151335ea8a0cf85a7c30a07381842ed53bd47..916f1be14bfd1b98aa47d2b6af724fe1ca9cca92 100644 --- a/data_share/frameworks/native/proxy/src/data_share_service_proxy.cpp +++ b/data_share/frameworks/native/proxy/src/data_share_service_proxy.cpp @@ -15,8 +15,10 @@ #include "data_share_service_proxy.h" +#include "data_ability_observer_interface.h" #include "datashare_itypes_utils.h" #include "datashare_log.h" +#include "datashare_string_utils.h" #include "ishared_result_set.h" namespace OHOS { @@ -519,5 +521,61 @@ bool DataShareServiceProxy::IsSilentProxyEnable(const std::string &uri) } return enable; } + +int DataShareServiceProxy::RegisterObserver(const Uri &uri, const sptr &dataObserver) +{ + if (dataObserver == nullptr) { + LOG_ERROR("DataObserver is nullptr, uri:%{public}s", + DataShareStringUtils::Anonymous(uri.ToString()).c_str()); + return DATA_SHARE_ERROR; + } + MessageParcel data; + if (!data.WriteInterfaceToken(IDataShareService::GetDescriptor())) { + LOG_ERROR("Write interface token failed"); + return DATA_SHARE_ERROR; + } + if (!ITypesUtil::Marshal(data, uri.ToString(), dataObserver)) { + LOG_ERROR("Failed to marshalling"); + return DATA_SHARE_ERROR; + } + MessageParcel reply; + MessageOption option; + int32_t err = Remote()->SendRequest( + static_cast(InterfaceCode::DATA_SHARE_SERVICE_CMD_REGISTER_OBSERVER), data, reply, option); + if (err != NO_ERROR) { + LOG_ERROR("RegisterObserver fail to sendRequest. uri:%{public}s, err:%{public}d", + DataShareStringUtils::Anonymous(uri.ToString()).c_str(), err); + return DATA_SHARE_ERROR; + } + return reply.ReadInt32(); +} + +int DataShareServiceProxy::UnRegisterObserver(const Uri &uri, const sptr &dataObserver) +{ + if (dataObserver == nullptr) { + LOG_ERROR("DataObserver is nullptr, uri:%{public}s", + DataShareStringUtils::Anonymous(uri.ToString()).c_str()); + return DATA_SHARE_ERROR; + } + MessageParcel data; + if (!data.WriteInterfaceToken(IDataShareService::GetDescriptor())) { + LOG_ERROR("Write interface token failed"); + return DATA_SHARE_ERROR; + } + if (!ITypesUtil::Marshal(data, uri.ToString(), dataObserver)) { + LOG_ERROR("Failed to Marshalling"); + return DATA_SHARE_ERROR; + } + MessageParcel reply; + MessageOption option; + int32_t err = Remote()->SendRequest( + static_cast(InterfaceCode::DATA_SHARE_SERVICE_CMD_UNREGISTER_OBSERVER), data, reply, option); + if (err != NO_ERROR) { + LOG_ERROR("UnRegisterObserver fail to sendRequest. uri: %{public}s, err: %{public}d", + DataShareStringUtils::Anonymous(uri.ToString()).c_str(), err); + return DATA_SHARE_ERROR; + } + return reply.ReadInt32(); +} } // namespace DataShare } // namespace OHOS diff --git a/data_share/interfaces/inner_api/BUILD.gn b/data_share/interfaces/inner_api/BUILD.gn index b1eda91db0a8a6a7e44b5cf0f84d20e04110a2bc..343d4ebc5cca33f6600aff122bb643497a9992c6 100644 --- a/data_share/interfaces/inner_api/BUILD.gn +++ b/data_share/interfaces/inner_api/BUILD.gn @@ -81,6 +81,8 @@ datashare_consumer_external_deps = [ "c_utils:utils", "common_event_service:cesfwk_innerkits", "hilog:libhilog", + "hitrace:hitrace_meter", + "hitrace:libhitracechain", "ipc:ipc_js", "ipc:ipc_single", "samgr:samgr_proxy", @@ -94,6 +96,7 @@ ohos_shared_library("datashare_consumer") { debug = false } include_dirs = [ + "${datashare_common_native_path}/include", "${kvstore_base_path}/frameworks/common", "${kvstore_base_path}/interfaces/innerkits/distributeddata/include", ] @@ -127,6 +130,7 @@ ohos_shared_library("datashare_provider") { ] sources = [ + "${datashare_common_native_path}/src/datashare_string_utils.cpp", "${datashare_native_provider_path}/src/datashare_ext_ability.cpp", "${datashare_native_provider_path}/src/datashare_ext_ability_context.cpp", "${datashare_native_provider_path}/src/datashare_stub.cpp", @@ -205,6 +209,7 @@ ohos_static_library("datashare_consumer_static") { debug = false } include_dirs = [ + "${datashare_common_native_path}/include", "${kvstore_base_path}/frameworks/common", "${kvstore_base_path}/interfaces/innerkits/distributeddata/include", ] diff --git a/data_share/interfaces/inner_api/common/include/datashare_operation_statement.h b/data_share/interfaces/inner_api/common/include/datashare_operation_statement.h index f5735e14ffe4774d74229594b01257e4cca9f05c..a4688bca674bb8c73ea452d7af9f4543c8cdff3c 100644 --- a/data_share/interfaces/inner_api/common/include/datashare_operation_statement.h +++ b/data_share/interfaces/inner_api/common/include/datashare_operation_statement.h @@ -27,6 +27,17 @@ enum class Operation : int32_t { DELETE, }; +struct UpdateOperation { + DataShareValuesBucket valuesBucket; + DataSharePredicates predicates; +}; +using UpdateOperations = std::map>; + +struct BatchUpdateResult { + std::string uri; + std::vector codes; +}; + struct OperationStatement { Operation operationType; std::string uri; diff --git a/data_share/interfaces/inner_api/consumer/include/datashare_helper.h b/data_share/interfaces/inner_api/consumer/include/datashare_helper.h index c0da2ed8a8e402f3daf05912979b3025fb717046..7589c458fb06a2f70265bab10a55cf1586956874 100644 --- a/data_share/interfaces/inner_api/consumer/include/datashare_helper.h +++ b/data_share/interfaces/inner_api/consumer/include/datashare_helper.h @@ -171,6 +171,16 @@ public: */ virtual int Update(Uri &uri, const DataSharePredicates &predicates, const DataShareValuesBucket &value) = 0; + /** + * @brief Batch updates data records in the database. + * + * @param updateOperations Indicates the param of data to update. + * @param results Indicates the number of data records updated. + * + * @return Return the execution results of batch updates. + */ + virtual int BatchUpdate(const UpdateOperations &operations, std::vector &results) = 0; + /** * @brief Deletes one or more data records from the database. * diff --git a/data_share/test/native/BUILD.gn b/data_share/test/native/BUILD.gn index 081f07a85bae6506210ea8dfec8dbf15b7fae025..7d5c3f8be9a2f97b150fb7ab3450451cb55fc6e0 100644 --- a/data_share/test/native/BUILD.gn +++ b/data_share/test/native/BUILD.gn @@ -105,6 +105,7 @@ ohos_unittest("SlientAccessTest") { "ability_base:zuri", "ability_runtime:ability_manager", "ability_runtime:abilitykit_native", + "ability_runtime:dataobs_manager", "access_token:libaccesstoken_sdk", "access_token:libnativetoken", "access_token:libtoken_setproc", diff --git a/data_share/test/native/unittest/mediadatashare_test/src/slientaccess_test.cpp b/data_share/test/native/unittest/mediadatashare_test/src/slientaccess_test.cpp index 2edbad7e20f51428f26fb0d4fd7f6a20f5a7daa4..dd1258e5906cbf15dcf0959d95d546c36857499f 100644 --- a/data_share/test/native/unittest/mediadatashare_test/src/slientaccess_test.cpp +++ b/data_share/test/native/unittest/mediadatashare_test/src/slientaccess_test.cpp @@ -16,6 +16,7 @@ #include #include "accesstoken_kit.h" +#include "data_ability_observer_stub.h" #include "datashare_helper.h" #include "datashare_log.h" #include "hap_token_info.h" @@ -39,11 +40,38 @@ public: protected: static constexpr const char *DATA_SHARE_URI = "datashare:///com.acts.datasharetest"; static constexpr const char *SLIENT_ACCESS_URI = "datashare:///com.acts.datasharetest/entry/DB00/TBL00?Proxy=true"; + static constexpr const char *SLIENT_REGISTER_URI = "datashare:///com.acts.datasharetest/entry/DB00/" + "TBL02?Proxy=true"; std::string TBL_STU_NAME = "name"; std::string TBL_STU_AGE = "age"; static std::shared_ptr CreateDataShareHelper(int32_t saId, std::string uri); static std::shared_ptr g_slientAccessHelper; }; + +class IDataShareAbilityObserverTest : public AAFwk::DataAbilityObserverStub { +public: + IDataShareAbilityObserverTest() = default; + + ~IDataShareAbilityObserverTest() + {} + + void OnChange() + { + name = "OnChangeName"; + } + + std::string GetName() + { + return name; + } + + void SetName(std::string name) + { + this->name = name; + } +private: + std::string name; +}; std::shared_ptr SlientAccessTest::g_slientAccessHelper; std::shared_ptr SlientAccessTest::CreateDataShareHelper(int32_t saId, std::string uri) { @@ -182,5 +210,109 @@ HWTEST_F(SlientAccessTest, SlientAccess_Delete_Test_001, TestSize.Level0) EXPECT_EQ((retVal > 0), true); LOG_INFO("SlientAccess_Delete_Test_001::End"); } + +HWTEST_F(SlientAccessTest, SlientAccess_Register_Test_001, TestSize.Level0) +{ + LOG_INFO("SlientAccess_Register_Test_001::Start"); + auto helper = g_slientAccessHelper; + Uri uri(SLIENT_ACCESS_URI); + sptr dataObserver(new (std::nothrow) IDataShareAbilityObserverTest()); + dataObserver->SetName("zhangsan"); + helper->RegisterObserver(uri, dataObserver); + EXPECT_EQ(dataObserver->GetName(), "zhangsan"); + DataShare::DataShareValuesBucket valuesBucket; + std::string value = "lisi"; + valuesBucket.Put(TBL_STU_NAME, value); + int age = 25; + valuesBucket.Put(TBL_STU_AGE, age); + int retVal = helper->Insert(uri, valuesBucket); + EXPECT_EQ((retVal > 0), true); + EXPECT_EQ(dataObserver->GetName(), "OnChangeName"); + + DataShare::DataSharePredicates deletePredicates; + deletePredicates.EqualTo(TBL_STU_NAME, "lisi")->And()->EqualTo(TBL_STU_NAME, 25); + retVal = helper->Delete(uri, deletePredicates); + EXPECT_EQ((retVal >= 0), true); + helper->UnregisterObserver(uri, dataObserver); + LOG_INFO("SlientAccess_Register_Test_001::End"); +} + +HWTEST_F(SlientAccessTest, SlientAccess_RegisterErrorUri_Test_001, TestSize.Level0) +{ + LOG_INFO("SlientAccess_RegisterErrorUri_Test_001::Start"); + auto helper = g_slientAccessHelper; + Uri uri(SLIENT_ACCESS_URI); + sptr dataObserver(new (std::nothrow) IDataShareAbilityObserverTest()); + dataObserver->SetName("zhangsan"); + Uri uriRegister(SLIENT_REGISTER_URI); + helper->RegisterObserver(uriRegister, dataObserver); + EXPECT_EQ(dataObserver->GetName(), "zhangsan"); + DataShare::DataShareValuesBucket valuesBucket; + std::string value = "lisi"; + valuesBucket.Put(TBL_STU_NAME, value); + int age = 25; + valuesBucket.Put(TBL_STU_AGE, age); + int retVal = helper->Insert(uri, valuesBucket); + EXPECT_EQ((retVal > 0), true); + EXPECT_NE(dataObserver->GetName(), "OnChangeName"); + + DataShare::DataSharePredicates deletePredicates; + deletePredicates.EqualTo(TBL_STU_NAME, "lisi")->And()->EqualTo(TBL_STU_NAME, 25); + retVal = helper->Delete(uri, deletePredicates); + EXPECT_EQ((retVal >= 0), true); + helper->UnregisterObserver(uriRegister, dataObserver); + LOG_INFO("SlientAccess_RegisterErrorUri_Test_001::End"); +} + +HWTEST_F(SlientAccessTest, SlientAccess_NoRegister_Test_001, TestSize.Level0) +{ + LOG_INFO("SlientAccess_NoRegister_Test_001::Start"); + auto helper = g_slientAccessHelper; + Uri uri(SLIENT_ACCESS_URI); + sptr dataObserver(new (std::nothrow) IDataShareAbilityObserverTest()); + dataObserver->SetName("zhangsan"); + EXPECT_EQ(dataObserver->GetName(), "zhangsan"); + DataShare::DataShareValuesBucket valuesBucket; + std::string value = "lisi"; + valuesBucket.Put(TBL_STU_NAME, value); + int age = 25; + valuesBucket.Put(TBL_STU_AGE, age); + int retVal = helper->Insert(uri, valuesBucket); + EXPECT_EQ((retVal > 0), true); + EXPECT_NE(dataObserver->GetName(), "OnChangeName"); + + DataShare::DataSharePredicates deletePredicates; + deletePredicates.EqualTo(TBL_STU_NAME, "lisi")->And()->EqualTo(TBL_STU_NAME, 25); + retVal = helper->Delete(uri, deletePredicates); + EXPECT_EQ((retVal >= 0), true); + helper->UnregisterObserver(uri, dataObserver); + LOG_INFO("SlientAccess_NoRegister_Test_001::End"); +} + +HWTEST_F(SlientAccessTest, SlientAccess_NoRegister_Test_002, TestSize.Level0) +{ + LOG_INFO("SlientAccess_NoRegister_Test_002::Start"); + auto helper = g_slientAccessHelper; + Uri uri(SLIENT_ACCESS_URI); + sptr dataObserver(new (std::nothrow) IDataShareAbilityObserverTest()); + dataObserver->SetName("zhangsan"); + helper->RegisterObserver(uri, dataObserver); + helper->UnregisterObserver(uri, dataObserver); + EXPECT_EQ(dataObserver->GetName(), "zhangsan"); + DataShare::DataShareValuesBucket valuesBucket; + std::string value = "lisi"; + valuesBucket.Put(TBL_STU_NAME, value); + int age = 25; + valuesBucket.Put(TBL_STU_AGE, age); + int retVal = helper->Insert(uri, valuesBucket); + EXPECT_EQ((retVal > 0), true); + EXPECT_NE(dataObserver->GetName(), "OnChangeName"); + + DataShare::DataSharePredicates deletePredicates; + deletePredicates.EqualTo(TBL_STU_NAME, "lisi")->And()->EqualTo(TBL_STU_NAME, 25); + retVal = helper->Delete(uri, deletePredicates); + EXPECT_EQ((retVal >= 0), true); + LOG_INFO("SlientAccess_NoRegister_Test_002::End"); +} } // namespace DataShare } // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/BUILD.gn index c1b809b9ac0842f93ba868f61921cc4a080a456c..44bef8b3bc9d5823097aca5d3c1fb20fc768e627 100644 --- a/datamgr_service/services/distributeddataservice/adapter/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/BUILD.gn @@ -36,6 +36,7 @@ config("distributeddata_adapter_public_config") { "include", "${kv_store_path}/interfaces/innerkits/distributeddata/include/", "${kv_store_common_path}", + "${data_service_path}/framework/include", ] } @@ -53,6 +54,7 @@ ohos_shared_library("distributeddata_adapter") { configs = [ ":distributeddata_adapter_private_config" ] deps = [ + "${data_service_path}/framework:distributeddatasvcfwk", "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/adapter/account:distributeddata_account_static", "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/adapter/communicator:distributeddata_communicator_static", "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/adapter/dfx:distributeddata_dfx_static", diff --git a/datamgr_service/services/distributeddataservice/adapter/CMakeLists.txt b/datamgr_service/services/distributeddataservice/adapter/CMakeLists.txt index 19652a1460967b3418e59eae05f6340cae2662c0..3f76667f64ea9b96c5cda1173337b03054bb2dcc 100644 --- a/datamgr_service/services/distributeddataservice/adapter/CMakeLists.txt +++ b/datamgr_service/services/distributeddataservice/adapter/CMakeLists.txt @@ -40,7 +40,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/dfx/src) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../../utils_native/base/include) include(${MOCK_DIR}/include/CMakeLists.txt OPTIONAL) include(${KV_STORE_DIR}/interfaces/CMakeLists.txt OPTIONAL) -set(links secure mock distributeddb crypto) +set(links secure mock distributeddb crypto svcFwk) add_library(adapter SHARED ${adapterSrc}) target_link_libraries(adapter ${links}) diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/BUILD.gn b/datamgr_service/services/distributeddataservice/adapter/communicator/BUILD.gn index 31359ac626dc90546824a84682eaeca877925c7b..873e9ae5431f75da906f2267668cc1fe60782189 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/BUILD.gn @@ -51,11 +51,13 @@ ohos_static_library("distributeddata_communicator_static") { "${kv_store_distributeddb_path}/include", "${kv_store_distributeddb_path}/interfaces/include/relational", "${kv_store_path}/interfaces/innerkits/distributeddata/include", + "${data_service_path}/framework/include", ] cflags_cc = [ "-fvisibility=hidden" ] deps = [ + "${data_service_path}/framework:distributeddatasvcfwk", "../dfx:distributeddata_dfx_static", "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/adapter/utils:distributeddata_utils_static", ] diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/src/device_manager_adapter.cpp b/datamgr_service/services/distributeddataservice/adapter/communicator/src/device_manager_adapter.cpp index 6c69a44933a754cc10b9a26ee4d73c192d7d6242..705bfb3225fe0b7b1fc524781980cced64f22b57 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/src/device_manager_adapter.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/src/device_manager_adapter.cpp @@ -23,6 +23,7 @@ #include "net_conn_callback_stub.h" #include "net_conn_client.h" #include "net_handle.h" +#include "serializable/serializable.h" namespace OHOS::DistributedData { using namespace OHOS::DistributedHardware; @@ -31,6 +32,19 @@ using namespace OHOS::NetManagerStandard; using KvStoreUtils = OHOS::DistributedKv::KvStoreUtils; constexpr int32_t DM_OK = 0; constexpr const char *PKG_NAME = "ohos.distributeddata.service"; +static DeviceManagerAdapter::NetworkType Convert(NetManagerStandard::NetBearType bearType) +{ + switch (bearType) { + case NetManagerStandard::BEARER_WIFI: + return DeviceManagerAdapter::WIFI; + case NetManagerStandard::BEARER_CELLULAR: + return DeviceManagerAdapter::CELLULAR; + case NetManagerStandard::BEARER_ETHERNET: + return DeviceManagerAdapter::ETHERNET; + default: + return DeviceManagerAdapter::OTHER; + } +} class DataMgrDmStateCall final : public DistributedHardware::DeviceStateCallback { public: explicit DataMgrDmStateCall(DeviceManagerAdapter &dmAdapter) : dmAdapter_(dmAdapter) {} @@ -98,46 +112,68 @@ private: int32_t NetConnCallbackObserver::NetAvailable(sptr &netHandle) { ZLOGI("OnNetworkAvailable"); - dmAdapter_.SetNetAvailable(true); - dmAdapter_.Online(dmAdapter_.cloudDmInfo); return DistributedKv::SUCCESS; } int32_t NetConnCallbackObserver::NetUnavailable() { ZLOGI("OnNetworkUnavailable"); - dmAdapter_.SetNetAvailable(false); - return DistributedKv::SUCCESS; + dmAdapter_.SetNet(DeviceManagerAdapter::NONE); + return 0; } int32_t NetConnCallbackObserver::NetCapabilitiesChange(sptr &netHandle, const sptr &netAllCap) { ZLOGI("OnNetCapabilitiesChange"); - return DistributedKv::SUCCESS; + if (netHandle == nullptr || netAllCap == nullptr) { + return 0; + } + if (netAllCap->netCaps_.count(NetManagerStandard::NET_CAPABILITY_VALIDATED) && !netAllCap->bearerTypes_.empty()) { + dmAdapter_.SetNet(Convert(*netAllCap->bearerTypes_.begin())); + } else { + dmAdapter_.SetNet(DeviceManagerAdapter::NONE); + } + return 0; } int32_t NetConnCallbackObserver::NetConnectionPropertiesChange(sptr &netHandle, const sptr &info) { ZLOGI("OnNetConnectionPropertiesChange"); - return DistributedKv::SUCCESS; + return 0; } int32_t NetConnCallbackObserver::NetLost(sptr &netHandle) { ZLOGI("OnNetLost"); - dmAdapter_.SetNetAvailable(false); - dmAdapter_.Offline(dmAdapter_.cloudDmInfo); - return DistributedKv::SUCCESS; + dmAdapter_.SetNet(DeviceManagerAdapter::NONE); + return 0; } int32_t NetConnCallbackObserver::NetBlockStatusChange(sptr &netHandle, bool blocked) { ZLOGI("OnNetBlockStatusChange"); - return DistributedKv::SUCCESS; + return 0; } +struct DeviceExtraInfo final : public Serializable { + static constexpr int32_t OH_OS_TYPE = 10; + + int32_t OS_TYPE = OH_OS_TYPE; + + DeviceExtraInfo() {}; + ~DeviceExtraInfo() {}; + bool Marshal(json &node) const override + { + return SetValue(node[GET_NAME(OS_TYPE)], OS_TYPE); + }; + bool Unmarshal(const json &node) override + { + return GetValue(node, GET_NAME(OS_TYPE), OS_TYPE); + }; +}; + DeviceManagerAdapter::DeviceManagerAdapter() : cloudDmInfo({ "cloudDeviceId", "cloudDeviceName", 0, "cloudNetworkId", 0 }) { @@ -217,6 +253,13 @@ void DeviceManagerAdapter::Online(const DmDeviceInfo &info) ZLOGE("get device info fail"); return; } + syncTask_.Insert(dvInfo.uuid, dvInfo.uuid); + if (dvInfo.osType != OH_OS_TYPE) { + ZLOGI("[online] uuid:%{public}s, name:%{public}s, type:%{public}d is not oh device", + KvStoreUtils::ToBeAnonymous(dvInfo.uuid).c_str(), dvInfo.deviceName.c_str(), dvInfo.deviceType); + NotifyReadyEvent(dvInfo.uuid); + return; + } ZLOGI("[online] uuid:%{public}s, name:%{public}s, type:%{public}d", KvStoreUtils::ToBeAnonymous(dvInfo.uuid).c_str(), dvInfo.deviceName.c_str(), dvInfo.deviceType); SaveDeviceInfo(dvInfo, DeviceChangeType::DEVICE_ONLINE); @@ -241,7 +284,7 @@ void DeviceManagerAdapter::Online(const DmDeviceInfo &info) } executors_->Schedule(std::chrono::milliseconds(SYNC_TIMEOUT), [this, dvInfo]() { - TimeOut(dvInfo.uuid); + NotifyReadyEvent(dvInfo.uuid); }); for (const auto &item : observers) { // set compatible identify, sync service meta @@ -254,20 +297,6 @@ void DeviceManagerAdapter::Online(const DmDeviceInfo &info) } } -void DeviceManagerAdapter::TimeOut(const std::string uuid) -{ - if (uuid.empty()) { - ZLOGE("uuid empty!"); - return; - } - if (syncTask_.Contains(uuid) && uuid != CLOUD_DEVICE_UUID) { - ZLOGI("[TimeOutReadyEvent] uuid:%{public}s", KvStoreUtils::ToBeAnonymous(uuid).c_str()); - std::string event = R"({"extra": {"deviceId":")" + uuid + R"(" } })"; - DeviceManager::GetInstance().NotifyEvent(PKG_NAME, DmNotifyEvent::DM_NOTIFY_EVENT_ONDEVICEREADY, event); - } - syncTask_.Erase(uuid); -} - void DeviceManagerAdapter::NotifyReadyEvent(const std::string &uuid) { if (uuid.empty() || !syncTask_.Contains(uuid)) { @@ -275,6 +304,9 @@ void DeviceManagerAdapter::NotifyReadyEvent(const std::string &uuid) } syncTask_.Erase(uuid); + if (uuid == CLOUD_DEVICE_UUID) { + return; + } ZLOGI("[NotifyReadyEvent] uuid:%{public}s", KvStoreUtils::ToBeAnonymous(uuid).c_str()); std::string event = R"({"extra": {"deviceId":")" + uuid + R"(" } })"; DeviceManager::GetInstance().NotifyEvent(PKG_NAME, DmNotifyEvent::DM_NOTIFY_EVENT_ONDEVICEREADY, event); @@ -331,6 +363,11 @@ void DeviceManagerAdapter::OnReady(const DmDeviceInfo &info) ZLOGE("get device info fail"); return; } + if (dvInfo.osType != OH_OS_TYPE) { + ZLOGW("[OnReady] uuid:%{public}s, name:%{public}s, type:%{public}d is not oh device", + KvStoreUtils::ToBeAnonymous(dvInfo.uuid).c_str(), dvInfo.deviceName.c_str(), dvInfo.deviceType); + return; + } readyDevices_.InsertOrAssign(dvInfo.uuid, std::make_pair(DeviceState::DEVICE_ONREADY, dvInfo)); ZLOGI("[OnReady] uuid:%{public}s, name:%{public}s, type:%{public}d", KvStoreUtils::ToBeAnonymous(dvInfo.uuid).c_str(), dvInfo.deviceName.c_str(), dvInfo.deviceType); @@ -357,7 +394,16 @@ bool DeviceManagerAdapter::GetDeviceInfo(const DmDeviceInfo &dmInfo, DeviceInfo ZLOGW("uuid or udid empty"); return false; } - dvInfo = { uuid, udid, networkId, std::string(dmInfo.deviceName), dmInfo.deviceTypeId }; + if (uuid == CLOUD_DEVICE_UUID) { + dvInfo = { uuid, udid, networkId, std::string(dmInfo.deviceName), dmInfo.deviceTypeId, OH_OS_TYPE }; + return true; + } + DeviceExtraInfo deviceExtraInfo; + if (!DistributedData::Serializable::Unmarshall(dmInfo.extraData, deviceExtraInfo)) { + ZLOGE("Unmarshall failed, deviceExtraInfo:%{public}s", dmInfo.extraData.c_str()); + return false; + } + dvInfo = { uuid, udid, networkId, std::string(dmInfo.deviceName), dmInfo.deviceTypeId, deviceExtraInfo.OS_TYPE }; return true; } @@ -412,8 +458,16 @@ std::vector DeviceManagerAdapter::GetRemoteDevices() auto networkId = std::string(dmInfo.networkId); auto uuid = GetUuidByNetworkId(networkId); auto udid = GetUdidByNetworkId(networkId); + DeviceExtraInfo deviceExtraInfo; + if (!DistributedData::Serializable::Unmarshall(dmInfo.extraData, deviceExtraInfo)) { + ZLOGE("Unmarshall failed, deviceExtraInfo:%{public}s", dmInfo.extraData.c_str()); + continue; + } + if (deviceExtraInfo.OS_TYPE != OH_OS_TYPE) { + continue; + } DeviceInfo dvInfo = { std::move(uuid), std::move(udid), std::move(networkId), - std::string(dmInfo.deviceName), dmInfo.deviceTypeId }; + std::string(dmInfo.deviceName), dmInfo.deviceTypeId, deviceExtraInfo.OS_TYPE }; dvInfos.emplace_back(std::move(dvInfo)); } return dvInfos; @@ -436,6 +490,16 @@ bool DeviceManagerAdapter::IsDeviceReady(const std::string& id) return (it.first && it.second.first == DeviceState::DEVICE_ONREADY); } +bool DeviceManagerAdapter::IsOHOsType(const std::string& id) +{ + DeviceInfo dvInfo; + if (!deviceInfos_.Get(id, dvInfo)) { + InitDeviceInfo(); + return deviceInfos_.Get(id, dvInfo); + } + return true; +} + size_t DeviceManagerAdapter::GetOnlineSize() { return readyDevices_.Size(); @@ -501,9 +565,15 @@ DeviceInfo DeviceManagerAdapter::GetLocalDeviceInfo() if (uuid.empty()) { return {}; } - ZLOGI("[LocalDevice] uuid:%{public}s, name:%{public}s, type:%{public}d", KvStoreUtils::ToBeAnonymous(uuid).c_str(), - info.deviceName, info.deviceTypeId); - return { std::move(uuid), std::move(udid), std::move(networkId), std::string(info.deviceName), info.deviceTypeId }; + DeviceExtraInfo deviceExtraInfo; + if (!DistributedData::Serializable::Unmarshall(info.extraData, deviceExtraInfo)) { + ZLOGE("Unmarshall failed, deviceExtraInfo:%{public}s", info.extraData.c_str()); + return {}; + } + ZLOGI("[LocalDevice] uuid:%{public}s, name:%{public}s, type:%{public}d, osType:%{public}d", + KvStoreUtils::ToBeAnonymous(uuid).c_str(), info.deviceName, info.deviceTypeId, deviceExtraInfo.OS_TYPE); + return { std::move(uuid), std::move(udid), std::move(networkId), std::string(info.deviceName), info.deviceTypeId, + deviceExtraInfo.OS_TYPE }; } std::string DeviceManagerAdapter::GetUuidByNetworkId(const std::string &networkId) @@ -619,22 +689,52 @@ bool DeviceManagerAdapter::RegOnNetworkChange() bool DeviceManagerAdapter::IsNetworkAvailable() { - { - std::shared_lock lock(mutex_); - if (isNetAvailable_ || expireTime_ > std::chrono::steady_clock::now()) { - return isNetAvailable_; - } + if (defaultNetwork_ != NONE || expireTime_ > GetTimeStamp()) { + return defaultNetwork_ != NONE; } - NetHandle handle; - auto status = NetConnClient::GetInstance().GetDefaultNet(handle); - return SetNetAvailable(status == 0 && handle.GetNetId() != 0); + return RefreshNet() != NONE; +} + +DeviceManagerAdapter::NetworkType DeviceManagerAdapter::SetNet(NetworkType netWorkType) +{ + auto oldNet = defaultNetwork_; + bool ready = oldNet == NONE && netWorkType != NONE && (GetTimeStamp() - netLostTime_) > NET_LOST_DURATION; + bool offline = oldNet != NONE && netWorkType == NONE; + if (offline) { + netLostTime_ = GetTimeStamp(); + } + defaultNetwork_ = netWorkType; + expireTime_ = GetTimeStamp() + EFFECTIVE_DURATION; + if (ready) { + OnReady(cloudDmInfo); + } + if (offline) { + Offline(cloudDmInfo); + } + return netWorkType; } -bool DeviceManagerAdapter::SetNetAvailable(bool isNetAvailable) +DeviceManagerAdapter::NetworkType DeviceManagerAdapter::GetNetworkType(bool retrieve) { - std::unique_lock lock(mutex_); - isNetAvailable_ = isNetAvailable; - expireTime_ = std::chrono::steady_clock::now() + std::chrono::milliseconds(EFFECTIVE_DURATION); - return isNetAvailable_; + if (!retrieve) { + return defaultNetwork_; + } + return RefreshNet(); +} + +DeviceManagerAdapter::NetworkType DeviceManagerAdapter::RefreshNet() +{ + NetHandle handle; + auto status = NetConnClient::GetInstance().GetDefaultNet(handle); + if (status != 0 || handle.GetNetId() == 0) { + return SetNet(NONE); + } + NetAllCapabilities capabilities; + status = NetConnClient::GetInstance().GetNetCapabilities(handle, capabilities); + if (status != 0 || !capabilities.netCaps_.count(NetManagerStandard::NET_CAPABILITY_VALIDATED) || + capabilities.bearerTypes_.empty()) { + return SetNet(NONE); + } + return SetNet(Convert(*capabilities.bearerTypes_.begin())); } } // namespace OHOS::DistributedData diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_adapter.h b/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_adapter.h index 09ad9fa6954789ab19a5d9d5d6d65c68c8f63c70..e9b69825e9c2a56404d9452c5cb179bca9a9f886 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_adapter.h +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_adapter.h @@ -28,7 +28,6 @@ #include "app_data_change_listener.h" #include "app_device_change_listener.h" #include "block_data.h" -#include "session.h" #include "socket.h" #include "softbus_bus_center.h" #include "softbus_client.h" 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 3915b30a62b49ae1b86f2d9f9a67c58f00813f22..ea27a878e5984c6e388399450b153b0009d81972 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 @@ -23,7 +23,6 @@ #include "log_print.h" #include "reporter.h" #include "securec.h" -#include "session.h" #include "softbus_adapter.h" #include "softbus_bus_center.h" #include "softbus_error_code.h" @@ -57,6 +56,7 @@ public: // notify all listeners when received message static void NotifyDataListeners(const uint8_t *data, const int size, const std::string &deviceId, const PipeInfo &pipeInfo); + static std::string GetPipeId(const std::string &name); private: static SoftBusAdapter *softBusAdapter_; @@ -436,11 +436,17 @@ void AppDataListenerWrap::OnServerBytesReceived(int32_t socket, const void *data return; }; std::string peerDevUuid = DmAdapter::GetInstance().GetUuidByNetworkId(std::string(info.networkId)); + if (!DmAdapter::GetInstance().IsOHOsType(peerDevUuid)) { + ZLOGD("[OnBytesReceived] Not OH device socket:%{public}d, peer name:%{public}s, peer devId:%{public}s," + "data len:%{public}u", socket, info.name.c_str(), KvStoreUtils::ToBeAnonymous(peerDevUuid).c_str(), + dataLen); + return; + } ZLOGD("[OnBytesReceived] socket:%{public}d, peer name:%{public}s, peer devId:%{public}s, data len:%{public}u", socket, info.name.c_str(), KvStoreUtils::ToBeAnonymous(peerDevUuid).c_str(), dataLen); - std::string pipeId = info.name; + std::string pipeId = GetPipeId(info.name); if (pipeId.empty()) { ZLOGE("pipId is invalid"); return; @@ -449,6 +455,15 @@ void AppDataListenerWrap::OnServerBytesReceived(int32_t socket, const void *data NotifyDataListeners(reinterpret_cast(data), dataLen, peerDevUuid, { pipeId, "" }); } +std::string AppDataListenerWrap::GetPipeId(const std::string &name) +{ + auto pos = name.find('_'); + if (pos != std::string::npos) { + return name.substr(0, pos); + } + return name; +} + void AppDataListenerWrap::NotifyDataListeners(const uint8_t *data, const int size, const std::string &deviceId, const PipeInfo &pipeInfo) { 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 4a18383f372ad67186ed842e5c319f6a1974d54a..c972c9e42ced8db336d78e72e163b1206ee16142 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_client.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_client.cpp @@ -95,7 +95,8 @@ Status SoftBusClient::OpenConnect(const ISocketListener *listener) socketInfo.peerName = const_cast(peerName.c_str()); std::string networkId = DmAdapter::GetInstance().ToNetworkID(device_.deviceId); socketInfo.peerNetworkId = const_cast(networkId.c_str()); - socketInfo.name = const_cast(peerName.c_str()); + std::string clientName = (pipe_.pipeId + "_client_" + socketInfo.peerNetworkId).substr(0, 64); + socketInfo.name = const_cast(clientName.c_str()); std::string pkgName = "ohos.distributeddata"; socketInfo.pkgName = pkgName.data(); socketInfo.dataType = DATA_TYPE_BYTES; diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_client.h b/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_client.h index acc343e9a7155cd5772033d78bef325d64ed0e1d..74520fc9a2392b4323d5b0a6d2d53bbf2f6ec0a3 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_client.h +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_client.h @@ -22,7 +22,6 @@ #include "commu_types.h" #include "executor_pool.h" -#include "session.h" #include "socket.h" #include "softbus_bus_center.h" namespace OHOS::AppDistributedKv { diff --git a/datamgr_service/services/distributeddataservice/adapter/include/communicator/commu_types.h b/datamgr_service/services/distributeddataservice/adapter/include/communicator/commu_types.h index 8f60d6d01778162761161400699a0d10f9b8687c..1b51780382596d9f4218383b7e815966894d0b6d 100644 --- a/datamgr_service/services/distributeddataservice/adapter/include/communicator/commu_types.h +++ b/datamgr_service/services/distributeddataservice/adapter/include/communicator/commu_types.h @@ -26,6 +26,7 @@ struct API_EXPORT DeviceInfo { std::string networkId; std::string deviceName; uint32_t deviceType; + int32_t osType; }; enum RouteType : int32_t { diff --git a/datamgr_service/services/distributeddataservice/adapter/include/communicator/device_manager_adapter.h b/datamgr_service/services/distributeddataservice/adapter/include/communicator/device_manager_adapter.h index 295033a5c585165d93ec2f90e3c5d51f644e23e8..3fd6556ec20da492548f4c005965f4b8d10a39d1 100644 --- a/datamgr_service/services/distributeddataservice/adapter/include/communicator/device_manager_adapter.h +++ b/datamgr_service/services/distributeddataservice/adapter/include/communicator/device_manager_adapter.h @@ -37,6 +37,13 @@ public: DEVICE_ONREADY, DEVICE_BUTT }; + enum NetworkType { + NONE, + CELLULAR, + WIFI, + ETHERNET, + OTHER + }; using DmDeviceInfo = OHOS::DistributedHardware::DmDeviceInfo; using DeviceInfo = OHOS::AppDistributedKv::DeviceInfo; using PipeInfo = OHOS::AppDistributedKv::PipeInfo; @@ -54,6 +61,7 @@ public: std::vector GetRemoteDevices(); std::vector GetOnlineDevices(); bool IsDeviceReady(const std::string &id); + bool IsOHOsType(const std::string &id); size_t GetOnlineSize(); DeviceInfo GetDeviceInfo(const std::string &id); std::string GetUuidByNetworkId(const std::string &networkId); @@ -66,6 +74,7 @@ public: std::string ToNetworkID(const std::string &id); void NotifyReadyEvent(const std::string &uuid); bool IsNetworkAvailable(); + NetworkType GetNetworkType(bool retrieve = false); friend class DataMgrDmStateCall; friend class NetConnCallbackObserver; @@ -74,7 +83,8 @@ private: ~DeviceManagerAdapter(); std::function RegDevCallback(); bool RegOnNetworkChange(); - bool SetNetAvailable(bool isNetAvailable); + NetworkType SetNet(NetworkType netWorkType); + NetworkType RefreshNet(); bool GetDeviceInfo(const DmDeviceInfo &dmInfo, DeviceInfo &dvInfo); void SaveDeviceInfo(const DeviceInfo &deviceInfo, const AppDistributedKv::DeviceChangeType &type); void InitDeviceInfo(bool onlyCache = true); @@ -84,8 +94,13 @@ private: void Offline(const DmDeviceInfo &info); void OnChanged(const DmDeviceInfo &info); void OnReady(const DmDeviceInfo &info); - void TimeOut(const std::string uuid); std::vector GetObservers(); + static inline uint64_t GetTimeStamp() + { + return std::chrono::duration_cast( + std::chrono::steady_clock::now().time_since_epoch()) + .count(); + } std::mutex devInfoMutex_ {}; DeviceInfo localInfo_ {}; @@ -94,12 +109,14 @@ private: LRUBucket deviceInfos_ {64}; static constexpr size_t TIME_TASK_CAPACITY = 50; static constexpr int32_t SYNC_TIMEOUT = 60 * 1000; // ms + static constexpr int32_t OH_OS_TYPE = 10; ConcurrentMap syncTask_ {}; std::shared_ptr executors_; - mutable std::shared_mutex mutex_; static constexpr int32_t EFFECTIVE_DURATION = 30 * 1000; // ms - Time expireTime_ = std::chrono::steady_clock::now(); - bool isNetAvailable_ = false; + static constexpr int32_t NET_LOST_DURATION = 10 * 1000; // ms + uint64_t expireTime_ = GetTimeStamp(); + uint64_t netLostTime_ = GetTimeStamp(); + NetworkType defaultNetwork_ = NONE; ConcurrentMap> readyDevices_; }; } // namespace DistributedData diff --git a/datamgr_service/services/distributeddataservice/app/src/kvstore_data_service.cpp b/datamgr_service/services/distributeddataservice/app/src/kvstore_data_service.cpp index 45409734eb65867b5e0c41a6f112f7321bb2bcae..5f02dd48196da6c19187864234d41c683ddb53ce 100644 --- a/datamgr_service/services/distributeddataservice/app/src/kvstore_data_service.cpp +++ b/datamgr_service/services/distributeddataservice/app/src/kvstore_data_service.cpp @@ -569,11 +569,8 @@ KvStoreDataService::KvStoreClientDeathObserverImpl::KvStoreClientDeathObserverIm KvStoreDataService::KvStoreClientDeathObserverImpl::KvStoreClientDeathObserverImpl( KvStoreDataService::KvStoreClientDeathObserverImpl &&impl) - : dataService_(impl.dataService_) + : uid_(impl.uid_), pid_(impl.pid_), token_(impl.token_), dataService_(impl.dataService_) { - uid_ = impl.uid_; - pid_ = impl.pid_; - token_ = impl.token_; appId_.appId = std::move(impl.appId_.appId); impl.Reset(); } diff --git a/datamgr_service/services/distributeddataservice/framework/BUILD.gn b/datamgr_service/services/distributeddataservice/framework/BUILD.gn index aa0df79dd0afd49eaae79fe29e9a51f226cb5a5c..a589f6c6a1aa7cade180ca5a78e98ebae66fca15 100644 --- a/datamgr_service/services/distributeddataservice/framework/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/framework/BUILD.gn @@ -62,6 +62,7 @@ ohos_shared_library("distributeddatasvcfwk") { "cloud/sharing_center.cpp", "cloud/subscription.cpp", "cloud/sync_event.cpp", + "cloud/sync_strategy.cpp", "directory/directory_manager.cpp", "dump/dump_manager.cpp", "eventcenter/event.cpp", diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_event.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_event.cpp index 8146446d3a983f1a9a38632879a71367e5c4b185..bfaf3c9eb16bf519dc41416ba55176eede336adc 100644 --- a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_event.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_event.cpp @@ -16,12 +16,12 @@ #include "cloud/cloud_event.h" namespace OHOS::DistributedData { -CloudEvent::CloudEvent(int32_t evtId, CloudEvent::StoreInfo storeInfo) +CloudEvent::CloudEvent(int32_t evtId, StoreInfo storeInfo) : Event(evtId), storeInfo_(std::move(storeInfo)) { } -const CloudEvent::StoreInfo& CloudEvent::GetStoreInfo() const +const StoreInfo& CloudEvent::GetStoreInfo() const { return storeInfo_; } 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 1c1ee97ec6d0bef80a7f5b7c95c9c88a5fc190b8..0ed24b9c816f664fe7abd6ef75a764ea9e896490 100644 --- a/datamgr_service/services/distributeddataservice/framework/cloud/make_query_event.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/make_query_event.cpp @@ -16,7 +16,7 @@ #include "cloud/make_query_event.h" namespace OHOS::DistributedData { -MakeQueryEvent::MakeQueryEvent(CloudEvent::StoreInfo storeInfo, +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), diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/sync_strategy.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/sync_strategy.cpp new file mode 100644 index 0000000000000000000000000000000000000000..15a08fc812f8f25f606d242582cbc39f5507197d --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/cloud/sync_strategy.cpp @@ -0,0 +1,28 @@ +/* + * 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 "cloud/sync_strategy.h" +namespace OHOS::DistributedData { +int32_t SyncStrategy::CheckSyncAction(const StoreInfo& storeInfo) +{ + return 0; +} + +std::shared_ptr SyncStrategy::SetNext(std::shared_ptr next) +{ + next_ = next; + return next_; +} +} 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 9ce38785cb00df0d1ba45e27f960e889b2c477f1..19837945dea7a0438f1295cbf9df31902f7fcc0b 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_event.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_event.h @@ -18,6 +18,7 @@ #include #include "eventcenter/event.h" +#include "store/store_info.h" namespace OHOS::DistributedData { class API_EXPORT CloudEvent : public Event { @@ -33,15 +34,6 @@ public: CLOUD_BUTT }; - struct StoreInfo { - uint32_t tokenId = 0; - std::string bundleName; - std::string storeName; - int32_t instanceId = 0; - int32_t user = 0; - std::string deviceId; - }; - CloudEvent(int32_t evtId, StoreInfo storeInfo); ~CloudEvent() = default; const StoreInfo& GetStoreInfo() const; diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/sync_strategy.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/sync_strategy.h new file mode 100644 index 0000000000000000000000000000000000000000..843237183ee314258d702203cf62f04356c01265 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/sync_strategy.h @@ -0,0 +1,31 @@ +/* + * 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_SERVICES_FRAMEWORK_CLOUD_SYNC_STRATEGY_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_SYNC_STRATEGY_H +#include "serializable/serializable.h" +#include "store/store_info.h" +namespace OHOS::DistributedData { +class API_EXPORT SyncStrategy { +public: + virtual ~SyncStrategy() = default; + 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_; +}; +} +#endif //OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_SYNC_STRATEGY_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/error/general_error.h b/datamgr_service/services/distributeddataservice/framework/include/error/general_error.h index b88501538ea2860e63922b825814b5c49ade9d06..90425a12b67df7fc2f6295abec31395852b79d53 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/error/general_error.h +++ b/datamgr_service/services/distributeddataservice/framework/include/error/general_error.h @@ -24,6 +24,7 @@ enum GeneralError : int32_t { E_LOCKED_BY_OTHERS, E_RECODE_LIMIT_EXCEEDED, E_NO_SPACE_FOR_ASSET, + E_BLOCKED_BY_NETWORK_STRATEGY, E_BUSY, E_INVALID_ARGS, E_NOT_INIT, diff --git a/datamgr_service/services/distributeddataservice/framework/include/snapshot/machine_status.h b/datamgr_service/services/distributeddataservice/framework/include/snapshot/machine_status.h index 8d4aa0bf9a0c0bd8ac5b27edcd9ba1625fb98f0b..e7c83aff8d76457639eec964ff3e7eedcbcb3eb4 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/snapshot/machine_status.h +++ b/datamgr_service/services/distributeddataservice/framework/include/snapshot/machine_status.h @@ -50,14 +50,6 @@ struct AssetBindInfo { std::string field; std::string assetName; }; - -struct StoreInfo { - uint32_t tokenId = 0; - int32_t instanceId = 0; - int32_t user; - std::string bundleName; - std::string storeName; -}; } // namespace DistributedData } // namespace OHOS #endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_SNAPSHOT_MACHINE_STATUS_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/snapshot/snapshot.h b/datamgr_service/services/distributeddataservice/framework/include/snapshot/snapshot.h index 6cfbbfcf926a93457c3768064c13f57dd6658049..8a9fa7eef25338ffde134d0fa883dc2ffe32d085 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/snapshot/snapshot.h +++ b/datamgr_service/services/distributeddataservice/framework/include/snapshot/snapshot.h @@ -17,6 +17,7 @@ #define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_SNAPSHOT_SNAPSHOT_H #include "machine_status.h" #include "store/general_value.h" +#include "store/store_info.h" #include "visibility.h" namespace OHOS { namespace DistributedData { diff --git a/datamgr_service/services/distributeddataservice/framework/include/store/store_info.h b/datamgr_service/services/distributeddataservice/framework/include/store/store_info.h new file mode 100644 index 0000000000000000000000000000000000000000..8138955aaabd97e38a5bc4c431a8499c5c63c398 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/include/store/store_info.h @@ -0,0 +1,31 @@ +/* +* 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_SERVICES_FRAMEWORK_STORE_STORE_INFO_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_STORE_INFO_H + +#include + +namespace OHOS::DistributedData { +struct StoreInfo { + uint32_t tokenId = 0; + std::string bundleName; + std::string storeName; + int32_t instanceId = 0; + int32_t user = 0; + std::string deviceId; +}; +} // namespace OHOS::DistributedData +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_STORE_INFO_H diff --git a/datamgr_service/services/distributeddataservice/framework/store/auto_cache.cpp b/datamgr_service/services/distributeddataservice/framework/store/auto_cache.cpp index b4f8647c6096bfd3a86f16641f27f4759ce9e436..b7a5b7d1daa74e6458073422de5844316890c0cb 100644 --- a/datamgr_service/services/distributeddataservice/framework/store/auto_cache.cpp +++ b/datamgr_service/services/distributeddataservice/framework/store/auto_cache.cpp @@ -227,11 +227,11 @@ bool AutoCache::Delegate::Close() { std::unique_lock lock(mutex_); if (store_ != nullptr) { - store_->Unwatch(Origin::ORIGIN_ALL, *this); auto status = store_->Close(); if (status == Error::E_BUSY) { return false; } + store_->Unwatch(Origin::ORIGIN_ALL, *this); } return true; } diff --git a/datamgr_service/services/distributeddataservice/service/BUILD.gn b/datamgr_service/services/distributeddataservice/service/BUILD.gn index 0bf302b912ba0d7aa628ee7b6eaabd6e171e31e6..98d29c081683101d98826d1d82c4a7e9ba346860 100644 --- a/datamgr_service/services/distributeddataservice/service/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/BUILD.gn @@ -77,6 +77,8 @@ ohos_shared_library("distributeddatasvc") { "cloud/cloud_types_util.cpp", "cloud/cloud_value_util.cpp", "cloud/sync_manager.cpp", + "cloud/sync_strategies/network_sync_strategy.cpp", + "common/common_types_utils.cpp", "common/value_proxy.cpp", "config/src/config_factory.cpp", "config/src/model/backup_config.cpp", diff --git a/datamgr_service/services/distributeddataservice/service/CMakeLists.txt b/datamgr_service/services/distributeddataservice/service/CMakeLists.txt index a6c9ff80ef73b44fd778cfe889f6e500737c5d5c..bdcb5dab321a34903e63f9c7c470b00eb73162cb 100644 --- a/datamgr_service/services/distributeddataservice/service/CMakeLists.txt +++ b/datamgr_service/services/distributeddataservice/service/CMakeLists.txt @@ -14,6 +14,7 @@ set(KV_STORE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../../kv_store") aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/backup/src serviceSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/bootstrap/src serviceSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/cloud serviceSrc) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/cloud/sync_strategies serviceSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/common serviceSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/config/src serviceSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/config/src/model serviceSrc) @@ -46,6 +47,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/crypto/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/bootstrap/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/permission/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/matrix/include) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/cloud/sync_strategies) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/data_share/common) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/data_share/data) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/data_share/strategies/data_proxy) @@ -64,7 +66,6 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../../kv_store/frameworks/ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../../relational_store/interfaces/inner_api/rdb/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../../relational_store/interfaces/inner_api/common_type/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../../data_share/frameworks/native/common/include) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../../data_share/frameworks/native/common/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../../data_object/frameworks/innerkitsimpl/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../../udmf/framework/common) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../../udmf/framework/innerkitsimpl/data) 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 960d9ca4678ad62d0f3e0429a8d41a9796c0bc1a..435a1ae2f5b62347b332dbf2b5726c5d6edb8647 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp @@ -34,10 +34,12 @@ #include "metadata/meta_data_manager.h" #include "rdb_cloud_data_translate.h" #include "rdb_types.h" +#include "relational_store_manager.h" #include "runtime_config.h" #include "store/auto_cache.h" #include "store/general_store.h" #include "sync_manager.h" +#include "sync_strategies/network_sync_strategy.h" #include "utils/anonymous.h" #include "values_bucket.h" namespace OHOS::CloudData { @@ -50,6 +52,9 @@ using DmAdapter = OHOS::DistributedData::DeviceManagerAdapter; using Account = OHOS::DistributedKv::AccountDelegate; using AccessTokenKit = Security::AccessToken::AccessTokenKit; __attribute__((used)) CloudServiceImpl::Factory CloudServiceImpl::factory_; +const CloudServiceImpl::SaveStrategy CloudServiceImpl::STRATEGY_SAVERS[Strategy::STRATEGY_BUTT] = { + &CloudServiceImpl::SaveNetworkStrategy +}; CloudServiceImpl::Factory::Factory() noexcept { @@ -321,6 +326,138 @@ int32_t CloudServiceImpl::NotifyDataChange(const std::string &eventId, const std return SUCCESS; } +std::map CloudServiceImpl::ExecuteStatistics(const std::string &storeId, + const CloudInfo &cloudInfo, const SchemaMeta &schemaMeta) +{ + std::map result; + for (auto& database : schemaMeta.databases) { + if (storeId.empty() || database.alias == storeId) { + StoreMetaData meta; + meta.bundleName = schemaMeta.bundleName; + meta.storeId = database.name; + meta.user = std::to_string(cloudInfo.user); + meta.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + auto it = cloudInfo.apps.find(schemaMeta.bundleName); + if (it == cloudInfo.apps.end()) { + ZLOGE("bundleName:%{public}s is not exist", schemaMeta.bundleName.c_str()); + break; + } + meta.instanceId = it->second.instanceId; + MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta, true); + result.insert_or_assign(database.alias, QueryStatistics(meta, database)); + } + } + return result; +} + +StatisticInfos CloudServiceImpl::QueryStatistics(const StoreMetaData &storeMetaData, + const DistributedData::Database &database) +{ + std::vector infos; + auto store = AutoCache::GetInstance().GetStore(storeMetaData, {}); + if (store == nullptr) { + ZLOGE("store failed, store is nullptr,bundleName:%{public}s", + Anonymous::Change(storeMetaData.bundleName).c_str()); + return infos; + } + infos.reserve(database.tables.size()); + for (auto& table : database.tables) { + auto [success, info] = QueryTableStatistic(table.name, store); + if (success) { + info.table = table.alias; + infos.push_back(std::move(info)); + } + } + return infos; +} + +std::pair CloudServiceImpl::QueryTableStatistic(const std::string &tableName, + AutoCache::Store store) +{ + StatisticInfo info; + auto sql = BuildStatisticSql(tableName); + auto cursor = store->Query(tableName, sql, {}); + if (cursor == nullptr || cursor->GetCount() != 1 || cursor->MoveToFirst() != E_OK) { + ZLOGE("query failed, cursor is nullptr or move to first failed,tableName:%{public}s", + Anonymous::Change(tableName).c_str()); + return { false, info }; + } + DistributedData::VBucket entry; + if (cursor->GetEntry(entry) != E_OK) { + ZLOGE("get entry failed,tableName:%{public}s", Anonymous::Change(tableName).c_str()); + return { false, info }; + } + auto it = entry.find("inserted"); + if (it != entry.end() && it->second.index() == TYPE_INDEX) { + info.inserted = std::get(it->second); + } + it = entry.find("updated"); + if (it != entry.end() && it->second.index() == TYPE_INDEX) { + info.updated = std::get(it->second); + } + it = entry.find("normal"); + if (it != entry.end() && it->second.index() == TYPE_INDEX) { + info.normal = std::get(it->second); + } + return { true, info }; +} + +std::string CloudServiceImpl::BuildStatisticSql(const std::string &tableName) +{ + std::string logTable = DistributedDB::RelationalStoreManager::GetDistributedLogTableName(tableName); + std::string sql = "select "; + sql.append("count(case when cloud_gid = '' and flag&(0x1|0x8|0x20) = 0x20 then 1 end) as inserted,"); + sql.append("count(case when cloud_gid <> '' and flag&0x20 != 0 then 1 end) as updated,"); + sql.append("count(case when cloud_gid <> '' and flag&(0x1|0x8|0x20) = 0 then 1 end) as normal"); + sql.append(" from ").append(logTable); + + return sql; +} + +std::pair> CloudServiceImpl::QueryStatistics(const std::string &id, + const std::string &bundleName, const std::string &storeId) +{ + std::map result; + auto tokenId = IPCSkeleton::GetCallingTokenID(); + auto user = Account::GetInstance()->GetUserByToken(tokenId); + auto [status, cloudInfo] = GetCloudInfoFromMeta(user); + if (status != SUCCESS) { + ZLOGE("get cloud meta failed user:%{public}d", static_cast(cloudInfo.user)); + return { ERROR, result }; + } + if (id != cloudInfo.id || bundleName.empty() || cloudInfo.apps.find(bundleName) == cloudInfo.apps.end()) { + ZLOGE("[server] id:%{public}s, [meta] id:%{public}s, bundleName:%{public}s", + Anonymous::Change(cloudInfo.id).c_str(), Anonymous::Change(id).c_str(), bundleName.c_str()); + return { ERROR, result }; + } + SchemaMeta schemaMeta; + std::string schemaKey = cloudInfo.GetSchemaKey(bundleName); + if (!MetaDataManager::GetInstance().LoadMeta(schemaKey, schemaMeta, true)) { + ZLOGE("get load meta failed user:%{public}d", static_cast(cloudInfo.user)); + return { ERROR, result }; + } + result = ExecuteStatistics(storeId, cloudInfo, schemaMeta); + return { SUCCESS, result }; +} + +int32_t CloudServiceImpl::SetGlobalCloudStrategy(Strategy strategy, const std::vector &values) +{ + if (strategy < 0 || strategy >= Strategy::STRATEGY_BUTT) { + ZLOGE("invalid strategy:%{public}d, size:%{public}zu", strategy, values.size()); + return INVALID_ARGUMENT; + } + auto tokenId = IPCSkeleton::GetCallingTokenID(); + HapInfo hapInfo; + hapInfo.user = Account::GetInstance()->GetUserByToken(tokenId); + if (hapInfo.user == INVALID_USER_ID || hapInfo.user == 0) { + ZLOGE("invalid user:%{public}d, strategy:%{public}d, size:%{public}zu", hapInfo.user, strategy, + values.size()); + return ERROR; + } + hapInfo.bundleName = SyncStrategy::GLOBAL_BUNDLE; + return STRATEGY_SAVERS[strategy](values, hapInfo); +} + int32_t CloudServiceImpl::OnInitialize() { DistributedDB::RuntimeConfig::SetCloudTranslate(std::make_shared()); @@ -375,10 +512,9 @@ int32_t CloudServiceImpl::OnUserChange(uint32_t code, const std::string &user, c return E_OK; } -int32_t CloudServiceImpl::Online(const std::string &device) +int32_t CloudServiceImpl::OnReady(const std::string& device) { if (device != DeviceManagerAdapter::CLOUD_DEVICE_UUID) { - ZLOGI("Not network online"); return SUCCESS; } std::vector users; @@ -586,6 +722,7 @@ int32_t CloudServiceImpl::CloudStatic::OnAppUninstall(const std::string &bundleN { MetaDataManager::GetInstance().DelMeta(Subscription::GetRelationKey(user, bundleName), true); MetaDataManager::GetInstance().DelMeta(CloudInfo::GetSchemaKey(user, bundleName, index), true); + MetaDataManager::GetInstance().DelMeta(NetworkSyncStrategy::GetKey(user, bundleName), true); return E_OK; } @@ -622,7 +759,7 @@ void CloudServiceImpl::CloudShare(const Event &event) } std::pair> CloudServiceImpl::PreShare( - const CloudEvent::StoreInfo& storeInfo, GenQuery& query) + const StoreInfo& storeInfo, GenQuery& query) { StoreMetaData meta; meta.bundleName = storeInfo.bundleName; @@ -777,7 +914,7 @@ std::pair> CloudServiceImpl::Alloc return { E_INVALID_ARGS, {} }; } auto memo = std::make_shared(predicates); - CloudEvent::StoreInfo storeInfo; + StoreInfo storeInfo; storeInfo.bundleName = hapInfo.bundleName; storeInfo.tokenId = tokenId; storeInfo.user = hapInfo.user; @@ -1044,4 +1181,37 @@ void CloudServiceImpl::InitSubTask(const Subscription &sub) expireTime_ = expire > now ? expire : now; } +int32_t CloudServiceImpl::SetCloudStrategy(Strategy strategy, const std::vector &values) +{ + if (strategy < 0 || strategy >= Strategy::STRATEGY_BUTT) { + ZLOGE("invalid strategy:%{public}d, size:%{public}zu", strategy, values.size()); + return INVALID_ARGUMENT; + } + auto tokenId = IPCSkeleton::GetCallingTokenID(); + auto hapInfo = GetHapInfo(tokenId); + if (hapInfo.bundleName.empty() || hapInfo.user == INVALID_USER_ID || hapInfo.user == 0) { + ZLOGE("invalid, user:%{public}d, bundleName:%{public}s, strategy:%{public}d, values size:%{public}zu", + hapInfo.user, hapInfo.bundleName.c_str(), strategy, values.size()); + return ERROR; + } + return STRATEGY_SAVERS[strategy](values, hapInfo); +} + +int32_t CloudServiceImpl::SaveNetworkStrategy(const std::vector &values, const HapInfo &hapInfo) +{ + NetworkSyncStrategy::StrategyInfo info; + info.strategy = 0; + info.user = hapInfo.user; + info.bundleName = hapInfo.bundleName; + if (values.empty()) { + return MetaDataManager::GetInstance().DelMeta(info.GetKey(), true) ? SUCCESS : ERROR; + } + for (auto &value : values) { + auto strategy = std::get_if(&value); + if (strategy != nullptr) { + info.strategy |= static_cast(*strategy); + } + } + return MetaDataManager::GetInstance().SaveMeta(info.GetKey(), info, true) ? SUCCESS : ERROR; +} } // namespace OHOS::CloudData \ No newline at end of file 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 10c446d04cab21824b0da53502bdf15d2c38b887..b6dff4b7ba109ed77f182e39cbc6898338c983c6 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h @@ -32,6 +32,7 @@ namespace OHOS::CloudData { class CloudServiceImpl : public CloudServiceStub { public: using StoreMetaData = DistributedData::StoreMetaData; + using StoreInfo = DistributedData::StoreInfo; CloudServiceImpl(); ~CloudServiceImpl() = default; int32_t EnableCloud(const std::string &id, const std::map &switches) override; @@ -40,11 +41,9 @@ public: 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; - int32_t OnInitialize() override; - int32_t OnBind(const BindInfo &info) override; - int32_t OnUserChange(uint32_t code, const std::string &user, const std::string &account) override; - int32_t Online(const std::string &device) override; - int32_t Offline(const std::string &device) override; + std::pair> QueryStatistics(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, @@ -61,6 +60,14 @@ 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 OnInitialize() override; + int32_t OnBind(const BindInfo &info) override; + int32_t OnUserChange(uint32_t code, const std::string &user, const std::string &account) override; + int32_t OnReady(const std::string &device) override; + int32_t Offline(const std::string &device) override; + private: using StaticActs = DistributedData::StaticActs; class CloudStatic : public StaticActs { @@ -88,6 +95,7 @@ private: using Task = ExecutorPool::Task; using TaskId = ExecutorPool::TaskId; using Duration = ExecutorPool::Duration; + using AutoCache = DistributedData::AutoCache; struct HapInfo { int32_t user; @@ -119,6 +127,11 @@ private: std::pair GetSchemaMeta(int32_t userId, const std::string &bundleName, int32_t instanceId); std::pair GetAppSchemaFromServer(int32_t user, const std::string &bundleName); + 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); void GetSchema(const Event &event); void CloudShare(const Event &event); @@ -129,13 +142,18 @@ private: void Execute(Task task); void CleanSubscription(Subscription &sub); int32_t DoClean(CloudInfo &cloudInfo, const std::map &actions); - std::pair> PreShare(const CloudEvent::StoreInfo& storeInfo, + 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::pair> GetDbInfoFromExtraData( const DistributedData::ExtraData &extraData, const SchemaMeta &schemaMeta); std::shared_ptr GetSharingHandle(const HapInfo& hapInfo); + + using SaveStrategy = int32_t (*)(const std::vector &values, const HapInfo &hapInfo); + static const SaveStrategy STRATEGY_SAVERS[Strategy::STRATEGY_BUTT]; + static int32_t SaveNetworkStrategy(const std::vector &values, const HapInfo &hapInfo); + std::shared_ptr executor_; SyncManager syncManager_; std::mutex mutex_; diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.cpp b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.cpp index ee9b71ad2e340ccf97e7b3feffe0fa80d5c3b15e..4aa3c79bdb01d7c4e778a7dc04671d4e1dde7054 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.cpp +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.cpp @@ -16,7 +16,7 @@ #include "cloud_service_stub.h" #include "ipc_skeleton.h" -#include "itypes_util.h" +#include "cloud_types_util.h" #include "log_print.h" #include "permission/permission_validator.h" #include "rdb_types.h" @@ -32,6 +32,8 @@ const CloudServiceStub::Handler CloudServiceStub::HANDLERS[TRANS_BUTT] = { &CloudServiceStub::OnClean, &CloudServiceStub::OnNotifyDataChange, &CloudServiceStub::OnNotifyChange, + &CloudServiceStub::OnQueryStatistics, + &CloudServiceStub::OnSetGlobalCloudStrategy, &CloudServiceStub::OnAllocResourceAndShare, &CloudServiceStub::OnShare, &CloudServiceStub::OnUnshare, @@ -41,6 +43,7 @@ const CloudServiceStub::Handler CloudServiceStub::HANDLERS[TRANS_BUTT] = { &CloudServiceStub::OnQueryByInvitation, &CloudServiceStub::OnConfirmInvitation, &CloudServiceStub::OnChangeConfirmation, + &CloudServiceStub::OnSetCloudStrategy, }; int CloudServiceStub::OnRemoteRequest(uint32_t code, OHOS::MessageParcel &data, OHOS::MessageParcel &reply) @@ -58,34 +61,28 @@ int CloudServiceStub::OnRemoteRequest(uint32_t code, OHOS::MessageParcel &data, return -1; } - if (!TokenIdKit::IsSystemAppByFullTokenID(IPCSkeleton::GetCallingFullTokenID())) { - ZLOGE("permission denied! code:%{public}u, BUTT:%{public}d", code, TRANS_BUTT); + if (((code >= TRANS_CONFIG_HEAD && code < TRANS_CONFIG_BUTT) || + (code >= TRANS_SHARE_HEAD && code < TRANS_SHARE_BUTT)) && + !TokenIdKit::IsSystemAppByFullTokenID(IPCSkeleton::GetCallingFullTokenID())) { + ZLOGE("permission denied! code:%{public}u", code); auto result = static_cast(PERMISSION_DENIED); return ITypesUtil::Marshal(reply, result) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; } - if (code >= TRANS_HEAD && code < TRANS_ALLOC_RESOURCE_AND_SHARE) { - auto permit = - DistributedKv::PermissionValidator::GetInstance().IsCloudConfigPermit(IPCSkeleton::GetCallingTokenID()); - if (!permit) { - ZLOGE("cloud config permission denied! code:%{public}u, BUTT:%{public}d", code, TRANS_BUTT); - auto result = static_cast(CLOUD_CONFIG_PERMISSION_DENIED); - return ITypesUtil::Marshal(reply, result) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; - } - } - - std::string id; - if (!ITypesUtil::Unmarshal(data, id)) { - ZLOGE("Unmarshal id:%{public}s", Anonymous::Change(id).c_str()); - return IPC_STUB_INVALID_DATA_ERR; + if (code >= TRANS_CONFIG_HEAD && code < TRANS_CONFIG_BUTT && + !DistributedKv::PermissionValidator::GetInstance().IsCloudConfigPermit(IPCSkeleton::GetCallingTokenID())) { + ZLOGE("cloud config permission denied! code:%{public}u, BUTT:%{public}d", code, TRANS_BUTT); + auto result = static_cast(CLOUD_CONFIG_PERMISSION_DENIED); + return ITypesUtil::Marshal(reply, result) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; } - return (this->*HANDLERS[code])(id, data, reply); + return (this->*HANDLERS[code])(data, reply); } -int32_t CloudServiceStub::OnEnableCloud(const std::string &id, MessageParcel &data, MessageParcel &reply) +int32_t CloudServiceStub::OnEnableCloud(MessageParcel &data, MessageParcel &reply) { + std::string id; std::map switches; - if (!ITypesUtil::Unmarshal(data, switches)) { + if (!ITypesUtil::Unmarshal(data, id, switches)) { ZLOGE("Unmarshal id:%{public}s", Anonymous::Change(id).c_str()); return IPC_STUB_INVALID_DATA_ERR; } @@ -93,17 +90,23 @@ int32_t CloudServiceStub::OnEnableCloud(const std::string &id, MessageParcel &da return ITypesUtil::Marshal(reply, result) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; } -int32_t CloudServiceStub::OnDisableCloud(const std::string &id, MessageParcel &data, MessageParcel &reply) +int32_t CloudServiceStub::OnDisableCloud(MessageParcel &data, MessageParcel &reply) { + std::string id; + if (!ITypesUtil::Unmarshal(data, id)) { + ZLOGE("Unmarshal id:%{public}s", Anonymous::Change(id).c_str()); + return IPC_STUB_INVALID_DATA_ERR; + } auto result = DisableCloud(id); return ITypesUtil::Marshal(reply, result) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; } -int32_t CloudServiceStub::OnChangeAppSwitch(const std::string &id, MessageParcel &data, MessageParcel &reply) +int32_t CloudServiceStub::OnChangeAppSwitch(MessageParcel &data, MessageParcel &reply) { + std::string id; std::string bundleName; int32_t appSwitch = SWITCH_OFF; - if (!ITypesUtil::Unmarshal(data, bundleName, appSwitch)) { + if (!ITypesUtil::Unmarshal(data, id, bundleName, appSwitch)) { ZLOGE("Unmarshal id:%{public}s", Anonymous::Change(id).c_str()); return IPC_STUB_INVALID_DATA_ERR; } @@ -111,10 +114,11 @@ int32_t CloudServiceStub::OnChangeAppSwitch(const std::string &id, MessageParcel return ITypesUtil::Marshal(reply, result) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; } -int32_t CloudServiceStub::OnClean(const std::string &id, MessageParcel &data, MessageParcel &reply) +int32_t CloudServiceStub::OnClean(MessageParcel &data, MessageParcel &reply) { + std::string id; std::map actions; - if (!ITypesUtil::Unmarshal(data, actions)) { + if (!ITypesUtil::Unmarshal(data, id, actions)) { ZLOGE("Unmarshal id:%{public}s", Anonymous::Change(id).c_str()); return IPC_STUB_INVALID_DATA_ERR; } @@ -122,10 +126,11 @@ int32_t CloudServiceStub::OnClean(const std::string &id, MessageParcel &data, Me return ITypesUtil::Marshal(reply, result) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; } -int32_t CloudServiceStub::OnNotifyDataChange(const std::string &id, MessageParcel &data, MessageParcel &reply) +int32_t CloudServiceStub::OnNotifyDataChange(MessageParcel &data, MessageParcel &reply) { + std::string id; std::string bundleName; - if (!ITypesUtil::Unmarshal(data, bundleName)) { + if (!ITypesUtil::Unmarshal(data, id, bundleName)) { ZLOGE("Unmarshal id:%{public}s", Anonymous::Change(id).c_str()); return IPC_STUB_INVALID_DATA_ERR; } @@ -133,13 +138,25 @@ int32_t CloudServiceStub::OnNotifyDataChange(const std::string &id, MessageParce return ITypesUtil::Marshal(reply, result) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; } -int32_t CloudServiceStub::OnAllocResourceAndShare(const std::string& storeId, MessageParcel& data, - MessageParcel& reply) +int32_t CloudServiceStub::OnSetGlobalCloudStrategy(MessageParcel &data, MessageParcel &reply) { + Strategy strategy; + std::vector values; + if (!ITypesUtil::Unmarshal(data, strategy, values)) { + ZLOGE("Unmarshal strategy:%{public}d, values size:%{public}zu", strategy, values.size()); + return IPC_STUB_INVALID_DATA_ERR; + } + auto status = SetGlobalCloudStrategy(strategy, values); + return ITypesUtil::Marshal(reply, status) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; +} + +int32_t CloudServiceStub::OnAllocResourceAndShare(MessageParcel &data, MessageParcel &reply) +{ + std::string storeId; DistributedRdb::PredicatesMemo predicatesMemo; std::vector columns; std::vector participants; - if (!ITypesUtil::Unmarshal(data, predicatesMemo, columns, participants)) { + if (!ITypesUtil::Unmarshal(data, storeId, predicatesMemo, columns, participants)) { ZLOGE("Unmarshal storeId:%{public}s", Anonymous::Change(storeId).c_str()); return IPC_STUB_INVALID_DATA_ERR; } @@ -147,22 +164,37 @@ int32_t CloudServiceStub::OnAllocResourceAndShare(const std::string& storeId, Me return ITypesUtil::Marshal(reply, status, resultSet) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; } -int32_t CloudServiceStub::OnNotifyChange(const std::string &id, MessageParcel &data, MessageParcel &reply) +int32_t CloudServiceStub::OnNotifyChange(MessageParcel &data, MessageParcel &reply) { + std::string eventId; std::string extraData; int32_t userId; - if (!ITypesUtil::Unmarshal(data, extraData, userId)) { - ZLOGE("Unmarshal id:%{public}s", Anonymous::Change(id).c_str()); + if (!ITypesUtil::Unmarshal(data, eventId, extraData, userId)) { + ZLOGE("Unmarshal eventId:%{public}s", Anonymous::Change(eventId).c_str()); return IPC_STUB_INVALID_DATA_ERR; } - auto result = NotifyDataChange(id, extraData, userId); + auto result = NotifyDataChange(eventId, extraData, userId); return ITypesUtil::Marshal(reply, result) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; } -int32_t CloudServiceStub::OnShare(const std::string &sharingRes, MessageParcel &data, MessageParcel &reply) +int32_t CloudServiceStub::OnQueryStatistics(MessageParcel &data, MessageParcel &reply) { + std::string id; + std::string bundleName; + std::string storeId; + if (!ITypesUtil::Unmarshal(data, id, bundleName, storeId)) { + ZLOGE("Unmarshal id:%{public}s", Anonymous::Change(id).c_str()); + return IPC_STUB_INVALID_DATA_ERR; + } + auto result = QueryStatistics(id, bundleName, storeId); + return ITypesUtil::Marshal(reply, result.first, result.second) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; +} + +int32_t CloudServiceStub::OnShare(MessageParcel &data, MessageParcel &reply) +{ + std::string sharingRes; Participants participants; - if (!ITypesUtil::Unmarshal(data, participants)) { + if (!ITypesUtil::Unmarshal(data, sharingRes, participants)) { ZLOGE("Unmarshal sharingRes:%{public}s", Anonymous::Change(sharingRes).c_str()); return IPC_STUB_INVALID_DATA_ERR; } @@ -171,10 +203,11 @@ int32_t CloudServiceStub::OnShare(const std::string &sharingRes, MessageParcel & return ITypesUtil::Marshal(reply, status, results) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; } -int32_t CloudServiceStub::OnUnshare(const std::string &sharingRes, MessageParcel &data, MessageParcel &reply) +int32_t CloudServiceStub::OnUnshare(MessageParcel &data, MessageParcel &reply) { + std::string sharingRes; Participants participants; - if (!ITypesUtil::Unmarshal(data, participants)) { + if (!ITypesUtil::Unmarshal(data, sharingRes, participants)) { ZLOGE("Unmarshal sharingRes:%{public}s", Anonymous::Change(sharingRes).c_str()); return IPC_STUB_INVALID_DATA_ERR; } @@ -183,17 +216,23 @@ int32_t CloudServiceStub::OnUnshare(const std::string &sharingRes, MessageParcel return ITypesUtil::Marshal(reply, status, results) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; } -int32_t CloudServiceStub::OnExit(const std::string &sharingRes, MessageParcel &data, MessageParcel &reply) +int32_t CloudServiceStub::OnExit(MessageParcel &data, MessageParcel &reply) { + std::string sharingRes; + if (!ITypesUtil::Unmarshal(data, sharingRes)) { + ZLOGE("Unmarshal sharingRes:%{public}s", Anonymous::Change(sharingRes).c_str()); + return IPC_STUB_INVALID_DATA_ERR; + } std::pair result; auto status = Exit(sharingRes, result); return ITypesUtil::Marshal(reply, status, result) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; } -int32_t CloudServiceStub::OnChangePrivilege(const std::string &sharingRes, MessageParcel &data, MessageParcel &reply) +int32_t CloudServiceStub::OnChangePrivilege(MessageParcel &data, MessageParcel &reply) { + std::string sharingRes; Participants participants; - if (!ITypesUtil::Unmarshal(data, participants)) { + if (!ITypesUtil::Unmarshal(data, sharingRes, participants)) { ZLOGE("Unmarshal sharingRes:%{public}s", Anonymous::Change(sharingRes).c_str()); return IPC_STUB_INVALID_DATA_ERR; } @@ -202,26 +241,35 @@ int32_t CloudServiceStub::OnChangePrivilege(const std::string &sharingRes, Messa return ITypesUtil::Marshal(reply, status, results) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; } -int32_t CloudServiceStub::OnQuery(const std::string &sharingRes, MessageParcel &data, MessageParcel &reply) +int32_t CloudServiceStub::OnQuery(MessageParcel &data, MessageParcel &reply) { + std::string sharingRes; + if (!ITypesUtil::Unmarshal(data, sharingRes)) { + ZLOGE("Unmarshal sharingRes:%{public}s", Anonymous::Change(sharingRes).c_str()); + return IPC_STUB_INVALID_DATA_ERR; + } QueryResults results; auto status = Query(sharingRes, results); return ITypesUtil::Marshal(reply, status, results) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; } -int32_t CloudServiceStub::OnQueryByInvitation( - const std::string &invitation, MessageParcel &data, MessageParcel &reply) +int32_t CloudServiceStub::OnQueryByInvitation(MessageParcel &data, MessageParcel &reply) { + std::string invitation; + if (!ITypesUtil::Unmarshal(data, invitation)) { + ZLOGE("Unmarshal invitation:%{public}s", Anonymous::Change(invitation).c_str()); + return IPC_STUB_INVALID_DATA_ERR; + } QueryResults results; auto status = QueryByInvitation(invitation, results); return ITypesUtil::Marshal(reply, status, results) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; } -int32_t CloudServiceStub::OnConfirmInvitation( - const std::string &invitation, MessageParcel &data, MessageParcel &reply) +int32_t CloudServiceStub::OnConfirmInvitation(MessageParcel &data, MessageParcel &reply) { + std::string invitation; int32_t confirmation; - if (!ITypesUtil::Unmarshal(data, confirmation)) { + if (!ITypesUtil::Unmarshal(data, invitation, confirmation)) { ZLOGE("Unmarshal invitation:%{public}s", Anonymous::Change(invitation).c_str()); return IPC_STUB_INVALID_DATA_ERR; } @@ -230,11 +278,11 @@ int32_t CloudServiceStub::OnConfirmInvitation( return ITypesUtil::Marshal(reply, status, result) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; } -int32_t CloudServiceStub::OnChangeConfirmation( - const std::string &sharingRes, MessageParcel &data, MessageParcel &reply) +int32_t CloudServiceStub::OnChangeConfirmation(MessageParcel &data, MessageParcel &reply) { + std::string sharingRes; int32_t confirmation; - if (!ITypesUtil::Unmarshal(data, confirmation)) { + if (!ITypesUtil::Unmarshal(data, sharingRes, confirmation)) { ZLOGE("Unmarshal sharingRes:%{public}s", Anonymous::Change(sharingRes).c_str()); return IPC_STUB_INVALID_DATA_ERR; } @@ -242,4 +290,16 @@ int32_t CloudServiceStub::OnChangeConfirmation( auto status = ChangeConfirmation(sharingRes, confirmation, result); return ITypesUtil::Marshal(reply, status, result) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; } + +int32_t CloudServiceStub::OnSetCloudStrategy(MessageParcel &data, MessageParcel &reply) +{ + Strategy strategy; + std::vector values; + if (!ITypesUtil::Unmarshal(data, strategy, values)) { + ZLOGE("Unmarshal strategy:%{public}d, values size:%{public}zu", strategy, values.size()); + return IPC_STUB_INVALID_DATA_ERR; + } + auto status = SetCloudStrategy(strategy, values); + return ITypesUtil::Marshal(reply, status) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; +} } // namespace OHOS::CloudData 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 0b5717ab8d14b9efe26d244f1aeffb3f978a2d62..4a8fae7368a68e50feac44c64597d66aa25b4646 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.h +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.h @@ -25,23 +25,27 @@ public: int OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply) override; private: - using Handler = int32_t (CloudServiceStub::*)(const std::string &id, MessageParcel &data, MessageParcel &reply); - int32_t OnEnableCloud(const std::string &id, MessageParcel &data, MessageParcel &reply); - int32_t OnDisableCloud(const std::string &id, MessageParcel &data, MessageParcel &reply); - int32_t OnChangeAppSwitch(const std::string &id, MessageParcel &data, MessageParcel &reply); - int32_t OnClean(const std::string &id, MessageParcel &data, MessageParcel &reply); - int32_t OnNotifyDataChange(const std::string &id, MessageParcel &data, MessageParcel &reply); - int32_t OnNotifyChange(const std::string &id, MessageParcel &data, MessageParcel &reply); + using Handler = int32_t (CloudServiceStub::*)(MessageParcel &data, MessageParcel &reply); + int32_t OnEnableCloud(MessageParcel &data, MessageParcel &reply); + int32_t OnDisableCloud(MessageParcel &data, MessageParcel &reply); + int32_t OnChangeAppSwitch(MessageParcel &data, MessageParcel &reply); + int32_t OnClean(MessageParcel &data, MessageParcel &reply); + int32_t OnNotifyDataChange(MessageParcel &data, MessageParcel &reply); + int32_t OnNotifyChange(MessageParcel &data, MessageParcel &reply); + int32_t OnQueryStatistics(MessageParcel &data, MessageParcel &reply); + int32_t OnSetGlobalCloudStrategy(MessageParcel &data, MessageParcel &reply); - int32_t OnAllocResourceAndShare(const std::string &storeId, MessageParcel &data, MessageParcel &reply); - int32_t OnShare(const std::string &sharingRes, MessageParcel &data, MessageParcel &reply); - int32_t OnUnshare(const std::string &sharingRes, MessageParcel &data, MessageParcel &reply); - int32_t OnExit(const std::string &sharingRes, MessageParcel &data, MessageParcel &reply); - int32_t OnChangePrivilege(const std::string &sharingRes, MessageParcel &data, MessageParcel &reply); - int32_t OnQuery(const std::string &sharingRes, MessageParcel &data, MessageParcel &reply); - int32_t OnQueryByInvitation(const std::string &invitation, MessageParcel &data, MessageParcel &reply); - int32_t OnConfirmInvitation(const std::string &invitation, MessageParcel &data, MessageParcel &reply); - int32_t OnChangeConfirmation(const std::string &sharingRes, MessageParcel &data, MessageParcel &reply); + int32_t OnAllocResourceAndShare(MessageParcel &data, MessageParcel &reply); + int32_t OnShare(MessageParcel &data, MessageParcel &reply); + int32_t OnUnshare(MessageParcel &data, MessageParcel &reply); + int32_t OnExit(MessageParcel &data, MessageParcel &reply); + int32_t OnChangePrivilege(MessageParcel &data, MessageParcel &reply); + int32_t OnQuery(MessageParcel &data, MessageParcel &reply); + int32_t OnQueryByInvitation(MessageParcel &data, MessageParcel &reply); + int32_t OnConfirmInvitation(MessageParcel &data, MessageParcel &reply); + int32_t OnChangeConfirmation(MessageParcel &data, MessageParcel &reply); + + int32_t OnSetCloudStrategy(MessageParcel &data, MessageParcel &reply); static const Handler HANDLERS[TRANS_BUTT]; }; } // namespace OHOS::CloudData diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_types_util.cpp b/datamgr_service/services/distributeddataservice/service/cloud/cloud_types_util.cpp index 12484fd057ea9fd02149ba10deb39f48cf3b212a..f66d8f0b38b73ff89f2811034d7087d72278f678 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_types_util.cpp +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_types_util.cpp @@ -74,4 +74,27 @@ bool Unmarshalling(ValuesBucket &output, MessageParcel &data) { return Unmarshal(data, output.values_); } + +template<> +bool Marshalling(const StatisticInfo &input, MessageParcel &data) +{ + return ITypesUtil::Marshal(data, input.table, input.inserted, input.updated, input.normal); +} + +template<> +bool Unmarshalling(StatisticInfo &output, MessageParcel &data) +{ + return ITypesUtil::Unmarshal(data, output.table, output.inserted, output.updated, output.normal); +} + +template<> +bool Unmarshalling(Strategy &output, MessageParcel &data) +{ + uint32_t result; + if (!data.ReadUint32(result) || result < Strategy::STRATEGY_HEAD || result >= Strategy::STRATEGY_BUTT) { + return false; + } + output = static_cast(result); + return true; +} } // namespace OHOS::ITypesUtil \ No newline at end of file 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 e70f487394c5471ec84a6d9fe07d441f3d2895c3..7931c8abb46d70d8ba69ec5958e6d981fe92c0be 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 "cloud_types.h" #include "values_bucket.h" @@ -28,6 +29,8 @@ using SharingCode = OHOS::CloudData::SharingCode; using Asset = OHOS::NativeRdb::AssetValue; using ValueObject = OHOS::NativeRdb::ValueObject; using ValuesBucket = OHOS::NativeRdb::ValuesBucket; +using StatisticInfo = OHOS::CloudData::StatisticInfo; +using Strategy = OHOS::CloudData::Strategy; template<> bool Marshalling(const Participant &input, MessageParcel &data); @@ -51,5 +54,13 @@ template<> bool Marshalling(const ValuesBucket &input, MessageParcel &data); template<> bool Unmarshalling(ValuesBucket &output, MessageParcel &data); + +template<> +bool Marshalling(const StatisticInfo &input, MessageParcel &data); +template<> +bool Unmarshalling(StatisticInfo &output, MessageParcel &data); + +template<> +bool Unmarshalling(Strategy &output, MessageParcel &data); } // namespace OHOS::ITypesUtil #endif // OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_TYPES_UTIL_H diff --git a/datamgr_service/services/distributeddataservice/service/cloud/sync_manager.cpp b/datamgr_service/services/distributeddataservice/service/cloud/sync_manager.cpp index d739aae727b8ac318b44c394ff0302ba241e0f9e..cae601c0adfacedd3abd532045155a880490bae6 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/sync_manager.cpp +++ b/datamgr_service/services/distributeddataservice/service/cloud/sync_manager.cpp @@ -23,6 +23,7 @@ #include "eventcenter/event_center.h" #include "log_print.h" #include "metadata/meta_data_manager.h" +#include "sync_strategies/network_sync_strategy.h" #include "store/auto_cache.h" #include "utils/anonymous.h" namespace OHOS::CloudData { @@ -124,6 +125,7 @@ bool SyncManager::SyncInfo::Contains(const std::string& storeName) SyncManager::SyncManager() { EventCenter::GetInstance().Subscribe(CloudEvent::LOCAL_CHANGE, GetClientChangeHandler()); + syncStrategy_ = std::make_shared(); } SyncManager::~SyncManager() @@ -225,8 +227,15 @@ ExecutorPool::Task SyncManager::GetSyncTask(int32_t times, bool retry, RefCount if (!info.Contains(database.name)) { continue; } - CloudEvent::StoreInfo storeInfo = { 0, schema.bundleName, database.name, - cloud.apps[schema.bundleName].instanceId, cloud.user }; + StoreInfo storeInfo = { 0, schema.bundleName, database.name, cloud.apps[schema.bundleName].instanceId, + cloud.user }; + 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()); + info.SetError(status); + continue; + } auto query = info.GenerateQuery(database.name, database.GetTableNames()); auto evt = std::make_unique(std::move(storeInfo), SyncEvent::EventInfo { info.mode_, info.wait_, retry, std::move(query), info.async_ }); @@ -347,7 +356,7 @@ int32_t SyncManager::Compare(uint64_t syncId, int32_t user) void SyncManager::UpdateSchema(const SyncManager::SyncInfo &syncInfo) { - CloudEvent::StoreInfo storeInfo; + StoreInfo storeInfo; storeInfo.user = syncInfo.user_; storeInfo.bundleName = syncInfo.bundleName_; EventCenter::GetInstance().PostEvent(std::make_unique(CloudEvent::GET_SCHEMA, storeInfo)); diff --git a/datamgr_service/services/distributeddataservice/service/cloud/sync_manager.h b/datamgr_service/services/distributeddataservice/service/cloud/sync_manager.h index d68e7b57d9430beb5a69ce9b35e1ed206ae4677b..ee1323f703772d1acb1ccb5df4d3a896bf904dd9 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/sync_manager.h +++ b/datamgr_service/services/distributeddataservice/service/cloud/sync_manager.h @@ -23,6 +23,7 @@ #include "utils/ref_count.h" #include "concurrent_map.h" #include "cloud/cloud_info.h" +#include "cloud/sync_strategy.h" namespace OHOS::CloudData { class SyncManager { public: @@ -76,6 +77,8 @@ private: using Duration = ExecutorPool::Duration; using Retryer = std::function; using CloudInfo = DistributedData::CloudInfo; + using StoreInfo = DistributedData::StoreInfo; + using SyncStrategy = DistributedData::SyncStrategy; static constexpr ExecutorPool::Duration RETRY_INTERVAL = std::chrono::seconds(10); // second static constexpr ExecutorPool::Duration LOCKED_INTERVAL = std::chrono::seconds(30); // second @@ -98,6 +101,7 @@ private: std::shared_ptr executor_; ConcurrentMap actives_; ConcurrentMap activeInfos_; + std::shared_ptr syncStrategy_; }; } // namespace OHOS::CloudData #endif // OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_SYNC_MANAGER_H 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 new file mode 100644 index 0000000000000000000000000000000000000000..043cb5e781247617300924db0ee67bbb3cfe82a4 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/cloud/sync_strategies/network_sync_strategy.cpp @@ -0,0 +1,128 @@ +/* + * 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 "NetworkSyncStrategy" + +#include "network_sync_strategy.h" +#include "metadata/meta_data_manager.h" +#include "device_manager_adapter.h" +#include "error/general_error.h" +#include "utils/constant.h" +#include "log_print.h" +namespace OHOS::CloudData { +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 info; + StrategyInfo::Unmarshall(value, info); + ZLOGI("flag:%{public}d, value:%{public}s", flag, value.c_str()); + if (info.user != user_) { + return true; + } + if (flag == MetaDataManager::INSERT || flag == MetaDataManager::UPDATE) { + strategies_.InsertOrAssign(info.bundleName, std::move(info)); + } else if (flag == MetaDataManager::DELETE) { + strategies_.Erase(info.bundleName); + } else { + ZLOGE("ignored operation"); + } + return true; + }, true); +} +NetworkSyncStrategy::~NetworkSyncStrategy() +{ + MetaDataManager::GetInstance().Unsubscribe(StrategyInfo::PREFIX); +} +int32_t NetworkSyncStrategy::CheckSyncAction(const StoreInfo &storeInfo) +{ + if (!DeviceManagerAdapter::GetInstance().IsNetworkAvailable()) { + return E_NETWORK_ERROR; + } + if (storeInfo.user != user_) { + strategies_.Clear(); + user_ = storeInfo.user; + } + StrategyInfo info = GetStrategy(storeInfo.user, storeInfo.bundleName); + if (info.user == StrategyInfo::INVALID_USER) { + info = GetStrategy(storeInfo.user, GLOBAL_BUNDLE); + } + if (!Check(info.strategy)) { + return E_BLOCKED_BY_NETWORK_STRATEGY; + } + return next_ ? next_->CheckSyncAction(storeInfo) : E_OK; +} + +bool NetworkSyncStrategy::StrategyInfo::Marshal(Serializable::json &node) const +{ + SetValue(node[GET_NAME(user)], user); + SetValue(node[GET_NAME(bundleName)], bundleName); + SetValue(node[GET_NAME(strategy)], strategy); + return true; +} + +bool NetworkSyncStrategy::StrategyInfo::Unmarshal(const Serializable::json &node) +{ + GetValue(node, GET_NAME(user), user); + GetValue(node, GET_NAME(bundleName), bundleName); + GetValue(node, GET_NAME(strategy), strategy); + return false; +} + +std::string NetworkSyncStrategy::StrategyInfo::GetKey() +{ + return Constant::Join(StrategyInfo::PREFIX, Constant::KEY_SEPARATOR, { std::to_string(user), bundleName }); +} + +std::string NetworkSyncStrategy::GetKey(int32_t user) +{ + return Constant::Join(StrategyInfo::PREFIX, Constant::KEY_SEPARATOR, { std::to_string(user) }); +} + +std::string NetworkSyncStrategy::GetKey(int32_t user, const std::string &bundleName) +{ + return Constant::Join(StrategyInfo::PREFIX, Constant::KEY_SEPARATOR, { std::to_string(user), bundleName }); +} + +bool NetworkSyncStrategy::Check(uint32_t strategy) +{ + auto networkType = DeviceManagerAdapter::GetInstance().GetNetworkType(); + if (networkType == DeviceManagerAdapter::NONE) { + networkType = DeviceManagerAdapter::GetInstance().GetNetworkType(true); + } + switch (networkType) { + case DeviceManagerAdapter::WIFI: + case DeviceManagerAdapter::ETHERNET: + return (strategy & WIFI) == WIFI; + case DeviceManagerAdapter::CELLULAR: + return (strategy & CELLULAR) == CELLULAR; + default: + ZLOGD("verification failed! strategy:%{public}d, networkType:%{public}d", strategy, networkType); + return false; + } +} + +NetworkSyncStrategy::StrategyInfo NetworkSyncStrategy::GetStrategy(int32_t user, const std::string &bundleName) +{ + auto [res, info] = strategies_.Find(bundleName); + if (res) { + return info; + } + MetaDataManager::GetInstance().LoadMeta(GetKey(user, bundleName), info, true); + strategies_.Insert(info.bundleName, info); + return info; +} +} diff --git a/datamgr_service/services/distributeddataservice/service/cloud/sync_strategies/network_sync_strategy.h b/datamgr_service/services/distributeddataservice/service/cloud/sync_strategies/network_sync_strategy.h new file mode 100644 index 0000000000000000000000000000000000000000..369128f15c06be0569dcb931610e17401d1c8e53 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/cloud/sync_strategies/network_sync_strategy.h @@ -0,0 +1,57 @@ +/* + * 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_SERVICES_CLOUD_NETWORK_SYNC_STRATEGY_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_NETWORK_SYNC_STRATEGY_H +#include "cloud/sync_strategy.h" +#include "concurrent_map.h" +#include "serializable/serializable.h" +namespace OHOS::CloudData { +class NetworkSyncStrategy : public DistributedData::SyncStrategy { +public: + using StoreInfo = DistributedData::StoreInfo; + enum Strategy : uint32_t { + // should equal to NetWorkStrategy::WIFI in cloud_types.h + WIFI = 0x01, + // should equal to NetWorkStrategy::CELLULAR in cloud_types.h + CELLULAR = 0x02, + BUTT + }; + struct StrategyInfo : public DistributedData::Serializable { + int32_t user = INVALID_USER; + std::string bundleName; + uint32_t strategy = DEFAULT_STRATEGY; + bool Marshal(json &node) const override; + bool Unmarshal(const json &node) override; + std::string GetKey(); + static constexpr uint32_t INVALID_USER = -1; + static constexpr const char *PREFIX = "NETWORK_SYNC_STRATEGY"; + }; + NetworkSyncStrategy(); + ~NetworkSyncStrategy(); + int32_t CheckSyncAction(const StoreInfo& storeInfo) override; + + static std::string GetKey(int32_t user); + static std::string GetKey(int32_t user, const std::string& bundleName); +private: + StrategyInfo GetStrategy(int32_t user, const std::string& bundleName); + + static bool Check(uint32_t strategy); + static constexpr uint32_t DEFAULT_STRATEGY = WIFI | CELLULAR; + std::shared_ptr next_; + int32_t user_ = -1; + ConcurrentMap strategies_; +}; +} +#endif //OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_NETWORK_SYNC_STRATEGY_H diff --git a/datamgr_service/services/distributeddataservice/service/common/common_types_utils.cpp b/datamgr_service/services/distributeddataservice/service/common/common_types_utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5ba62e002f7dc573bb47a2b2da61d9407d6e19bc --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/common/common_types_utils.cpp @@ -0,0 +1,31 @@ +/* +* 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 "common_types_utils.h" + +namespace OHOS::ITypesUtil { +template<> +bool Marshalling(const Asset &input, MessageParcel &data) +{ + return ITypesUtil::Marshal(data, input.name, input.uri, input.path, input.createTime, + input.modifyTime, input.size, input.status, input.hash); +} +template<> +bool Unmarshalling(Asset &output, MessageParcel &data) +{ + return Unmarshal(data, output.name, output.uri, output.path, output.createTime, + output.modifyTime, output.size, output.status, output.hash); +} +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/common/common_types_utils.h b/datamgr_service/services/distributeddataservice/service/common/common_types_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..1d79d350b6243dcc21a22e4fa157ebacdbaabb75 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/common/common_types_utils.h @@ -0,0 +1,27 @@ +/* +* 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_DATAMGR_SERVICE_COMMON_COMMON_TYPES_UTILS_H +#define OHOS_DISTRIBUTED_DATA_DATAMGR_SERVICE_COMMON_COMMON_TYPES_UTILS_H + +#include "itypes_util.h" +#include "common_types.h" +namespace OHOS::ITypesUtil { +using Asset = OHOS::CommonType::Asset; +template<> +bool Marshalling(const Asset &input, MessageParcel &data); +template<> +bool Unmarshalling(Asset &output, MessageParcel &data); +} +#endif // OHOS_DISTRIBUTED_DATA_DATAMGR_SERVICE_COMMON_COMMON_TYPES_UTILS_H diff --git a/datamgr_service/services/distributeddataservice/service/data_share/BUILD.gn b/datamgr_service/services/distributeddataservice/service/data_share/BUILD.gn index 51c1d15038621490a97bd2d3eae55b39a8201a15..2b7931617b4ebad078180925ad46abda6bc3b502 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/data_share/BUILD.gn @@ -28,6 +28,7 @@ config("module_public_config") { "${datashare_path}/interfaces/inner_api/common/include", "${datashare_path}/interfaces/inner_api/consumer/include", "../crypto/include", + "../permission/include", ] } group("build_module") { @@ -56,6 +57,7 @@ ohos_shared_library("data_share_service") { "data/published_data.cpp", "data/resultset_json_formatter.cpp", "data/template_data.cpp", + "data_provider_config.cpp", "data_share_obs_proxy.cpp", "data_share_profile_config.cpp", "data_share_service_impl.cpp", 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 new file mode 100644 index 0000000000000000000000000000000000000000..141b574f7d289fed807ef75bb68bf9a517e884e0 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/data_share/data_provider_config.cpp @@ -0,0 +1,127 @@ +/* +* 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 "DataProviderConfig" + +#include "data_provider_config.h" + +#include "accesstoken_kit.h" +#include "account/account_delegate.h" +#include "datashare_errno.h" +#include "hap_token_info.h" +#include "log_print.h" +#include "utils/anonymous.h" + +namespace OHOS::DataShare { +using namespace OHOS::DistributedData; +DataProviderConfig::DataProviderConfig(const std::string &uri, uint32_t callerTokenId) +{ + providerInfo_.uri = uri; + providerInfo_.currentUserId = DistributedKv::AccountDelegate::GetInstance()->GetUserByToken(callerTokenId); +} + +int DataProviderConfig::GetFromProxyData() +{ + Uri uriTemp(providerInfo_.uri); + if (uriTemp.GetAuthority().empty()) { + ZLOGE("proxy authority empty! uri: %{public}s", Anonymous::Change(providerInfo_.uri).c_str()); + return E_URI_NOT_EXIST; + } + providerInfo_.bundleName = uriTemp.GetAuthority(); + BundleInfo bundleInfo; + if (!BundleMgrProxy::GetInstance()->GetBundleInfoFromBMS( + providerInfo_.bundleName, providerInfo_.currentUserId, bundleInfo)) { + ZLOGE("BundleInfo failed! bundleName: %{public}s", providerInfo_.bundleName.c_str()); + return E_BUNDLE_NAME_NOT_EXIST; + } + for (auto &hapModuleInfo : bundleInfo.hapModuleInfos) { + for (auto &data : hapModuleInfo.proxyDatas) { + if (data.uri != providerInfo_.uri) { + continue; + } + providerInfo_.uri = std::move(data.uri); + providerInfo_.readPermission = std::move(data.requiredReadPermission); + providerInfo_.writePermission = std::move(data.requiredWritePermission); + providerInfo_.moduleName = std::move(hapModuleInfo.moduleName); + return E_OK; + } + } + return E_URI_NOT_EXIST; +} + +int DataProviderConfig::GetFromExtension() +{ + if (!GetFromUriPath()) { + ZLOGE("Uri Path failed! uri:%{public}s", Anonymous::Change(providerInfo_.uri).c_str()); + return E_URI_NOT_EXIST; + } + BundleInfo bundleInfo; + if (!BundleMgrProxy::GetInstance()->GetBundleInfoFromBMS( + providerInfo_.bundleName, providerInfo_.currentUserId, bundleInfo)) { + ZLOGE("BundleInfo failed! bundleName: %{public}s", providerInfo_.bundleName.c_str()); + return E_BUNDLE_NAME_NOT_EXIST; + } + if (bundleInfo.extensionInfos.size() == 0) { + ZLOGE("extension empty! uri:%{public}s", Anonymous::Change(providerInfo_.uri).c_str()); + return E_URI_NOT_EXIST; + } + ExtensionAbility firstExtension = bundleInfo.extensionInfos.at(0); + for (auto &item : bundleInfo.extensionInfos) { + if (item.type != AppExecFwk::ExtensionAbilityType::DATASHARE) { + continue; + } + Uri uriTemp(item.uri); + if (providerInfo_.uri.find(uriTemp.GetAuthority()) == std::string::npos) { + continue; + } + firstExtension = item; + break; + } + providerInfo_.readPermission = std::move(firstExtension.readPermission); + providerInfo_.writePermission = std::move(firstExtension.writePermission); + return E_OK; +} + +bool DataProviderConfig::GetFromUriPath() +{ + Uri uriTemp(providerInfo_.uri); + std::vector pathSegments; + uriTemp.GetPathSegments(pathSegments); + if (pathSegments.size() < static_cast(PATH_PARAM::PARAM_SIZE) || + pathSegments[static_cast(PATH_PARAM::BUNDLE_NAME)].empty() || + pathSegments[static_cast(PATH_PARAM::MODULE_NAME)].empty() || + pathSegments[static_cast(PATH_PARAM::STORE_NAME)].empty() || + pathSegments[static_cast(PATH_PARAM::TABLE_NAME)].empty()) { + ZLOGE("Invalid uri ! uri: %{public}s", Anonymous::Change(providerInfo_.uri).c_str()); + return false; + } + providerInfo_.bundleName = pathSegments[static_cast(PATH_PARAM::BUNDLE_NAME)]; + providerInfo_.moduleName = pathSegments[static_cast(PATH_PARAM::MODULE_NAME)]; + providerInfo_.storeName = pathSegments[static_cast(PATH_PARAM::STORE_NAME)]; + providerInfo_.tableName = pathSegments[static_cast(PATH_PARAM::TABLE_NAME)]; + return true; +} + +std::pair DataProviderConfig::GetProviderInfo(bool isProxyData) +{ + auto func = isProxyData ? + &DataProviderConfig::GetFromProxyData : &DataProviderConfig::GetFromExtension; + auto ret = (this->*func)(); + if (ret != E_OK) { + ZLOGE("failed! isProxyData:%{public}d, ret: %{public}d, uri: %{public}s", + isProxyData, ret, Anonymous::Change(providerInfo_.uri).c_str()); + } + return std::make_pair(ret, providerInfo_); +} +} // namespace OHOS::DataShare 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 new file mode 100644 index 0000000000000000000000000000000000000000..afc66085a11d450848709a4604ad3a9fb8f22ced --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/data_share/data_provider_config.h @@ -0,0 +1,61 @@ +/* +* 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 DATASHARESERVICE_DATA_PROVIDER_CONFIG_H +#define DATASHARESERVICE_DATA_PROVIDER_CONFIG_H + +#include +#include + +#include "account/account_delegate.h" +#include "bundle_mgr_proxy.h" +#include "data_share_profile_info.h" +#include "hap_module_info.h" +#include "uri_utils.h" + +namespace OHOS::DataShare { +using namespace OHOS::RdbBMSAdapter; +using BundleInfo = OHOS::AppExecFwk::BundleInfo; +using ExtensionAbility = OHOS::AppExecFwk::ExtensionAbilityInfo; +class DataProviderConfig { +public: + DataProviderConfig(const std::string &uri, uint32_t callerTokenId); + + struct ProviderInfo { + std::string uri; + int32_t currentUserId = -1; + std::string bundleName; + std::string moduleName; + std::string storeName; + std::string tableName; + std::string readPermission; + std::string writePermission; + }; + + std::pair GetProviderInfo(bool isProxyData); +private: + bool GetFromUriPath(); + int GetFromProxyData(); + int GetFromExtension(); + enum class PATH_PARAM : int32_t { + BUNDLE_NAME = 0, + MODULE_NAME, + STORE_NAME, + TABLE_NAME, + PARAM_SIZE + }; + ProviderInfo providerInfo_; +}; +} // namespace OHOS::DataShare +#endif 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 5a1664050595b30c05c63cc3201cb3a863a71fb3..1d9994832cac82cae9ddf43e71799bc910e95392 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 @@ -22,6 +22,8 @@ #include "app_connect_manager.h" #include "common_event_manager.h" #include "common_event_support.h" +#include "data_ability_observer_interface.h" +#include "data_provider_config.h" #include "dataobs_mgr_client.h" #include "datashare_errno.h" #include "datashare_template.h" @@ -31,6 +33,7 @@ #include "ipc_skeleton.h" #include "log_print.h" #include "matching_skills.h" +#include "permit_delegate.h" #include "scheduler_manager.h" #include "subscriber_managers/published_data_subscriber_manager.h" #include "template_data.h" @@ -39,6 +42,7 @@ namespace OHOS::DataShare { using FeatureSystem = DistributedData::FeatureSystem; using DumpManager = OHOS::DistributedData::DumpManager; +using namespace OHOS::DistributedData; __attribute__((used)) DataShareServiceImpl::Factory DataShareServiceImpl::factory_; DataShareServiceImpl::Factory::Factory() { @@ -618,4 +622,72 @@ bool DataShareServiceImpl::IsSilentProxyEnable(const std::string &uri) } return success; } + +int32_t DataShareServiceImpl::RegisterObserver(const std::string &uri, + const sptr &remoteObj) +{ + auto callerTokenId = IPCSkeleton::GetCallingTokenID(); + DataProviderConfig providerConfig(uri, callerTokenId); + auto isProxyData = PROXY_URI_SCHEMA == Uri(uri).GetScheme(); + auto [errCode, providerInfo] = providerConfig.GetProviderInfo(isProxyData); + if (errCode != E_OK) { + ZLOGE("ProviderInfo failed! token:0x%{public}x,ret:%{public}d,uri:%{public}s", callerTokenId, + errCode, DistributedData::Anonymous::Change(providerInfo.uri).c_str()); + return errCode; + } + if (isProxyData && providerInfo.readPermission.empty()) { + ZLOGE("reject permission, tokenId:0x%{public}x, uri:%{public}s", callerTokenId, uri.c_str()); + return ERR_PERMISSION_DENIED; + } + if (!PermitDelegate::VerifyPermission(providerInfo.readPermission, callerTokenId)) { + ZLOGE("Permission denied! token:0x%{public}x, permission:%{public}s, uri:%{public}s", + callerTokenId, providerInfo.readPermission.c_str(), + DistributedData::Anonymous::Change(providerInfo.uri).c_str()); + return ERR_PERMISSION_DENIED; + } + auto obServer = iface_cast(remoteObj); + if (obServer == nullptr) { + ZLOGE("ObServer is nullptr, uri: %{public}s", DistributedData::Anonymous::Change(uri).c_str()); + return ERR_INVALID_VALUE; + } + auto obsMgrClient = AAFwk::DataObsMgrClient::GetInstance(); + if (obsMgrClient == nullptr) { + return ERROR; + } + return obsMgrClient->RegisterObserver(Uri(uri), obServer); +} + +int32_t DataShareServiceImpl::UnregisterObserver(const std::string &uri, + const sptr &remoteObj) +{ + auto callerTokenId = IPCSkeleton::GetCallingTokenID(); + DataProviderConfig providerConfig(uri, callerTokenId); + auto isProxyData = PROXY_URI_SCHEMA == Uri(uri).GetScheme(); + auto [errCode, providerInfo] = providerConfig.GetProviderInfo(isProxyData); + if (errCode != E_OK) { + ZLOGE("ProviderInfo failed! token:0x%{public}x,ret:%{public}d,uri:%{public}s", callerTokenId, + errCode, DistributedData::Anonymous::Change(providerInfo.uri).c_str()); + return errCode; + } + if (isProxyData && providerInfo.readPermission.empty()) { + ZLOGE("reject permission, tokenId:0x%{public}x, uri:%{public}s", callerTokenId, uri.c_str()); + return ERR_PERMISSION_DENIED; + } + if (!PermitDelegate::VerifyPermission(providerInfo.readPermission, callerTokenId)) { + ZLOGE("Permission denied! token:0x%{public}x, permission:%{public}s, uri:%{public}s", + callerTokenId, providerInfo.readPermission.c_str(), + DistributedData::Anonymous::Change(providerInfo.uri).c_str()); + return ERR_PERMISSION_DENIED; + } + auto obsMgrClient = AAFwk::DataObsMgrClient::GetInstance(); + if (obsMgrClient == nullptr) { + return ERROR; + } + auto obServer = iface_cast(remoteObj); + if (obServer == nullptr) { + ZLOGE("ObServer is nullptr, uri: %{public}s", DistributedData::Anonymous::Change(uri).c_str()); + return ERR_INVALID_VALUE; + } + return obsMgrClient->UnregisterObserver(Uri(uri), obServer); +} } // namespace OHOS::DataShare diff --git a/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_impl.h b/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_impl.h index 07e7cec3cee88ce4efd2ff90fbd0704557ffd043..f8d6b48909c0e170c7266fc982c3f1370d7c51f9 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_impl.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_impl.h @@ -81,6 +81,8 @@ public: int32_t OnInitialize() override; int32_t EnableSilentProxy(const std::string &uri, bool enable) override; bool IsSilentProxyEnable(const std::string &uri) override; + int32_t RegisterObserver(const std::string &uri, const sptr &remoteObj) override; + int32_t UnregisterObserver(const std::string &uri, const sptr &remoteObj) override; private: using StaticActs = DistributedData::StaticActs; @@ -110,6 +112,7 @@ private: bool GetCallerBundleName(std::string &bundleName); static Factory factory_; static constexpr int32_t ERROR = -1; + static constexpr const char *PROXY_URI_SCHEMA = "datashareproxy"; PublishStrategy publishStrategy_; GetDataStrategy getDataStrategy_; SubscribeStrategy subscribeStrategy_; diff --git a/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_stub.cpp b/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_stub.cpp index 593ee190089fa08b382fd77751aeb52c72f2f18a..7f84313c504335676636e6d4c42ed75a87377f00 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_stub.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_stub.cpp @@ -381,5 +381,39 @@ int32_t DataShareServiceStub::OnRemoteIsSilentProxyEnable(MessageParcel &data, M } return E_OK; } + +int32_t DataShareServiceStub::OnRemoteRegisterObserver(MessageParcel &data, MessageParcel &reply) +{ + std::string uri; + sptr remoteObj; + if (!ITypesUtil::Unmarshal(data, uri, remoteObj)) { + ZLOGE("Unmarshal failed,uri: %{public}s", DistributedData::Anonymous::Change(uri).c_str()); + return IPC_STUB_INVALID_DATA_ERR; + } + int32_t status = RegisterObserver(uri, remoteObj); + if (!ITypesUtil::Marshal(reply, status)) { + ZLOGE("Marshal failed,status:0x%{public}x,uri:%{public}s", status, + DistributedData::Anonymous::Change(uri).c_str()); + return IPC_STUB_WRITE_PARCEL_ERR; + } + return E_OK; +} + +int32_t DataShareServiceStub::OnRemoteUnregisterObserver(MessageParcel &data, MessageParcel &reply) +{ + std::string uri; + sptr remoteObj; + if (!ITypesUtil::Unmarshal(data, uri, remoteObj)) { + ZLOGE("Unmarshal failed,uri: %{public}s", DistributedData::Anonymous::Change(uri).c_str()); + return IPC_STUB_INVALID_DATA_ERR; + } + int32_t status = UnregisterObserver(uri, remoteObj); + if (!ITypesUtil::Marshal(reply, status)) { + ZLOGE("Marshal failed,status:0x%{public}x,uri:%{public}s", status, + DistributedData::Anonymous::Change(uri).c_str()); + return IPC_STUB_WRITE_PARCEL_ERR; + } + return E_OK; +} } // namespace DataShare } // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_stub.h b/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_stub.h index e350eb1ce04d88e956d7876f2df29394157ec75f..5e213657c25c03c23cbcecef7264f02e95240c77 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_stub.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_stub.h @@ -48,6 +48,8 @@ private: int32_t OnRemoteNotifyObserver(MessageParcel& data, MessageParcel& reply); int32_t OnRemoteSetSilentSwitch(MessageParcel& data, MessageParcel& reply); int32_t OnRemoteIsSilentProxyEnable(MessageParcel& data, MessageParcel& reply); + int32_t OnRemoteRegisterObserver(MessageParcel& data, MessageParcel& reply); + int32_t OnRemoteUnregisterObserver(MessageParcel& data, MessageParcel& reply); using RequestHandle = int (DataShareServiceStub::*)(MessageParcel &, MessageParcel &); static constexpr RequestHandle HANDLERS[DATA_SHARE_SERVICE_CMD_MAX] = { &DataShareServiceStub::OnRemoteInsert, @@ -69,7 +71,9 @@ private: &DataShareServiceStub::OnRemoteNotifyConnectDone, &DataShareServiceStub::OnRemoteNotifyObserver, &DataShareServiceStub::OnRemoteSetSilentSwitch, - &DataShareServiceStub::OnRemoteIsSilentProxyEnable}; + &DataShareServiceStub::OnRemoteIsSilentProxyEnable, + &DataShareServiceStub::OnRemoteRegisterObserver, + &DataShareServiceStub::OnRemoteUnregisterObserver}; }; } // namespace DataShare } // namespace OHOS diff --git a/datamgr_service/services/distributeddataservice/service/data_share/idata_share_service.h b/datamgr_service/services/distributeddataservice/service/data_share/idata_share_service.h index 83d16bc3c1913568c79adb6fbb603f5fe6fa2971..2276ab588fd9cb2d933af106c8663d2429dba25a 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/idata_share_service.h +++ b/datamgr_service/services/distributeddataservice/service/data_share/idata_share_service.h @@ -24,6 +24,7 @@ #include "datashare_values_bucket.h" #include "datashare_template.h" #include "data_proxy_observer.h" +#include "iremote_object.h" namespace OHOS::DataShare { class IDataShareService { @@ -49,6 +50,8 @@ public: DATA_SHARE_SERVICE_CMD_NOTIFY_OBSERVERS, DATA_SHARE_SERVICE_CMD_SET_SILENT_SWITCH, DATA_SHARE_SERVICE_CMD_IS_SILENT_PROXY_ENABLE, + DATA_SHARE_SERVICE_CMD_REGISTER_OBSERVER, + DATA_SHARE_SERVICE_CMD_UNREGISTER_OBSERVER, DATA_SHARE_SERVICE_CMD_MAX }; @@ -85,6 +88,9 @@ public: virtual void NotifyObserver(const std::string &uri) = 0; virtual int32_t EnableSilentProxy(const std::string &uri, bool enable) = 0; virtual bool IsSilentProxyEnable(const std::string &uri) = 0; + virtual int32_t RegisterObserver(const std::string &uri, const sptr &remoteObj) = 0; + virtual int32_t UnregisterObserver(const std::string &uri, + const sptr &remoteObj) = 0; }; } // namespace OHOS::DataShare #endif 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 6f17ca9ea600c812db69747c74ce7655a069e143..7d2be643d84a7a60efce43602fdc6fa9319b6cab 100644 --- a/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/kvdb/kvdb_service_impl.cpp @@ -540,6 +540,9 @@ int32_t KVDBServiceImpl::OnUserChange(uint32_t code, const std::string &user, co int32_t KVDBServiceImpl::OnReady(const std::string &device) { + if (device == DeviceManagerAdapter::CLOUD_DEVICE_UUID) { + return SUCCESS; + } std::vector metaData; auto prefix = StoreMetaData::GetPrefix({ DMAdapter::GetInstance().GetLocalDevice().uuid }); if (!MetaDataManager::GetInstance().LoadMeta(prefix, metaData)) { diff --git a/datamgr_service/services/distributeddataservice/service/object/object_asset_machine.h b/datamgr_service/services/distributeddataservice/service/object/object_asset_machine.h index fef1ccee2c86913058c35ec2c4339f7f7ee999cc..14283191bd486b62b1e6e8db591ec5c5c2e23428 100644 --- a/datamgr_service/services/distributeddataservice/service/object/object_asset_machine.h +++ b/datamgr_service/services/distributeddataservice/service/object/object_asset_machine.h @@ -18,6 +18,7 @@ #define DISTRIBUTEDDATAMGR_OBJECT_ASSET_MACHINE_H #include "snapshot/machine_status.h" +#include "store/store_info.h" namespace OHOS { namespace DistributedObject { diff --git a/datamgr_service/services/distributeddataservice/service/object/object_types_utils.cpp b/datamgr_service/services/distributeddataservice/service/object/object_types_utils.cpp index 544efac34d51a460d402499750ba56433a865c42..21f9e7b28ee72ef686f25d019b4ad1b90db5ab6a 100644 --- a/datamgr_service/services/distributeddataservice/service/object/object_types_utils.cpp +++ b/datamgr_service/services/distributeddataservice/service/object/object_types_utils.cpp @@ -22,10 +22,4 @@ bool Unmarshalling(AssetBindInfo &output, MessageParcel &data) return ITypesUtil::Unmarshal(data, output.storeName, output.tableName, output.primaryKey, output.field, output.assetName); } -template<> -bool Unmarshalling(Asset &output, MessageParcel &data) -{ - return Unmarshal(data, output.name, output.uri, output.path, output.createTime, - output.modifyTime, output.size, output.status, output.hash); -} } \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/object/object_types_utils.h b/datamgr_service/services/distributeddataservice/service/object/object_types_utils.h index 34cb3bc20f9ce52f4344c4cd0c8d7749570a78c0..20d9939c02ab2257b2f926802321343b9929e7af 100644 --- a/datamgr_service/services/distributeddataservice/service/object/object_types_utils.h +++ b/datamgr_service/services/distributeddataservice/service/object/object_types_utils.h @@ -20,10 +20,7 @@ namespace OHOS::ITypesUtil { using AssetBindInfo = OHOS::ObjectStore::AssetBindInfo; -using Asset = OHOS::ObjectStore::Asset; template<> bool Unmarshalling(AssetBindInfo &output, MessageParcel &data); -template<> -bool Unmarshalling(Asset &output, MessageParcel &data); } #endif // DISTRIBUTEDDATAMGR_OBJECT_TYPES_UTILS_H diff --git a/datamgr_service/services/distributeddataservice/service/permission/include/permit_delegate.h b/datamgr_service/services/distributeddataservice/service/permission/include/permit_delegate.h index 23853358f0ab447d4443a4c095b1c5dab89782da..3a93ef9d55e819980baeed9c3ea3d0605ff1240b 100644 --- a/datamgr_service/services/distributeddataservice/service/permission/include/permit_delegate.h +++ b/datamgr_service/services/distributeddataservice/service/permission/include/permit_delegate.h @@ -37,6 +37,8 @@ public: API_EXPORT bool SyncActivate(const ActiveParam ¶m); API_EXPORT bool VerifyPermission(const CheckParam ¶m, uint8_t flag); API_EXPORT void DelCache(const std::string &key); + API_EXPORT static bool VerifyPermission(const std::string &permission, + uint32_t callerTokenId); private: PermitDelegate(); diff --git a/datamgr_service/services/distributeddataservice/service/permission/src/permit_delegate.cpp b/datamgr_service/services/distributeddataservice/service/permission/src/permit_delegate.cpp index 52b9af7c4e4c59c0c06f9c8d3c555f601a40d843..5e59276f95cc3a15f235f1ee32fabb145de14099 100644 --- a/datamgr_service/services/distributeddataservice/service/permission/src/permit_delegate.cpp +++ b/datamgr_service/services/distributeddataservice/service/permission/src/permit_delegate.cpp @@ -15,6 +15,7 @@ #define LOG_TAG "PermitDelegate" #include "permit_delegate.h" +#include "accesstoken_kit.h" #include "device_manager_adapter.h" #include "log_print.h" #include "metadata/appid_meta_data.h" @@ -158,4 +159,17 @@ void PermitDelegate::DelCache(const std::string &key) { metaDataBucket_.Delete(key); } + +bool PermitDelegate::VerifyPermission(const std::string &permission, + uint32_t callerTokenId) +{ + if (!permission.empty()) { + int status = + Security::AccessToken::AccessTokenKit::VerifyAccessToken(callerTokenId, permission); + if (status != Security::AccessToken::PermissionState::PERMISSION_GRANTED) { + return false; + } + } + return true; +} } // namespace OHOS::DistributedData 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 1ba52d4c739ff855d4a0015f981a06c24cc1f28e..a26d1e21ab0b7cc3cfadc53b40c2814925f8ef53 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp @@ -428,7 +428,7 @@ int RdbServiceImpl::DoSync(const RdbSyncerParam ¶m, const RdbService::Option void RdbServiceImpl::DoCompensateSync(const BindEvent& event) { auto bindInfo = event.GetBindInfo(); - CloudEvent::StoreInfo storeInfo; + StoreInfo storeInfo; storeInfo.bundleName = bindInfo.bundleName; storeInfo.tokenId = bindInfo.tokenId; storeInfo.user = bindInfo.user; @@ -454,7 +454,7 @@ void RdbServiceImpl::DoCompensateSync(const BindEvent& event) void RdbServiceImpl::DoCloudSync(const RdbSyncerParam ¶m, const RdbService::Option &option, const PredicatesMemo &predicates, const AsyncDetail &async) { - CloudEvent::StoreInfo storeInfo; + StoreInfo storeInfo; storeInfo.bundleName = param.bundleName_; storeInfo.tokenId = IPCSkeleton::GetCallingTokenID(); storeInfo.user = AccountDelegate::GetInstance()->GetUserByToken(storeInfo.tokenId); @@ -628,7 +628,7 @@ std::pair> RdbServiceImpl::Query auto rdbQuery = std::make_shared(); rdbQuery->MakeQuery(predicates); rdbQuery->SetColumns(columns); - CloudEvent::StoreInfo storeInfo; + StoreInfo storeInfo; storeInfo.bundleName = param.bundleName_; storeInfo.tokenId = IPCSkeleton::GetCallingTokenID(); storeInfo.user = AccountDelegate::GetInstance()->GetUserByToken(storeInfo.tokenId); @@ -642,7 +642,7 @@ std::pair> RdbServiceImpl::Query return { RDB_OK, std::make_shared(cursor) }; } -std::pair> RdbServiceImpl::AllocResource(CloudEvent::StoreInfo& storeInfo, +std::pair> RdbServiceImpl::AllocResource(StoreInfo& storeInfo, std::shared_ptr rdbQuery) { std::pair> result; @@ -668,7 +668,7 @@ int32_t RdbServiceImpl::GetSchema(const RdbSyncerParam ¶m) } if (executors_ != nullptr) { - CloudEvent::StoreInfo storeInfo; + StoreInfo storeInfo; storeInfo.tokenId = IPCSkeleton::GetCallingTokenID(); storeInfo.bundleName = param.bundleName_; storeInfo.storeName = RemoveSuffix(param.storeName_); @@ -959,7 +959,7 @@ int32_t RdbServiceImpl::NotifyDataChange(const RdbSyncerParam ¶m, const RdbC Anonymous::Change(param.storeName_).c_str()); return RDB_ERROR; } - CloudEvent::StoreInfo storeInfo; + StoreInfo storeInfo; storeInfo.tokenId = IPCSkeleton::GetCallingTokenID(); storeInfo.bundleName = param.bundleName_; storeInfo.storeName = RemoveSuffix(param.storeName_); 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 5c21e6f7b9b9665725039f3f69be75de07bb7657..309bf4707a40e229a74a567c1f8e3eead4da0515 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h @@ -43,7 +43,7 @@ public: using SecretKeyMetaData = DistributedData::SecretKeyMetaData; using DetailAsync = DistributedData::GeneralStore::DetailAsync; using Handler = std::function> &)>; - using StoreInfo = DistributedData::CloudEvent::StoreInfo; + using StoreInfo = DistributedData::StoreInfo; RdbServiceImpl(); virtual ~RdbServiceImpl(); diff --git a/datamgr_service/services/distributeddataservice/service/test/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/BUILD.gn index c1e32f9468af69a46bd2bd7d4087f2e26a888e41..4fc4238fbf86827e518388353e0cad94a230a779 100644 --- a/datamgr_service/services/distributeddataservice/service/test/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/test/BUILD.gn @@ -373,6 +373,53 @@ ohos_unittest("MetaDataTest") { ] } +ohos_unittest("UdmfRunTimeStoreTest") { + module_out_path = module_output_path + sources = [ + "${data_service_path}/app/src/kvstore_meta_manager.cpp", + "udmf_run_time_store_test.cpp", + ] + + include_dirs = [ + "${data_service_path}/adapter/include/account", + "${data_service_path}/adapter/include/communicator", + "${data_service_path}/app/src", + "${data_service_path}/service/kvdb", + "${data_service_path}/service/udmf", + "${kv_store_path}/frameworks/innerkitsimpl/distributeddatafwk/include", + "${kv_store_path}/frameworks/innerkitsimpl/distributeddatasvc/include", + "${kv_store_path}/frameworks/innerkitsimpl/kvdb/include", + ] + + configs = [ ":module_private_config" ] + + external_deps = [ + "ability_base:base", + "ability_base:want", + "access_token:libaccesstoken_sdk", + "access_token:libnativetoken", + "access_token:libtoken_setproc", + "c_utils:utils", + "dataclassification:data_transit_mgr", + "dsoftbus:softbus_client", + "hilog:libhilog", + "ipc:ipc_core", + "kv_store:distributeddata_inner", + "udmf:udmf_client", + ] + + deps = [ + "${data_service_path}/adapter:distributeddata_adapter", + "${data_service_path}/adapter/communicator:distributeddata_communicator_static", + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/service:distributeddatasvc", + "${data_service_path}/service/udmf:udmf_server", + "${kv_store_path}/frameworks/libs/distributeddb:distributeddb", + "//third_party/googletest:gtest_main", + "//third_party/openssl:libcrypto_shared", + ] +} + ############################################################################### group("unittest") { testonly = true @@ -392,6 +439,7 @@ group("unittest") { ":MetaDataTest", ":ObjectAssetMachineTest", ":RdbResultSetImplTest", + ":UdmfRunTimeStoreTest", ":ValueProxyTest", ] } 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 6b8c965a22942e3e438f8edc4a28d028cae79972..09f631376efab915dc06ac99e9d02d1d05b1d374 100644 --- a/datamgr_service/services/distributeddataservice/service/test/cloud_data_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/cloud_data_test.cpp @@ -28,6 +28,7 @@ #include "metadata/store_meta_data.h" #include "metadata/store_meta_data_local.h" #include "mock/db_store_mock.h" +#include "store/store_info.h" #include "rdb_types.h" using namespace testing::ext; using namespace OHOS::DistributedData; @@ -188,7 +189,7 @@ HWTEST_F(CloudDataTest, GetSchema, TestSize.Level0) SchemaMeta schemaMeta; ASSERT_FALSE( MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetSchemaKey(TEST_CLOUD_BUNDLE), schemaMeta, true)); - CloudEvent::StoreInfo storeInfo { OHOS::IPCSkeleton::GetCallingTokenID(), TEST_CLOUD_BUNDLE, TEST_CLOUD_STORE, 0 }; + StoreInfo storeInfo { OHOS::IPCSkeleton::GetCallingTokenID(), TEST_CLOUD_BUNDLE, TEST_CLOUD_STORE, 0 }; auto event = std::make_unique(CloudEvent::GET_SCHEMA, storeInfo); EventCenter::GetInstance().PostEvent(std::move(event)); ASSERT_FALSE( diff --git a/datamgr_service/services/distributeddataservice/service/test/cloud_test.cpp b/datamgr_service/services/distributeddataservice/service/test/cloud_test.cpp index fd87a48e51bd9eaa827898a0d3c6787d2db8edee..b1edd4951141a0701d41eeb29ade5f16f18a448c 100644 --- a/datamgr_service/services/distributeddataservice/service/test/cloud_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/cloud_test.cpp @@ -55,7 +55,7 @@ HWTEST_F(CloudTest, EventInfo, TestSize.Level1) SyncEvent::EventInfo eventInfo1(mode, wait, retry, query, async); SyncEvent::EventInfo eventInfo2(std::move(eventInfo1)); SyncEvent::EventInfo eventInfo3 = std::move(eventInfo2); - CloudEvent::StoreInfo storeInfo{ IPCSkeleton::GetCallingTokenID(), testCloudBundle, testCloudStore, 0 }; + StoreInfo storeInfo{ IPCSkeleton::GetCallingTokenID(), testCloudBundle, testCloudStore, 0 }; SyncEvent evt(storeInfo, eventInfo3); EXPECT_EQ(evt.GetMode(), mode); EXPECT_EQ(evt.GetWait(), wait); diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/cloudservicestub_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/fuzztest/cloudservicestub_fuzzer/BUILD.gn index 32dcbf688d4392f336ec9b182cf16977fcf1b1d3..09649a2110b04b2aae4f3bf16996223f693732d1 100644 --- a/datamgr_service/services/distributeddataservice/service/test/fuzztest/cloudservicestub_fuzzer/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/cloudservicestub_fuzzer/BUILD.gn @@ -69,6 +69,8 @@ ohos_fuzztest("CloudServiceStubFuzzTest") { "${data_service_path}/service/cloud/cloud_types_util.cpp", "${data_service_path}/service/cloud/cloud_value_util.cpp", "${data_service_path}/service/cloud/sync_manager.cpp", + "${data_service_path}/service/cloud/sync_strategies/network_sync_strategy.cpp", + "${data_service_path}/service/common/common_types_utils.cpp", "${data_service_path}/service/common/value_proxy.cpp", "${data_service_path}/service/config/src/config_factory.cpp", "${data_service_path}/service/config/src/model/backup_config.cpp", diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareservicestub_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareservicestub_fuzzer/BUILD.gn index 43c210eef236c060825143404aea92f6133b29aa..2c0ce064f4316d4a8c6dd58b5f3cc29709d11797 100644 --- a/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareservicestub_fuzzer/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/datashareservicestub_fuzzer/BUILD.gn @@ -29,6 +29,8 @@ ohos_fuzztest("DataShareServiceStubFuzzTest") { "${data_service_path}/service/data_share/strategies", "${data_service_path}/service/data_share/subscriber_managers", "${data_service_path}/service/data_share", + "${data_service_path}/service/kvdb", + "${data_service_path}/service/permission/include", "${datashare_path}/frameworks/native/common/include", "${datashare_path}/interfaces/inner_api/common/include", "${datashare_path}/interfaces/inner_api/consumer/include", @@ -62,6 +64,7 @@ ohos_fuzztest("DataShareServiceStubFuzzTest") { "${data_service_path}/service/data_share/data/published_data.cpp", "${data_service_path}/service/data_share/data/resultset_json_formatter.cpp", "${data_service_path}/service/data_share/data/template_data.cpp", + "${data_service_path}/service/data_share/data_provider_config.cpp", "${data_service_path}/service/data_share/data_share_obs_proxy.cpp", "${data_service_path}/service/data_share/data_share_profile_config.cpp", "${data_service_path}/service/data_share/data_share_service_impl.cpp", @@ -90,6 +93,7 @@ ohos_fuzztest("DataShareServiceStubFuzzTest") { "${data_service_path}/service/data_share/strategies/update_strategy.cpp", "${data_service_path}/service/data_share/subscriber_managers/published_data_subscriber_manager.cpp", "${data_service_path}/service/data_share/subscriber_managers/rdb_subscriber_manager.cpp", + "${data_service_path}/service/permission/src/permit_delegate.cpp", "datashareservicestub_fuzzer.cpp", ] diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicestub_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicestub_fuzzer/BUILD.gn index d8df633907bab6b10311ef2b93107537e6c67921..e5e6751134d6341b4a815fdae861399c288dd004 100644 --- a/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicestub_fuzzer/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/objectservicestub_fuzzer/BUILD.gn @@ -56,6 +56,7 @@ ohos_fuzztest("ObjectServiceStubFuzzTest") { sources = [ "${data_service_path}/service/backup/src/backup_manager.cpp", "${data_service_path}/service/bootstrap/src/bootstrap.cpp", + "${data_service_path}/service/common/common_types_utils.cpp", "${data_service_path}/service/common/value_proxy.cpp", "${data_service_path}/service/config/src/config_factory.cpp", "${data_service_path}/service/config/src/model/backup_config.cpp", 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 296fc94cecbe4e5f9782016e2bc4b326d934f9b1..9faf854c0e65735c3a94ffb1784dcbf7e281176b 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 @@ -64,12 +64,12 @@ void ObjectAssetMachineTest::SetUp() .assetName = "asset1.jpg", }; AssetBindInfo_ = AssetBindInfo; - StoreInfo storeInfo{ + StoreInfo storeInfo { .tokenId = 0, - .instanceId = 1, - .user = 100, .bundleName = "bundleName_test", .storeName = "store_test", + .instanceId = 1, + .user = 100, }; storeInfo_ = storeInfo; ChangedAssetInfo changedAssetInfo(asset, AssetBindInfo, storeInfo); diff --git a/datamgr_service/services/distributeddataservice/service/test/udmf_run_time_store_test.cpp b/datamgr_service/services/distributeddataservice/service/test/udmf_run_time_store_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e93f814fc61b3fd1e1de2bfc58d642441841c5e8 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/udmf_run_time_store_test.cpp @@ -0,0 +1,326 @@ +/* +* 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 "UdmfRunTimeStoreTest" +#include + +#include "accesstoken_kit.h" +#include "bootstrap.h" +#include "device_manager_adapter.h" +#include "executor_pool.h" +#include "gtest/gtest.h" +#include "ipc_skeleton.h" +#include "kvstore_meta_manager.h" +#include "metadata/meta_data_manager.h" +#include "nativetoken_kit.h" +#include "token_setproc.h" +#define private public +#include "store/runtime_store.h" +#undef private +using namespace testing::ext; +using namespace OHOS::DistributedData; +using namespace OHOS::Security::AccessToken; +using namespace OHOS::UDMF; +using DmAdapter = OHOS::DistributedData::DeviceManagerAdapter; +using Entry = DistributedDB::Entry; +using Key = DistributedDB::Key; +using Value = DistributedDB::Value; + +namespace OHOS::Test { +namespace DistributedDataTest { + +static void GrantPermissionNative() +{ + const char **perms = new const char *[2]; + perms[0] = "ohos.permission.DISTRIBUTED_DATASYNC"; + perms[1] = "ohos.permission.ACCESS_SERVICE_DM"; + TokenInfoParams infoInstance = { + .dcapsNum = 0, + .permsNum = 2, + .aclsNum = 0, + .dcaps = nullptr, + .perms = perms, + .acls = nullptr, + .processName = "distributed_data_test", + .aplStr = "system_basic", + }; + uint64_t tokenId = GetAccessTokenId(&infoInstance); + SetSelfTokenID(tokenId); + AccessTokenKit::ReloadNativeTokenInfo(); + delete[] perms; +} + +class UdmfRunTimeStoreTest : public testing::Test { +public: + static void SetUpTestCase(void) + { + GrantPermissionNative(); + DistributedData::Bootstrap::GetInstance().LoadComponents(); + DistributedData::Bootstrap::GetInstance().LoadDirectory(); + DistributedData::Bootstrap::GetInstance().LoadCheckers(); + size_t max = 2; + size_t min = 1; + auto executors = std::make_shared(max, min); + DmAdapter::GetInstance().Init(executors); + DistributedKv::KvStoreMetaManager::GetInstance().BindExecutor(executors); + DistributedKv::KvStoreMetaManager::GetInstance().InitMetaParameter(); + DistributedKv::KvStoreMetaManager::GetInstance().InitMetaListener(); + } + static void TearDownTestCase(void){}; + void SetUp(){}; + void TearDown(){}; + void GetRandomKey(std::vector& key, uint32_t defaultSize); + void GetRandomValue(std::vector& value, uint32_t defaultSize); + + const uint32_t MAX_KEY_SIZE = 1024; + const uint32_t MAX_VALUE_SIZE = 4 * 1024 * 1024; + const std::string STORE_ID = "drag"; + const std::string KEY_PREFIX = "TEST_"; +}; + +void UdmfRunTimeStoreTest::GetRandomKey(std::vector& key, uint32_t defaultSize) +{ + key.resize(defaultSize); + RAND_bytes(key.data(), defaultSize); + + if (defaultSize >= KEY_PREFIX.length()) { + vector vectorPrefix(KEY_PREFIX.begin(), KEY_PREFIX.end()); + std::copy(vectorPrefix.begin(), vectorPrefix.end(), key.begin()); + } +} + +void UdmfRunTimeStoreTest::GetRandomValue(std::vector& value, uint32_t defaultSize) +{ + value.resize(defaultSize); + RAND_bytes(value.data(), defaultSize); +} + +/** +* @tc.name: PutEntries001 +* @tc.desc: check for legal parameters, sum size of all entries is smaller than 512M. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfRunTimeStoreTest, PutEntries001, TestSize.Level1) +{ + auto store = std::make_shared(STORE_ID); + bool result = store->Init(); + EXPECT_EQ(true, result); + + Key key; + Value value; + GetRandomValue(value, MAX_KEY_SIZE); // 1K + vector entrysRand; + for (int i = 0; i < 129; ++i) { + GetRandomKey(key, MAX_KEY_SIZE); // 1K + entrysRand.push_back({ key, value }); + } + + int32_t status = store->PutEntries(entrysRand); + EXPECT_EQ(E_OK, status); + + vector entries; + status = store->GetEntries(KEY_PREFIX, entries); + EXPECT_EQ(E_OK, status); + EXPECT_EQ(129, entries.size()); + + status = store->Delete(KEY_PREFIX); + EXPECT_EQ(E_OK, status); +} + +/** +* @tc.name: PutEntries002 +* @tc.desc: check for legal parameters, sum size of all entries is equal to 512M. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfRunTimeStoreTest, PutEntries002, TestSize.Level1) +{ + auto store = std::make_shared(STORE_ID); + bool result = store->Init(); + EXPECT_EQ(true, result); + + Key key; + Value value; + GetRandomKey(key, MAX_KEY_SIZE); // 1K + GetRandomValue(value, MAX_VALUE_SIZE); // 4M + vector entrysRand(127, { key, value }); + Value emptyValue; + for (int i = 0; i < 3969; i++) { + entrysRand.push_back({ key, emptyValue }); + } + int32_t status = store->PutEntries(entrysRand); + EXPECT_EQ(E_OK, status); + + vector entries; + status = store->GetEntries(KEY_PREFIX, entries); + EXPECT_EQ(E_OK, status); + EXPECT_EQ(1, entries.size()); + + status = store->Delete(KEY_PREFIX); + EXPECT_EQ(E_OK, status); +} + +/** +* @tc.name: PutEntries003 +* @tc.desc: test rollback, sum size of all entries is larger to 512M. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfRunTimeStoreTest, PutEntries003, TestSize.Level1) +{ + auto store = std::make_shared(STORE_ID); + bool result = store->Init(); + EXPECT_EQ(true, result); + + Key key; + Value value; + GetRandomKey(key, MAX_KEY_SIZE); // 1K + GetRandomValue(value, MAX_VALUE_SIZE); // 4M + vector entrysRand(127, { key, value }); + Value emptyValue; + for (int i = 0; i < 3970; i++) { + entrysRand.push_back({ key, emptyValue }); + } + + int32_t status = store->PutEntries(entrysRand); + EXPECT_EQ(E_DB_ERROR, status); + + vector entries; + status = store->GetEntries(KEY_PREFIX, entries); + EXPECT_EQ(E_OK, status); + EXPECT_EQ(0, entries.size()); +} + +/** +* @tc.name: PutEntries004 +* @tc.desc: test rollback, illegal size of key or value. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfRunTimeStoreTest, PutEntries004, TestSize.Level1) +{ + auto store = std::make_shared(STORE_ID); + bool result = store->Init(); + EXPECT_EQ(true, result); + + Key key; + Key keyInvalid; + Value value; + Value valueInvalid; + GetRandomKey(key, MAX_KEY_SIZE); // 1K + GetRandomKey(keyInvalid, MAX_KEY_SIZE + 1); // 1K + 1 + GetRandomValue(value, MAX_VALUE_SIZE); // 4M + GetRandomValue(valueInvalid, MAX_VALUE_SIZE + 1); // 4M + 1 + vector entrysMix1(1, { keyInvalid, value }); + vector entrysMix2(1, { key, valueInvalid }); + + int32_t status = store->PutEntries(entrysMix1); + EXPECT_EQ(E_DB_ERROR, status); + vector entries; + status = store->GetEntries(KEY_PREFIX, entries); + EXPECT_EQ(E_OK, status); + EXPECT_EQ(0, entries.size()); + + status = store->PutEntries(entrysMix2); + EXPECT_EQ(E_DB_ERROR, status); + entries.clear(); + status = store->GetEntries(KEY_PREFIX, entries); + EXPECT_EQ(E_OK, status); + EXPECT_EQ(0, entries.size()); +} + +/** +* @tc.name: PutEntries005 +* @tc.desc: test rollback, mix illegal entries and legal entries. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfRunTimeStoreTest, PutEntries005, TestSize.Level1) +{ + auto store = std::make_shared(STORE_ID); + bool result = store->Init(); + EXPECT_EQ(true, result); + + Key key; + Key keyInvalid; + Value value; + Value valueInvalid; + vector entrysRand; + for (int i = 0; i < 129; ++i) { + GetRandomKey(key, MAX_KEY_SIZE); // 1K + GetRandomValue(value, MAX_KEY_SIZE); // 1K + entrysRand.push_back({ key, value }); + } + + GetRandomKey(keyInvalid, MAX_KEY_SIZE + 1); // 1K + 1 + GetRandomValue(value, MAX_KEY_SIZE); // 1K + entrysRand[128] = { keyInvalid, value }; + int32_t status = store->PutEntries(entrysRand); + EXPECT_EQ(E_DB_ERROR, status); + vector entries; + status = store->GetEntries(KEY_PREFIX, entries); + EXPECT_EQ(E_OK, status); + EXPECT_EQ(0, entries.size()); + + GetRandomKey(key, MAX_KEY_SIZE); // 1K + GetRandomValue(valueInvalid, MAX_VALUE_SIZE + 1); // 4M + 1 + entrysRand[128] = { key, valueInvalid }; + status = store->PutEntries(entrysRand); + EXPECT_EQ(E_DB_ERROR, status); + status = store->GetEntries(KEY_PREFIX, entries); + EXPECT_EQ(E_OK, status); + EXPECT_EQ(0, entries.size()); +} + +/** +* @tc.name: DeleteEntries001 +* @tc.desc: check for legal parameters, delete entries success. +* @tc.type: FUNC +* @tc.require: +*/ +HWTEST_F(UdmfRunTimeStoreTest, DeleteEntries001, TestSize.Level1) +{ + auto store = std::make_shared(STORE_ID); + bool result = store->Init(); + EXPECT_EQ(true, result); + + Value value; + GetRandomValue(value, MAX_KEY_SIZE); // 1K + vector keys(129); + vector entrysRand; + for (int i = 0; i < 129; ++i) { + GetRandomKey(keys[i], MAX_KEY_SIZE); // 1K + entrysRand.push_back({ keys[i], value }); + } + + int32_t status = store->PutEntries(entrysRand); + EXPECT_EQ(E_OK, status); + + vector entries; + status = store->GetEntries(KEY_PREFIX, entries); + EXPECT_EQ(E_OK, status); + EXPECT_EQ(129, entries.size()); + + status = store->DeleteEntries(keys); + EXPECT_EQ(E_OK, status); + + entries.clear(); + status = store->GetEntries(KEY_PREFIX, entries); + EXPECT_EQ(E_OK, status); + EXPECT_EQ(0, entries.size()); +} +}; // namespace DistributedDataTest +}; // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/unittest/cloud/cloud_data_test.cpp b/datamgr_service/services/distributeddataservice/service/test/unittest/cloud/cloud_data_test.cpp index 1923bf4355e7e52dc1763562ac787d3dfd47cbf9..5180d7d9de3da72639ff4dbbdc1862b7d3c57fe7 100644 --- a/datamgr_service/services/distributeddataservice/service/test/unittest/cloud/cloud_data_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/unittest/cloud/cloud_data_test.cpp @@ -190,9 +190,9 @@ HWTEST_F(CloudDataTest, GetSchemaTest001, TestSize.Level0) ASSERT_TRUE(MetaDataManager::GetInstance().DelMeta(cloudInfo.GetSchemaKey(TEST_CLOUD_BUNDLE), true)); SchemaMeta schemaMeta; ASSERT_FALSE(MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetSchemaKey(TEST_CLOUD_BUNDLE), schemaMeta, true)); - CloudEvent::StoreInfo storeInfo{ IPCSkeleton::GetCallingTokenID(), TEST_CLOUD_BUNDLE, TEST_CLOUD_STORE, 0 }; + StoreInfo storeInfo{ IPCSkeleton::GetCallingTokenID(), TEST_CLOUD_BUNDLE, TEST_CLOUD_STORE, 0 }; auto event = std::make_unique(CloudEvent::GET_SCHEMA, std::move(storeInfo)); - EventCenter::GetInstance().PostEvent(move(event)); + EventCenter::GetInstance().PostEvent(std::move(event)); ASSERT_TRUE(MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetSchemaKey(TEST_CLOUD_BUNDLE), schemaMeta, true)); ASSERT_EQ(to_string(schemaMeta.Marshall()), to_string(SCHEMA_META.Marshall())); } @@ -236,7 +236,7 @@ HWTEST_F(CloudDataTest, LocalChangeTest001, TestSize.Level0) ASSERT_TRUE(store != nullptr); }; EventCenter::GetInstance().Subscribe(CloudEvent::CLOUD_SYNC, process); - CloudEvent::StoreInfo storeInfo{ IPCSkeleton::GetCallingTokenID(), TEST_CLOUD_BUNDLE, TEST_CLOUD_STORE, 0 }; + StoreInfo storeInfo{ IPCSkeleton::GetCallingTokenID(), TEST_CLOUD_BUNDLE, TEST_CLOUD_STORE, 0 }; auto query = std::make_shared(); auto info = ChangeEvent::EventInfo(GeneralStore::CLOUD_TIME_FIRST, 0, false, query, nullptr); auto evt = std::make_unique(std::move(storeInfo), std::move(info)); diff --git a/interface_sdk/api/@ohos.application.DataShareExtensionAbility.d.ts b/interface_sdk/api/@ohos.application.DataShareExtensionAbility.d.ts index 406d04513f6ef04ee4b87a992a36a705843080c1..8b80c6485d02af997973f91d0436c1300a38237b 100644 --- a/interface_sdk/api/@ohos.application.DataShareExtensionAbility.d.ts +++ b/interface_sdk/api/@ohos.application.DataShareExtensionAbility.d.ts @@ -23,6 +23,16 @@ import ExtensionContext from './application/ExtensionContext'; import Want from './@ohos.app.ability.Want'; import dataSharePredicates from './@ohos.data.dataSharePredicates'; import { ValuesBucket } from './@ohos.data.ValuesBucket'; +import dataShare from './@ohos.data.dataShare'; + +/** + * Struct for a batch update operation. + * + * @syscap SystemCapability.DistributedDataManager.DataShare.Provider + * @stagemodelonly + * @since 12 + */ +type UpdateOperation = dataShare.UpdateOperation; /** * This module provides data sharing and expansion capabilities. @@ -89,6 +99,21 @@ export default class DataShareExtensionAbility { callback: AsyncCallback ): void; + /** + * Updates data records in the database. + * + * @param { Record> } operations - Indicates the data to update. + * @param { AsyncCallback>> } callback - Callback used to return the result. + * @syscap SystemCapability.DistributedDataManager.DataShare.Provider + * @systemapi + * @StageModelOnly + * @since 12 + */ + batchUpdate?( + operations: Record>, + callback: AsyncCallback>> + ): void; + /** * Deletes one or more data records. This method should be implemented by a data share. * diff --git a/interface_sdk/api/@ohos.data.cloudData.d.ts b/interface_sdk/api/@ohos.data.cloudData.d.ts index f4455fdc5bea20330c54828bb720008409d0462e..3faabb817b593c1d6ec66f204c4ab5b646da0a3c 100644 --- a/interface_sdk/api/@ohos.data.cloudData.d.ts +++ b/interface_sdk/api/@ohos.data.cloudData.d.ts @@ -20,13 +20,13 @@ import { AsyncCallback } from './@ohos.base'; import type relationalStore from './@ohos.data.relationalStore'; +import commonType from './@ohos.data.commonType'; /** * Provides methods for cloud capabilities. * * @namespace cloudData * @syscap SystemCapability.DistributedDataManager.CloudSync.Config - * @systemapi * @since 10 */ declare namespace cloudData { @@ -111,6 +111,56 @@ declare namespace cloudData { extraData: string; } + /** + * Additional data for querying data statistics information. + * + * @interface StatisticInfo + * @syscap SystemCapability.DistributedDataManager.CloudSync.Config + * @systemapi + * @since 12 + */ + interface StatisticInfo { + /** + * Cloud table name. + * + * @type { string } + * @syscap SystemCapability.DistributedDataManager.CloudSync.Config + * @systemapi + * @since 12 + */ + table: string; + + /** + * Number of records to be inserted to the cloud. + * + * @type { number } + * @syscap SystemCapability.DistributedDataManager.CloudSync.Config + * @systemapi + * @since 12 + */ + inserted: number; + + /** + * Number of inconsistent records between the local device and the cloud. + * + * @type { number } + * @syscap SystemCapability.DistributedDataManager.CloudSync.Config + * @systemapi + * @since 12 + */ + updated: number; + + /** + * Number of consistent records between the local device and the cloud. + * + * @type { number } + * @syscap SystemCapability.DistributedDataManager.CloudSync.Config + * @systemapi + * @since 12 + */ + normal: number; + } + /** * Provides methods to set CloudSync config. * @@ -363,6 +413,28 @@ declare namespace cloudData { */ static notifyDataChange(accountId: string, bundleName: string, callback: AsyncCallback): void; + /** + * Queries statistics of the cloud records. + * + * @permission ohos.permission.CLOUDDATA_CONFIG + * @param { string } accountId - Indicates the account ID. The account ID is required by hashing cloud account. + * @param { string } bundleName - Indicates the name of application. + * @param { string } [storeId] - Indicates the store ID. + * @returns { Promise>> } Promise used to return the result. + * @throws { BusinessError } 201 - Permission verification failed, usually the result returned by VerifyAccessToken. + * @throws { BusinessError } 202 - Permission denied. The application is not a system application. + * @throws { BusinessError } 401 - Parameter error. + * @throws { BusinessError } 801 - Capability not supported. + * @syscap SystemCapability.DistributedDataManager.CloudSync.Config + * @systemapi + * @since 12 + */ + static queryStatistics( + accountId: string, + bundleName: string, + storeId?: string + ): Promise>>; + /** * deletes cloud information from local data. * @@ -432,6 +504,63 @@ declare namespace cloudData { static clear(accountId: string, appActions: Record): Promise; } + /** + * Enumerates the strategy types of cloud sync. + * + * @enum { number } + * @syscap SystemCapability.DistributedDataManager.CloudSync.Client + * @since 12 + */ + enum StrategyType { + + /** + * Sync via the network. + * + * @syscap SystemCapability.DistributedDataManager.CloudSync.Client + * @since 12 + */ + NETWORK + } + + /** + * Enumerates the types of cloud sync via the network. + * + * @enum { number } + * @syscap SystemCapability.DistributedDataManager.CloudSync.Client + * @since 12 + */ + enum NetWorkStrategy { + + /** + * Sync using WiFi. + * + * @syscap SystemCapability.DistributedDataManager.CloudSync.Client + * @since 12 + */ + WIFI = 1, + + /** + * Sync using the cellular network. + * + * @syscap SystemCapability.DistributedDataManager.CloudSync.Client + * @since 12 + */ + CELLULAR = 2, + } + + /** + * Sets cloud strategy. + * + * @param { StrategyType } strategy - Indicates the strategy type of the cloud sync. + * @param { Array } param - Indicates specific strategy of the cloud sync. + * @returns { Promise } Promise used to return the result. + * @throws { BusinessError } 401 - Parameter error. + * @throws { BusinessError } 801 - Capability not supported. + * @syscap SystemCapability.DistributedDataManager.CloudSync.Client + * @since 12 + */ + function setCloudStrategy(strategy: StrategyType, param?: Array): Promise; + /** * Provides methods to implement cloud sharing. * diff --git a/interface_sdk/api/@ohos.data.dataShare.d.ts b/interface_sdk/api/@ohos.data.dataShare.d.ts index 93733b1da7621ad3bd333301c706ca6e4e8b8daa..46ca8a54d83cb69609c91ded75040ef02699f0fd 100644 --- a/interface_sdk/api/@ohos.data.dataShare.d.ts +++ b/interface_sdk/api/@ohos.data.dataShare.d.ts @@ -376,6 +376,37 @@ declare namespace dataShare { result: number; } + /** + * Struct for a batch update operation. + * + * @interface UpdateOperation + * @syscap SystemCapability.DistributedDataManager.DataShare.Consumer + * @systemapi + * @stagemodelonly + * @since 12 + */ + interface UpdateOperation { + /** + * Indicates the data to update. + * + * @syscap SystemCapability.DistributedDataManager.DataShare.Consumer + * @systemapi + * @stagemodelonly + * @since 12 + */ + values: ValuesBucket; + + /** + * Indicates filter criteria. + * + * @syscap SystemCapability.DistributedDataManager.DataShare.Consumer + * @systemapi + * @stagemodelonly + * @since 12 + */ + predicates: dataSharePredicates.DataSharePredicates; + } + /** * DataShareHelper * @@ -749,6 +780,21 @@ declare namespace dataShare { */ update(uri: string, predicates: dataSharePredicates.DataSharePredicates, value: ValuesBucket): Promise; + /** + * Updates data records in the database. + * + * @param { Record> } operations - Indicates the data to update. + * @returns {Promise>>} {Record>}: The result set of batch operations. + * @throws { BusinessError } 401 - Parameter error. + * @throws { BusinessError } 15700000 - Inner error. + * @throws { BusinessError } 15700010 - The dataShareHelper has been closed. + * @syscap SystemCapability.DistributedDataManager.DataShare.Consumer + * @systemapi + * @stagemodelonly + * @since 12 + */ + batchUpdate(operations: Record>): Promise>>; + /** * Inserts multiple data records into the database. * diff --git a/interface_sdk/api/@ohos.data.relationalStore.d.ts b/interface_sdk/api/@ohos.data.relationalStore.d.ts index 3186ffdca769aa86196f0f5d7ada028b4dfa5905..3efa98b9ad45310f482a4d2e27c5b71204759434 100644 --- a/interface_sdk/api/@ohos.data.relationalStore.d.ts +++ b/interface_sdk/api/@ohos.data.relationalStore.d.ts @@ -497,7 +497,15 @@ declare namespace relationalStore { * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core * @since 10 */ - NO_SPACE_FOR_ASSET + NO_SPACE_FOR_ASSET, + + /** + * BLOCKED_BY_NETWORK_STRATEGY: means the sync blocked by network strategy. + * + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @since 12 + */ + BLOCKED_BY_NETWORK_STRATEGY } /** diff --git a/kv_store/databaseutils/src/acl.cpp b/kv_store/databaseutils/src/acl.cpp index 4f33429697fe28017abe627432f97c69b52e3d5b..a4998b424189dc524fe48350311338bba45f8dd9 100644 --- a/kv_store/databaseutils/src/acl.cpp +++ b/kv_store/databaseutils/src/acl.cpp @@ -33,20 +33,18 @@ namespace OHOS { namespace DATABASE_UTILS { using namespace DistributedKv; -Acl::Acl(const std::string &path) : path_(path), hasError_(false) +Acl::Acl(const std::string& path) : path_(path), hasError_(false) { /* init acl from file's defaule or mode*/ AclFromDefault(); } -Acl::Acl() -{ -} +Acl::Acl() {} ACL_PERM Acl::ReCalcMaskPerm() { ACL_PERM perm; - for (const auto &e : entries_) { + for (const auto& e : entries_) { if (e.tag_ == ACL_TAG::USER || e.tag_ == ACL_TAG::GROUP_OBJ || e.tag_ == ACL_TAG::GROUP) { perm.Merge(e.perm_); } @@ -59,19 +57,18 @@ bool Acl::IsEmpty() return entries_.empty(); } -void Acl::CompareInsertEntry(const AclXattrEntry &entry) +void Acl::CompareInsertEntry(const AclXattrEntry& entry) { if (entries_.count(entry)) { auto it = entries_.find(entry); entries_.erase(it); } - if (entry.perm_.IsReadable() || entry.perm_.IsWritable() || - entry.perm_.IsExecutable()) { + if (entry.perm_.IsReadable() || entry.perm_.IsWritable() || entry.perm_.IsExecutable()) { entries_.insert(entry); } } -int Acl::InsertEntry(const AclXattrEntry &entry) +int Acl::InsertEntry(const AclXattrEntry& entry) { if (entries_.size() >= ENTRIES_MAX_NUM) { return E_ERROR; @@ -92,7 +89,7 @@ int Acl::InsertEntry(const AclXattrEntry &entry) return E_OK; } -std::unique_ptr Acl::Serialize(int32_t &bufSize) +std::unique_ptr Acl::Serialize(int32_t& bufSize) { bufSize = sizeof(AclXattrHeader) + sizeof(AclXattrEntry) * entries_.size(); if (bufSize > static_cast(BUF_MAX_SIZE)) { @@ -107,8 +104,8 @@ std::unique_ptr Acl::Serialize(int32_t &bufSize) } int32_t restSize = bufSize - sizeof(AclXattrHeader); - AclXattrEntry *ptr = reinterpret_cast(buf.get() + sizeof(AclXattrHeader)); - for (const auto &e : entries_) { + AclXattrEntry* ptr = reinterpret_cast(buf.get() + sizeof(AclXattrHeader)); + for (const auto& e : entries_) { auto err = memcpy_s(ptr++, restSize, &e, sizeof(AclXattrEntry)); if (err != EOK) { bufSize = 0; @@ -119,9 +116,9 @@ std::unique_ptr Acl::Serialize(int32_t &bufSize) return buf; } -int Acl::DeSerialize(const char *p, int32_t bufSize) +int Acl::DeSerialize(const char* p, int32_t bufSize) { - header_ = *reinterpret_cast(p); + header_ = *reinterpret_cast(p); bufSize -= sizeof(AclXattrHeader); p += sizeof(AclXattrHeader); @@ -129,9 +126,8 @@ int Acl::DeSerialize(const char *p, int32_t bufSize) * `e->tag != ACL_TAG::UNDEFINED` is unreliable outside the buffer, so check * it after checking the size of remaining buffer. */ - for (const AclXattrEntry *e = reinterpret_cast(p); - bufSize >= static_cast(sizeof(AclXattrEntry)) && e->tag_ != ACL_TAG::UNDEFINED; - e++) { + for (const AclXattrEntry* e = reinterpret_cast(p); + bufSize >= static_cast(sizeof(AclXattrEntry)) && e->tag_ != ACL_TAG::UNDEFINED; e++) { InsertEntry(*e); bufSize -= sizeof(AclXattrEntry); } @@ -165,12 +161,11 @@ void Acl::AclFromMode() return; } - InsertEntry(AclXattrEntry(ACL_TAG::USER_OBJ, AclXattrEntry::ACL_UNDEFINED_ID, - (st.st_mode & S_IRWXU) >> USER_OFFSET)); - InsertEntry(AclXattrEntry(ACL_TAG::GROUP_OBJ, AclXattrEntry::ACL_UNDEFINED_ID, - (st.st_mode & S_IRWXG) >> GROUP_OFFSET)); - InsertEntry(AclXattrEntry(ACL_TAG::OTHER, AclXattrEntry::ACL_UNDEFINED_ID, - (st.st_mode & S_IRWXO))); + InsertEntry( + AclXattrEntry(ACL_TAG::USER_OBJ, AclXattrEntry::ACL_UNDEFINED_ID, (st.st_mode & S_IRWXU) >> USER_OFFSET)); + InsertEntry( + AclXattrEntry(ACL_TAG::GROUP_OBJ, AclXattrEntry::ACL_UNDEFINED_ID, (st.st_mode & S_IRWXG) >> GROUP_OFFSET)); + InsertEntry(AclXattrEntry(ACL_TAG::OTHER, AclXattrEntry::ACL_UNDEFINED_ID, (st.st_mode & S_IRWXO))); } int32_t Acl::SetDefault() @@ -211,9 +206,9 @@ Acl::~Acl() } } -bool Acl::HasEntry(const AclXattrEntry &Acl) +bool Acl::HasEntry(const AclXattrEntry& Acl) { return entries_.find(Acl) != entries_.end(); } -} -} \ No newline at end of file +} // namespace DATABASE_UTILS +} // namespace OHOS \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/common/include/db_constant.h b/kv_store/frameworks/libs/distributeddb/common/include/db_constant.h index 41efc2ca4b2c5c7d0967d6d6e2b28ea380c113c6..2f8bcf9d5a5b68d23c29e7a19303aceeb3a07e98 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/db_constant.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/db_constant.h @@ -165,6 +165,7 @@ public: static constexpr const char *LOG_TABLE_VERSION_5_1 = "5.01"; static constexpr const char *LOG_TABLE_VERSION_5_2 = "5.02"; // fix failure caused by comparing NULL using <> static constexpr const char *LOG_TABLE_VERSION_5_3 = "5.03"; // add sharing_resource field + static constexpr const char *LOG_TABLE_VERSION_5_4 = "5.04"; // new flag bit 0x20 added, upgrade trigger static const std::string LOG_TABLE_VERSION_CURRENT; static const std::string LOG_TABLE_VERSION_KEY; diff --git a/kv_store/frameworks/libs/distributeddb/common/include/runtime_context.h b/kv_store/frameworks/libs/distributeddb/common/include/runtime_context.h index c4e275416c7c3cd40e9b16370f1e4b53f05ce716..217549f94ed7aff832b1b7ceee094772f979c61e 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/runtime_context.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/runtime_context.h @@ -196,6 +196,7 @@ public: virtual void RecordAllTimeChange() = 0; virtual void ResetDBTimeChangeStatus(const std::vector &dbId) = 0; virtual bool CheckDBTimeChange(const std::vector &dbId) = 0; + virtual bool IsTimeTickMonitorValid() const = 0; protected: RuntimeContext() = default; virtual ~RuntimeContext() {} 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 6330bfbb00777a4001f44e61ecc0ed3d3eb31c15..97f8b8192ba9a2c2f540e728de7f0157c6acd93c 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 @@ -74,7 +74,7 @@ uint32_t AssetOperationUtils::EraseBitMask(uint32_t status) void AssetOperationUtils::UpdateAssetsFlag(std::vector &from, std::vector &target) { if (from.size() != target.size()) { - LOGE("the num of VBucket are not equal when update assets flag."); + LOGW("the num of VBucket are not equal when update assets flag."); return; } for (size_t i = 0; i < from.size(); ++i) { diff --git a/kv_store/frameworks/libs/distributeddb/common/src/db_constant.cpp b/kv_store/frameworks/libs/distributeddb/common/src/db_constant.cpp index 4bad00ae369a069f4202f361bb14fc3d48560c0e..43399e1c5f56f1ad3106117e663afa2af1578955 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/db_constant.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/db_constant.cpp @@ -75,7 +75,7 @@ const std::string DBConstant::LOG_POSTFIX = "_log"; const std::string DBConstant::LOG_TABLE_VERSION_1 = "1.0"; const std::string DBConstant::LOG_TABLE_VERSION_2 = "2.0"; -const std::string DBConstant::LOG_TABLE_VERSION_CURRENT = LOG_TABLE_VERSION_5_3; +const std::string DBConstant::LOG_TABLE_VERSION_CURRENT = LOG_TABLE_VERSION_5_4; const std::string DBConstant::LOG_TABLE_VERSION_KEY = "log_table_version"; diff --git a/kv_store/frameworks/libs/distributeddb/common/src/runtime_context_impl.cpp b/kv_store/frameworks/libs/distributeddb/common/src/runtime_context_impl.cpp index e5a6fc9997721d9cb7b4ff970316880e2e36b38e..21b23de6f0307017d7f392cb110cf3d73827c3e7 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/runtime_context_impl.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/runtime_context_impl.cpp @@ -775,6 +775,10 @@ void RuntimeContextImpl::StopTaskPool() void RuntimeContextImpl::StopTimeTickMonitorIfNeed() { + if (IsCommunicatorAggregatorValid()) { + return; + } + // release monitor in client std::lock_guard autoLock(timeTickMonitorLock_); if (timeTickMonitor_ == nullptr) { return; @@ -1194,4 +1198,10 @@ bool RuntimeContextImpl::CheckDBTimeChange(const std::vector &dbId) std::lock_guard autoLock(deviceTimeInfoLock_); return dbTimeChange_[dbId]; } + +bool RuntimeContextImpl::IsTimeTickMonitorValid() const +{ + std::lock_guard autoLock(timeTickMonitorLock_); + return timeTickMonitor_ != nullptr; +} } // 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 72d8f31572b32f1f728fb7c8acd04c890b8b9df1..e717b94d010650b4f074e7e7f7de215bb5c42080 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 @@ -179,6 +179,7 @@ public: void RecordAllTimeChange() override; void ResetDBTimeChangeStatus(const std::vector &dbId) override; bool CheckDBTimeChange(const std::vector &dbId) override; + bool IsTimeTickMonitorValid() const override; private: static constexpr int MAX_TP_THREADS = 10; // max threads of the task pool. static constexpr int MIN_TP_THREADS = 1; // min threads of the task pool. diff --git a/kv_store/frameworks/libs/distributeddb/common/src/time_tick_monitor.cpp b/kv_store/frameworks/libs/distributeddb/common/src/time_tick_monitor.cpp index 24912e3accb394d0f66fdf68d17b0d00ba63b20d..35942ee3e131fe0007fe09880b1ef6249c3f480f 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/time_tick_monitor.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/time_tick_monitor.cpp @@ -132,6 +132,8 @@ int TimeTickMonitor::TimeTick(TimerId timerId) int64_t changedOffset = systemOffset - monotonicOffset; if (std::abs(changedOffset) > MAX_NOISE) { LOGI("Local system time may be changed! changedOffset %ld", changedOffset); + RuntimeContext::GetInstance()->RecordAllTimeChange(); + RuntimeContext::GetInstance()->ClearAllDeviceTimeInfo(); NotificationChain *notifier = nullptr; { std::lock_guard autoLock(timeTickMonitorLock_); diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/src/grd_api_manager.cpp b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/src/grd_api_manager.cpp index bafc6daa9859b933b2f724ea0f6929801a2ad9af..5e57da3baec87c4d12c1b396a3536fb95d7b7a93 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/src/grd_api_manager.cpp +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/src/grd_api_manager.cpp @@ -110,7 +110,7 @@ GRD_APIInfo GetApiInfoInstance() { GRD_APIInfo GRD_TempApiStruct; #ifndef _WIN32 - g_library = dlopen("/system/lib64/libgaussdb_rd.z.so", RTLD_LAZY); + g_library = dlopen("libgaussdb_rd.z.so", RTLD_LAZY); if (!g_library) { GRD_DBApiInitCommon(GRD_TempApiStruct); // When calling specific function, read whether init is successful. } else { 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 90c5598421a848e024d4f6c0e5a0e9a12b9e8a32..66ac53c0abfef1f2077be3c30261e8f861751b6a 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 @@ -204,9 +204,12 @@ public: int UpsertData(RecordStatus status, const std::string &tableName, const std::vector &records); - int UpdateRecordFlag(const std::string &tableName, const std::string &gid, bool recordConflict) override; + int UpdateRecordFlag(const std::string &tableName, bool recordConflict, const LogInfo &logInfo) override; int GetCompensatedSyncQuery(std::vector &syncQuery) override; + + int MarkFlagAsConsistent(const std::string &tableName, const DownloadData &downloadData, + const std::set &gidFilters) override; protected: int FillReferenceData(CloudSyncData &syncData); 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 fe8449c71055db318c5f89af5a580f83cf18ce59..bcb47543a310029e972b210703bdebcfc0f872af 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 @@ -105,6 +105,10 @@ public: static std::pair> GetHashValueWithPrimaryKeyMap(const VBucket &vBucket, const TableSchema &tableSchema, const TableInfo &localTable, const std::map &pkMap, bool allowEmpty); + static std::string GetUpdateRecordFlagSql(const std::string &tableName, bool recordConflict, + const LogInfo &logInfo); + static int BindStepConsistentFlagStmt(sqlite3_stmt *stmt, const VBucket &data, + const std::set &gidFilters); template static int GetValueFromOneField(Type &cloudValue, T &outVal) 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 5116bbe1676e043e81953dbff3b2f70cb0c0bdb1..d0a51e2bfad76dd977ecdcda120ef98178df3820 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 @@ -138,8 +138,8 @@ public: return E_OK; } - virtual int UpdateRecordFlag([[gnu::unused]] const std::string &tableName, [[gnu::unused]] const std::string &gid, - [[gnu::unused]] bool recordConflict) + virtual int UpdateRecordFlag([[gnu::unused]] const std::string &tableName, + [[gnu::unused]] bool recordConflict, [[gnu::unused]] const LogInfo &logInfo) { return E_OK; } @@ -148,6 +148,12 @@ public: { return E_OK; } + + virtual int MarkFlagAsConsistent([[gnu::unused]] const std::string &tableName, + [[gnu::unused]] const DownloadData &downloadData, [[gnu::unused]] const std::set &gidFilters) + { + return E_OK; + } }; } 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 cef8b719b5770cadc86777382dcb1c8535bc5257..92ed6a335791f7c71921c1bcf8ad338fc3e1fec9 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/include/storage_proxy.h +++ b/kv_store/frameworks/libs/distributeddb/storage/include/storage_proxy.h @@ -117,9 +117,12 @@ public: int SetIAssetLoader(const std::shared_ptr &loader); - int UpdateRecordFlag(const std::string &tableName, const std::string &gid, bool recordConflict); + int UpdateRecordFlag(const std::string &tableName, bool recordConflict, const LogInfo &logInfo); int GetCompensatedSyncQuery(std::vector &syncQuery); + + int MarkFlagAsConsistent(const std::string &tableName, const DownloadData &downloadData, + const std::set &gidFilters); 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 ce90eb0657e78b663b3aeea2e97da19ba21cbb7e..b441239779d0b1503ce4583cef9f1d160e9620f1 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 @@ -1104,4 +1104,77 @@ int CloudStorageUtils::BindUpdateLogStmtFromVBucket(const VBucket &vBucket, cons } return E_OK; } + +std::string CloudStorageUtils::GetUpdateRecordFlagSql(const std::string &tableName, bool recordConflict, + const LogInfo &logInfo) +{ + 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)); + 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 "; + + if (recordConflict && !(isDeleted && gidEmpty)) { + sql += "flag | " + compensatedBit + " ELSE flag | " + compensatedBit; + } else { + sql += "flag & ~" + compensatedBit + " & ~" + consistentBit + " ELSE flag & ~" + compensatedBit; + } + sql += " end) 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; +} + +int CloudStorageUtils::BindStepConsistentFlagStmt(sqlite3_stmt *stmt, const VBucket &data, + const std::set &gidFilters) +{ + std::string gidStr; + int errCode = CloudStorageUtils::GetValueFromVBucket(CloudDbConstant::GID_FIELD, data, gidStr); + if (errCode != E_OK || gidStr.empty()) { + LOGE("Get gid from bucket fail when mark flag as consistent, errCode = %d", errCode); + return errCode; + } + if (gidStr.empty()) { + LOGE("Get empty gid from bucket when mark flag as consistent."); + return -E_CLOUD_ERROR; + } + // this data has not yet downloaded asset, skipping + if (gidFilters.find(gidStr) != gidFilters.end()) { + return E_OK; + } + errCode = SQLiteUtils::BindTextToStatement(stmt, 1, gidStr); // 1 is cloud_gid + if (errCode != E_OK) { + LOGE("Bind cloud_gid to mark flag as consistent stmt failed, %d", errCode); + return errCode; + } + int64_t modifyTime; + errCode = CloudStorageUtils::GetValueFromVBucket(CloudDbConstant::MODIFY_FIELD, data, modifyTime); + if (errCode != E_OK) { + LOGE("Get modify time from bucket fail when mark flag as consistent, errCode = %d", errCode); + return errCode; + } + errCode = SQLiteUtils::BindInt64ToStatement(stmt, 2, modifyTime); // 2 is timestamp + if (errCode != E_OK) { + LOGE("Bind modify time to mark flag as consistent stmt failed, %d", errCode); + return errCode; + } + errCode = SQLiteUtils::StepWithRetry(stmt); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + errCode = E_OK; + } else { + LOGE("[Storage Executor]Step mark flag as consistent stmt failed, %d", errCode); + } + return errCode; +} } 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 bf15e697d88a67ffb89c36406bcbad813597747e..b7cf2bbc80449514b05004b8fd7215e3e3aba921 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/data_transformer.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/data_transformer.h @@ -44,6 +44,7 @@ enum class LogInfoFlag : uint32_t { FLAG_LOCAL = 0x2, FLAG_LOGIC_DELETE = 0x8, FLAG_WAIT_COMPENSATED_SYNC = 0x10, + FLAG_DEVICE_CLOUD_CONSISTENCY = 0x20, }; struct RowDataWithLog { 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 ba082afbc233871aae345d34a5ba8265f0f530b2..ea3d924bb9415eb27b9576b74432d92a97da86da 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 @@ -1286,9 +1286,6 @@ int RelationalSyncAbleStorage::FillCloudLogAndAsset(const OpType opType, const C bool ignoreEmptyGid) { CHECK_STORAGE_ENGINE; - if (opType == OpType::UPDATE && data.updData.assets.empty()) { - return E_OK; - } int errCode = E_OK; auto writeHandle = static_cast( storageEngine_->FindExecutor(true, OperatePerm::NORMAL_PERM, errCode)); @@ -1745,18 +1742,14 @@ int RelationalSyncAbleStorage::UpsertDataInTransaction(SQLiteSingleVerRelational return PutCloudSyncDataInner(handle, tableName, downloadData); } -int RelationalSyncAbleStorage::UpdateRecordFlag(const std::string &tableName, const std::string &gid, - bool recordConflict) +int RelationalSyncAbleStorage::UpdateRecordFlag(const std::string &tableName, bool recordConflict, + const LogInfo &logInfo) { if (transactionHandle_ == nullptr) { LOGE("[RelationalSyncAbleStorage] the transaction has not been started"); return -E_INVALID_DB; } - if (gid.empty()) { - LOGE("[RelationalSyncAbleStorage] gid is empty."); - return -E_INVALID_ARGS; - } - return transactionHandle_->UpdateRecordFlag(tableName, recordConflict, gid); + return transactionHandle_->UpdateRecordFlag(tableName, recordConflict, logInfo); } int RelationalSyncAbleStorage::FillCloudLogAndAssetInner(SQLiteSingleVerRelationalStorageExecutor *handle, @@ -1776,6 +1769,8 @@ int RelationalSyncAbleStorage::FillCloudLogAndAssetInner(SQLiteSingleVerRelation errCode = UpdateRecordFlagAfterUpload(handle, data.tableName, data.insData); } else if (opType == OpType::UPDATE) { errCode = UpdateRecordFlagAfterUpload(handle, data.tableName, data.updData); + } else if (opType == OpType::DELETE) { + errCode = UpdateRecordFlagAfterUpload(handle, data.tableName, data.delData); } return errCode; } @@ -1783,13 +1778,25 @@ int RelationalSyncAbleStorage::FillCloudLogAndAssetInner(SQLiteSingleVerRelation int RelationalSyncAbleStorage::UpdateRecordFlagAfterUpload(SQLiteSingleVerRelationalStorageExecutor *handle, const std::string &tableName, const CloudSyncBatch &updateData) { + if (updateData.timestamp.size() != updateData.extend.size()) { + LOGE("the num of extend:%zu and timestamp:%zu is not equal.", + updateData.extend.size(), updateData.timestamp.size()); + return -E_INVALID_ARGS; + } for (size_t i = 0; i < updateData.extend.size(); ++i) { const auto &record = updateData.extend[i]; if (DBCommon::IsRecordError(record)) { continue; } const auto &rowId = updateData.rowid[i]; - int errCode = handle->UpdateRecordFlag(tableName, DBCommon::IsRecordIgnored(record), "", rowId); + std::string cloudGid; + (void)CloudStorageUtils::GetValueFromVBucket(CloudDbConstant::GID_FIELD, record, cloudGid); + LogInfo logInfo; + logInfo.cloudGid = cloudGid; + logInfo.timestamp = updateData.timestamp[i]; + logInfo.dataKey = rowId; + logInfo.hashKey = {}; + int errCode = handle->UpdateRecordFlag(tableName, DBCommon::IsRecordIgnored(record), logInfo); if (errCode != E_OK) { LOGE("[RDBStorage] Update record flag failed in index %zu", i); return errCode; @@ -1979,5 +1986,19 @@ int RelationalSyncAbleStorage::CreateTempSyncTriggerInner(SQLiteSingleVerRelatio } return handle->CreateTempSyncTrigger(trackerTable); } + +int RelationalSyncAbleStorage::MarkFlagAsConsistent(const std::string &tableName, const DownloadData &downloadData, + const std::set &gidFilters) +{ + if (transactionHandle_ == nullptr) { + LOGE("the transaction has not been started"); + return -E_INVALID_DB; + } + int errCode = transactionHandle_->MarkFlagAsConsistent(tableName, downloadData, gidFilters); + if (errCode != E_OK) { + LOGE("[RelationalSyncAbleStorage] mark flag as consistent failed.%d", errCode); + } + return errCode; +} } #endif \ No newline at end of file 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 2ca1aede645f0c87c7c3047253b0d3d1be220757..3abb6a7ddcb9bd2f2e8705f74d1e49515bd99f5c 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 @@ -102,7 +102,7 @@ std::string CloudSyncLogTableManager::GetInsertTrigger(const TableInfo &table, c insertTrigger += " (data_key, device, ori_device, timestamp, wtimestamp, flag, hash_key, cloud_gid, "; insertTrigger += " extend_field, cursor, version, sharing_resource)"; insertTrigger += " VALUES (new." + std::string(DBConstant::SQLITE_INNER_ROWID) + ", '', '',"; - insertTrigger += " get_raw_sys_time(), get_raw_sys_time(), 0x02, "; + insertTrigger += " get_raw_sys_time(), get_raw_sys_time(), 0x02|0x20, "; insertTrigger += CalcPrimaryKeyHash("NEW.", table, identity) + ", CASE WHEN (SELECT count(*)<>0 FROM "; insertTrigger += logTblName + " WHERE hash_key = " + CalcPrimaryKeyHash("NEW.", table, identity); insertTrigger += ") THEN (SELECT cloud_gid FROM " + logTblName + " WHERE hash_key = "; @@ -133,7 +133,7 @@ std::string CloudSyncLogTableManager::GetUpdateTrigger(const TableInfo &table, c updateTrigger += "WHERE key = 'log_trigger_switch' AND value = 'true')\n"; updateTrigger += "BEGIN\n"; // if user change the primary key, we can still use gid to identify which one is updated updateTrigger += "\t UPDATE " + logTblName; - updateTrigger += " SET timestamp=get_raw_sys_time(), device='', flag=0x02"; + updateTrigger += " SET timestamp=get_raw_sys_time(), device='', flag=0x02|0x20"; if (!table.GetTrackerTable().GetTrackerColNames().empty()) { updateTrigger += table.GetTrackerTable().GetExtendAssignValSql(); } @@ -162,7 +162,9 @@ std::string CloudSyncLogTableManager::GetDeleteTrigger(const TableInfo &table, c deleteTrigger += "WHERE key = 'log_trigger_switch' AND VALUE = 'true')\n"; deleteTrigger += "BEGIN\n"; deleteTrigger += "\t UPDATE " + GetLogTableName(table); - deleteTrigger += " SET data_key=-1,flag=0x03,timestamp=get_raw_sys_time()"; + deleteTrigger += " SET data_key=-1,"; + deleteTrigger += "flag=(CASE WHEN cloud_gid='' then 0x03 else 0x03|0x20 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/sqlite_single_relational_storage_engine.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_relational_storage_engine.cpp index f5cc46a5e29547df0c47833c38ec28ea4743c3e2..2670627c9ecb003279993007d6ef98edd2617615 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 @@ -228,7 +228,7 @@ int SQLiteSingleRelationalStorageEngine::CreateDistributedTable(const std::strin } if (isUpgraded && (schemaChanged || trackerSchemaChanged)) { // Used for upgrading the stock data of the trackerTable - errCode = UpgradeTrackerTableLog(tableName, schema); + errCode = GenLogInfoForUpgrade(tableName, schema, schemaChanged); } return errCode; } @@ -985,10 +985,9 @@ int SQLiteSingleRelationalStorageEngine::CleanTrackerDeviceTable(const std::vect return errCode; } -int SQLiteSingleRelationalStorageEngine::UpgradeTrackerTableLog(const std::string &tableName, - RelationalSchemaObject &schema) +int SQLiteSingleRelationalStorageEngine::GenLogInfoForUpgrade(const std::string &tableName, + RelationalSchemaObject &schema, bool schemaChanged) { - LOGD("Upgrade tracker table log."); int errCode = E_OK; auto *handle = static_cast(FindExecutor(true, OperatePerm::NORMAL_PERM, errCode)); @@ -1002,8 +1001,8 @@ int SQLiteSingleRelationalStorageEngine::UpgradeTrackerTableLog(const std::strin return errCode; } - TableInfo table = schema_.GetTable(tableName); - errCode = handle->UpgradedLogForExistedData(table); + TableInfo table = GetSchema().GetTable(tableName); + errCode = handle->UpgradedLogForExistedData(table, schemaChanged); if (errCode != E_OK) { LOGE("Upgrade tracker table log failed. %d", errCode); (void)handle->Rollback(); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_relational_storage_engine.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_relational_storage_engine.h index 57264f88e82c4657ece5de372e060dea97d51d75..6a04786bfea84ae5b83c8eebe3a232638362bcbf 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_relational_storage_engine.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_relational_storage_engine.h @@ -87,7 +87,7 @@ private: int CleanTrackerDeviceTable(const std::vector &tableNames, RelationalSchemaObject &trackerSchemaObj, SQLiteSingleVerRelationalStorageExecutor *&handle); - int UpgradeTrackerTableLog(const std::string &tableName, RelationalSchemaObject &schema); + int GenLogInfoForUpgrade(const std::string &tableName, RelationalSchemaObject &schema, bool schemaChanged); static std::map> GetReachableWithShared( const std::map> &reachableReference, 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 050c3d2ec2ff3f74990f0b87e95a94b0ed13bd63..d3bb78377a94173548d3f8bf7d0c0535ad63b763 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_executor.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_ver_relational_storage_executor.cpp @@ -42,12 +42,13 @@ static constexpr const char *HASH_KEY = "HASH_KEY"; static constexpr const char *SHARING_RESOURCE = "SHARING_RESOURCE"; static constexpr const char *FLAG_IS_CLOUD = "FLAG & 0x02 = 0"; // see if 1th bit of a flag is cloud // set 1th bit of flag to one which is local, clean 5th bit of flag to one which is wait compensated sync -static constexpr const char *SET_FLAG_LOCAL_AND_CLEAN_WAIT_COMPENSATED_SYNC = "(FLAG | 0x02) & (~0x10)"; +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 static constexpr const char *DATA_IS_DELETE = "data_key = -1 AND FLAG & 0X08 = 0"; // see if data is delete -static constexpr const int SET_FLAG_ZERO_MASK = 0x0B; // clear 2th bit of flag 1011 use with & -static constexpr const int SET_FLAG_ONE_MASK = 0x04; // set 2th bit of flag 0100 use with | -static constexpr const int SET_CLOUD_FLAG = 0x0D; // set 1th bit of flag to 0 1101 use with & +static constexpr const int SET_FLAG_ZERO_MASK = ~0x04; // clear 2th bit of flag +static constexpr const int SET_FLAG_ONE_MASK = 0x04; // set 2th bit of flag +static constexpr const int SET_CLOUD_FLAG = ~0x02; // set 1th bit of flag to 0 static constexpr const int DATA_KEY_INDEX = 0; static constexpr const int TIMESTAMP_INDEX = 3; static constexpr const int W_TIMESTAMP_INDEX = 4; @@ -162,7 +163,7 @@ int SQLiteSingleVerRelationalStorageExecutor::GeneLogInfoForExistedData(sqlite3 std::string logTable = DBConstant::RELATIONAL_PREFIX + tableName + "_log"; std::string sql = "INSERT OR REPLACE INTO " + logTable + " SELECT " + std::string(DBConstant::SQLITE_INNER_ROWID) + ", '', '', " + timeOffsetStr + " + " + std::string(DBConstant::SQLITE_INNER_ROWID) + ", " + - timeOffsetStr + " + " + std::string(DBConstant::SQLITE_INNER_ROWID) + ", 0x2, " + + timeOffsetStr + " + " + std::string(DBConstant::SQLITE_INNER_ROWID) + ", 0x02|0x20, " + calPrimaryKeyHash + ", '', "; if (tableInfo.GetTableSyncType() == TableSyncType::DEVICE_COOPERATION) { sql += "'', ''"; @@ -611,6 +612,8 @@ int IdentifyCloudType(CloudSyncData &cloudSyncData, VBucket &data, VBucket &log, cloudSyncData.delData.record.push_back(data); cloudSyncData.delData.extend.push_back(log); cloudSyncData.delData.hashKey.push_back(*hashKey); + cloudSyncData.delData.timestamp.push_back(*timeStamp); + cloudSyncData.delData.rowid.push_back(*rowid); } else { bool isInsert = log.find(CloudDbConstant::GID_FIELD) == log.end(); if (data.empty()) { 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 1b085caa8af0ca4f448e0592bb95a2fc98d1ea91..ff0584493a083fffeecb4eb671f34f6d1162b59c 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 @@ -171,16 +171,18 @@ public: int CleanResourceForDroppedTable(const std::string &tableName); - int UpgradedLogForExistedData(TableInfo &tableInfo); + int UpgradedLogForExistedData(TableInfo &tableInfo, bool schemaChanged); - int UpdateRecordFlag(const std::string &tableName, bool recordConflict, const std::string &gid, - int64_t dataKey = DBConstant::DEFAULT_ROW_ID); + int UpdateRecordFlag(const std::string &tableName, bool recordConflict, const LogInfo &logInfo); int GetWaitCompensatedSyncDataPk(const TableSchema &table, std::vector &data); void SetPutDataMode(PutDataMode mode); void SetMarkFlagOption(MarkFlagOption option); + + int MarkFlagAsConsistent(const std::string &tableName, const DownloadData &downloadData, + const std::set &gidFilters); private: int DoCleanLogs(const std::vector &tableNameList, const RelationalSchemaObject &localSchema); @@ -414,7 +416,8 @@ private: int GetRecordFromStmt(sqlite3_stmt *stmt, const std::vector fields, int startIndex, VBucket &record); - static constexpr const char *UPDATE_FLAG_CLOUD = "flag = 0"; + static constexpr const char *CONSISTENT_FLAG = "0x20"; + static constexpr const char *UPDATE_FLAG_CLOUD = "flag = flag & 0x20"; static constexpr const char *UPDATE_FLAG_WAIT_COMPENSATED_SYNC = "flag = flag | 0x10"; static constexpr const char *FLAG_IS_WAIT_COMPENSATED_SYNC = "flag & 0x10 != 0"; 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 d931c0dc03ffa72c2a01ffa59486e686d475a577..90c18469513969aea690a02c0c6e6d4560ef83ed 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 @@ -457,14 +457,27 @@ int SQLiteSingleVerRelationalStorageExecutor::GetClearWaterMarkTables( return E_OK; } -int SQLiteSingleVerRelationalStorageExecutor::UpgradedLogForExistedData(TableInfo &tableInfo) +int SQLiteSingleVerRelationalStorageExecutor::UpgradedLogForExistedData(TableInfo &tableInfo, bool schemaChanged) { - if (tableInfo.GetTrackerTable().IsEmpty() || tableInfo.GetTableSyncType() == TableSyncType::DEVICE_COOPERATION) { + if (tableInfo.GetTableSyncType() == TableSyncType::DEVICE_COOPERATION) { return E_OK; } + std::string logTable = DBCommon::GetLogTableName(tableInfo.GetTableName()); + if (schemaChanged) { + std::string markAsInconsistent = "UPDATE " + logTable + " SET flag=" + + "(CASE WHEN (cloud_gid='' and data_key=-1 and flag&0x02=0x02) then flag else flag|0x20 END)"; + int ret = SQLiteUtils::ExecuteRawSQL(dbHandle_, markAsInconsistent); + if (ret != E_OK) { + LOGE("Mark upgrade log info as inconsistent failed:%d", ret); + return ret; + } + } + if (tableInfo.GetTrackerTable().IsEmpty()) { + return E_OK; + } + LOGI("Upgrade tracker table log, schemaChanged:%d.", schemaChanged); int64_t timeOffset = 0; std::string timeOffsetStr = std::to_string(timeOffset); - std::string logTable = DBConstant::RELATIONAL_PREFIX + tableInfo.GetTableName() + "_log"; std::string sql = "UPDATE " + logTable + " SET extend_field = " + tableInfo.GetTrackerTable().GetUpgradedExtendValSql(); int errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, sql); @@ -972,10 +985,10 @@ std::string SQLiteSingleVerRelationalStorageExecutor::GetCloudDeleteSql(const st std::string sql; if (isLogicDelete_) { // 1001 which is logicDelete|cloudForcePush|local|delete - sql += "flag = 9, cursor = (SELECT case when (MAX(cursor) is null) then 1 else MAX(cursor) + 1 END " \ - "FROM " + logTable + ")"; + sql += "flag = flag&" + std::string(CONSISTENT_FLAG) + "|0x09, cursor = (SELECT case when " + "(MAX(cursor) is null) then 1 else MAX(cursor) + 1 END FROM " + logTable + ")"; } else { - sql += "data_key = -1, flag = 1"; + sql += "data_key = -1, flag = flag&" + std::string(CONSISTENT_FLAG) + "|0x01"; } sql += ", cloud_gid = '', version = '', "; if (!isLogicDelete_) { @@ -1284,26 +1297,40 @@ int SQLiteSingleVerRelationalStorageExecutor::FillHandleWithOpType(const OpType bool fillAsset, bool ignoreEmptyGid, const TableSchema &tableSchema) { int errCode = E_OK; - if (opType == OpType::UPDATE_VERSION) { - errCode = FillCloudVersionForUpload(data); - } else if (opType == OpType::SET_UPLOADING) { - errCode = FillCloudAssetForUpload(opType, tableSchema, data.insData); - if (errCode != E_OK) { - LOGE("Failed to set uploading for ins data, %d.", errCode); - return errCode; - } - errCode = FillCloudAssetForUpload(opType, tableSchema, data.updData); - } else if (opType == OpType::INSERT) { - errCode = UpdateCloudLogGid(data, ignoreEmptyGid); - if (errCode != E_OK) { - LOGE("Failed to fill cloud log gid, %d.", errCode); - return errCode; + switch (opType) { + case OpType::UPDATE_VERSION: { + errCode = FillCloudVersionForUpload(data); + break; } - if (fillAsset) { + case OpType::SET_UPLOADING: { errCode = FillCloudAssetForUpload(opType, tableSchema, data.insData); + if (errCode != E_OK) { + LOGE("Failed to set uploading for ins data, %d.", errCode); + return errCode; + } + errCode = FillCloudAssetForUpload(opType, tableSchema, data.updData); + break; + } + case OpType::INSERT: { + errCode = UpdateCloudLogGid(data, ignoreEmptyGid); + if (errCode != E_OK) { + LOGE("Failed to fill cloud log gid, %d.", errCode); + return errCode; + } + if (fillAsset) { + errCode = FillCloudAssetForUpload(opType, tableSchema, data.insData); + } + break; } - } else if (fillAsset) { - errCode = FillCloudAssetForUpload(opType, tableSchema, data.updData); + case OpType::UPDATE: { + if (!fillAsset || data.updData.assets.empty()) { + break; + } + errCode = FillCloudAssetForUpload(opType, tableSchema, data.updData); + break; + } + default: + break; } return errCode; } @@ -1700,12 +1727,14 @@ void SQLiteSingleVerRelationalStorageExecutor::SetMarkFlagOption(MarkFlagOption int64_t SQLiteSingleVerRelationalStorageExecutor::GetDataFlag() { if (putDataMode_ != PutDataMode::USER) { - return static_cast(LogInfoFlag::FLAG_CLOUD); + return static_cast(LogInfoFlag::FLAG_CLOUD) | + static_cast(LogInfoFlag::FLAG_DEVICE_CLOUD_CONSISTENCY); } 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); return static_cast(flag); } @@ -1753,34 +1782,46 @@ std::vector SQLiteSingleVerRelationalStorageExecutor::GetUpdateField(cons } int SQLiteSingleVerRelationalStorageExecutor::UpdateRecordFlag(const std::string &tableName, bool recordConflict, - const std::string &gid, int64_t dataKey) + const LogInfo &logInfo) { - if (gid.empty() && dataKey == DBConstant::DEFAULT_ROW_ID) { - LOGE("[RDBExecutor] Update record flag failed with invalid args!"); - return -E_INVALID_ARGS; + bool useHashKey = false; + if (logInfo.cloudGid.empty() && logInfo.dataKey == DBConstant::DEFAULT_ROW_ID) { + if (logInfo.hashKey.empty()) { + LOGE("[RDBExecutor] Update record flag failed with invalid args!"); + return -E_INVALID_ARGS; + } + useHashKey = true; } - std::string sql = "UPDATE " + DBCommon::GetLogTableName(tableName) + " SET flag = "; - if (recordConflict) { - sql += "flag | " + std::to_string(static_cast(LogInfoFlag::FLAG_WAIT_COMPENSATED_SYNC)); - } else { - sql += "flag & " + std::to_string(~static_cast(LogInfoFlag::FLAG_WAIT_COMPENSATED_SYNC)); + std::string sql = CloudStorageUtils::GetUpdateRecordFlagSql(tableName, recordConflict, logInfo); + sqlite3_stmt *stmt = nullptr; + int errCode = SQLiteUtils::GetStatement(dbHandle_, sql, stmt); + if (errCode != E_OK) { + LOGE("[Storage Executor] Get stmt failed when update record flag, %d", errCode); + return errCode; } - sql += " WHERE "; - if (!gid.empty()) { - sql += " cloud_gid = '" + gid + "'"; + int ret = E_OK; + errCode = SQLiteUtils::BindInt64ToStatement(stmt, 1, logInfo.timestamp); // 1 is timestamp + if (errCode != E_OK) { + LOGE("[Storage Executor] Bind timestamp to update record flag stmt failed, %d", errCode); + SQLiteUtils::ResetStatement(stmt, true, ret); + return errCode; } - if (dataKey != DBConstant::DEFAULT_ROW_ID) { - if (!gid.empty()) { - sql += " OR "; + if (useHashKey) { + errCode = SQLiteUtils::BindBlobToStatement(stmt, 2, logInfo.hashKey); // 2 is hash_key + if (errCode != E_OK) { + LOGE("[Storage Executor] Bind hashKey to update record flag stmt failed, %d", errCode); + SQLiteUtils::ResetStatement(stmt, true, ret); + return errCode; } - sql += " data_key = '" + std::to_string(dataKey) + "'"; } - sql += ";"; - int errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, sql); - if (errCode != E_OK) { - LOGE("[RDBExecutor] Update record flag failed! errCode = %d", errCode); + errCode = SQLiteUtils::StepWithRetry(stmt); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + errCode = E_OK; + } else { + LOGE("[Storage Executor]Step update record flag stmt failed, %d", errCode); } - return errCode; + SQLiteUtils::ResetStatement(stmt, true, ret); + return errCode == E_OK ? ret : errCode; } int SQLiteSingleVerRelationalStorageExecutor::GetWaitCompensatedSyncDataPk(const TableSchema &table, @@ -1884,5 +1925,37 @@ 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) 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) { + continue; + } + errCode = CloudStorageUtils::BindStepConsistentFlagStmt(stmt, data, gidFilters); + if (errCode != E_OK) { + break; + } + } + SQLiteUtils::ResetStatement(stmt, true, ret); + return errCode == E_OK ? ret : errCode; +} } // namespace DistributedDB #endif \ No newline at end of file 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 abf30191ed86bec3056c8961ae0470fb7919dcac..0a934f905f680aa5202d28b2a080493cc455209c 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/storage_proxy.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/storage_proxy.cpp @@ -505,13 +505,13 @@ int StorageProxy::SetIAssetLoader(const std::shared_ptr &loader) return store_->SetIAssetLoader(loader); } -int StorageProxy::UpdateRecordFlag(const std::string &tableName, const std::string &gid, bool recordConflict) +int StorageProxy::UpdateRecordFlag(const std::string &tableName, bool recordConflict, const LogInfo &logInfo) { std::shared_lock readLock(storeMutex_); if (store_ == nullptr) { return E_INVALID_DB; } - return store_->UpdateRecordFlag(tableName, gid, recordConflict); + return store_->UpdateRecordFlag(tableName, recordConflict, logInfo); } int StorageProxy::GetCompensatedSyncQuery(std::vector &syncQuery) @@ -522,4 +522,14 @@ int StorageProxy::GetCompensatedSyncQuery(std::vector &syncQuer } return store_->GetCompensatedSyncQuery(syncQuery); } + +int StorageProxy::MarkFlagAsConsistent(const std::string &tableName, const DownloadData &downloadData, + const std::set &gidFilters) +{ + std::shared_lock readLock(storeMutex_); + if (store_ == nullptr) { + return E_INVALID_DB; + } + return store_->MarkFlagAsConsistent(tableName, downloadData, gidFilters); +} } 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 d986797d54143ba448e01c480a1c0cfc793a4714..58cd44ec18aac91842a191c69c5487e8c270ace9 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 @@ -30,6 +30,7 @@ public: static constexpr const int ASSETS_INDEX = 3; static constexpr const int HASH_KEY_INDEX = 4; static constexpr const int PRIMARY_KEY_INDEX = 5; + static constexpr const int TIMESTAMP_INDEX = 6; static int GetCloudPkVals(const VBucket &datum, const std::vector &pkColNames, int64_t dataKey, std::vector &cloudPkVals); 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 882854c76017d86943d906b0553a249d4fcb10d1..14dfb83ef72990a4f80c92cbb300cfe77348e39c 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 @@ -437,8 +437,8 @@ int CloudSyncer::FillCloudAssets(const std::string &tableName, VBucket &normalAs return E_OK; } -int CloudSyncer::HandleDownloadResult(bool recordConflict, const std::string &tableName, DownloadCommitList &commitList, - uint32_t &successCount) +int CloudSyncer::HandleDownloadResult(const DownloadItem &downloadItem, const std::string &tableName, + DownloadCommitList &commitList, uint32_t &successCount) { successCount = 0; int errCode = storageProxy_->StartTransaction(TransactType::IMMEDIATE); @@ -446,7 +446,7 @@ int CloudSyncer::HandleDownloadResult(bool recordConflict, const std::string &ta LOGE("[CloudSyncer] start transaction Failed before handle download."); return errCode; } - errCode = CommitDownloadAssets(recordConflict, tableName, commitList, successCount); + errCode = CommitDownloadAssets(downloadItem, tableName, commitList, successCount); if (errCode != E_OK) { successCount = 0; int ret = E_OK; @@ -495,12 +495,13 @@ int CloudSyncer::CloudDbDownloadAssets(TaskId taskId, InnerProcessInfo &info, co return errorCode; } if (downloadItem.strategy == OpType::DELETE) { - continue; + downloadItem.assets = {}; + downloadItem.gid = ""; } // Process result of each asset commitList.push_back(std::make_tuple(downloadItem.gid, std::move(downloadItem.assets), errorCode == E_OK)); downloadStatus = downloadStatus == E_OK ? errorCode : downloadStatus; - int ret = CommitDownloadResult(downloadItem.recordConflict, info, commitList, errorCode); + int ret = CommitDownloadResult(downloadItem, info, commitList, errorCode); if (ret != E_OK && ret != -E_REMOVE_ASSETS_FAILED) { return ret; } @@ -518,6 +519,7 @@ void CloudSyncer::GetDownloadItem(const DownloadList &downloadList, size_t i, Do downloadItem.assets = std::get(downloadList[i]); downloadItem.hashKey = std::get(downloadList[i]); downloadItem.primaryKeyValList = std::get(downloadList[i]); + downloadItem.timestamp = std::get(downloadList[i]); } int CloudSyncer::DownloadAssets(InnerProcessInfo &info, const std::vector &pKColNames, @@ -653,7 +655,8 @@ int CloudSyncer::HandleTagAssets(const Key &hashKey, const DataInfo &dataInfo, s param.withoutRowIdData.assetInsertData.push_back(std::make_tuple(idx, param.assetsDownloadList.size())); } param.assetsDownloadList.push_back( - std::make_tuple(dataInfo.cloudLogInfo.cloudGid, prefix, strategy, assetsMap, hashKey, pkVals)); + std::make_tuple(dataInfo.cloudLogInfo.cloudGid, prefix, strategy, assetsMap, hashKey, + pkVals, dataInfo.cloudLogInfo.timestamp)); return ret; } @@ -742,7 +745,7 @@ int CloudSyncer::SaveData(SyncParam ¶m) // Get latest cloudWaterMark VBucket &lastData = param.downloadData.data.back(); param.cloudWaterMark = std::get(lastData[CloudDbConstant::CURSOR_FIELD]); - return E_OK; + return UpdateFlagForSavedRecord(param); } int CloudSyncer::PreCheck(CloudSyncer::TaskId &taskId, const TableName &tableName) @@ -1026,12 +1029,10 @@ int CloudSyncer::SaveUploadData(Info &insertInfo, Info &updateInfo, Info &delete { int errCode = E_OK; if (!uploadData.delData.record.empty() && !uploadData.delData.extend.empty()) { - errCode = cloudDB_.BatchDelete(uploadData.tableName, uploadData.delData.record, - uploadData.delData.extend, deleteInfo); + errCode = BatchDelete(deleteInfo, uploadData, innerProcessInfo); if (errCode != E_OK) { return errCode; } - innerProcessInfo.upLoadInfo.successCount += deleteInfo.successCount; } if (!uploadData.insData.record.empty() && !uploadData.insData.extend.empty()) { @@ -1669,14 +1670,14 @@ void CloudSyncer::UpdateCloudWaterMark(TaskId taskId, const SyncParam ¶m) } } -int CloudSyncer::CommitDownloadResult(bool recordConflict, InnerProcessInfo &info, DownloadCommitList &commitList, - int errCode) +int CloudSyncer::CommitDownloadResult(const DownloadItem &downloadItem, InnerProcessInfo &info, + DownloadCommitList &commitList, int errCode) { if (commitList.empty()) { return E_OK; } uint32_t successCount = 0u; - int ret = HandleDownloadResult(recordConflict, info.tableName, commitList, successCount); + int ret = HandleDownloadResult(downloadItem, info.tableName, commitList, successCount); if (errCode == E_OK) { info.downLoadInfo.failCount += (commitList.size() - successCount); info.downLoadInfo.successCount -= (commitList.size() - successCount); 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 5f3a497e62897f4c8507c867b5ef9faa25fb2d4e..25e32cdfbc6bb3bcff55323e1292651a2355fba0 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 @@ -89,6 +89,7 @@ protected: std::map assets; Key hashKey; std::vector primaryKeyValList; + Timestamp timestamp; bool recordConflict = false; }; struct ResumeTaskInfo { @@ -225,8 +226,8 @@ protected: int FillCloudAssets(const std::string &tableName, VBucket &normalAssets, VBucket &failedAssets); - int HandleDownloadResult(bool recordConflict, const std::string &tableName, DownloadCommitList &commitList, - uint32_t &successCount); + int HandleDownloadResult(const DownloadItem &downloadItem, const std::string &tableName, + DownloadCommitList &commitList, uint32_t &successCount); int FillDownloadExtend(TaskId taskId, const std::string &tableName, const std::string &cloudWaterMark, VBucket &extend); @@ -253,7 +254,8 @@ protected: int TagStatusByStrategy(bool isExist, SyncParam ¶m, DataInfo &dataInfo, OpType &strategyOpResult); - int CommitDownloadResult(bool recordConflict, InnerProcessInfo &info, DownloadCommitList &commitList, int errCode); + int CommitDownloadResult(const DownloadItem &downloadItem, InnerProcessInfo &info, + DownloadCommitList &commitList, int errCode); int GetLocalInfo(size_t index, SyncParam ¶m, DataInfoWithLog &logInfo, std::map &localLogInfoCache, VBucket &localAssetInfo); @@ -311,6 +313,8 @@ protected: int BatchUpdate(Info &updateInfo, CloudSyncData &uploadData, InnerProcessInfo &innerProcessInfo); + int BatchDelete(Info &deleteInfo, CloudSyncData &uploadData, InnerProcessInfo &innerProcessInfo); + int DownloadAssetsOneByOne(const InnerProcessInfo &info, DownloadItem &downloadItem, std::map &downloadAssets); @@ -320,8 +324,8 @@ protected: int DownloadAssetsOneByOneInner(bool isSharedTable, const InnerProcessInfo &info, DownloadItem &downloadItem, std::map &downloadAssets); - int CommitDownloadAssets(bool recordConflict, const std::string &tableName, DownloadCommitList &commitList, - uint32_t &successCount); + int CommitDownloadAssets(const DownloadItem &downloadItem, const std::string &tableName, + DownloadCommitList &commitList, uint32_t &successCount); void GenerateCompensatedSync(); @@ -331,6 +335,8 @@ protected: int PrepareAndDowload(const std::string &table, const CloudTaskInfo &taskInfo, bool isFirstDownload); + int UpdateFlagForSavedRecord(const SyncParam ¶m); + std::mutex dataLock_; TaskId lastTaskId_; std::list taskQueue_; 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 81f6043b4405152b2f43ead6f7fd3baa05e24f47..1851d0a3c64098bf7d762f906c7a77d7154ea33b 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 @@ -302,8 +302,8 @@ int CloudSyncer::DownloadAssetsOneByOneInner(bool isSharedTable, const InnerProc return errCode; } -int CloudSyncer::CommitDownloadAssets(bool recordConflict, const std::string &tableName, DownloadCommitList &commitList, - uint32_t &successCount) +int CloudSyncer::CommitDownloadAssets(const DownloadItem &downloadItem, const std::string &tableName, + DownloadCommitList &commitList, uint32_t &successCount) { int errCode = storageProxy_->SetLogTriggerStatus(false); if (errCode != E_OK) { @@ -326,7 +326,18 @@ int CloudSyncer::CommitDownloadAssets(bool recordConflict, const std::string &ta if (errCode != E_OK) { break; } - errCode = storageProxy_->UpdateRecordFlag(tableName, gid, recordConflict); + LogInfo logInfo; + logInfo.cloudGid = gid; + // download must contain gid, just set the default value here. + logInfo.dataKey = DBConstant::DEFAULT_ROW_ID; + logInfo.hashKey = downloadItem.hashKey; + logInfo.timestamp = downloadItem.timestamp; + // there are failed assets, reset the timestamp to prevent the flag from being marked as consistent. + if (failedAssets.size() > 1) { + logInfo.timestamp = 0u; + } + + errCode = storageProxy_->UpdateRecordFlag(tableName, downloadItem.recordConflict, logInfo); if (errCode != E_OK) { break; } @@ -463,4 +474,34 @@ int CloudSyncer::GetLocalInfo(size_t index, SyncParam ¶m, DataInfoWithLog &l } return errCode; } + +int CloudSyncer::UpdateFlagForSavedRecord(const SyncParam ¶m) +{ + DownloadList downloadList; + { + std::lock_guard autoLock(dataLock_); + downloadList = currentContext_.assetDownloadList; + } + std::set gidFilters; + for (const auto &tuple: downloadList) { + gidFilters.insert(std::get(tuple)); + } + return storageProxy_->MarkFlagAsConsistent(param.tableName, param.downloadData, gidFilters); +} + +int CloudSyncer::BatchDelete(Info &deleteInfo, CloudSyncData &uploadData, InnerProcessInfo &innerProcessInfo) +{ + int errCode = cloudDB_.BatchDelete(uploadData.tableName, uploadData.delData.record, + uploadData.delData.extend, deleteInfo); + if (errCode != E_OK) { + LOGE("[CloudSyncer] Failed to batch delete, %d", errCode); + return errCode; + } + innerProcessInfo.upLoadInfo.successCount += deleteInfo.successCount; + errCode = storageProxy_->FillCloudLogAndAsset(OpType::DELETE, uploadData); + if (errCode != E_OK) { + LOGE("[CloudSyncer] Failed to fill back when doing upload delData, %d.", errCode); + } + return errCode; +} } \ 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 ecea7eef9029c3de4602e02b31aa25c96d49f5c4..dfa8511365610e0ef884c2a2df0a29d335b769a6 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 @@ -22,7 +22,7 @@ #include "ref_object.h" namespace DistributedDB { using DownloadList = std::vector, Key, - std::vector>>; + std::vector, Timestamp>>; class ICloudSyncer : public virtual RefObject { public: using TaskId = uint64_t; 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 7c76c068c52eb8cdcb5fc4a633644d686146b5eb..4052ec3318b9598a07f2af2e5587f7cdee3fe263 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 @@ -132,6 +132,9 @@ int GenericSyncer::Initialize(ISyncInterface *syncInterface, bool isNeedActive) // StartCommunicator may start an auto sync, this function can not in syncerLock_ syncEngine_->StartCommunicator(); + if (RuntimeContext::GetInstance()->CheckDBTimeChange(syncInterface_->GetIdentifier())) { + ResetTimeSyncMarkByTimeChange(metadata_, *syncInterface_); + } return E_OK; } @@ -927,8 +930,6 @@ int GenericSyncer::InitTimeChangedListener() } timeChangedListener_ = RuntimeContext::GetInstance()->RegisterTimeChangedLister( [this](void *changedOffset) { - RuntimeContext::GetInstance()->RecordAllTimeChange(); - RuntimeContext::GetInstance()->ClearAllDeviceTimeInfo(); RecordTimeChangeOffset(changedOffset); }, [this]() { @@ -946,9 +947,6 @@ int GenericSyncer::InitTimeChangedListener() std::lock_guard autoLock(timeChangeListenerMutex_); timeChangeListenerFinalize_ = false; } - if (RuntimeContext::GetInstance()->CheckDBTimeChange(syncInterface_->GetIdentifier())) { - ResetTimeSyncMarkByTimeChange(metadata_, *syncInterface_); - } return E_OK; } @@ -1180,6 +1178,9 @@ int GenericSyncer::UpgradeSchemaVerInMeta() void GenericSyncer::ResetTimeSyncMarkByTimeChange(std::shared_ptr &metadata, ISyncInterface &storage) { + if (syncEngine_ != nullptr) { + syncEngine_->TimeChange(); + } int errCode = metadata->ClearAllTimeSyncFinishMark(); if (errCode != E_OK) { LOGW("[GenericSyncer] %s clear time sync finish mark failed %d", label_.c_str(), errCode); diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/isync_engine.h b/kv_store/frameworks/libs/distributeddb/syncer/src/device/isync_engine.h index 8bca65d7dfbac13921d24d887522636cecfea58a..f87d5b2caa3d4827a64063e014fe582b9ab52f50 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/isync_engine.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/isync_engine.h @@ -98,6 +98,8 @@ public: virtual void AddSubscribe(SyncGenericInterface *storage, const std::map> &subscribeQuery) = 0; + + virtual void TimeChange() = 0; protected: ~ISyncEngine() override {}; }; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/isync_state_machine.h b/kv_store/frameworks/libs/distributeddb/syncer/src/device/isync_state_machine.h index 8efbd5070de5ecbee17929e2ddafa0a17a493b6e..809b4f832b864817d592a1596668a0a8bd1c664e 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/isync_state_machine.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/isync_state_machine.h @@ -74,6 +74,8 @@ public: // schema change and reset ability finish status virtual void SchemaChange() = 0; + + virtual void TimeChange() = 0; }; } // 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 e07e8192a4d0a43329612e97dc678b4e972b5f7a..1aef59f203fe8331c42976dfdf74b840dd43530b 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 @@ -184,6 +184,8 @@ public: virtual bool IsSchemaCompatible() const = 0; virtual void SetDbAbility(DbAbility &remoteDbAbility) = 0; + + virtual void TimeChange() = 0; protected: virtual ~ISyncTaskContext() {}; }; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/meta_data.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/device/meta_data.cpp index 919ea3e94608f0fe09b9af4d8e62dc46d9daa8ad..c5a060c54e6b9ae7e9c9cdbbac93b6d15f08fe1d 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/meta_data.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/meta_data.cpp @@ -22,6 +22,7 @@ #include "db_errno.h" #include "hash.h" #include "log_print.h" +#include "platform_specific.h" #include "securec.h" #include "sync_types.h" #include "time_helper.h" @@ -948,7 +949,14 @@ int Metadata::InitLocalMetaData() if (localMetaData.localSchemaVersion != 0) { return E_OK; } - localMetaData.localSchemaVersion += 1; + uint64_t curTime = 0; + errCode = OS::GetCurrentSysTimeInMicrosecond(curTime); + if (errCode != E_OK) { + LOGW("[Metadata] get system time failed when init schema version!"); + localMetaData.localSchemaVersion += 1; + } else { + localMetaData.localSchemaVersion = curTime; + } errCode = SaveLocalMetaData(localMetaData); if (errCode != E_OK) { LOGE("[Metadata] init local schema version failed:%d", errCode); 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 109eab6bdf4d5d58c2bb9712af1fc80e87597a40..aaade848d73a996d59d30d315dadcd953d368fa8 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 @@ -654,7 +654,7 @@ void SingleVerDataSync::UpdateSendInfo(SyncTimeRange dataTimeRange, SingleVerSyn void SingleVerDataSync::FillDataRequestPacket(DataRequestPacket *packet, SingleVerSyncTaskContext *context, SyncEntry &syncData, int sendCode, int mode) { - SetDataRequestCommonInfo(*packet); + SetDataRequestCommonInfo(*context, *packet); SyncType curType = (context->IsQuerySync()) ? SyncType::QUERY_SYNC_TYPE : SyncType::MANUAL_FULL_SYNC_TYPE; uint32_t version = std::min(context->GetRemoteSoftwareVersion(), SOFTWARE_VERSION_CURRENT); WaterMark localMark = 0; @@ -803,7 +803,7 @@ int SingleVerDataSync::PullRequestStart(SingleVerSyncTaskContext *context) uint32_t version = std::min(context->GetRemoteSoftwareVersion(), SOFTWARE_VERSION_CURRENT); WaterMark endMark = context->GetEndMark(); SyncTimeRange dataTime = {localMark, deleteMark, localMark, deleteMark}; - SetDataRequestCommonInfo(*packet); + SetDataRequestCommonInfo(*context, *packet); packet->SetBasicInfo(E_OK, version, context->GetMode()); packet->SetExtraConditions(RuntimeContext::GetInstance()->GetPermissionCheckParam(storage_->GetDbProperties())); packet->SetWaterMark(localMark, peerMark, deleteMark); @@ -969,7 +969,7 @@ int SingleVerDataSync::DataRequestRecvPre(SingleVerSyncTaskContext *context, con (void)SendDataAck(context, message, errCode, 0); return errCode; } - errCode = SchemaVersionMatchCheck(context, packet); + errCode = SingleVerDataSyncUtils::SchemaVersionMatchCheck(deviceId_, *packet, *context, metadata_); if (errCode != E_OK) { (void)SendDataAck(context, message, errCode, 0); } @@ -1684,7 +1684,7 @@ void SingleVerDataSync::UpdateMtuSize() void SingleVerDataSync::FillRequestReSendPacket(const SingleVerSyncTaskContext *context, DataRequestPacket *packet, DataSyncReSendInfo reSendInfo, SyncEntry &syncData, int sendCode) { - SetDataRequestCommonInfo(*packet); + SetDataRequestCommonInfo(*context, *packet); SyncType curType = (context->IsQuerySync()) ? SyncType::QUERY_SYNC_TYPE : SyncType::MANUAL_FULL_SYNC_TYPE; WaterMark peerMark = 0; GetPeerWaterMark(curType, context->GetQuerySyncId(), context->GetDeviceId(), @@ -2132,10 +2132,13 @@ void SingleVerDataSync::RecordClientId(const SingleVerSyncTaskContext *context) } } -void SingleVerDataSync::SetDataRequestCommonInfo(DataRequestPacket &packet) +void SingleVerDataSync::SetDataRequestCommonInfo(const SingleVerSyncTaskContext &context, DataRequestPacket &packet) { packet.SetSenderTimeOffset(metadata_->GetLocalTimeOffset()); packet.SetSystemTimeOffset(metadata_->GetSystemTimeOffset(deviceId_)); + if (context.GetRemoteSoftwareVersion() < SOFTWARE_VERSION_RELEASE_9_0) { + return; + } auto [err, localSchemaVer] = metadata_->GetLocalSchemaVersion(); if (err != E_OK) { LOGW("[DataSync] get local schema version failed:%d", err); @@ -2143,18 +2146,4 @@ void SingleVerDataSync::SetDataRequestCommonInfo(DataRequestPacket &packet) } packet.SetSchemaVersion(localSchemaVer); } - -int SingleVerDataSync::SchemaVersionMatchCheck(SingleVerSyncTaskContext *context, const DataRequestPacket *packet) -{ - if (context->GetRemoteSoftwareVersion() < SOFTWARE_VERSION_RELEASE_9_0) { - return E_OK; - } - auto remoteSchemaVersion = metadata_->GetRemoteSchemaVersion(deviceId_); - if (remoteSchemaVersion != packet->GetSchemaVersion()) { - LOGE("[DataSync] remote schema version misMatch, need ability sync again, packet %" PRIu64 " cache %" PRIu64, - packet->GetSchemaVersion(), remoteSchemaVersion); - return -E_NEED_ABILITY_SYNC; - } - return E_OK; -} } // 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 806f93759d03d97ed691717df4de2bda53f7cc7f..0be2eab87b02c1d8360031e5e25487c96e487211 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 @@ -253,9 +253,7 @@ protected: void RecordClientId(const SingleVerSyncTaskContext *context); - void SetDataRequestCommonInfo(DataRequestPacket &packet); - - int SchemaVersionMatchCheck(SingleVerSyncTaskContext *context, const DataRequestPacket *packet); + void SetDataRequestCommonInfo(const SingleVerSyncTaskContext &context, DataRequestPacket &packet); uint32_t mtuSize_; SyncGenericInterface* storage_; 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 6be9b3a5e73ea77bf020afbbd323a42b63904e16..071c9ab06e161c5fd3002f4f8f0b02b8995fab8f 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 @@ -494,4 +494,19 @@ std::pair SingleVerDataSyncUtils::GetTimeOffsetFromReque senderLocalOffset = packet->GetSenderTimeOffset(); return res; } + +int SingleVerDataSyncUtils::SchemaVersionMatchCheck(const std::string &deviceId, const DataRequestPacket &packet, + SingleVerSyncTaskContext &context, std::shared_ptr &metadata) +{ + if (context.GetRemoteSoftwareVersion() < SOFTWARE_VERSION_RELEASE_9_0) { + return E_OK; + } + auto remoteSchemaVersion = metadata->GetRemoteSchemaVersion(deviceId); + if (remoteSchemaVersion != packet.GetSchemaVersion()) { + LOGE("[DataSync] remote schema version misMatch, need ability sync again, packet %" PRIu64 " cache %" PRIu64, + packet.GetSchemaVersion(), remoteSchemaVersion); + return -E_NEED_ABILITY_SYNC; + } + return E_OK; +} } \ No newline at end of file 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 bd5c7b052a34ceb69e3654a6e76f77f02a7ead0f..bdfde107edbc7134028faf4d737ccc7762ccd6c0 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 @@ -93,6 +93,9 @@ public: const std::vector &inData, UpdateWaterMark &isUpdate); static std::pair GetTimeOffsetFromRequestMsg(const Message *message); + + static int SchemaVersionMatchCheck(const std::string &deviceId, const DataRequestPacket &packet, + SingleVerSyncTaskContext &context, std::shared_ptr &metadata); private: static int RunPermissionCheckInner(const SingleVerSyncTaskContext *context, const SyncGenericInterface* storage, const std::string &label, const DataRequestPacket *packet, int mode); 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 545f2b1331d353f153d920238db31856eb08bc0f..59f642a409885608b46f1e0eea004c067935464d 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 @@ -1313,4 +1313,13 @@ void SingleVerSyncStateMachine::SchemaChange() { abilitySync_->SetAbilitySyncFinishedStatus(false, *context_); } + +void SingleVerSyncStateMachine::TimeChange() +{ + if (timeSync_ == nullptr) { + LOGW("[SingleVerSyncStateMachine] time sync is null when time change"); + return; + } + timeSync_->ClearTimeSyncFinish(); +} } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_state_machine.h b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_state_machine.h index abe333fe1df35337fb109469363bdbfe0107d0d6..5816fa9ee59a691351171767d5e41a8a04f0812a 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_state_machine.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/singlever/single_ver_sync_state_machine.h @@ -102,6 +102,8 @@ public: void NotifyClosing() override; void SchemaChange() override; + + void TimeChange() override; protected: // Step the SingleVerSyncStateMachine void SyncStep() override; 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 addb29b3d0cd416bbb7c27f75481a717327b4a5b..abc6b8fd7d26c99e832ce2808b2422928a5492c7 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 @@ -1241,4 +1241,21 @@ void SyncEngine::AddQuerySubscribe(SyncGenericInterface *storage, const std::str } subManager_->ActiveRemoteSubscribeQuery(device, query); } + +void SyncEngine::TimeChange() +{ + std::vector decContext; + { + // copy context + std::lock_guard lock(contextMapLock_); + for (const auto &iter : syncTaskContextMap_) { + RefObject::IncObjRef(iter.second); + decContext.push_back(iter.second); + } + } + for (auto &iter : decContext) { + iter->TimeChange(); + RefObject::DecObjRef(iter); + } +} } // 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 17ff19852da6a86d839b94f9e7e4b5915085b2e5..11f124d2580fca2727f2b3cf75014d38c071c807 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 @@ -122,6 +122,8 @@ public: void AddSubscribe(SyncGenericInterface *storage, const std::map> &subscribeQuery) override; + + void TimeChange() override; protected: // Create a context virtual ISyncTaskContext *CreateSyncTaskContext() = 0; 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 857213d1b4580037a56509315b6291a1df75ae9b..d2aff3316cefc73a07c3105cafc1868d0f23934d 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 @@ -513,4 +513,8 @@ void SyncStateMachine::StopFeedDogForGetDataInner(TimerId timerId) void SyncStateMachine::SchemaChange() { } + +void SyncStateMachine::TimeChange() +{ +} } // namespace DistributedDB 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 eed991ef89095448b87a6da82940bb7281692c68..040fb9b7f27497fc5265f206f729c2e44424e861 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 @@ -82,6 +82,8 @@ public: void NotifyClosing() override; void SchemaChange() override; + + void TimeChange() override; protected: // SyncOperation is timeout, step to timeout state 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 fb01678aa4dea99d7d14eeea19296ced96870e20..6ddf322a5084a284900a69af95cbbb8125fb15c3 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 @@ -822,4 +822,13 @@ bool SyncTaskContext::IsSchemaCompatible() const void SyncTaskContext::SetDbAbility([[gnu::unused]] DbAbility &remoteDbAbility) { } + +void SyncTaskContext::TimeChange() +{ + if (stateMachine_ == nullptr) { + LOGW("[SyncTaskContext] machine is null when time change"); + return; + } + stateMachine_->TimeChange(); +} } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_task_context.h b/kv_store/frameworks/libs/distributeddb/syncer/src/device/sync_task_context.h index 1577b83dd2a2dbb63eeef17298c0778d77f944cf..ace971a870e1d1d29d3741153603ed472e942f64 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 @@ -212,6 +212,8 @@ public: bool IsSchemaCompatible() const override; void SetDbAbility(DbAbility &remoteDbAbility) override; + + void TimeChange() override; protected: const static int KILL_WAIT_SECONDS = INT32_MAX; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/time_sync.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/device/time_sync.cpp index 6322fe0cfd9ce3397e52279a65ab03403b37824e..6e0397cdbd9cd53214000dff12b622fb7d553e94 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/time_sync.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/time_sync.cpp @@ -139,6 +139,7 @@ TimeSync::TimeSync() timeHelper_(nullptr), retryTime_(0), driverTimerId_(0), + isSynced_(false), isAckReceived_(false), timeChangedListener_(nullptr), timeDriverLockCount_(0), @@ -202,6 +203,7 @@ int TimeSync::Initialize(ICommunicator *communicator, const std::shared_ptrIsTimeSyncFinish(deviceId_); return errCode; } @@ -514,7 +516,7 @@ int TimeSync::TimeSyncDriver(TimerId timerId) int TimeSync::GetTimeOffset(TimeOffset &outOffset, uint32_t timeout, uint32_t sessionId) { - if (!metadata_->IsTimeSyncFinish(deviceId_)) { + if (!isSynced_) { { std::lock_guard lock(cvLock_); isAckReceived_ = false; @@ -548,7 +550,7 @@ int TimeSync::GetTimeOffset(TimeOffset &outOffset, uint32_t timeout, uint32_t se bool TimeSync::IsNeedSync() const { - return !metadata_->IsTimeSyncFinish(deviceId_); + return !isSynced_; } void TimeSync::SetOnline(bool isOnline) @@ -683,7 +685,7 @@ void TimeSync::ReTimeSyncIfNeed(const TimeSyncPacket &ackPacket) if ((std::abs(timeOffsetIgnoreRtt) >= INT64_MAX / 2) || reTimeSync) { // 2 is half of INT64_MAX LOGI("[TimeSync][RequestRecv] timeOffSet invalid, should do time sync"); - metadata_->SetTimeSyncFinishMark(deviceId_, false); + SetTimeSyncFinishInner(false); RuntimeContext::GetInstance()->ClearDeviceTimeInfo(deviceId_); } @@ -742,15 +744,17 @@ int TimeSync::SaveOffsetWithAck(const TimeSyncPacket &ackPacket) info.recordTime = timeHelper_->GetSysCurrentTime(); info.rtt = rtt; RuntimeContext::GetInstance()->SetDeviceTimeInfo(deviceId_, info); - return metadata_->SetTimeSyncFinishMark(deviceId_, true); + SetTimeSyncFinishInner(true); + // save finish next time after save failed + return E_OK; } TimeOffset TimeSync::CalculateRawTimeOffset(const TimeSyncPacket &timeSyncInfo, TimeOffset deltaTime) { - // deltaTime = (t1 + requestLocalOffset + rtt/2) - (t1' + responseLocalOffset) - // rawTimeOffset = (t1 + rtt/2) - t1' - // rawTimeOffset = deltaTime - requestLocalOffset + responseLocalOffset - return deltaTime - timeSyncInfo.GetRequestLocalOffset() + timeSyncInfo.GetResponseLocalOffset(); + // deltaTime = (t1' + response - t1 - request + t2' + response - t2 - request)/2 + // rawTimeOffset = request - response + (t1' - t1 + t2' - t2)/2 + // rawTimeOffset = deltaTime + requestLocalOffset - responseLocalOffset + return deltaTime + timeSyncInfo.GetRequestLocalOffset() - timeSyncInfo.GetResponseLocalOffset(); } bool TimeSync::CheckSkipTimeSync(const DeviceTimeInfo &info) @@ -789,18 +793,19 @@ void TimeSync::SetTimeSyncFinishIfNeed() } int64_t systemTimeOffset = metadata_->GetSystemTimeOffset(deviceId_); LOGD("[TimeSync] Check db offset %" PRId64 " cache offset %" PRId64, systemTimeOffset, info.systemTimeOffset); - if (!CheckSkipTimeSync(info) || (metadata_->IsTimeSyncFinish(deviceId_) && - std::abs(systemTimeOffset - info.systemTimeOffset) >= MAX_TIME_OFFSET_NOISE)) { - (void)metadata_->SetTimeSyncFinishMark(deviceId_, false); + if (!CheckSkipTimeSync(info) || (IsNeedSync() && + std::abs(systemTimeOffset - info.systemTimeOffset) >= MAX_TIME_OFFSET_NOISE)) { + SetTimeSyncFinishInner(false); return; } - errCode = metadata_->SetTimeSyncFinishMark(deviceId_, true); - if (errCode != E_OK) { - return; + if (IsNeedSync()) { + SetTimeSyncFinishInner(true); } - errCode = metadata_->SetSystemTimeOffset(deviceId_, info.systemTimeOffset); - if (errCode != E_OK) { - return; + if (systemTimeOffset != info.systemTimeOffset) { + errCode = metadata_->SetSystemTimeOffset(deviceId_, info.systemTimeOffset); + if (errCode != E_OK) { + return; + } } LOGI("[TimeSync] Mark time sync finish success"); } @@ -808,10 +813,7 @@ void TimeSync::SetTimeSyncFinishIfNeed() void TimeSync::ClearTimeSyncFinish() { RuntimeContext::GetInstance()->ClearDeviceTimeInfo(deviceId_); - int errCode = metadata_->SetTimeSyncFinishMark(deviceId_, false); - if (errCode != E_OK) { - LOGW("[TimeSync] Clear %.3s time sync finish mark failed %d", deviceId_.c_str(), errCode); - } + SetTimeSyncFinishInner(false); } int TimeSync::GenerateTimeOffsetIfNeed(TimeOffset systemOffset, TimeOffset senderLocalOffset) @@ -820,7 +822,7 @@ int TimeSync::GenerateTimeOffsetIfNeed(TimeOffset systemOffset, TimeOffset sende return E_OK; } auto [errCode, info] = RuntimeContext::GetInstance()->GetDeviceTimeInfo(deviceId_); - bool syncFinish = metadata_->IsTimeSyncFinish(deviceId_); + bool syncFinish = !IsNeedSync(); bool timeChange = metadata_->IsTimeChange(deviceId_); // avoid local time change but remote record time sync finish // should return re time sync, after receive time sync request, reset time change mark @@ -834,12 +836,10 @@ int TimeSync::GenerateTimeOffsetIfNeed(TimeOffset systemOffset, TimeOffset sende RuntimeContext::GetInstance()->ClearDeviceTimeInfo(deviceId_); return -E_NEED_TIME_SYNC; } - // Sender's deltaTime = (t1 + requestLocalOffset + rtt/2) - (t1' + responseLocalOffset) - // Sender's systemOffset = (t1 + rtt/2) - t1' - // Sender's systemOffset = Sender's deltaTime - requestLocalOffset + responseLocalOffset - // Sender's deltaTime = Sender's systemOffset + requestLocalOffset - responseLocalOffset - // Receiver's deltaTime = -Sender's deltaTime = -Sender's systemOffset - requestLocalOffset + responseLocalOffset - TimeOffset offset = -systemOffset - senderLocalOffset + metadata_->GetLocalTimeOffset(); + // Sender's systemOffset = Sender's deltaTime + requestLocalOffset - responseLocalOffset + // Sender's deltaTime = Sender's systemOffset - requestLocalOffset + responseLocalOffset + // Receiver's deltaTime = -Sender's deltaTime = -Sender's systemOffset + requestLocalOffset - responseLocalOffset + TimeOffset offset = -systemOffset + senderLocalOffset - metadata_->GetLocalTimeOffset(); errCode = metadata_->SetSystemTimeOffset(deviceId_, -systemOffset); if (errCode != E_OK) { return errCode; @@ -848,13 +848,23 @@ int TimeSync::GenerateTimeOffsetIfNeed(TimeOffset systemOffset, TimeOffset sende if (errCode != E_OK) { return errCode; } - errCode = metadata_->SetTimeSyncFinishMark(deviceId_, true); - if (errCode != E_OK) { - return errCode; - } + SetTimeSyncFinishInner(true); info.systemTimeOffset = -systemOffset; info.recordTime = timeHelper_->GetSysCurrentTime(); RuntimeContext::GetInstance()->SetDeviceTimeInfo(deviceId_, info); return E_OK; } + +void TimeSync::SetTimeSyncFinishInner(bool finish) +{ + isSynced_ = finish; + if (IsRemoteLowVersion(SOFTWARE_VERSION_RELEASE_9_0)) { + return; + } + int errCode = metadata_->SetTimeSyncFinishMark(deviceId_, finish); + if (errCode != E_OK) { + LOGW("[TimeSync] Set %.3s time sync finish %d mark failed %d", deviceId_.c_str(), static_cast(finish), + errCode); + } +} } // namespace DistributedDB \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/device/time_sync.h b/kv_store/frameworks/libs/distributeddb/syncer/src/device/time_sync.h index 0e17ea63aad274d2178e5d43b2e32232c6769cea..b8ec799191ed1a955b9c370aa7339d94cb96a7aa 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/device/time_sync.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/device/time_sync.h @@ -145,6 +145,8 @@ protected: bool CheckSkipTimeSync(const DeviceTimeInfo &info); + void SetTimeSyncFinishInner(bool finish); + static TimeOffset CalculateRawTimeOffset(const TimeSyncPacket &timeSyncInfo, TimeOffset deltaTime); ICommunicator *communicateHandle_; @@ -154,6 +156,7 @@ protected: int retryTime_; TimerId driverTimerId_; TimerAction driverCallback_; + bool isSynced_; bool isAckReceived_; std::condition_variable conditionVar_; mutable std::mutex cvLock_; 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 7dc02e6a2e97e8ba4b0fc4e36bdaceb993339210..59902a6bb6f7dcfefa3aa414783df6e192ae0e1a 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 @@ -248,7 +248,8 @@ void InsertTriggerTest(DistributedDB::TableSyncType tableSyncType) EXPECT_EQ(errCode, E_OK); int resultCount = 0; - errCode = RelationalTestUtils::ExecSql(db, sql, nullptr, [curTime, &resultCount] (sqlite3_stmt *stmt) { + errCode = RelationalTestUtils::ExecSql(db, sql, nullptr, + [tableSyncType, curTime, &resultCount] (sqlite3_stmt *stmt) { EXPECT_EQ(sqlite3_column_int64(stmt, 0), 1); // 1 is row id std::string device = ""; EXPECT_EQ(SQLiteUtils::GetColumnTextValue(stmt, 1, device), E_OK); @@ -262,7 +263,11 @@ void InsertTriggerTest(DistributedDB::TableSyncType tableSyncType) int64_t diff = MULTIPLES_BETWEEN_SECONDS_AND_MICROSECONDS * TO_100_NS; EXPECT_TRUE(wtimestamp - timestamp < diff); EXPECT_TRUE(static_cast(curTime - timestamp) < diff); - EXPECT_EQ(sqlite3_column_int(stmt, 5), 2); // 5 is column index flag == 2 + if (tableSyncType == DistributedDB::CLOUD_COOPERATION) { + EXPECT_EQ(sqlite3_column_int(stmt, 5), 0x02|0x20); // 5 is column index flag == 0x02|0x20 + } else { + EXPECT_EQ(sqlite3_column_int(stmt, 5), 2); // 5 is column index flag == 2 + } resultCount++; return OK; }); @@ -343,7 +348,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, InsertTriggerTest003, Te EXPECT_EQ(SQLiteUtils::GetColumnTextValue(stmt, 2, oriDevice), E_OK); // 2 is column index EXPECT_EQ(oriDevice, ""); - EXPECT_EQ(sqlite3_column_int(stmt, 3), 2); // 3 is column index flag == 2 + EXPECT_EQ(sqlite3_column_int(stmt, 3), 0x02|0x20); // 3 is column index flag == 0x02|0x20 std::string gidStr; EXPECT_EQ(SQLiteUtils::GetColumnTextValue(stmt, 4, gidStr), E_OK); // 4 is column index EXPECT_EQ(gid, gidStr); @@ -399,7 +404,7 @@ void UpdateTriggerTest(bool primaryKeyIsRowId) EXPECT_EQ(sqlite3_column_int64(stmt, 0), 1); // 1 is row id } - EXPECT_EQ(sqlite3_column_int(stmt, 5), 2); // 5 is column index, flag == 2 + EXPECT_EQ(sqlite3_column_int(stmt, 5), 0x02|0x20); // 5 is column index, flag == 0x02|0x20 std::string device = ""; EXPECT_EQ(SQLiteUtils::GetColumnTextValue(stmt, 1, device), E_OK); 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 f5632c743bafbd56d5bec0b3bec344994778fc08..6f533e010e903b8e1857e8d5bb6127f05780d2a5 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 @@ -1691,5 +1691,99 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CreateDistributedTable001, TestSize.Le BlockSync(query, delegate_); CheckCloudTableCount(table, actualCount); } + +/* + * @tc.name: CloseDbTest001 + * @tc.desc: Test process of db close during sync + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBCloudCheckSyncTest, CloseDbTest001, TestSize.Level1) +{ + /** + * @tc.steps:step1. insert user table record. + * @tc.expected: step1. ok. + */ + const int actualCount = 10; // 10 is count of records + InsertUserTableRecord(tableName_, actualCount); + + /** + * @tc.steps:step2. wait for 2 seconds during the query to close the database. + * @tc.expected: step2. ok. + */ + std::mutex callMutex; + int callCount = 0; + virtualCloudDb_->ForkQuery([](const std::string &, VBucket &) { + std::this_thread::sleep_for(std::chrono::seconds(2)); // block notify 2s + }); + const auto callback = [&callCount, &callMutex]( + const std::map &) { + { + std::lock_guard autoLock(callMutex); + callCount++; + } + }; + Query query = Query::Select().FromTable({ tableName_ }); + ASSERT_EQ(delegate_->Sync({ "CLOUD" }, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime), OK); + std::this_thread::sleep_for(std::chrono::seconds(1)); // block notify 1s + EXPECT_EQ(mgr_->CloseStore(delegate_), DBStatus::OK); + delegate_ = nullptr; + mgr_ = nullptr; + + /** + * @tc.steps:step3. wait for 2 seconds to check the process call count. + * @tc.expected: step3. ok. + */ + std::this_thread::sleep_for(std::chrono::seconds(2)); // block notify 2s + EXPECT_EQ(callCount, 0L); +} + +/* + * @tc.name: ConsistentFlagTest001 + * @tc.desc: Test the consistency flag of no asset table + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBCloudCheckSyncTest, ConsistentFlagTest001, TestSize.Level1) +{ + /** + * @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); + InsertCloudTableRecord(tableName_, 0, cloudCount, 0, false); + Query query = Query::Select().FromTable({ tableName_ }); + BlockSync(query, delegate_); + + /** + * @tc.steps:step2. check the 0x20 bit of flag after sync + * @tc.expected: step2. ok. + */ + std::string querySql = "select count(*) from " + DBCommon::GetLogTableName(tableName_) + + " where flag&0x20=0;"; + EXPECT_EQ(sqlite3_exec(db_, querySql.c_str(), QueryCountCallback, + reinterpret_cast(localCount), nullptr), SQLITE_OK); + + /** + * @tc.steps:step3. delete local data and check + * @tc.expected: step3. ok. + */ + std::string sql = "delete from " + tableName_ + " where id = '1';"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db_, sql), E_OK); + EXPECT_EQ(sqlite3_exec(db_, querySql.c_str(), QueryCountCallback, + reinterpret_cast(localCount - 1), nullptr), SQLITE_OK); + + /** + * @tc.steps:step4. check the 0x20 bit of flag after sync + * @tc.expected: step4. ok. + */ + BlockSync(query, delegate_); + EXPECT_EQ(sqlite3_exec(db_, querySql.c_str(), QueryCountCallback, + reinterpret_cast(localCount), nullptr), SQLITE_OK); +} } #endif \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_save_cloud_data_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_save_cloud_data_test.cpp index 0d12f97efc7d0b24130cd2c37f4c56ff62bde9e9..56ae2d09e8e2b182fddbc92d08199fe5e702c9b0 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_save_cloud_data_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_save_cloud_data_test.cpp @@ -1118,7 +1118,7 @@ namespace { DBCommon::VectorToString(deviceVec, getDevice); EXPECT_EQ(device, getDevice); EXPECT_EQ(sqlite3_column_int64(stmt, 1), BASE_MODIFY_TIME + 1); - EXPECT_EQ(sqlite3_column_int(stmt, 2), 1); // 2 is flag + EXPECT_EQ(sqlite3_column_int(stmt, 2), 0x20|0x01); // 2 is flag count++; return OK; }); @@ -1473,4 +1473,63 @@ namespace { EXPECT_EQ(storage->CallFillReferenceData(syncData), E_OK); RefObject::KillAndDecObjRef(storage); } + + /** + * @tc.name: ConsistentFlagTest001 + * @tc.desc: Check the 0x20 bit of flag changed from the trigger + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ + HWTEST_F(DistributedDBCloudSaveCloudDataTest, ConsistentFlagTest001, TestSize.Level1) + { + /** + * @tc.steps:step1. create db, create table, prepare data. + * @tc.expected: step1. success. + */ + PrepareDataBase(g_tableName, PrimaryKeyType::SINGLE_PRIMARY_KEY, true); + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + ASSERT_NE(db, nullptr); + std::string sql = "insert into " + g_tableName + "(id, name) values(10, 'xx1'), (11, 'xx2')"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + sql = "delete from " + g_tableName + " where id=11;"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + + /** + * @tc.steps:step2 query inserted and updated data, check flag + * @tc.expected: step2. success. + */ + sql = "select flag from " + DBCommon::GetLogTableName(g_tableName) + + " where data_key in('10', '1')"; + int errCode = RelationalTestUtils::ExecSql(db, sql, nullptr, [] (sqlite3_stmt *stmt) { + EXPECT_EQ(sqlite3_column_int(stmt, 0), 0x20|0x02); + return OK; + }); + EXPECT_EQ(errCode, E_OK); + + /** + * @tc.steps:step3 query deleted data which gid is not empty, check flag + * @tc.expected: step3. success. + */ + sql = "select flag from " + DBCommon::GetLogTableName(g_tableName) + + " where data_key=-1 and cloud_gid !='';"; + errCode = RelationalTestUtils::ExecSql(db, sql, nullptr, [] (sqlite3_stmt *stmt) { + EXPECT_EQ(sqlite3_column_int(stmt, 0), 0x20|0x03); + return OK; + }); + EXPECT_EQ(errCode, E_OK); + + /** + * @tc.steps:step4 query deleted data which gid is empty, check flag + * @tc.expected: step4. success. + */ + sql = "select flag from " + DBCommon::GetLogTableName(g_tableName) + + " where data_key=-1 and cloud_gid ='';"; + errCode = RelationalTestUtils::ExecSql(db, sql, nullptr, [] (sqlite3_stmt *stmt) { + EXPECT_EQ(sqlite3_column_int(stmt, 0), 0x03); + return OK; + }); + EXPECT_EQ(errCode, E_OK); + EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); + } } 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 a629b57c049e55b90eba35d160af7392f9e70294..8940ed3c058a0ca49b9ae454b14cdf7f255894e1 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 @@ -25,6 +25,7 @@ #include "relational_sync_able_storage.h" #include "runtime_config.h" #include "sqlite_relational_store.h" +#include "time_helper.h" #include "virtual_asset_loader.h" #include "virtual_cloud_data_translate.h" @@ -764,8 +765,11 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudGid001, TestS * @tc.expected: return -E_INVALID_ARGS. */ syncData.insData.extend.clear(); + Timestamp now = TimeHelper::GetSysCurrentTime(); bucket1.insert_or_assign(CloudDbConstant::GID_FIELD, std::string("1")); bucket2.insert_or_assign(CloudDbConstant::CREATE_FIELD, std::string("2")); + syncData.insData.timestamp.push_back((int64_t)now / CloudDbConstant::TEN_THOUSAND); + syncData.insData.timestamp.push_back((int64_t)now / CloudDbConstant::TEN_THOUSAND); syncData.insData.extend.push_back(bucket1); syncData.insData.extend.push_back(bucket2); EXPECT_EQ(g_cloudStore->FillCloudLogAndAsset(OpType::INSERT, syncData, false, false), -E_INVALID_ARGS); 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 8686d6b9388f89c5ccfd960e193dabbce6fff1f9..570b9a5da87e1d764597050c83aa7bb8d5311d6b 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 @@ -16,6 +16,7 @@ #include "cloud/asset_operation_utils.h" #include "cloud/cloud_storage_utils.h" #include "cloud/cloud_db_constant.h" +#include "cloud_db_sync_utils_test.h" #include "distributeddb_data_generate_unit_test.h" #include "distributeddb_tools_unit_test.h" #include "mock_asset_loader.h" @@ -91,6 +92,10 @@ const Asset ASSET_COPY2 = {.version = 1, .size = "256", .hash = "ASE"}; const Assets ASSETS_COPY1 = { ASSET_COPY, ASSET_COPY2 }; +const std::string QUERY_CONSISTENT_SQL = "select count(*) from " + DBCommon::GetLogTableName(ASSETS_TABLE_NAME) + + " where flag&0x20=0;"; +const std::string QUERY_COMPENSATED_SQL = "select count(*) from " + DBCommon::GetLogTableName(ASSETS_TABLE_NAME) + + " where flag&0x10!=0;"; string g_storePath; string g_testDir; @@ -310,6 +315,18 @@ void UpdateAssetsForLocal(sqlite3 *&db, int id, uint32_t status) SQLiteUtils::ResetStatement(stmt, true, errCode); } +void CheckConsistentCount(sqlite3 *db, int64_t expectCount) +{ + EXPECT_EQ(sqlite3_exec(db, QUERY_CONSISTENT_SQL.c_str(), CloudDBSyncUtilsTest::QueryCountCallback, + reinterpret_cast(expectCount), nullptr), SQLITE_OK); +} + +void CheckCompensatedCount(sqlite3 *db, int64_t expectCount) +{ + EXPECT_EQ(sqlite3_exec(db, QUERY_COMPENSATED_SQL.c_str(), CloudDBSyncUtilsTest::QueryCountCallback, + reinterpret_cast(expectCount), nullptr), SQLITE_OK); +} + void CloseDb() { delete g_observer; @@ -1225,5 +1242,345 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetForDupDataTest int errCode; SQLiteUtils::ResetStatement(stmt, true, errCode); } + +/** + * @tc.name: FillAssetId019 + * @tc.desc: Test the stability of cleaning asset id + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId019, TestSize.Level0) +{ + /** + * @tc.steps:step1. local insert assets and sync. + * @tc.expected: step1. return OK. + */ + int localCount = 20; + InsertLocalData(db, 0, localCount, ASSETS_TABLE_NAME, false); + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK); + + /** + * @tc.steps:step2. construct multiple abnormal data_key, then RemoveDeviceData. + * @tc.expected: step2. return OK. + */ + std::string sql = "update " + DBCommon::GetLogTableName(ASSETS_TABLE_NAME) + + " set data_key='999' where data_key>'10';"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK); + EXPECT_EQ(g_delegate->RemoveDeviceData("", FLAG_ONLY), OK); +} + +/** + * @tc.name: ConsistentFlagTest001 + * @tc.desc:Assets are the different, check the 0x20 bit of flag after sync + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, ConsistentFlagTest001, TestSize.Level0) +{ + /** + * @tc.steps:step1. init data for the different asset, sync and check flag + * @tc.expected: step1. return OK. + */ + int localCount = 10; // 10 is num of local + int cloudCount = 20; // 20 is num of cloud + InsertLocalData(db, 0, localCount, ASSETS_TABLE_NAME, false); + UpdateLocalData(db, ASSETS_TABLE_NAME, ASSETS_COPY1); + InsertCloudDBData(0, cloudCount, 0, ASSETS_TABLE_NAME); + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK); + CheckConsistentCount(db, cloudCount); + + /** + * @tc.steps:step2. update local data, sync and check flag + * @tc.expected: step2. return OK. + */ + UpdateLocalData(db, ASSETS_TABLE_NAME, ASSETS_COPY1); + DeleteCloudDBData(1, 1, ASSETS_TABLE_NAME); + CheckConsistentCount(db, 0L); + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK); + CheckConsistentCount(db, cloudCount); +} + +/** + * @tc.name: ConsistentFlagTest002 + * @tc.desc: Assets are the same, check the 0x20 bit of flag after sync + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, ConsistentFlagTest002, TestSize.Level0) +{ + /** + * @tc.steps:step1. init data for the same asset, sync and check flag + * @tc.expected: step1. return OK. + */ + int cloudCount = 20; // 20 is num of cloud + InsertLocalData(db, 0, cloudCount, ASSETS_TABLE_NAME, true); + InsertCloudDBData(0, cloudCount, 0, ASSETS_TABLE_NAME); + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK); + CheckConsistentCount(db, cloudCount); + + /** + * @tc.steps:step2. update local data, sync and check flag + * @tc.expected: step2. return OK. + */ + int deleteLocalCount = 5; + DeleteLocalRecord(db, 0, deleteLocalCount, ASSETS_TABLE_NAME); + CheckConsistentCount(db, cloudCount - deleteLocalCount); + UpdateLocalData(db, ASSETS_TABLE_NAME, ASSETS_COPY1); + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK); + CheckConsistentCount(db, cloudCount); +} + +/** + * @tc.name: ConsistentFlagTest003 + * @tc.desc: Download returns a conflict, check the 0x20 bit of flag after sync + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, ConsistentFlagTest003, TestSize.Level1) +{ + /** + * @tc.steps:step1. init data + * @tc.expected: step1. return OK. + */ + int localCount = 20; // 20 is num of local + int cloudCount = 10; // 10 is num of cloud + InsertLocalData(db, 0, localCount, ASSETS_TABLE_NAME, false); + UpdateLocalData(db, ASSETS_TABLE_NAME, ASSETS_COPY1); + InsertCloudDBData(0, cloudCount, 0, ASSETS_TABLE_NAME); + + /** + * @tc.steps:step2. fork download, return CLOUD_RECORD_EXIST_CONFLICT once + * @tc.expected: step2. return OK. + */ + std::shared_ptr assetLoader = make_shared(); + ASSERT_EQ(g_delegate->SetIAssetLoader(assetLoader), DBStatus::OK); + int index = 0; + EXPECT_CALL(*assetLoader, Download(testing::_, testing::_, testing::_, testing::_)) + .WillRepeatedly( + [&index](const std::string &, const std::string &gid, const Type &, std::map &assets) { + LOGD("download gid:%s, index:%d", gid.c_str(), ++index); + if (index == 1) { // 1 is first download + return DBStatus::CLOUD_RECORD_EXIST_CONFLICT; + } + return DBStatus::OK; + }); + + /** + * @tc.steps:step3. fork upload, check consistent count + * @tc.expected: step3. return OK. + */ + int upIdx = 0; + g_virtualCloudDb->ForkUpload([this, localCount, cloudCount, &upIdx](const std::string &tableName, VBucket &extend) { + LOGD("upload index:%d", ++upIdx); + if (upIdx == 1) { // 1 is first upload + CheckConsistentCount(db, localCount - cloudCount - 1); + } + }); + + /** + * @tc.steps:step4. fork query, check consistent count + * @tc.expected: step4. return OK. + */ + int queryIdx = 0; + g_virtualCloudDb->ForkQuery([this, localCount, &queryIdx](const std::string &, VBucket &) { + LOGD("query index:%d", ++queryIdx); + if (queryIdx == 3) { // 3 is the last query + CheckConsistentCount(db, localCount - 1); + } + }); + + /** + * @tc.steps:step5. sync, check consistent count + * @tc.expected: step5. return OK. + */ + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK); + std::this_thread::sleep_for(std::chrono::seconds(2)); // wait compensation sync finish + CheckConsistentCount(db, localCount); +} + +/** + * @tc.name: ConsistentFlagTest004 + * @tc.desc: Upload returns error, check the 0x20 bit of flag after sync + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, ConsistentFlagTest004, TestSize.Level0) +{ + /** + * @tc.steps:step1. init data + * @tc.expected: step1. return OK. + */ + int localCount = 20; // 20 is num of local + int cloudCount = 10; // 10 is num of cloud + InsertLocalData(db, 0, localCount, ASSETS_TABLE_NAME, false); + UpdateLocalData(db, ASSETS_TABLE_NAME, ASSETS_COPY1); + InsertCloudDBData(0, cloudCount, 0, ASSETS_TABLE_NAME); + + /** + * @tc.steps:step2. fork upload, return error filed of type string + * @tc.expected: step2. return OK. + */ + int upIdx = 0; + g_virtualCloudDb->ForkUpload([&upIdx](const std::string &tableName, VBucket &extend) { + LOGD("upload index:%d", ++upIdx); + if (upIdx == 1) { + extend.insert_or_assign(CloudDbConstant::ERROR_FIELD, std::string("x")); + } + }); + + /** + * @tc.steps:step3. sync, check consistent count + * @tc.expected: step3. return OK. + */ + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK); + CheckConsistentCount(db, localCount - 1); + + /** + * @tc.steps:step4. update local data, fork upload, return error filed of type int64_t + * @tc.expected: step4. return OK. + */ + UpdateLocalData(db, ASSETS_TABLE_NAME, ASSETS_COPY1); + upIdx = 0; + g_virtualCloudDb->ForkUpload([&upIdx](const std::string &tableName, VBucket &extend) { + LOGD("upload index:%d", ++upIdx); + if (upIdx == 1) { + int64_t err = DBStatus::CLOUD_RECORD_EXIST_CONFLICT; + extend.insert_or_assign(CloudDbConstant::ERROR_FIELD, err); + } + if (upIdx == 2) { + int64_t err = DBStatus::CLOUD_RECORD_EXIST_CONFLICT + 1; + extend.insert_or_assign(CloudDbConstant::ERROR_FIELD, err); + } + }); + + /** + * @tc.steps:step5. sync, check consistent count + * @tc.expected: step5. return OK. + */ + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK); + CheckConsistentCount(db, localCount - 1); +} + +/** + * @tc.name: ConsistentFlagTest005 + * @tc.desc: Local data changes during download, check the 0x20 bit of flag after sync + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, ConsistentFlagTest005, TestSize.Level0) +{ + /** + * @tc.steps:step1. init data + * @tc.expected: step1. return OK. + */ + int localCount = 20; // 20 is num of local + int cloudCount = 10; // 10 is num of cloud + InsertLocalData(db, 0, localCount, ASSETS_TABLE_NAME, false); + UpdateLocalData(db, ASSETS_TABLE_NAME, ASSETS_COPY1); + InsertCloudDBData(0, cloudCount, 0, ASSETS_TABLE_NAME); + + /** + * @tc.steps:step2. fork download, update local assets where id=2 + * @tc.expected: step2. return OK. + */ + std::shared_ptr assetLoader = make_shared(); + ASSERT_EQ(g_delegate->SetIAssetLoader(assetLoader), DBStatus::OK); + int index = 0; + EXPECT_CALL(*assetLoader, Download(testing::_, testing::_, testing::_, testing::_)) + .WillRepeatedly( + [this, &index](const std::string &, const std::string &gid, const Type &, + std::map &assets) { + LOGD("download gid:%s, index:%d", gid.c_str(), ++index); + if (index == 1) { // 1 is first download + std::string sql = "UPDATE " + ASSETS_TABLE_NAME + " SET assets=NULL where id=2;"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK); + } + return DBStatus::OK; + }); + + /** + * @tc.steps:step3. fork upload, check consistent count + * @tc.expected: step3. return OK. + */ + int upIdx = 0; + g_virtualCloudDb->ForkUpload([this, localCount, cloudCount, &upIdx](const std::string &tableName, VBucket &extend) { + LOGD("upload index:%d", ++upIdx); + if (upIdx == 1) { // 1 is first upload + CheckConsistentCount(db, localCount - cloudCount - 1); + } + }); + + /** + * @tc.steps:step4. sync, check consistent count + * @tc.expected: step4. return OK. + */ + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK); + CheckConsistentCount(db, localCount); +} + +/** + * @tc.name: ConsistentFlagTest006 + * @tc.desc: + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, ConsistentFlagTest006, TestSize.Level0) +{ + /** + * @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); + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK); + + /** + * @tc.steps:step2. fork download, update local assets where id=2 + * @tc.expected: step2. return OK. + */ + UpdateLocalData(db, ASSETS_TABLE_NAME, ASSETS_COPY1); + int delCount = 3; // 3 is num of cloud + DeleteCloudDBData(1, delCount, ASSETS_TABLE_NAME); + std::shared_ptr assetLoader = make_shared(); + ASSERT_EQ(g_delegate->SetIAssetLoader(assetLoader), DBStatus::OK); + int index = 0; + EXPECT_CALL(*assetLoader, Download(testing::_, testing::_, testing::_, testing::_)) + .WillRepeatedly( + [&index](const std::string &, const std::string &gid, const Type &, + std::map &assets) { + LOGD("download gid:%s, index:%d", gid.c_str(), ++index); + if (index == 1) { // 1 is first download + return DBStatus::CLOUD_RECORD_EXIST_CONFLICT; + } + return DBStatus::OK; + }); + + /** + * @tc.steps:step3. fork upload, check consistent count + * @tc.expected: step3. return OK. + */ + int upIdx = 0; + g_virtualCloudDb->ForkUpload([this, delCount, &upIdx](const std::string &tableName, VBucket &extend) { + LOGD("upload index:%d", ++upIdx); + if (upIdx == 1) { // 1 is first upload + CheckConsistentCount(db, delCount); + CheckCompensatedCount(db, 0L); + } + }); + + /** + * @tc.steps:step4. sync, check consistent count + * @tc.expected: step4. return OK. + */ + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK); + CheckConsistentCount(db, cloudCount); +} } // namespace #endif // RELATIONAL_STORE 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 4e85f49b00aa05a10477809645326c9e85ef1fe8..33351682bc026a8c69260bd74584bf88fd8317c7 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 @@ -112,6 +112,8 @@ DBStatus VirtualCloudDb::BatchInsertWithGid(const std::string &tableName, std::v for (size_t i = 0; i < record.size(); ++i) { if (extend[i].find(g_gidField) == extend[i].end()) { extend[i][g_gidField] = std::to_string(currentGid_++); + } else { + currentGid_++; } extend[i][g_cursorField] = std::to_string(currentCursor_++); extend[i][g_deleteField] = false; @@ -331,8 +333,28 @@ bool VirtualCloudDb::IsPrimaryKeyMatching(const std::vector &queryNod bool VirtualCloudDb::IsPrimaryKeyMatchingInner(const QueryNode &queryNode, VBucket &record) { for (const auto &value : queryNode.fieldValue) { - if (std::get(record[queryNode.fieldName]) == std::get(value)) { - return true; + size_t type = record[queryNode.fieldName].index(); + switch (type) { + case TYPE_INDEX: { + if (std::get(record[queryNode.fieldName]) == std::get(value)) { + return true; + } + break; + } + case TYPE_INDEX: { + if (std::get(record[queryNode.fieldName]) == std::get(value)) { + return true; + } + break; + } + case TYPE_INDEX: { + if (std::get(record[queryNode.fieldName]) == std::get(value)) { + return true; + } + break; + } + default: + break; } } return false; 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 c4e2f23408c20ed54239a8acb51c9908f4d45124..b277124f82f40806d27a5b33ca86d015b1d0ade4 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 @@ -240,7 +240,7 @@ HWTEST_F(DistributedDBMetaDataTest, MetadataTest005, TestSize.Level0) */ auto res = metadata_->GetLocalSchemaVersion(); EXPECT_EQ(res.first, E_OK); - EXPECT_EQ(res.second, 1u); + EXPECT_NE(res.second, 0u); /** * @tc.steps: step2. Set local schema version. * @tc.expected: step2. set success. 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 4e067da81c86deb8c5a643951e7704b461eed804..e94692e4f8f90ad5baf8180845ce2948409aaaff 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 @@ -1237,6 +1237,8 @@ HWTEST_F(DistributedDBRelationalMultiUserTest, RDBSyncOpt005, TestSize.Level0) * @tc.expected: step4. sync success, only time sync packet */ RuntimeContext::GetInstance()->NotifyTimestampChanged(100); + RuntimeContext::GetInstance()->RecordAllTimeChange(); + RuntimeContext::GetInstance()->ClearAllDeviceTimeInfo(); messageCount = 0; EXPECT_EQ(g_deviceB->GenericVirtualDevice::Sync(SYNC_MODE_PUSH_ONLY, query, true), OK); EXPECT_EQ(messageCount, 1); 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 0db86b02064d644dbe5426dc2b6a2686f45cb8aa..0cbf977eff085d7baa61f0765e4061b5bc6b8504 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 @@ -1730,6 +1730,7 @@ HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVSyncOpt002, TestSize.Level0) ASSERT_EQ(g_mgr.CloseKvStore(g_kvDelegatePtr), OK); g_kvDelegatePtr = nullptr; ASSERT_EQ(g_mgr.DeleteKvStore(STORE_ID), OK); + EXPECT_TRUE(RuntimeContext::GetInstance()->IsTimeTickMonitorValid()); /** * @tc.steps: step3. open new kv store * @tc.expected: step3. open OK. @@ -1941,6 +1942,8 @@ HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, KVTimeChange001, TestSize.Level * @tc.expected: step4. sync success, only time sync packet. */ RuntimeContext::GetInstance()->NotifyTimestampChanged(100); + RuntimeContext::GetInstance()->RecordAllTimeChange(); + RuntimeContext::GetInstance()->ClearAllDeviceTimeInfo(); messageCount = 0; Sync(devices, OK); EXPECT_EQ(messageCount, 1); // 1 contain time sync request packet diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_time_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_time_sync_test.cpp index 68d4d664552786840125b6b8738cf7484dfdca87..2a3725ff3498f5e41bb1e9e15c71f085f84ce5b6 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_time_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_time_sync_test.cpp @@ -496,4 +496,33 @@ HWTEST_F(DistributedDBTimeSyncTest, CheckRemoteVersion001, TestSize.Level0) EXPECT_TRUE(g_timeSyncA->IsRemoteLowVersion(SOFTWARE_VERSION_RELEASE_9_0)); g_virtualCommunicator->SetRemoteVersion(SOFTWARE_VERSION_RELEASE_9_0); EXPECT_FALSE(g_timeSyncA->IsRemoteLowVersion(SOFTWARE_VERSION_RELEASE_9_0)); +} + +/** + * @tc.name: SetTimeSyncFinish001 + * @tc.desc: Verify set time sync finish won't write into db when cache is finish. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBTimeSyncTest, SetTimeSyncFinish001, TestSize.Level0) +{ + /** + * @tc.steps: step1. Initialize the metadata and time sync + * @tc.expected: step1. Initialize successfully + */ + EXPECT_EQ(g_metadataA->Initialize(g_syncInterfaceA), E_OK); + EXPECT_EQ(g_metadataA->SetTimeSyncFinishMark(DEVICE_B, true), E_OK); + int errCode = g_timeSyncA->Initialize(g_virtualCommunicator, g_metadataA, g_syncInterfaceA, DEVICE_B); + EXPECT_EQ(errCode, E_OK); + /** + * @tc.steps: step2. Set time sync finish + * @tc.expected: step2. meta is not finish because time sync cache is finish + */ + EXPECT_EQ(g_metadataA->SetTimeSyncFinishMark(DEVICE_B, false), E_OK); + DeviceTimeInfo info; + RuntimeContext::GetInstance()->SetDeviceTimeInfo(DEVICE_B, info); + g_timeSyncA->SetTimeSyncFinishIfNeed(); + EXPECT_FALSE(g_metadataA->IsTimeSyncFinish(DEVICE_B)); + RuntimeContext::GetInstance()->ClearAllDeviceTimeInfo(); } \ 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 225e73221e0e31ab607b6a2f469909ef9835710f..f79afd34fc879f63e7ce50fdaf26efd516b33175 100644 --- a/mock/innerkits/device_manager/devicemanagersdk/include/dm_device_info.h +++ b/mock/innerkits/device_manager/devicemanagersdk/include/dm_device_info.h @@ -1,22 +1,23 @@ /* - * 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_DEVICE_INFO_H #define OHOS_DM_DEVICE_INFO_H #include +#include #include #include "dm_app_image_info.h" @@ -26,53 +27,304 @@ namespace OHOS { namespace DistributedHardware { +/** +* @brief Device manager event notify. +*/ typedef enum DmNotifyEvent { + /** + * Device manager start event. + */ DM_NOTIFY_EVENT_START = 0, + /** + * Device manager on ready event. + */ DM_NOTIFY_EVENT_ONDEVICEREADY, // Add event here DM_NOTIFY_EVENT_BUTT, } DmNotifyEvent; +/** +* @brief Device Type definitions. +*/ typedef enum DmDeviceType { + /** + * Indicates an unknown device type. + */ DEVICE_TYPE_UNKNOWN = 0x00, + /** + * Indicates a smart camera. + */ DEVICE_TYPE_WIFI_CAMERA = 0x08, + /** + * Indicates a smart speaker. + */ DEVICE_TYPE_AUDIO = 0x0A, + /** + * Indicates a smart pc. + */ DEVICE_TYPE_PC = 0x0C, + /** + * Indicates a smart phone. + */ DEVICE_TYPE_PHONE = 0x0E, + /** + * Indicates a smart pad. + */ DEVICE_TYPE_PAD = 0x11, + /** + * Indicates a smart watch. + */ DEVICE_TYPE_WATCH = 0x6D, + /** + * Indicates a car. + */ DEVICE_TYPE_CAR = 0x83, + /** + * Indicates a smart TV. + */ DEVICE_TYPE_TV = 0x9C, + /** + * Indicates smart display + */ + DEVICE_TYPE_SMART_DISPLAY = 0xA02, + /** + * Indicates 2in1 + */ + DEVICE_TYPE_2IN1 = 0xA2F, } DmDeviceType; +/** +* @brief Device state change event definition. +*/ typedef enum DmDeviceState { + /** + * Device status is unknown. + */ DEVICE_STATE_UNKNOWN = -1, + /** + * Device online action, which indicates the device is physically online. + */ DEVICE_STATE_ONLINE = 0, + /** + * Device ready action, which indicates the information between devices has + * been synchronized in the Distributed Data Service (DDS) module, + * and the device is ready for running distributed services. + */ DEVICE_INFO_READY = 1, + /** + * Device offline action, which Indicates the device is physically offline. + */ DEVICE_STATE_OFFLINE = 2, + /** + * Device change action, which Indicates the device is physically change. + */ DEVICE_INFO_CHANGED = 3, } DmDeviceState; +/** +* @brief Device authentication form. +*/ +typedef enum DmAuthForm { + /** + * Device Auth invalid. + */ + INVALID_TYPE = -1, + /** + * Peer To Peer Device auth. + */ + PEER_TO_PEER = 0, + /** + * Identical Account Device auth. + */ + IDENTICAL_ACCOUNT = 1, + /** + * Across Account Device auth. + */ + ACROSS_ACCOUNT = 2, +} DmAuthForm; + +/** +* @brief Device Information. +*/ typedef struct DmDeviceInfo { + /** + * Device Id of the device. + */ char deviceId[DM_MAX_DEVICE_ID_LEN]; + /** + * Device name of the device. + */ char deviceName[DM_MAX_DEVICE_NAME_LEN]; + /** + * Device type of the device. + */ uint16_t deviceTypeId; + /** + * NetworkId of the device. + */ char networkId[DM_MAX_DEVICE_ID_LEN]; + /** + * The distance of discovered device, in centimeter(cm). + */ int32_t range; + /** + * NetworkType of the device. + */ + int32_t networkType; + /** + * Device authentication form. + */ + DmAuthForm authForm; + /** + * Extra data of the device. + * include json keys: "CONN_ADDR_TYPE", "BR_MAC_", "BLE_MAC", "WIFI_IP", "WIFI_PORT", "CUSTOM_DATA" + */ + std::string extraData; } DmDeviceInfo; +/** +* @brief Device Basic Information. +*/ +typedef struct DmDeviceBasicInfo { + /** + * Device Id of the device. + */ + char deviceId[DM_MAX_DEVICE_ID_LEN]; + /** + * Device name of the device. + */ + char deviceName[DM_MAX_DEVICE_NAME_LEN]; + /** + * Device type of the device. + */ + uint16_t deviceTypeId; + /** + * NetworkId of the device. + */ + char networkId[DM_MAX_DEVICE_ID_LEN]; +} DmDeviceBasicInfo; + +/** +* @brief Device Authentication param. +*/ typedef struct DmAuthParam { + /** + * the token used for this authentication. + */ std::string authToken; + /** + * the package name used for this authentication. + */ std::string packageName; + /** + * the app name used for this authentication. + */ std::string appName; + /** + * the app description used for this authentication. + */ std::string appDescription; + /** + * the auth type used for this authentication. + */ int32_t authType; + /** + * the business used for this authentication. + */ int32_t business; + /** + * the pin code used for this authentication. + */ int32_t pincode; + /** + * the direction used for this authentication. + */ int32_t direction; + /** + * the pin token used for this authentication. + */ int32_t pinToken; + /** + * the app image info used for this authentication. + */ DmAppImageInfo imageinfo; } DmAuthParam; + +/** +* @brief Peer target id Information. +*/ +typedef struct PeerTargetId { + /** + * device id. + */ + std::string deviceId; + /** + * br mac address. + */ + std::string brMac; + /** + * ble mac address. + */ + std::string bleMac; + /** + * wlan ip address. + */ + std::string wifiIp; + /** + * wlan ip port. + */ + uint16_t wifiPort; + + 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 + { + return (deviceId < other.deviceId) && (brMac < other.brMac) && (bleMac < other.bleMac) && + (wifiIp < other.wifiIp) && (wifiPort < other.wifiPort); + } +} PeerTargetId; + +typedef enum { + BIT_NETWORK_TYPE_UNKNOWN = 0, /**< Unknown network type */ + BIT_NETWORK_TYPE_WIFI, /**< WIFI network type */ + BIT_NETWORK_TYPE_BLE, /**< BLE network type */ + BIT_NETWORK_TYPE_BR, /**< BR network type */ + BIT_NETWORK_TYPE_P2P, /**< P2P network type */ + BIT_NETWORK_TYPE_COUNT, /**< Invalid type */ +} DmNetworkType; + +typedef enum { + NUMBER_PIN_CODE = 0, + QR_CODE, + VISIBLE_LLIGHT, + SUPER_SONIC, +} DmPinType; + +typedef enum { + STATUS_DM_AUTH_DEFAULT = 0, + STATUS_DM_AUTH_FINISH = 7, + STATUS_DM_SHOW_AUTHORIZE_UI = 8, + STATUS_DM_CLOSE_AUTHORIZE_UI = 9, + STATUS_DM_SHOW_PIN_DISPLAY_UI = 10, + STATUS_DM_CLOSE_PIN_DISPLAY_UI = 11, + STATUS_DM_SHOW_PIN_INPUT_UI = 12, + STATUS_DM_CLOSE_PIN_INPUT_UI = 13, +} DmAuthStatus; + +const std::string DEVICE_TYPE_UNKNOWN_STRING = "UNKNOWN"; +const std::string DEVICE_TYPE_PHONE_STRING = "PHONE"; +const std::string DEVICE_TYPE_PAD_STRING = "PAD"; +const std::string DEVICE_TYPE_TV_STRING = "TV"; +const std::string DEVICE_TYPE_CAR_STRING = "CAR"; +const std::string DEVICE_TYPE_WATCH_STRING = "WATCH"; +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"; } // namespace DistributedHardware } // namespace OHOS #endif // OHOS_DM_DEVICE_INFO_H diff --git a/mock/innerkits/netmanager_base/innerkits/netconnclient/include/net_all_capabilities.h b/mock/innerkits/netmanager_base/innerkits/netconnclient/include/net_all_capabilities.h index 03c6b602400709772801f9003e63d65898dd9f17..9ba1d39c003a82fc45cd3ede973c480246c151c6 100644 --- a/mock/innerkits/netmanager_base/innerkits/netconnclient/include/net_all_capabilities.h +++ b/mock/innerkits/netmanager_base/innerkits/netconnclient/include/net_all_capabilities.h @@ -49,18 +49,34 @@ struct NetAllCapabilities final: public Parcelable { std::set bearerTypes_; NetAllCapabilities() = default; - NetAllCapabilities(const NetAllCapabilities &cap); - NetAllCapabilities &operator=(const NetAllCapabilities &cap); + NetAllCapabilities(const NetAllCapabilities &cap) {} + NetAllCapabilities &operator=(const NetAllCapabilities &cap) + { + return *this; + } - bool CapsIsValid() const; - bool CapsIsNull() const; - bool Marshalling(Parcel &parcel) const override; - bool Unmarshalling(Parcel &parcel); - std::string ToString(const std::string &tab) const; + bool CapsIsValid() const + { + return false; + } + bool CapsIsNull() const + { + return false; + } + bool Marshalling(Parcel &parcel) const override + { + return false; + } + bool Unmarshalling(Parcel &parcel) + { + return false; + } + std::string ToString(const std::string &tab) const + { + return std::string(); + } private: - void ToStrNetCaps(const std::set &netCaps, std::string &str) const; - void ToStrNetBearTypes(const std::set &bearerTypes, std::string &str) const; }; } // namespace NetManagerStandard } // namespace OHOS diff --git a/mock/innerkits/samgr_standard/samgr_proxy/include/system_ability_status_change_stub.h b/mock/innerkits/samgr_standard/samgr_proxy/include/system_ability_status_change_stub.h index e2205eef959cea1f9764fba27e8cd04ec7c9e6e3..75a1c096b2b5e60461f1e908ab60e5f020a4abe2 100644 --- a/mock/innerkits/samgr_standard/samgr_proxy/include/system_ability_status_change_stub.h +++ b/mock/innerkits/samgr_standard/samgr_proxy/include/system_ability_status_change_stub.h @@ -23,19 +23,20 @@ namespace OHOS { class SystemAbilityStatusChangeStub : public IRemoteStub { public: - SystemAbilityStatusChangeStub(); + SystemAbilityStatusChangeStub() {} ~SystemAbilityStatusChangeStub() = default; - int32_t OnRemoteRequest(uint32_t code, MessageParcel& data, MessageParcel& reply, MessageOption& option) override; + int32_t OnRemoteRequest(uint32_t code, MessageParcel& data, MessageParcel& reply, MessageOption& option) override + { + return IPCObjectStub::OnRemoteRequest(code, data, reply, option); + } protected: - static bool CheckInputSysAbilityId(int32_t systemAbilityId); + static bool CheckInputSysAbilityId(int32_t systemAbilityId) + { + return false; + } private: - int32_t OnAddSystemAbilityInner(MessageParcel& data, MessageParcel& reply); - int32_t OnRemoveSystemAbilityInner(MessageParcel& data, MessageParcel& reply); - static bool CanRequest(); - static bool EnforceInterceToken(MessageParcel& data); - using SystemAbilityStatusChangeStubFunc = int32_t (SystemAbilityStatusChangeStub::*)(MessageParcel& data, MessageParcel& reply); std::map memberFuncMap_; diff --git a/mock/src/mock_file.cpp b/mock/src/mock_file.cpp index 909c7681e891f02c3ea64a8b0ddc552ac6381e5c..794ade96d4b8065a326df004fb9dd0f2c49a4e10 100644 --- a/mock/src/mock_file.cpp +++ b/mock/src/mock_file.cpp @@ -30,6 +30,7 @@ bool CommonFunc::CheckPublicDirPath(const std::string& sandboxPath) namespace ModuleFileUri { std::string FileUri::GetName() { + return ""; } std::string FileUri::GetPath() diff --git a/mock/src/mock_napi_base_context.cpp b/mock/src/mock_napi_base_context.cpp index be8e2f9dea9b1daa03769121ed8d5582811ea732..770e6e40e4692e788c5157f7ff3edc82ef8ac64b 100644 --- a/mock/src/mock_napi_base_context.cpp +++ b/mock/src/mock_napi_base_context.cpp @@ -33,6 +33,7 @@ napi_value WrapWant(napi_env env, const Want &want) { return nullptr; } bool UnwrapWant(napi_env env, napi_value param, Want &want) { return false; } int UnwrapInt32FromJS(napi_env env, napi_value param, int defaultValue) { return 0; } std::string UnwrapStringFromJS(napi_env env, napi_value param, const std::string &defaultValue) { return defaultValue; } +bool UnwrapArrayInt32FromJS(napi_env env, napi_value param, std::vector &value) { return ""; } bool UnwrapArrayStringFromJS(napi_env env, napi_value param, std::vector &value) { return true; } napi_value WrapVoidToJS(napi_env env) { return nullptr; } bool IsArrayForNapiValue(napi_env env, napi_value param, uint32_t &arraySize) { return true; } diff --git a/relational_store/CMakeLists.txt b/relational_store/CMakeLists.txt index f1c299dab75722576091bc95e0372af7446c36e7..adf220c2976c45f5fc5b1d6bf49f30482b2c4068 100644 --- a/relational_store/CMakeLists.txt +++ b/relational_store/CMakeLists.txt @@ -23,6 +23,7 @@ aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/appdatafwk/sr list(REMOVE_ITEM relational_store_src "${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/appdatafwk/src/general_endian.cpp") aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/rdb/src relational_store_src) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/rdbmock/frameworks/native/rdb relational_store_src) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/dataability/src rdb_adapter_src) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/rdb_bms_adaptor/src rdb_adapter_src) @@ -49,6 +50,7 @@ include(${KV_STORE_DIR}/interfaces/CMakeLists.txt OPTIONAL) set(links secure mock distributeddb kvdb) add_library(relational_store SHARED ${relational_store_src} ${rdb_adapter_src}) target_link_libraries(relational_store ${links}) +target_include_directories(relational_store PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/rdbmock/frameworks/native/rdb) target_include_directories(relational_store PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/inner_api/rdb/include) target_include_directories(relational_store PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/inner_api/appdatafwk/include) target_include_directories(relational_store PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/inner_api/common_type/include) @@ -56,6 +58,7 @@ target_include_directories(relational_store PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/i target_include_directories(relational_store PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/inner_api/rdb_data_ability_adapter/include) target_include_directories(relational_store PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/inner_api/rdb_data_share_adapter/include) target_include_directories(relational_store PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/inner_api/dataability/include) +target_compile_options(relational_store PRIVATE "-includemock.h") add_library(js_relational_store SHARED ${js_common_src} ${js_relational_store_src}) diff --git a/relational_store/frameworks/common/include/logger.h b/relational_store/frameworks/common/include/logger.h index ba67d14b466d2442a43537d9bf10a3388bbdd5d0..4f6241128ba98ee79f33a79a7fafa7d3d8bbce2a 100644 --- a/relational_store/frameworks/common/include/logger.h +++ b/relational_store/frameworks/common/include/logger.h @@ -41,7 +41,7 @@ static inline OHOS::HiviewDFX::HiLogLabel LogLabel() using HiLog = OHOS::HiviewDFX::HiLog; \ auto lable = LogLabel(); \ if (HiLogIsLoggable(lable.domain, lable.tag, LogLevel::LOG_DEBUG)) { \ - HiLog::Debug(lable, "::[%{public}s()-%{public}s:%{public}d]: " fmt, __FUNCTION__, FILENAME, __LINE__, \ + HiLog::Debug(lable, "::[%{public}s:%{public}d]: " fmt, __FUNCTION__, __LINE__, \ ##__VA_ARGS__); \ } \ } while (0) @@ -51,7 +51,7 @@ static inline OHOS::HiviewDFX::HiLogLabel LogLabel() using HiLog = OHOS::HiviewDFX::HiLog; \ auto lable = LogLabel(); \ if (HiLogIsLoggable(lable.domain, lable.tag, LogLevel::LOG_INFO)) { \ - HiLog::Info(lable, "::[%{public}s()-%{public}s:%{public}d]: " fmt, __FUNCTION__, FILENAME, __LINE__, \ + HiLog::Info(lable, "::[%{public}s:%{public}d]: " fmt, __FUNCTION__, __LINE__, \ ##__VA_ARGS__); \ } \ } while (0) @@ -61,7 +61,7 @@ static inline OHOS::HiviewDFX::HiLogLabel LogLabel() using HiLog = OHOS::HiviewDFX::HiLog; \ auto lable = LogLabel(); \ if (HiLogIsLoggable(lable.domain, lable.tag, LogLevel::LOG_WARN)) { \ - HiLog::Warn(lable, "::[%{public}s()-%{public}s:%{public}d]: " fmt, __FUNCTION__, FILENAME, __LINE__, \ + HiLog::Warn(lable, "::[%{public}s:%{public}d]: " fmt, __FUNCTION__, __LINE__, \ ##__VA_ARGS__); \ } \ } while (0) @@ -71,7 +71,7 @@ static inline OHOS::HiviewDFX::HiLogLabel LogLabel() using HiLog = OHOS::HiviewDFX::HiLog; \ auto lable = LogLabel(); \ if (HiLogIsLoggable(lable.domain, lable.tag, LogLevel::LOG_ERROR)) { \ - HiLog::Error(lable, "::[%{public}s()-%{public}s:%{public}d]: " fmt, __FUNCTION__, FILENAME, __LINE__, \ + HiLog::Error(lable, "::[%{public}s:%{public}d]: " fmt, __FUNCTION__, __LINE__, \ ##__VA_ARGS__); \ } \ } while (0) @@ -81,7 +81,7 @@ static inline OHOS::HiviewDFX::HiLogLabel LogLabel() using HiLog = OHOS::HiviewDFX::HiLog; \ auto lable = LogLabel(); \ if (HiLogIsLoggable(lable.domain, lable.tag, LogLevel::LOG_FATAL)) { \ - HiLog::Fatal(lable, "::[%{public}s()-%{public}s:%{public}d]: " fmt, __FUNCTION__, FILENAME, __LINE__, \ + HiLog::Fatal(lable, "::[%{public}s:%{public}d]: " fmt, __FUNCTION__, __LINE__, \ ##__VA_ARGS__); \ } \ } while (0) diff --git a/relational_store/frameworks/js/napi/cloud_data/BUILD.gn b/relational_store/frameworks/js/napi/cloud_data/BUILD.gn index a5053131fa80903706fb753923042f2f8488b21f..74f8597250dbec505d22f533d83b582377a3bd7b 100644 --- a/relational_store/frameworks/js/napi/cloud_data/BUILD.gn +++ b/relational_store/frameworks/js/napi/cloud_data/BUILD.gn @@ -31,6 +31,7 @@ ohos_shared_library("clouddata") { sources = [ "${cloud_data_napi_path}/src/entry_point.cpp", + "${cloud_data_napi_path}/src/js_client.cpp", "${cloud_data_napi_path}/src/js_cloud_share.cpp", "${cloud_data_napi_path}/src/js_cloud_utils.cpp", "${cloud_data_napi_path}/src/js_config.cpp", @@ -52,6 +53,7 @@ ohos_shared_library("clouddata") { "${relational_store_common_path}/include", "${relational_store_innerapi_path}/rdb/include", "${relational_store_innerapi_path}/cloud_data/include", + "${relational_store_innerapi_path}/common_type/include", "${relational_store_napi_path}/cloud_data/include", "${relational_store_napi_path}/common/include", ] diff --git a/relational_store/frameworks/js/napi/cloud_data/include/js_client.h b/relational_store/frameworks/js/napi/cloud_data/include/js_client.h new file mode 100644 index 0000000000000000000000000000000000000000..9c2d2eaffd82dbe5dd2236e030f2171b0912a125 --- /dev/null +++ b/relational_store/frameworks/js/napi/cloud_data/include/js_client.h @@ -0,0 +1,31 @@ +/* + * 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 CLOUD_DATA_JS_CLIENT_H +#define CLOUD_DATA_JS_CLIENT_H + +#include +#include +#include + +#include "napi/native_api.h" +#include "napi/native_common.h" +#include "napi/native_node_api.h" + +namespace OHOS::CloudData { +napi_value InitClient(napi_env env, napi_value info); +} + +#endif //CLOUD_DATA_JS_CLIENT_H diff --git a/relational_store/frameworks/js/napi/cloud_data/include/js_cloud_utils.h b/relational_store/frameworks/js/napi/cloud_data/include/js_cloud_utils.h index b9c202a59046f6a2bb4c31954c305c258954289e..b43bae988ce410c54ca8453f396eb94620be22c2 100644 --- a/relational_store/frameworks/js/napi/cloud_data/include/js_cloud_utils.h +++ b/relational_store/frameworks/js/napi/cloud_data/include/js_cloud_utils.h @@ -12,11 +12,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#ifndef CLOUD_DATA_JS_CLOUD_SHARE_H -#define CLOUD_DATA_JS_CLOUD_SHARE_H +#ifndef CLOUD_DATA_JS_CLOUD_UTILS_H +#define CLOUD_DATA_JS_CLOUD_UTILS_H #include "js_utils.h" #include "cloud_types.h" +#include "common_types.h" #include "rdb_predicates.h" #include "result_set.h" #include "js_config.h" @@ -28,6 +29,8 @@ using Privilege = OHOS::CloudData::Privilege; using RdbPredicates = OHOS::NativeRdb::RdbPredicates; using ResultSet = OHOS::NativeRdb::ResultSet; using ExtraData = OHOS::CloudData::JsConfig::ExtraData; +using StatisticInfo = OHOS::CloudData::StatisticInfo; +using Asset = OHOS::CommonType::AssetValue; template<> int32_t Convert2Value(napi_env env, napi_value input, ExtraData &output); @@ -41,6 +44,9 @@ int32_t Convert2Value(napi_env env, napi_value input, Privilege &output); template<> int32_t Convert2Value(napi_env env, napi_value input, std::shared_ptr &output); +template<> +int32_t Convert2Value(napi_env env, napi_value input, Asset &output); + template<> napi_value Convert2JSValue(napi_env env, const Participant &value); @@ -53,6 +59,9 @@ napi_value Convert2JSValue(napi_env env, const std::shared_ptr &value template<> napi_value Convert2JSValue(napi_env env, const std::pair &value); +template<> +napi_value Convert2JSValue(napi_env env, const StatisticInfo &value); + }; // namespace JSUtils } // namespace OHOS::AppDataMgrJsKit -#endif // CLOUD_DATA_JS_CLOUD_SHARE_H +#endif // CLOUD_DATA_JS_CLOUD_UTILS_H diff --git a/relational_store/frameworks/js/napi/cloud_data/include/js_config.h b/relational_store/frameworks/js/napi/cloud_data/include/js_config.h index cf1c8a0ae874b6adc47515975659a11c31f1cde4..7f384983f0b1f5347e84ec335825d5296192bf09 100644 --- a/relational_store/frameworks/js/napi/cloud_data/include/js_config.h +++ b/relational_store/frameworks/js/napi/cloud_data/include/js_config.h @@ -13,8 +13,8 @@ * limitations under the License. */ -#ifndef LDBPROJ_JS_CONFIG_H -#define LDBPROJ_JS_CONFIG_H +#ifndef CLOUD_DATA_JS_CONFIG_H +#define CLOUD_DATA_JS_CONFIG_H #include "cloud_manager.h" #include "js_const_properties.h" @@ -48,8 +48,9 @@ public: static napi_value ChangeAppCloudSwitch(napi_env env, napi_callback_info info); static napi_value Clean(napi_env env, napi_callback_info info); static napi_value NotifyDataChange(napi_env env, napi_callback_info info); + static napi_value QueryStatistics(napi_env env, napi_callback_info info); + static napi_value SetGlobalCloudStrategy(napi_env env, napi_callback_info info); }; } // namespace OHOS::CloudData - -#endif //LDBPROJ_JS_CONFIG_H +#endif //CLOUD_DATA_JS_CONFIG_H diff --git a/relational_store/frameworks/js/napi/cloud_data/include/js_const_properties.h b/relational_store/frameworks/js/napi/cloud_data/include/js_const_properties.h index b5e855982330557ba255aae81045d4f36fd94781..1771f7e4f11b89a935acdd9ad55c46ca553c1316 100644 --- a/relational_store/frameworks/js/napi/cloud_data/include/js_const_properties.h +++ b/relational_store/frameworks/js/napi/cloud_data/include/js_const_properties.h @@ -13,8 +13,8 @@ * limitations under the License. */ -#ifndef LDBPROJ_JS_CONST_PROPERTIES_H -#define LDBPROJ_JS_CONST_PROPERTIES_H +#ifndef CLOUD_DATA_JS_CONST_PROPERTIES_H +#define CLOUD_DATA_JS_CONST_PROPERTIES_H #include "napi/native_api.h" #include "napi/native_common.h" #include "napi/native_node_api.h" @@ -22,5 +22,6 @@ namespace OHOS::CloudData { napi_status InitConstProperties(napi_env env, napi_value exports); napi_status InitSharingConstProperties(napi_env env, napi_value exports); +napi_status InitClientProperties(napi_env env, napi_value exports); } // namespace OHOS::CloudData -#endif //LDBPROJ_JS_CONST_PROPERTIES_H +#endif //CLOUD_DATA_JS_CONST_PROPERTIES_H diff --git a/relational_store/frameworks/js/napi/cloud_data/include/js_error_utils.h b/relational_store/frameworks/js/napi/cloud_data/include/js_error_utils.h index c82bed05474450db52c2a1871751d28e550213ec..6ef3e013f374a8b83c5f2caf1349d36d0fb4d08a 100644 --- a/relational_store/frameworks/js/napi/cloud_data/include/js_error_utils.h +++ b/relational_store/frameworks/js/napi/cloud_data/include/js_error_utils.h @@ -13,8 +13,8 @@ * limitations under the License. */ -#ifndef LDBPROJ_JS_ERROR_UTILS_H -#define LDBPROJ_JS_ERROR_UTILS_H +#ifndef CLOUD_DATA_JS_ERROR_UTILS_H +#define CLOUD_DATA_JS_ERROR_UTILS_H #include #include @@ -66,4 +66,4 @@ napi_value GenerateErrorMsg(napi_env env, JsErrorCode jsInfo); } // namespace CloudData } // namespace OHOS -#endif //LDBPROJ_JS_ERROR_UTILS_H +#endif //CLOUD_DATA_JS_ERROR_UTILS_H diff --git a/relational_store/frameworks/js/napi/cloud_data/include/js_strategy_context.h b/relational_store/frameworks/js/napi/cloud_data/include/js_strategy_context.h new file mode 100644 index 0000000000000000000000000000000000000000..e3340aab17b9fcbe6152f91d961800a97f661a6a --- /dev/null +++ b/relational_store/frameworks/js/napi/cloud_data/include/js_strategy_context.h @@ -0,0 +1,80 @@ +/* +* 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 CLOUD_DATA_JS_STRATEGY_CONTEXT_H +#define CLOUD_DATA_JS_STRATEGY_CONTEXT_H + +#include +#include +#include + +#include "cloud_types.h" +#include "common_types.h" +#include "js_cloud_utils.h" +#include "js_error_utils.h" +#include "napi_queue.h" + +namespace OHOS { +namespace CloudData { +struct CloudStrategyContext : public ContextBase { + Strategy strategy; + std::vector param; + void SetDefault() + { + switch (strategy) { + case Strategy::STRATEGY_NETWORK: + param = {}; + return; + default: + param = {}; + return; + } + } + + std::pair CheckParam() + { + switch (strategy) { + case Strategy::STRATEGY_NETWORK: + if (!ConvertNetworkParam()) { + return { Status::INVALID_ARGUMENT, "member of param must be of type NetWorkStrategy" }; + } + break; + default: + return { Status::ERROR, "strategy must be of type StrategyType" }; + } + return { Status::SUCCESS, "" }; + } + +private: + bool ConvertNetworkParam() + { + std::vector tmp = { 0 }; + for (auto &value : param) { + if (std::get_if(&value) == nullptr) { + return false; + } + auto val = static_cast(std::round(std::get(value))); + if (val < 0 || val > NetWorkStrategy::NETWORK_STRATEGY_BUTT) { + return false; + } + tmp.push_back(val); + } + param = tmp; + return true; + } +}; +} +} +#endif //CLOUD_DATA_JS_STRATEGY_CONTEXT_H diff --git a/relational_store/frameworks/js/napi/cloud_data/src/entry_point.cpp b/relational_store/frameworks/js/napi/cloud_data/src/entry_point.cpp index a1a38cebd8e60e832b4ae5686980dfc9abd75849..9ae3567fa170725519f088c5165f76f0fb619411 100644 --- a/relational_store/frameworks/js/napi/cloud_data/src/entry_point.cpp +++ b/relational_store/frameworks/js/napi/cloud_data/src/entry_point.cpp @@ -13,6 +13,7 @@ * limitations under the License. */ +#include "js_client.h" #include "js_config.h" #include "js_const_properties.h" #include "logger.h" @@ -25,10 +26,13 @@ static napi_value Init(napi_env env, napi_value exports) { auto sharingExport = InitCloudSharing(env, exports); napi_status status = InitSharingConstProperties(env, sharingExport); - LOG_INFO("init Enumerate Constants %{public}d", status); + LOG_INFO("init Enumerate Constants of Sharing: %{public}d", status); exports = JsConfig::InitConfig(env, exports); status = InitConstProperties(env, exports); - LOG_INFO("init Enumerate Constants %{public}d", status); + LOG_INFO("init Enumerate Constants of Config: %{public}d", status); + exports = InitClient(env, exports); + status = InitClientProperties(env, exports); + LOG_INFO("init Enumerate Constants of Client: %{public}d", status); return exports; } diff --git a/relational_store/frameworks/js/napi/cloud_data/src/js_client.cpp b/relational_store/frameworks/js/napi/cloud_data/src/js_client.cpp new file mode 100644 index 0000000000000000000000000000000000000000..79a4c992e10bfcf8b36340ddf9828cfd20c042c8 --- /dev/null +++ b/relational_store/frameworks/js/napi/cloud_data/src/js_client.cpp @@ -0,0 +1,89 @@ +/* + * 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 "js_client.h" + +#include +#include +#include +#include "cloud_types.h" +#include "common_types.h" +#include "js_cloud_utils.h" +#include "js_error_utils.h" +#include "js_strategy_context.h" +#include "js_utils.h" +#include "logger.h" +#include "napi_queue.h" +#include "traits.h" + +namespace OHOS { +namespace CloudData { +using namespace OHOS::AppDataMgrJsKit; +/* + * [JS API Prototype] + * function setCloudStrategy(strategy: StrategyType, param?: Array): Promise; + */ +napi_value SetCloudStrategy(napi_env env, napi_callback_info info) +{ + auto ctxt = std::make_shared(); + ctxt->GetCbInfo(env, info, [env, ctxt](size_t argc, napi_value *argv) { + // strategy 1 required parameter, param 1 Optional parameter + ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::INVALID_ARGUMENT, "The number of parameters is incorrect."); + int32_t strategy = -1; + int status = JSUtils::Convert2ValueExt(env, argv[0], strategy); + ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK && strategy >= 0 && strategy < Strategy::STRATEGY_BUTT, + Status::INVALID_ARGUMENT, "The type of strategy must be StrategyType."); + ctxt->strategy = static_cast(strategy); + if (argc == 1 || JSUtils::IsNull(env, argv[1])) { + ctxt->SetDefault(); + } else { + // 'argv[1]' represents a vector param + status = JSUtils::Convert2Value(env, argv[1], ctxt->param); + ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK, Status::INVALID_ARGUMENT, + "The type of param must be Array"); + auto res = ctxt->CheckParam(); + ASSERT_BUSINESS_ERR(ctxt, res.first == JSUtils::OK, Status::INVALID_ARGUMENT, res.second); + } + }); + ASSERT_NULL(!ctxt->isThrowError, "SetCloudStrategy exit"); + auto execute = [env, ctxt]() { + auto [status, proxy] = CloudManager::GetInstance().GetCloudService(); + if (proxy == nullptr) { + if (status != CloudService::SERVER_UNAVAILABLE) { + status = CloudService::NOT_SUPPORT; + } + ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) + ? napi_ok: napi_generic_failure; + return; + } + LOG_DEBUG("SetCloudStrategy execute"); + + auto res = proxy->SetCloudStrategy(ctxt->strategy, ctxt->param); + ctxt->status = + (GenerateNapiError(res, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ? napi_ok : napi_generic_failure; + }; + return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute); +} + +napi_value InitClient(napi_env env, napi_value exports) +{ + napi_property_descriptor properties[] = { + DECLARE_NAPI_FUNCTION("setCloudStrategy", SetCloudStrategy) + }; + NAPI_CALL(env, napi_define_properties(env, exports, sizeof(properties) / sizeof(*properties), properties)); + return exports; +} +} // namespace CloudData +} // namespace OHOS diff --git a/relational_store/frameworks/js/napi/cloud_data/src/js_cloud_utils.cpp b/relational_store/frameworks/js/napi/cloud_data/src/js_cloud_utils.cpp index e19e284ae36ac014572b4869d249cead7d4cdcab..9b7f85bfecb0f3d82059b8b5eed9926aca339cfc 100644 --- a/relational_store/frameworks/js/napi/cloud_data/src/js_cloud_utils.cpp +++ b/relational_store/frameworks/js/napi/cloud_data/src/js_cloud_utils.cpp @@ -89,6 +89,35 @@ int32_t Convert2Value(napi_env env, napi_value input, Privilege &output) return napi_ok; } +template<> +int32_t Convert2Value(napi_env env, napi_value jsValue, Asset &output) +{ + napi_valuetype type = napi_undefined; + napi_status status = napi_typeof(env, jsValue, &type); + bool isArray; + napi_status status_array = napi_is_array(env, jsValue, &isArray); + if (status != napi_ok || type != napi_object || status_array != napi_ok || isArray) { + LOG_DEBUG("napi_typeof failed status = %{public}d type = %{public}d", status, type); + return napi_invalid_arg; + } + + NAPI_CALL_RETURN_ERR(GET_PROPERTY(env, jsValue, output, name), napi_invalid_arg); + NAPI_CALL_RETURN_ERR(GET_PROPERTY(env, jsValue, output, uri), napi_invalid_arg); + NAPI_CALL_RETURN_ERR(GET_PROPERTY(env, jsValue, output, createTime), napi_invalid_arg); + NAPI_CALL_RETURN_ERR(GET_PROPERTY(env, jsValue, output, modifyTime), napi_invalid_arg); + NAPI_CALL_RETURN_ERR(GET_PROPERTY(env, jsValue, output, size), napi_invalid_arg); + NAPI_CALL_RETURN_ERR(GET_PROPERTY(env, jsValue, output, path), napi_invalid_arg); + output.hash = output.modifyTime + "_" + output.size; + auto jsStatus = GetNamedProperty(env, jsValue, "status"); + if (jsStatus != nullptr) { + Convert2ValueExt(env, jsStatus, output.status); + } + if (output.status != Asset::STATUS_DELETE) { + output.status = Asset::STATUS_UNKNOWN; + } + return napi_ok; +} + template<> int32_t Convert2Value(napi_env env, napi_value input, std::shared_ptr &output) { @@ -197,5 +226,24 @@ napi_value Convert2JSValue(napi_env env, const std::pair & napi_set_named_property(env, jsValue, "value", val); return jsValue; } + +template<> +napi_value Convert2JSValue(napi_env env, const StatisticInfo &value) +{ + napi_value jsValue = nullptr; + napi_status status = napi_create_object(env, &jsValue); + if (status != napi_ok) { + return nullptr; + } + napi_value table = Convert2JSValue(env, value.table); + napi_value inserted = Convert2JSValue(env, value.inserted); + napi_value updated = Convert2JSValue(env, value.updated); + napi_value normal = Convert2JSValue(env, value.normal); + napi_set_named_property(env, jsValue, "table", table); + napi_set_named_property(env, jsValue, "inserted", inserted); + napi_set_named_property(env, jsValue, "updated", updated); + napi_set_named_property(env, jsValue, "normal", normal); + return jsValue; +} }; // namespace JSUtils } // namespace OHOS::AppDataMgrJsKit \ No newline at end of file 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 63484e873fcf41d99f5e813da29460827811c295..8d5d248cf2f3a0b1626d33ddd125612689e050e5 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 @@ -23,6 +23,7 @@ #include "js_error_utils.h" #include "js_utils.h" #include "js_cloud_utils.h" +#include "js_strategy_context.h" #include "logger.h" #include "napi_queue.h" @@ -314,6 +315,109 @@ napi_value JsConfig::NotifyDataChange(napi_env env, napi_callback_info info) return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute); } +/* + * [JS API Prototype] + * [Promise] + * QueryStatistics(accountId: string, bundleName: string, + * storeId?: number): Promise>>; + */ +napi_value JsConfig::QueryStatistics(napi_env env, napi_callback_info info) +{ + struct QueryStatisticsContext : public ContextBase { + std::string accountId; + std::string bundleName; + std::string storeId = ""; + std::map result; + }; + auto ctxt = std::make_shared(); + ctxt->GetCbInfo(env, info, [env, ctxt](size_t argc, napi_value* argv) { + // required 2 arguments :: + ASSERT_BUSINESS_ERR(ctxt, argc >= 2, Status::INVALID_ARGUMENT, "The number of parameters is incorrect."); + // 0 is the index of argument accountId + int status = JSUtils::Convert2Value(env, argv[0], ctxt->accountId); + ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK, Status::INVALID_ARGUMENT, + "The type of accountId must be string."); + // 1 is the index of argument bundleName + 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."); + // 2 is the index of argument storeId + if (argc > 2 && !JSUtils::IsNull(ctxt->env, argv[2])) { + // 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."); + } + }); + + ASSERT_NULL(!ctxt->isThrowError, "QueryStatistics exit"); + + auto execute = [ctxt]() { + auto [state, proxy] = CloudManager::GetInstance().GetCloudService(); + if (proxy == nullptr) { + if (state != CloudService::SERVER_UNAVAILABLE) { + state = CloudService::NOT_SUPPORT; + } + ctxt->status = (GenerateNapiError(state, ctxt->jsCode, ctxt->error) == Status::SUCCESS) + ? napi_ok + : napi_generic_failure; + return; + } + auto [status, result] = proxy->QueryStatistics(ctxt->accountId, ctxt->bundleName, ctxt->storeId); + ctxt->status = + (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ? napi_ok : napi_generic_failure; + ctxt->result = std::move(result); + }; + auto output = [env, ctxt](napi_value& result) { + result = JSUtils::Convert2JSValue(env, ctxt->result); + ASSERT_VALUE(ctxt, result != nullptr, napi_generic_failure, "output failed"); + }; + return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output); +} + +napi_value JsConfig::SetGlobalCloudStrategy(napi_env env, napi_callback_info info) +{ + auto ctxt = std::make_shared(); + ctxt->GetCbInfo(env, info, [env, ctxt](size_t argc, napi_value *argv) { + // strategy 1 required parameter, param 1 Optional parameter + ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::INVALID_ARGUMENT, "The number of parameters is incorrect."); + int32_t strategy = -1; + int status = JSUtils::Convert2ValueExt(env, argv[0], strategy); + ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK && strategy >= 0 && strategy < Strategy::STRATEGY_BUTT, + Status::INVALID_ARGUMENT, "The type of strategy must be StrategyType."); + ctxt->strategy = static_cast(strategy); + // 'argv[1]' represents a vector param or null + if (argc == 1 || JSUtils::IsNull(env, argv[1])) { + ctxt->SetDefault(); + } else { + // 'argv[1]' represents a vector param + status = JSUtils::Convert2Value(env, argv[1], ctxt->param); + ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK, Status::INVALID_ARGUMENT, + "The type of param must be Array"); + auto res = ctxt->CheckParam(); + ASSERT_BUSINESS_ERR(ctxt, res.first == JSUtils::OK, Status::INVALID_ARGUMENT, res.second); + } + }); + ASSERT_NULL(!ctxt->isThrowError, "SetGlobalCloudStrategy exit"); + auto execute = [env, ctxt]() { + auto [status, proxy] = CloudManager::GetInstance().GetCloudService(); + if (proxy == nullptr) { + if (status != CloudService::SERVER_UNAVAILABLE) { + status = CloudService::NOT_SUPPORT; + } + ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) + ? napi_ok: napi_generic_failure; + return; + } + LOG_DEBUG("SetGlobalCloudStrategy execute"); + + auto res = proxy->SetGlobalCloudStrategy(ctxt->strategy, ctxt->param); + ctxt->status = + (GenerateNapiError(res, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ? napi_ok : napi_generic_failure; + }; + return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute); +} + napi_value JsConfig::New(napi_env env, napi_callback_info info) { napi_value self = nullptr; @@ -352,6 +456,8 @@ napi_value JsConfig::InitConfig(napi_env env, napi_value exports) DECLARE_NAPI_STATIC_FUNCTION("clear", JsConfig::Clean), DECLARE_NAPI_STATIC_FUNCTION("clean", JsConfig::Clean), DECLARE_NAPI_STATIC_FUNCTION("notifyDataChange", JsConfig::NotifyDataChange), + DECLARE_NAPI_STATIC_FUNCTION("queryStatistics", JsConfig::QueryStatistics), + DECLARE_NAPI_STATIC_FUNCTION("setGlobalCloudStrategy", JsConfig::SetGlobalCloudStrategy), }; return properties; }; diff --git a/relational_store/frameworks/js/napi/cloud_data/src/js_const_properties.cpp b/relational_store/frameworks/js/napi/cloud_data/src/js_const_properties.cpp index 6fcd34462ad78795a187ef27693f62e434d18816..2fa342a4b6f8fe8bf6a286599393c36bd7f0e661 100644 --- a/relational_store/frameworks/js/napi/cloud_data/src/js_const_properties.cpp +++ b/relational_store/frameworks/js/napi/cloud_data/src/js_const_properties.cpp @@ -88,6 +88,25 @@ static napi_value ExportShareCode(napi_env env) return code; } +static napi_value ExportStrategy(napi_env env) +{ + napi_value strategy = nullptr; + napi_create_object(env, &strategy); + SetNamedProperty(env, strategy, "NETWORK", Strategy::STRATEGY_NETWORK); + napi_object_freeze(env, strategy); + return strategy; +} + +static napi_value ExportNetWorkStrategy(napi_env env) +{ + napi_value netStrategy = nullptr; + napi_create_object(env, &netStrategy); + SetNamedProperty(env, netStrategy, "WIFI", NetWorkStrategy::WIFI); + SetNamedProperty(env, netStrategy, "CELLULAR", NetWorkStrategy::CELLULAR); + napi_object_freeze(env, netStrategy); + return netStrategy; +} + napi_status InitConstProperties(napi_env env, napi_value exports) { const napi_property_descriptor properties[] = { @@ -115,4 +134,18 @@ napi_status InitSharingConstProperties(napi_env env, napi_value exports) return napi_define_properties(env, exports, count, properties); } + +napi_status InitClientProperties(napi_env env, napi_value exports) +{ + if (exports == nullptr) { + return napi_generic_failure; + } + const napi_property_descriptor properties[] = { + DECLARE_NAPI_PROPERTY("StrategyType", ExportStrategy(env)), + DECLARE_NAPI_PROPERTY("NetWorkStrategy", ExportNetWorkStrategy(env)), + }; + size_t count = sizeof(properties) / sizeof(properties[0]); + + return napi_define_properties(env, exports, count, properties); +} } // namespace OHOS::CloudData 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 90fb362000a3cd4256fbe389c019947157fd5d64..61e79450ff45f0a75448a3935e4621906e2ce9bd 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 @@ -100,6 +100,7 @@ static napi_value ExportProgressCode(napi_env env) SET_NAPI_PROPERTY(progressCode, "LOCKED_BY_OTHERS", int32_t(ProgressCode::LOCKED_BY_OTHERS)); SET_NAPI_PROPERTY(progressCode, "RECORD_LIMIT_EXCEEDED", int32_t(ProgressCode::RECORD_LIMIT_EXCEEDED)); SET_NAPI_PROPERTY(progressCode, "NO_SPACE_FOR_ASSET", int32_t(ProgressCode::NO_SPACE_FOR_ASSET)); + SET_NAPI_PROPERTY(progressCode, "BLOCKED_BY_NETWORK_STRATEGY", int32_t(ProgressCode::BLOCKED_BY_NETWORK_STRATEGY)); napi_object_freeze(env, progressCode); return progressCode; } 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 2320ca6585cc2a426e5aed33ec099482d1348194..806eb00793c9e35b812fe26119d98e55a4af9dba 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 @@ -978,28 +978,25 @@ napi_value RdbStoreProxy::Commit(napi_env env, napi_callback_info info) napi_value RdbStoreProxy::QueryByStep(napi_env env, napi_callback_info info) { DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - LOG_DEBUG("RdbStoreProxy::QueryByStep 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 || argc == 2, std::make_shared("2 or 3")); CHECK_RETURN(OK == ParserThis(env, self, context)); CHECK_RETURN(OK == ParseSql(env, argv[0], context)); if (argc == 2) { - CHECK_RETURN(OK == ParseColumns(env, argv[1], context)); + CHECK_RETURN(OK == ParseBindArgs(env, argv[1], context)); } }; auto exec = [context]() -> int { - LOG_DEBUG("RdbStoreProxy::QueryByStep Async"); RdbStoreProxy *obj = reinterpret_cast(context->boundObj); CHECK_RETURN_ERR(obj != nullptr && obj->rdbStore_ != nullptr); - context->resultSet = obj->rdbStore_->QueryByStep(context->sql, context->columns); - LOG_ERROR("RdbStoreProxy::QueryByStep is nullptr ? %{public}d ", context->resultSet == nullptr); + context->resultSet = obj->rdbStore_->QueryByStep(context->sql, context->bindArgs); + LOG_DEBUG("RdbStoreProxy::QueryByStep is nullptr ? %{public}d ", context->resultSet == nullptr); return (context->resultSet != nullptr) ? E_OK : E_ERROR; }; 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)); - LOG_DEBUG("RdbStoreProxy::QueryByStep end"); }; context->SetAction(env, info, input, exec, output); diff --git a/relational_store/frameworks/native/cloud_data/include/cloud_service_proxy.h b/relational_store/frameworks/native/cloud_data/include/cloud_service_proxy.h index e03c74caa299fce5660b7bfe8c9fe73a3e5e81ef..6f394d684421faf25661f8f93586429e803db9f5 100644 --- a/relational_store/frameworks/native/cloud_data/include/cloud_service_proxy.h +++ b/relational_store/frameworks/native/cloud_data/include/cloud_service_proxy.h @@ -31,6 +31,9 @@ public: 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; + 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, @@ -47,6 +50,8 @@ 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; + private: sptr remote_; }; diff --git a/relational_store/frameworks/native/cloud_data/include/cloud_types_util.h b/relational_store/frameworks/native/cloud_data/include/cloud_types_util.h index 68c48bdd3c5c299d42a94d7c9f804da043f6b27d..67f2ed2ff8aa0f0f5fbb07feda940408f9a461bb 100644 --- a/relational_store/frameworks/native/cloud_data/include/cloud_types_util.h +++ b/relational_store/frameworks/native/cloud_data/include/cloud_types_util.h @@ -18,6 +18,7 @@ #include "itypes_util.h" #include "cloud_types.h" #include "values_bucket.h" +#include "common_types.h" namespace OHOS::ITypesUtil { using Participant = OHOS::CloudData::Participant; @@ -28,6 +29,9 @@ using SharingCode = OHOS::CloudData::SharingCode; using Asset = OHOS::NativeRdb::AssetValue; using ValueObject = OHOS::NativeRdb::ValueObject; using ValuesBucket = OHOS::NativeRdb::ValuesBucket; +using StatisticInfo = OHOS::CloudData::StatisticInfo; +using CommonAsset = CommonType::Asset; +using Strategy = OHOS::CloudData::Strategy; template<> bool Marshalling(const Participant &input, MessageParcel &data); @@ -66,5 +70,14 @@ template<> bool Marshalling(const ValuesBucket &input, MessageParcel &data); template<> bool Unmarshalling(ValuesBucket &output, MessageParcel &data); + +template<> +bool Unmarshalling(StatisticInfo &output, MessageParcel &data); + +template<> +bool Marshalling(const Strategy &input, MessageParcel &data); + +template<> +bool Marshalling(const CommonAsset &input, MessageParcel &data); } // namespace OHOS::ITypesUtil #endif // OHOS_DISTRIBUTED_DATA_CLOUD_CLOUD_TYPES_UTIL_H diff --git a/relational_store/frameworks/native/cloud_data/src/cloud_service_proxy.cpp b/relational_store/frameworks/native/cloud_data/src/cloud_service_proxy.cpp index 869fa1642c00cc2a855090f88ad8db3f7cba6030..bb21d54fe03b9e82595935c639b9e4aaa2773cbf 100644 --- a/relational_store/frameworks/native/cloud_data/src/cloud_service_proxy.cpp +++ b/relational_store/frameworks/native/cloud_data/src/cloud_service_proxy.cpp @@ -102,6 +102,17 @@ int32_t CloudServiceProxy::NotifyDataChange(const std::string &id, const std::st return static_cast(status); } +int32_t CloudServiceProxy::SetGlobalCloudStrategy(Strategy strategy, const std::vector &values) +{ + MessageParcel reply; + int32_t status = IPC_SEND(TRANS_SET_GLOBAL_CLOUD_STRATEGY, reply, strategy, values); + if (status != SUCCESS) { + LOG_ERROR("status:0x%{public}x strategy:%{public}d values size:%{public}zu", status, + static_cast(strategy), values.size()); + } + return static_cast(status); +} + std::pair> CloudServiceProxy::AllocResourceAndShare( const std::string &storeId, const DistributedRdb::PredicatesMemo &predicates, const std::vector &columns, const std::vector &participants) @@ -127,6 +138,20 @@ int32_t CloudServiceProxy::NotifyDataChange(const std::string &eventId, const st return static_cast(status); } +std::pair> CloudServiceProxy::QueryStatistics(const std::string &id, + const std::string &bundleName, const std::string &storeId) +{ + MessageParcel reply; + int32_t status = IPC_SEND(TRANS_QUERY_STATISTICS, reply, id, bundleName, storeId); + if (status != SUCCESS) { + LOG_ERROR("status:0x%{public}x bundleName:%{public}.6s storeId:%{public}.6s", status, id.c_str(), + storeId.c_str()); + } + std::map infos; + ITypesUtil::Unmarshal(reply, infos); + return { status, infos }; +} + int32_t CloudServiceProxy::Share( const std::string &sharingRes, const Participants &participants, Results &results) { @@ -223,4 +248,15 @@ int32_t CloudServiceProxy::ChangeConfirmation(const std::string &sharingRes, ITypesUtil::Unmarshal(reply, result); return static_cast(status); } + +int32_t CloudServiceProxy::SetCloudStrategy(Strategy strategy, const std::vector &values) +{ + MessageParcel reply; + int32_t status = IPC_SEND(TRANS_SET_CLOUD_STRATEGY, reply, strategy, values); + if (status != SUCCESS) { + LOG_ERROR("status:0x%{public}x strategy:%{public}d values size:%{public}zu", status, + static_cast(strategy), values.size()); + } + return static_cast(status); +} } // namespace OHOS::CloudData \ No newline at end of file diff --git a/relational_store/frameworks/native/cloud_data/src/cloud_types_util.cpp b/relational_store/frameworks/native/cloud_data/src/cloud_types_util.cpp index 5d519c1501455a18006f9569775ae55a6b60b1a1..b5c4ac9e7e5ac6e66c4a936cbc67a8dd2b6e1e7f 100644 --- a/relational_store/frameworks/native/cloud_data/src/cloud_types_util.cpp +++ b/relational_store/frameworks/native/cloud_data/src/cloud_types_util.cpp @@ -126,4 +126,23 @@ bool Unmarshalling(ValuesBucket &output, MessageParcel &data) { return Unmarshal(data, output.values_); } + +template<> +bool Unmarshalling(StatisticInfo &output, MessageParcel &data) +{ + return ITypesUtil::Unmarshal(data, output.table, output.inserted, output.updated, output.normal); +} + +template<> +bool Marshalling(const Strategy &input, MessageParcel &data) +{ + return data.WriteUint32(static_cast(input)); +} + +template<> +bool Marshalling(const CommonAsset &input, MessageParcel &data) +{ + return ITypesUtil::Marshal(data, input.name, input.uri, input.path, input.createTime, + input.modifyTime, input.size, input.status, input.hash); +} } // namespace OHOS::ITypesUtil \ No newline at end of file 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 00d1fd9e82a867583865c4d35c313d57034a7ade..5d4a06cc0c17196ff9df0aa8be28f4b90edd9747 100644 --- a/relational_store/frameworks/native/rdb/include/rdb_store_impl.h +++ b/relational_store/frameworks/native/rdb/include/rdb_store_impl.h @@ -70,16 +70,15 @@ private: DistributedRdb::RdbStoreObserver *observer_ = nullptr; }; -class RdbStoreImpl : public RdbStore, public std::enable_shared_from_this { +class RdbStoreImpl : public RdbStore { public: RdbStoreImpl(const RdbStoreConfig &config, int &errCode); ~RdbStoreImpl() override; const RdbStoreConfig &GetConfig(); - int Insert(int64_t &outRowId, const std::string &table, const ValuesBucket &initialValues) override; - int BatchInsert(int64_t &outInsertNum, const std::string &table, - const std::vector &initialBatchValues) override; + 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 &initialValues, + 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; @@ -103,8 +102,7 @@ public: 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 = std::vector()) override; + int ExecuteSql(const std::string& sql, const std::vector& bindArgs) override; std::pair Execute(const std::string &sql, const std::vector &bindArgs) override; int ExecuteAndGetLong(int64_t &outValue, const std::string &sql, const std::vector &bindArgs) override; int ExecuteAndGetString(std::string &outValue, const std::string &sql, @@ -113,8 +111,7 @@ public: 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 = std::vector()) override; + int Backup(const std::string databasePath, const std::vector destEncryptKey) override; int Attach(const std::string &alias, const std::string &pathName, const std::vector destEncryptKey) override; int GetVersion(int &version) override; @@ -128,10 +125,8 @@ public: bool IsReadOnly() const override; bool IsMemoryRdb() const override; bool IsHoldingConnection() override; -#ifdef RDB_SUPPORT_ICU - int ConfigLocale(const std::string localeStr); -#endif - int Restore(const std::string backupPath, const std::vector &newKey = std::vector()) override; + int ConfigLocale(const std::string &localeStr); + int Restore(const std::string backupPath, const std::vector &newKey) override; void GetSchema(const RdbStoreConfig &config); std::string GetName(); std::string GetOrgPath(); @@ -176,7 +171,7 @@ public: ModifyTime GetModifyTime(const std::string& table, const std::string& columnName, std::vector& keys) override; - int CleanDirtyData(const std::string &table, uint64_t cursor = UINT64_MAX) override; + int CleanDirtyData(const std::string &table, uint64_t cursor) override; private: using ExecuteSqls = std::vector>>>; @@ -184,10 +179,8 @@ private: int CheckAttach(const std::string &sql); int BeginExecuteSql(const std::string &sql, std::shared_ptr &connection); int FreeTransaction(std::shared_ptr connection, const std::string &sql); - ExecuteSqls GenerateSql( - const std::string &table, const std::vector &initialBatchValues, int limitVariableNumber); - ExecuteSqls MakeExecuteSqls( - const std::string &sql, const std::vector &args, int fieldSize, int limitVariableNumber); + ExecuteSqls GenerateSql(const std::string& table, const std::vector& buckets, int limit); + ExecuteSqls MakeExecuteSqls(const std::string& sql, std::vector&& args, int fieldSize, int limit); int GetDataBasePath(const std::string &databasePath, std::string &backupFilePath); int ExecuteSqlInner(const std::string &sql, const std::vector &bindArgs); int ExecuteGetLongInner(const std::string &sql, const std::vector &bindArgs); @@ -195,8 +188,8 @@ private: 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()); + int InnerBackup(const std::string& databasePath, + const std::vector& destEncryptKey = std::vector()); ModifyTime GetModifyTimeByRowId(const std::string& logTable, std::vector& keys); inline std::string GetSqlArgs(size_t size); Uri GetUri(const std::string &event); @@ -213,32 +206,36 @@ private: void InitDelayNotifier(); bool ColHasSpecificField(const std::vector &columns); - const RdbStoreConfig rdbStoreConfig; - SqliteConnectionPool *connectionPool; - bool isOpen; - std::string path; - std::string orgPath; - bool isReadOnly; - bool isMemoryRdb; - std::string name; - std::string fileType; - DistributedRdb::RdbSyncerParam syncerParam_; + static constexpr char SCHEME_RDB[] = "rdb://"; + static constexpr uint32_t EXPANSION = 2; + static constexpr uint32_t AUTO_SYNC_MAX_INTERVAL = 3000; + static inline constexpr uint32_t INTERVAL = 10; + static constexpr const char *ROW_ID = "ROWID"; + + const RdbStoreConfig config_; + std::shared_ptr connectionPool_ = nullptr; + bool isOpen_ = false; + bool isReadOnly_; + bool isMemoryRdb_; bool isEncrypt_; + int64_t vSchema_ = 0; + std::string path_; + std::string orgPath_; + std::string name_; + std::string fileType_; + DistributedRdb::RdbSyncerParam syncerParam_; + std::shared_ptr pool_; std::shared_ptr delayNotifier_ = nullptr; mutable std::shared_mutex rwMutex_; - static inline constexpr uint32_t INTERVAL = 10; - static constexpr const char *ROW_ID = "ROWID"; + std::set cloudTables_; std::mutex mutex_; std::shared_ptr> syncTables_; - static constexpr char SCHEME_RDB[] = "rdb://"; std::map>> localObservers_; std::map>> localSharedObservers_; - static constexpr uint32_t EXPANSION = 2; - static constexpr uint32_t AUTO_SYNC_MAX_INTERVAL = 3000; }; } // namespace OHOS::NativeRdb #endif diff --git a/relational_store/frameworks/native/rdb/include/sqlite_connection.h b/relational_store/frameworks/native/rdb/include/sqlite_connection.h index 5cf2cfe2ebb8c2c4331823a6a68cd9b409bdb8d0..a76ae4d8c2fcfacd6d4a87e7d0ce653243126ac0 100644 --- a/relational_store/frameworks/native/rdb/include/sqlite_connection.h +++ b/relational_store/frameworks/native/rdb/include/sqlite_connection.h @@ -59,14 +59,14 @@ public: bool IsInTransaction(); int TryCheckPoint(); int LimitWalSize(); -#ifdef RDB_SUPPORT_ICU - int ConfigLocale(const std::string localeStr); -#endif + int ConfigLocale(const std::string &localeStr); int ExecuteForSharedBlock(int &rowNum, std::string sql, const std::vector &bindArgs, AppDataFwk::SharedBlock *sharedBlock, int startPos, int requiredPos, bool isCountAllRows); int CleanDirtyData(const std::string &table, uint64_t cursor); int RegisterCallBackObserver(const DataChangeCallback &clientChangedData); int GetMaxVariableNumber(); + uint32_t GetId() const; + int32_t SetId(uint32_t id); private: static constexpr const char *MERGE_ASSETS_FUNC = "merge_assets"; explicit SqliteConnection(bool isWriteConnection); @@ -115,6 +115,8 @@ private: bool isConfigured_ = false; int maxVariableNumber_; + bool hasClientObserver_ = false; + int id_; }; } // namespace NativeRdb diff --git a/relational_store/frameworks/native/rdb/include/sqlite_connection_pool.h b/relational_store/frameworks/native/rdb/include/sqlite_connection_pool.h index 44a5d253384b7c129301bcd37c7986f5dd21c34c..0e05b02d5a2b6922e2cd9ddd3e1738187c308b9d 100644 --- a/relational_store/frameworks/native/rdb/include/sqlite_connection_pool.h +++ b/relational_store/frameworks/native/rdb/include/sqlite_connection_pool.h @@ -24,61 +24,79 @@ #include #include #include - +#include #include "rdb_store_config.h" #include "sqlite_connection.h" #include "base_transaction.h" namespace OHOS { namespace NativeRdb { -class SqliteConnectionPool { +class SqliteConnectionPool : public std::enable_shared_from_this { public: - static SqliteConnectionPool *Create(const RdbStoreConfig &storeConfig, int &errCode); + static std::shared_ptr Create(const RdbStoreConfig &storeConfig, int &errCode); ~SqliteConnectionPool(); std::shared_ptr AcquireConnection(bool isReadOnly); - void ReleaseConnection(std::shared_ptr connection); - int ReOpenAvailableReadConnections(); -#ifdef RDB_SUPPORT_ICU - int ConfigLocale(const std::string localeStr); -#endif - int ChangeDbFileForRestore(const std::string newPath, const std::string backupPath, + int RestartReaders(); + int ConfigLocale(const std::string &localeStr); + int ChangeDbFileForRestore(const std::string &newPath, const std::string &backupPath, const std::vector &newKey); std::stack &GetTransactionStack(); std::mutex &GetTransactionStackMutex(); int AcquireTransaction(); void ReleaseTransaction(); - + std::shared_ptr AcquireByID(int32_t id); private: + struct ConnNode { + bool using_ = false; + uint32_t tid_ = 0; + uint32_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(bool justHold = false); + int64_t GetUsingTime() const; + bool IsWriter() const; + void Unused(); + }; + + struct Container { + using Creator = std::function>()>; + int max_ = 0; + int count_ = 0; + uint32_t left_ = 0; + uint32_t right_ = 0; + std::chrono::seconds timeout_; + std::list> nodes_; + std::list> details_; + std::mutex mutex_; + std::condition_variable cond_; + int32_t Initialize(int32_t max, int32_t timeout, Creator creator); + int32_t ConfigLocale(const std::string &locale); + std::shared_ptr Acquire(); + int32_t Release(std::shared_ptr node); + int32_t Clear(); + bool IsFull(); + int32_t Dump(const char *header); + std::shared_ptr AcquireById(int32_t id); + }; + explicit SqliteConnectionPool(const RdbStoreConfig &storeConfig); int Init(); - void InitReadConnectionCount(); - std::shared_ptr AcquireWriteConnection(); - void ReleaseWriteConnection(); - std::shared_ptr AcquireReadConnection(); - void ReleaseReadConnection(std::shared_ptr connection); + int32_t GetMaxReaders(); + void ReleaseNode(std::shared_ptr node); void CloseAllConnections(); - int InnerReOpenReadConnections(); + static constexpr int LIMITATION = 1024; RdbStoreConfig config_; - std::shared_ptr writeConnection_; - std::mutex writeMutex_; - std::condition_variable writeCondition_; - bool writeConnectionUsed_; - - std::vector> readConnections_; - std::mutex readMutex_; - std::mutex rdbMutex_; - std::condition_variable readCondition_; - int readConnectionCount_; - int idleReadConnectionCount_; - const static int LIMITATION = 1024; + Container writers_; + Container readers_; + int32_t maxReader_ = 0; std::stack transactionStack_; std::mutex transactionStackMutex_; std::condition_variable transCondition_; std::mutex transMutex_; bool transactionUsed_; - std::chrono::seconds writeTimeout_ = std::chrono::seconds(2); - std::chrono::seconds readTimeout_ = std::chrono::seconds(1); }; } // namespace NativeRdb 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 1ba23a076125b446e522414a2d809e126f15be8a..cc23995029b83c2918f851cac71f855374764cfb 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 @@ -34,7 +34,7 @@ namespace OHOS { namespace NativeRdb { class SqliteSharedResultSet : public AbsSharedResultSet { public: - SqliteSharedResultSet(std::shared_ptr store, SqliteConnectionPool *connectionPool, std::string path, + SqliteSharedResultSet(std::shared_ptr connectionPool, std::string path, std::string sql, const std::vector &bindArgs); ~SqliteSharedResultSet() override; int GetAllColumnNames(std::vector &columnNames) override; @@ -57,8 +57,7 @@ private: // The pick position of the shared block for search static const int PICK_POS = 3; - std::shared_ptr store_; - SqliteConnectionPool *connectionPool_; + std::shared_ptr connectionPool_; int resultSetBlockCapacity_; // The number of rows in the cursor int rowNum_; diff --git a/relational_store/frameworks/native/rdb/include/sqlite_statement.h b/relational_store/frameworks/native/rdb/include/sqlite_statement.h index 089c3a0bdd6d3f42cc2b54dc66a485c7472a4aee..d36fbe72ffcfd4724e8dac0a3840d2a745d3e3d4 100644 --- a/relational_store/frameworks/native/rdb/include/sqlite_statement.h +++ b/relational_store/frameworks/native/rdb/include/sqlite_statement.h @@ -30,8 +30,8 @@ class SqliteStatement { public: SqliteStatement(); ~SqliteStatement(); - static std::shared_ptr CreateStatement( - std::shared_ptrconnection, const std::string &sql); + static std::shared_ptr CreateStatement(std::shared_ptr connection, + const std::string& sql); int Prepare(sqlite3 *dbHandle, const std::string &sql); int Finalize(); int BindArguments(const std::vector &bindArgs) const; diff --git a/relational_store/frameworks/native/rdb/include/sqlite_utils.h b/relational_store/frameworks/native/rdb/include/sqlite_utils.h index 8dea084148b11660095cf3ed5cf5b7c4e60ea2ff..7a696bbf49c66f65ad914cc123094240a5c91ab7 100644 --- a/relational_store/frameworks/native/rdb/include/sqlite_utils.h +++ b/relational_store/frameworks/native/rdb/include/sqlite_utils.h @@ -24,34 +24,56 @@ namespace NativeRdb { class SqliteUtils { public: - static const int STATEMENT_SELECT; - static const int STATEMENT_INSERT; - static const int STATEMENT_UPDATE; - static const int STATEMENT_ATTACH; - static const int STATEMENT_DETACH; - static const int STATEMENT_BEGIN; - static const int STATEMENT_COMMIT; - static const int STATEMENT_ROLLBACK; - static const int STATEMENT_PRAGMA; - static const int STATEMENT_DDL; - static const int STATEMENT_OTHER; - static const int CONFLICT_CLAUSE_COUNT = 6; + static constexpr int STATEMENT_SELECT = 1; + static constexpr int STATEMENT_UPDATE = 2; + static constexpr int STATEMENT_ATTACH = 3; + static constexpr int STATEMENT_DETACH = 4; + static constexpr int STATEMENT_BEGIN = 5; + static constexpr int STATEMENT_COMMIT = 6; + static constexpr int STATEMENT_ROLLBACK = 7; + static constexpr int STATEMENT_PRAGMA = 8; + static constexpr int STATEMENT_DDL = 9; + static constexpr int STATEMENT_INSERT = 10; + static constexpr int STATEMENT_OTHER = 99; + static constexpr int CONFLICT_CLAUSE_COUNT = 6; static constexpr const char* REP = "#_"; static int GetSqlStatementType(const std::string &sql); static bool IsSqlReadOnly(int sqlType); static bool IsSpecial(int sqlType); - static int GetConflictClause(int conflictResolution, std::string &conflictClause); + static const char *GetConflictClause(int conflictResolution); static std::string StrToUpper(std::string s); static void Replace(std::string &src, const std::string &rep, const std::string &dst); - static bool DeleteFile(const std::string path); - static int RenameFile(const std::string srcFile, const std::string destFile); + static bool DeleteFile(const std::string &filePath); + static int RenameFile(const std::string &srcFile, const std::string &destFile); static std::string Anonymous(const std::string &srcFile); - static int GetFileSize(const std::string fileName); + static int GetFileSize(const std::string &fileName); private: - static const std::map SQL_TYPE_MAP; - static const std::string ON_CONFLICT_CLAUSE[CONFLICT_CLAUSE_COUNT]; + struct SqlType { + const char *sql; + int32_t type; + }; + static constexpr SqlType SQL_TYPE_MAP[] = { + { "ALT", SqliteUtils::STATEMENT_DDL }, + { "ATT", SqliteUtils::STATEMENT_ATTACH }, + { "BEG", SqliteUtils::STATEMENT_BEGIN }, + { "COM", SqliteUtils::STATEMENT_COMMIT }, + { "CRE", SqliteUtils::STATEMENT_DDL }, + { "DEL", SqliteUtils::STATEMENT_UPDATE }, + { "DET", SqliteUtils::STATEMENT_DETACH }, + { "DRO", SqliteUtils::STATEMENT_DDL }, + { "END", SqliteUtils::STATEMENT_COMMIT }, + { "INS", SqliteUtils::STATEMENT_INSERT }, + { "PRA", SqliteUtils::STATEMENT_PRAGMA }, + { "REP", SqliteUtils::STATEMENT_UPDATE }, + { "ROL", SqliteUtils::STATEMENT_ROLLBACK }, + { "SEL", SqliteUtils::STATEMENT_SELECT }, + { "UPD", SqliteUtils::STATEMENT_UPDATE } + }; + static constexpr size_t TYPE_SIZE = sizeof(SQL_TYPE_MAP) / sizeof(SqlType); + static constexpr const char* ON_CONFLICT_CLAUSE[CONFLICT_CLAUSE_COUNT] = { "", " OR ROLLBACK", " OR ABORT", + " OR FAIL", " OR IGNORE", " OR REPLACE" }; }; } // namespace NativeRdb 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 d2c7e9368795ec7b0529d1183a64baaf75ee8eab..a24310e819d8373308cf0281fecefba7b7d98dc8 100644 --- a/relational_store/frameworks/native/rdb/include/step_result_set.h +++ b/relational_store/frameworks/native/rdb/include/step_result_set.h @@ -29,8 +29,8 @@ namespace OHOS { namespace NativeRdb { class StepResultSet : public AbsResultSet { public: - StepResultSet(std::shared_ptr rdb, SqliteConnectionPool *connectionPool, const std::string &sql, - const std::vector &selectionArgs); + StepResultSet(std::shared_ptr connectionPool, const std::string& sql, + const std::vector& selectionArgs); ~StepResultSet() override; int GetAllColumnNames(std::vector &columnNames) override; @@ -59,6 +59,7 @@ private: template int GetValue(int32_t col, T &value); std::pair GetValueObject(int32_t col, size_t index); + std::pair, std::shared_ptr> GetStatement(); void Reset(); int FinishStep(); int PrepareStep(); @@ -69,17 +70,18 @@ private: // Interval of retrying step query in millisecond static const int STEP_QUERY_RETRY_INTERVAL = 1000; - std::shared_ptr rdb_; std::shared_ptr sqliteStatement_; + std::shared_ptr conn_; std::vector columnNames_; std::vector args_; std::string sql_; - SqliteConnectionPool *connectionPool_; + std::shared_ptr connectionPool_; // The value indicates the row count of the result set int rowCount_; // Whether reach the end of this result set or not bool isAfterLast_; mutable std::shared_mutex mutex_; + int connId_; }; } // namespace NativeRdb } // namespace OHOS 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 e9c425b28daadf27abfffb239988303feee904d7..0cf450b300709c49bcbb86eba6de43b07aa1f2c0 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,11 +36,10 @@ public: void Clear() override; #endif const RdbStoreConfig &GetConfig(); - int Insert(int64_t &outRowId, const std::string &table, const ValuesBucket &initialValues) override; - int BatchInsert(int64_t &outInsertNum, const std::string &table, - const std::vector &initialBatchValues) override; + 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 &initialValues, + 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; @@ -56,8 +55,7 @@ public: 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 = std::vector()) override; + int ExecuteSql(const std::string& sql, const std::vector& bindArgs) override; std::pair Execute(const std::string &sql, const std::vector &bindArgs) override; int ExecuteAndGetLong(int64_t &outValue, const std::string &sql, const std::vector &bindArgs) override; int ExecuteAndGetString(std::string &outValue, const std::string &sql, @@ -66,8 +64,7 @@ public: 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 = std::vector()) override; + int Backup(const std::string databasePath, const std::vector destEncryptKey) override; int Attach(const std::string &alias, const std::string &pathName, const std::vector destEncryptKey) override; int GetVersion(int &version) override; @@ -81,10 +78,8 @@ public: bool IsReadOnly() const override; bool IsMemoryRdb() const override; bool IsHoldingConnection() override; -#ifdef RDB_SUPPORT_ICU - int ConfigLocale(const std::string localeStr); -#endif - int Restore(const std::string backupPath, const std::vector &newKey = std::vector()) override; + int ConfigLocale(const std::string &localeStr); + int Restore(const std::string backupPath, const std::vector &newKey) override; std::string GetName(); std::string GetOrgPath(); std::string GetFileType(); @@ -105,32 +100,35 @@ private: std::string ExtractFilePath(const std::string &fileFullName); int BeginExecuteSql(const std::string &sql, std::shared_ptr &connection); int FreeTransaction(std::shared_ptr connection, const std::string &sql); - ExecuteSqls GenerateSql( - const std::string &table, const std::vector &initialBatchValues, int limitVariableNumber); - ExecuteSqls MakeExecuteSqls( - const std::string &sql, const std::vector &args, int fieldSize, int limitVariableNumber); + ExecuteSqls GenerateSql(const std::string& table, const std::vector& buckets, int limit); + ExecuteSqls MakeExecuteSqls(const std::string& sql, std::vector&& args, int fieldSize, int limit); int GetDataBasePath(const std::string &databasePath, std::string &backupFilePath); int ExecuteSqlInner(const std::string &sql, const std::vector &bindArgs); int ExecuteGetLongInner(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()); + int InnerBackup(const std::string &databasePath, + const std::vector &destEncryptKey = std::vector()); inline std::string GetSqlArgs(size_t size); int RegisterDataChangeCallback(); - const RdbStoreConfig rdbStoreConfig; - SqliteConnectionPool *connectionPool; - bool isOpen; - std::string path; - std::string orgPath; - bool isReadOnly; - bool isMemoryRdb; - std::string name; - std::string fileType; - bool isEncrypt_; + static constexpr char SCHEME_RDB[] = "rdb://"; static constexpr uint32_t EXPANSION = 2; static constexpr uint32_t AUTO_SYNC_MAX_INTERVAL = 20000; + static inline constexpr uint32_t INTERVAL = 10; + static constexpr const char *ROW_ID = "ROWID"; + + const RdbStoreConfig config_; + std::shared_ptr connectionPool_; + bool isOpen_ = false; + bool isReadOnly_; + bool isMemoryRdb_; + bool isEncrypt_; + int64_t vSchema_ = 0; + std::string path_; + std::string orgPath_; + std::string name_; + std::string fileType_; }; } // namespace OHOS::NativeRdb #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 index cf97f1c5191cfe6268d47510e8ed6539e831cb8b..0697839f5f225159b8853a7fe8cf2123bd755521 100644 --- a/relational_store/frameworks/native/rdb/mock/include/sqlite_connection.h +++ b/relational_store/frameworks/native/rdb/mock/include/sqlite_connection.h @@ -57,12 +57,12 @@ public: bool IsInTransaction(); int TryCheckPoint(); int LimitWalSize(); -#ifdef RDB_SUPPORT_ICU - int ConfigLocale(const std::string localeStr); -#endif + int ConfigLocale(const std::string &localeStr); int RegisterCallBackObserver(const DataChangeCallback &clientChangedData); int GetMaxVariableNumber(); + uint32_t GetId() const; + int32_t SetId(uint32_t id); private: static constexpr const char *MERGE_ASSETS_FUNC = "merge_assets"; explicit SqliteConnection(bool isWriteConnection); @@ -109,6 +109,8 @@ private: bool isConfigured_ = false; int maxVariableNumber_; + bool hasClientObserver_ = false; + int id_; }; } // namespace NativeRdb } // namespace OHOS diff --git a/relational_store/frameworks/native/rdb/mock/include/sqlite_connection_pool.h b/relational_store/frameworks/native/rdb/mock/include/sqlite_connection_pool.h index 85616bd44984be862f567f2e85ab312b1b75f1fb..0e05b02d5a2b6922e2cd9ddd3e1738187c308b9d 100644 --- a/relational_store/frameworks/native/rdb/mock/include/sqlite_connection_pool.h +++ b/relational_store/frameworks/native/rdb/mock/include/sqlite_connection_pool.h @@ -17,67 +17,86 @@ #define NATIVE_RDB_SQLITE_CONNECTION_POOL_H #include +#include #include #include #include #include #include #include - +#include #include "rdb_store_config.h" #include "sqlite_connection.h" #include "base_transaction.h" namespace OHOS { namespace NativeRdb { -class SqliteConnectionPool { +class SqliteConnectionPool : public std::enable_shared_from_this { public: - static SqliteConnectionPool *Create(const RdbStoreConfig &storeConfig, int &errCode); + static std::shared_ptr Create(const RdbStoreConfig &storeConfig, int &errCode); ~SqliteConnectionPool(); std::shared_ptr AcquireConnection(bool isReadOnly); - void ReleaseConnection(std::shared_ptr connection); - int ReOpenAvailableReadConnections(); -#ifdef RDB_SUPPORT_ICU - int ConfigLocale(const std::string localeStr); -#endif - int ChangeDbFileForRestore(const std::string newPath, const std::string backupPath, + int RestartReaders(); + int ConfigLocale(const std::string &localeStr); + int ChangeDbFileForRestore(const std::string &newPath, const std::string &backupPath, const std::vector &newKey); std::stack &GetTransactionStack(); std::mutex &GetTransactionStackMutex(); int AcquireTransaction(); void ReleaseTransaction(); - + std::shared_ptr AcquireByID(int32_t id); private: + struct ConnNode { + bool using_ = false; + uint32_t tid_ = 0; + uint32_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(bool justHold = false); + int64_t GetUsingTime() const; + bool IsWriter() const; + void Unused(); + }; + + struct Container { + using Creator = std::function>()>; + int max_ = 0; + int count_ = 0; + uint32_t left_ = 0; + uint32_t right_ = 0; + std::chrono::seconds timeout_; + std::list> nodes_; + std::list> details_; + std::mutex mutex_; + std::condition_variable cond_; + int32_t Initialize(int32_t max, int32_t timeout, Creator creator); + int32_t ConfigLocale(const std::string &locale); + std::shared_ptr Acquire(); + int32_t Release(std::shared_ptr node); + int32_t Clear(); + bool IsFull(); + int32_t Dump(const char *header); + std::shared_ptr AcquireById(int32_t id); + }; + explicit SqliteConnectionPool(const RdbStoreConfig &storeConfig); int Init(); - void InitReadConnectionCount(); - std::shared_ptr AcquireWriteConnection(); - void ReleaseWriteConnection(); - std::shared_ptr AcquireReadConnection(); - void ReleaseReadConnection(std::shared_ptr connection); + int32_t GetMaxReaders(); + void ReleaseNode(std::shared_ptr node); void CloseAllConnections(); - int InnerReOpenReadConnections(); + static constexpr int LIMITATION = 1024; RdbStoreConfig config_; - std::shared_ptr writeConnection_; - std::mutex writeMutex_; - std::condition_variable writeCondition_; - bool writeConnectionUsed_; - - std::vector> readConnections_; - std::mutex readMutex_; - std::mutex rdbMutex_; - std::condition_variable readCondition_; - int readConnectionCount_; - int idleReadConnectionCount_; - const static int LIMITATION = 1024; + Container writers_; + Container readers_; + int32_t maxReader_ = 0; std::stack transactionStack_; std::mutex transactionStackMutex_; std::condition_variable transCondition_; std::mutex transMutex_; bool transactionUsed_; - std::chrono::seconds writeTimeout_ = std::chrono::seconds(2); - std::chrono::seconds readTimeout_ = std::chrono::seconds(1); }; } // namespace NativeRdb 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 index d2c7e9368795ec7b0529d1183a64baaf75ee8eab..a24310e819d8373308cf0281fecefba7b7d98dc8 100644 --- a/relational_store/frameworks/native/rdb/mock/include/step_result_set.h +++ b/relational_store/frameworks/native/rdb/mock/include/step_result_set.h @@ -29,8 +29,8 @@ namespace OHOS { namespace NativeRdb { class StepResultSet : public AbsResultSet { public: - StepResultSet(std::shared_ptr rdb, SqliteConnectionPool *connectionPool, const std::string &sql, - const std::vector &selectionArgs); + StepResultSet(std::shared_ptr connectionPool, const std::string& sql, + const std::vector& selectionArgs); ~StepResultSet() override; int GetAllColumnNames(std::vector &columnNames) override; @@ -59,6 +59,7 @@ private: template int GetValue(int32_t col, T &value); std::pair GetValueObject(int32_t col, size_t index); + std::pair, std::shared_ptr> GetStatement(); void Reset(); int FinishStep(); int PrepareStep(); @@ -69,17 +70,18 @@ private: // Interval of retrying step query in millisecond static const int STEP_QUERY_RETRY_INTERVAL = 1000; - std::shared_ptr rdb_; std::shared_ptr sqliteStatement_; + std::shared_ptr conn_; std::vector columnNames_; std::vector args_; std::string sql_; - SqliteConnectionPool *connectionPool_; + std::shared_ptr connectionPool_; // The value indicates the row count of the result set int rowCount_; // Whether reach the end of this result set or not bool isAfterLast_; mutable std::shared_mutex mutex_; + int connId_; }; } // namespace NativeRdb } // namespace OHOS 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 1244c70451bc985eff3181aeeb5475c36be6c392..29ec10eb3433dd3ffc5084d0221830b72a7b04a5 100644 --- a/relational_store/frameworks/native/rdb/src/abs_result_set.cpp +++ b/relational_store/frameworks/native/rdb/src/abs_result_set.cpp @@ -22,7 +22,6 @@ #include "rdb_trace.h" #include "result_set.h" #include "sqlite_utils.h" - namespace OHOS { namespace NativeRdb { using namespace OHOS::Rdb; @@ -329,7 +328,7 @@ int AbsResultSet::GetColumnIndex(const std::string &columnName, int &columnIndex if (periodIndex != std::string::npos) { columnNameLower = columnNameLower.substr(periodIndex + 1); } - transform(columnNameLower.begin(), columnNameLower.end(), columnNameLower.begin(), ::tolower); + std::transform(columnNameLower.begin(), columnNameLower.end(), columnNameLower.begin(), ::tolower); std::vector columnNames; int ret = GetAllColumnNames(columnNames); if (ret != E_OK) { diff --git a/relational_store/frameworks/native/rdb/src/rdb_manager_impl.cpp b/relational_store/frameworks/native/rdb/src/rdb_manager_impl.cpp index caff8780b6f4f8a34f9a6044953bd8a44ca530f0..b6dc7a92d4b35011759e82fd8084af4d200c3cef 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_manager_impl.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_manager_impl.cpp @@ -173,7 +173,7 @@ RdbStoreDataServiceProxy::RdbStoreDataServiceProxy(const sptr &im sptr RdbStoreDataServiceProxy::GetFeatureInterface(const std::string &name) { - LOG_INFO("%s", name.c_str()); + LOG_INFO("%{public}s", name.c_str()); MessageParcel data; if (!data.WriteInterfaceToken(RdbStoreDataServiceProxy::GetDescriptor())) { LOG_ERROR("write descriptor failed"); 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 1ab7c39c4f979807ad9318bb2fa1a00d42648a51..1b13e2ec364a2e8f32b5bcfe2b2c33e18eae1f8d 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_store_config.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_store_config.cpp @@ -24,7 +24,7 @@ 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, const std::string &encryptAlgo) : name(name), path(name), storageMode(storageMode), @@ -419,6 +419,16 @@ std::string RdbStoreConfig::GetCustomDir() const return customDir_; } +void RdbStoreConfig::SetVisitorDir(const std::string &visitorDir) +{ + visitorDir_ = visitorDir; +} + +std::string RdbStoreConfig::GetVisitorDir() const +{ + return visitorDir_; +} + bool RdbStoreConfig::IsSearchable() const { return isSearchable_; @@ -448,4 +458,14 @@ void RdbStoreConfig::SetReadTime(int timeout) { readTimeout_ = timeout; } + +void RdbStoreConfig::SetRoleType(RoleType role) +{ + role_ = role; +} + +uint32_t RdbStoreConfig::GetRoleType() const +{ + return role_; +} } // 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 aa9fbea1e3ff87e255aa20196ebc29720f824d40..f62082c6ec9292954ef50daa7020e744749b5217 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_store_impl.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_store_impl.cpp @@ -40,13 +40,11 @@ #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) #include "delay_notify.h" -#include "iresult_set.h" #include "raw_data_parser.h" #include "rdb_device_manager_adapter.h" #include "rdb_manager_impl.h" #include "relational_store_manager.h" #include "rdb_security_manager.h" -#include "result_set_proxy.h" #include "runtime_config.h" #include "sqlite_shared_result_set.h" #include "sqlite_connection.h" @@ -64,31 +62,32 @@ using namespace OHOS::Rdb; using namespace std::chrono; int RdbStoreImpl::InnerOpen() { - LOG_DEBUG("open %{public}s.", SqliteUtils::Anonymous(rdbStoreConfig.GetPath()).c_str()); - int errCode = E_OK; - connectionPool = SqliteConnectionPool::Create(rdbStoreConfig, errCode); - if (connectionPool == nullptr) { - return errCode; - } + LOG_DEBUG("open %{public}s.", SqliteUtils::Anonymous(config_.GetPath()).c_str()); #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) - syncerParam_.bundleName_ = rdbStoreConfig.GetBundleName(); - syncerParam_.hapName_ = rdbStoreConfig.GetModuleName(); - syncerParam_.storeName_ = rdbStoreConfig.GetName(); - syncerParam_.customDir_ = rdbStoreConfig.GetCustomDir(); - syncerParam_.area_ = rdbStoreConfig.GetArea(); - syncerParam_.level_ = static_cast(rdbStoreConfig.GetSecurityLevel()); - syncerParam_.type_ = rdbStoreConfig.GetDistributedType(); - syncerParam_.isEncrypt_ = rdbStoreConfig.IsEncrypt(); - syncerParam_.isAutoClean_ = rdbStoreConfig.GetAutoClean(); - syncerParam_.isSearchable_ = rdbStoreConfig.IsSearchable(); + pool_ = TaskExecutor::GetInstance().GetExecutor(); + syncerParam_.bundleName_ = config_.GetBundleName(); + syncerParam_.hapName_ = config_.GetModuleName(); + syncerParam_.storeName_ = config_.GetName(); + syncerParam_.customDir_ = config_.GetCustomDir(); + syncerParam_.area_ = config_.GetArea(); + syncerParam_.level_ = static_cast(config_.GetSecurityLevel()); + syncerParam_.type_ = config_.GetDistributedType(); + syncerParam_.isEncrypt_ = config_.IsEncrypt(); + syncerParam_.isAutoClean_ = config_.GetAutoClean(); + syncerParam_.isSearchable_ = config_.IsSearchable(); syncerParam_.password_ = {}; - GetSchema(rdbStoreConfig); - errCode = RegisterDataChangeCallback(); + syncerParam_.roleType_ = config_.GetRoleType(); + if (config_.GetRoleType() == OWNER) { + GetSchema(config_); + } + + int errCode = RegisterDataChangeCallback(); if (errCode != E_OK) { LOG_ERROR("RegisterCallBackObserver is failed, err is %{public}d.", errCode); } #endif + isOpen_ = true; return E_OK; } @@ -109,9 +108,6 @@ void RdbStoreImpl::GetSchema(const RdbStoreConfig &config) } syncerParam_.password_ = std::vector(key.data(), key.data() + key.size()); key.assign(key.size(), 0); - if (pool_ == nullptr) { - pool_ = TaskExecutor::GetInstance().GetExecutor(); - } if (pool_ != nullptr) { auto param = syncerParam_; pool_->Execute([param]() { @@ -264,15 +260,17 @@ RdbStore::ModifyTime RdbStoreImpl::GetModifyTimeByRowId(const std::string &logTa int RdbStoreImpl::CleanDirtyData(const std::string &table, uint64_t cursor) { + if (config_.GetRoleType() == VISITOR) { + return E_NOT_SUPPORT; + } if (table.empty()) { return E_INVALID_ARGS; } - auto connection = connectionPool->AcquireConnection(false); + auto connection = connectionPool_->AcquireConnection(false); if (connection == nullptr) { return E_CON_OVER_LIMIT; } int errCode = connection->CleanDirtyData(table, cursor); - connectionPool->ReleaseConnection(connection); return errCode; } @@ -286,99 +284,96 @@ std::string RdbStoreImpl::GetSqlArgs(size_t size) } return args; } - RdbStoreImpl::RdbStoreImpl(const RdbStoreConfig &config, int &errCode) - : rdbStoreConfig(config), connectionPool(nullptr), isOpen(true), path(config.GetPath()), orgPath(config.GetPath()), - isReadOnly(config.IsReadOnly()), isMemoryRdb(config.IsMemoryRdb()), name(config.GetName()), - fileType(config.GetDatabaseFileType()), isEncrypt_(config.IsEncrypt()) -{ - errCode = InnerOpen(); - if (errCode != E_OK) { - LOG_ERROR("RdbStoreManager GetRdbStore fail to open RdbStore, err is %{public}d", errCode); - if (connectionPool) { - delete connectionPool; - connectionPool = nullptr; - } - isOpen = false; + : config_(config), connectionPool_(nullptr), isOpen_(false), isReadOnly_(config.IsReadOnly()), + isMemoryRdb_(config.IsMemoryRdb()), isEncrypt_(config.IsEncrypt()), path_(config.GetPath()), + orgPath_(config.GetPath()), name_(config.GetName()), fileType_(config.GetDatabaseFileType()) +{ + connectionPool_ = SqliteConnectionPool::Create(config_, errCode); + if (connectionPool_ == nullptr || errCode != E_OK) { + connectionPool_ = nullptr; + LOG_ERROR("InnerOpen failed, err is %{public}d, path:%{public}s", + errCode, SqliteUtils::Anonymous(path_).c_str()); + return; } + + InnerOpen(); } RdbStoreImpl::~RdbStoreImpl() { - LOG_DEBUG("destroy."); - if (connectionPool) { - delete connectionPool; - connectionPool = nullptr; - } + connectionPool_ = nullptr; } #ifdef WINDOWS_PLATFORM void RdbStoreImpl::Clear() { - delete connectionPool; - connectionPool = nullptr; + connectionPool_ = nullptr; } #endif const RdbStoreConfig &RdbStoreImpl::GetConfig() { - return rdbStoreConfig; + return config_; } -int RdbStoreImpl::Insert(int64_t &outRowId, const std::string &table, const ValuesBucket &initialValues) + +int RdbStoreImpl::Insert(int64_t &outRowId, const std::string &table, const ValuesBucket &values) { DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - return InsertWithConflictResolution(outRowId, table, initialValues, ConflictResolution::ON_CONFLICT_NONE); + return InsertWithConflictResolution(outRowId, table, values, ConflictResolution::ON_CONFLICT_NONE); } -int RdbStoreImpl::BatchInsert(int64_t &outInsertNum, const std::string &table, - const std::vector &initialBatchValues) +int RdbStoreImpl::BatchInsert(int64_t &outInsertNum, const std::string &table, const std::vector &values) { - if (initialBatchValues.empty()) { + if (config_.GetRoleType() == VISITOR) { + return E_NOT_SUPPORT; + } + if (values.empty()) { outInsertNum = 0; return E_OK; } - auto connection = connectionPool->AcquireConnection(false); + auto connection = connectionPool_->AcquireConnection(false); if (connection == nullptr) { return E_CON_OVER_LIMIT; } - auto executeSqlArgs = GenerateSql(table, initialBatchValues, connection->GetMaxVariableNumber()); + auto executeSqlArgs = GenerateSql(table, values, connection->GetMaxVariableNumber()); if (executeSqlArgs.empty()) { - connectionPool->ReleaseConnection(connection); LOG_ERROR("empty, table=%{public}s, values:%{public}zu, max number:%{public}d.", table.c_str(), - initialBatchValues.size(), connection->GetMaxVariableNumber()); + values.size(), connection->GetMaxVariableNumber()); return E_INVALID_ARGS; } + #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) if (delayNotifier_ != nullptr) { delayNotifier_->SetAutoSyncInterval(AUTO_SYNC_MAX_INTERVAL); } #endif + for (const auto &[sql, bindArgs] : executeSqlArgs) { for (const auto &args : bindArgs) { auto errCode = connection->ExecuteSql(sql, args); if (errCode != E_OK) { outInsertNum = -1; - connectionPool->ReleaseConnection(connection); 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; } } } - outInsertNum = initialBatchValues.size(); - connectionPool->ReleaseConnection(connection); + connection = nullptr; + outInsertNum = values.size(); DoCloudSync(table); return E_OK; } -RdbStoreImpl::ExecuteSqls RdbStoreImpl::GenerateSql( - const std::string &table, const std::vector &initialBatchValues, int limitVariableNumber) +RdbStoreImpl::ExecuteSqls RdbStoreImpl::GenerateSql(const std::string& table, const std::vector& buckets, + int limit) { std::vector> values; std::map fields; int32_t valuePosition = 0; - for (size_t row = 0; row < initialBatchValues.size(); row++) { - auto &vBucket = initialBatchValues[row]; + for (size_t row = 0; row < buckets.size(); row++) { + auto &vBucket = buckets[row]; if (values.max_size() == 0) { values.reserve(vBucket.values_.size() * EXPANSION); } @@ -390,9 +385,9 @@ RdbStoreImpl::ExecuteSqls RdbStoreImpl::GenerateSql( int32_t col = 0; auto it = fields.find(key); if (it == fields.end()) { - values.emplace_back(std::vector(initialBatchValues.size())); + values.emplace_back(std::vector(buckets.size())); col = valuePosition; - fields.insert(std::pair{key, col}); + fields.insert(std::make_pair(key, col)); valuePosition++; } else { col = it->second; @@ -402,10 +397,10 @@ RdbStoreImpl::ExecuteSqls RdbStoreImpl::GenerateSql( } std::string sql = "INSERT OR REPLACE INTO " + table + " ("; - std::vector args(initialBatchValues.size() * values.size()); + std::vector args(buckets.size() * values.size()); int32_t col = 0; for (auto &[key, pos] : fields) { - for (size_t row = 0; row < initialBatchValues.size(); ++row) { + for (size_t row = 0; row < buckets.size(); ++row) { args[col + row * fields.size()] = std::move(values[pos][row]); } col++; @@ -413,22 +408,22 @@ RdbStoreImpl::ExecuteSqls RdbStoreImpl::GenerateSql( } sql.pop_back(); sql.append(") VALUES "); - return MakeExecuteSqls(sql, args, fields.size(), limitVariableNumber); + return MakeExecuteSqls(sql, std::move(args), fields.size(), limit); } -RdbStoreImpl::ExecuteSqls RdbStoreImpl::MakeExecuteSqls( - const std::string &sql, const std::vector &args, int fieldSize, int limitVariableNumber) +RdbStoreImpl::ExecuteSqls RdbStoreImpl::MakeExecuteSqls(const std::string& sql, std::vector&& args, + int fieldSize, int limit) { if (fieldSize == 0) { return ExecuteSqls(); } size_t rowNumbers = args.size() / fieldSize; - size_t maxRowNumbersOneTimes = limitVariableNumber / fieldSize; + size_t maxRowNumbersOneTimes = limit / fieldSize; 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, limitVariableNumber %{public}d", - rowNumbers, maxRowNumbersOneTimes, executeTimes, remainingRows, fieldSize, limitVariableNumber); + "remainingRows %{public}zu, fieldSize %{public}d, limit %{public}d", + rowNumbers, maxRowNumbersOneTimes, executeTimes, remainingRows, fieldSize, limit); std::string singleRowSqlArgs = "(" + GetSqlArgs(fieldSize) + ")"; auto appendAgsSql = [&singleRowSqlArgs, &sql] (size_t rowNumber) { std::string sqlStr = sql; @@ -467,29 +462,31 @@ int RdbStoreImpl::Replace(int64_t &outRowId, const std::string &table, const Val } int RdbStoreImpl::InsertWithConflictResolution(int64_t &outRowId, const std::string &table, - const ValuesBucket &initialValues, ConflictResolution conflictResolution) + const ValuesBucket &values, ConflictResolution conflictResolution) { + if (config_.GetRoleType() == VISITOR) { + return E_NOT_SUPPORT; + } if (table.empty()) { return E_EMPTY_TABLE_NAME; } - if (initialValues.IsEmpty()) { + if (values.IsEmpty()) { return E_EMPTY_VALUES_BUCKET; } - std::string conflictClause; - int errCode = SqliteUtils::GetConflictClause(static_cast(conflictResolution), conflictClause); - if (errCode != E_OK) { - return errCode; + auto conflictClause = SqliteUtils::GetConflictClause(static_cast(conflictResolution)); + if (conflictClause == nullptr) { + return E_INVALID_CONFLICT_FLAG; } std::string sql; sql.append("INSERT").append(conflictClause).append(" INTO ").append(table).append("("); - size_t bindArgsSize = initialValues.values_.size(); + size_t bindArgsSize = values.values_.size(); std::vector bindArgs; bindArgs.reserve(bindArgsSize); const char *split = ""; - for (const auto &[key, val] : initialValues.values_) { + for (const auto &[key, val] : values.values_) { sql.append(split).append(key); if (val.GetType() == ValueObject::TYPE_ASSETS && conflictResolution == ConflictResolution::ON_CONFLICT_REPLACE) { @@ -508,13 +505,16 @@ int RdbStoreImpl::InsertWithConflictResolution(int64_t &outRowId, const std::str } sql.append(")"); - auto connection = connectionPool->AcquireConnection(false); - if (connection == nullptr) { - return E_CON_OVER_LIMIT; + int32_t errCode = E_OK; + { + auto connection = connectionPool_->AcquireConnection(false); + if (connection == nullptr) { + return E_CON_OVER_LIMIT; + } + + errCode = connection->ExecuteForLastInsertedRowId(outRowId, sql, bindArgs); } - errCode = connection->ExecuteForLastInsertedRowId(outRowId, sql, bindArgs); - connectionPool->ReleaseConnection(connection); if (errCode == E_OK) { DoCloudSync(table); } @@ -576,6 +576,9 @@ int RdbStoreImpl::UpdateWithConflictResolution(int &changedRows, const std::stri int RdbStoreImpl::UpdateWithConflictResolution(int &changedRows, const std::string &table, const ValuesBucket &values, const std::string &whereClause, const std::vector &bindArgs, ConflictResolution conflictResolution) { + if (config_.GetRoleType() == VISITOR) { + return E_NOT_SUPPORT; + } if (table.empty()) { return E_EMPTY_TABLE_NAME; } @@ -584,14 +587,13 @@ int RdbStoreImpl::UpdateWithConflictResolution(int &changedRows, const std::stri return E_EMPTY_VALUES_BUCKET; } - std::string conflictClause; - int errCode = SqliteUtils::GetConflictClause(static_cast(conflictResolution), conflictClause); - if (errCode != E_OK) { - return errCode; + auto clause = SqliteUtils::GetConflictClause(static_cast(conflictResolution)); + if (clause == nullptr) { + return E_INVALID_CONFLICT_FLAG; } std::string sql; - sql.append("UPDATE").append(conflictClause).append(" ").append(table).append(" SET "); + sql.append("UPDATE").append(clause).append(" ").append(table).append(" SET "); std::vector tmpBindArgs; size_t tmpBindSize = values.values_.size() + bindArgs.size(); tmpBindArgs.reserve(tmpBindSize); @@ -613,13 +615,15 @@ int RdbStoreImpl::UpdateWithConflictResolution(int &changedRows, const std::stri tmpBindArgs.insert(tmpBindArgs.end(), bindArgs.begin(), bindArgs.end()); - auto connection = connectionPool->AcquireConnection(false); - if (connection == nullptr) { - return E_CON_OVER_LIMIT; - } + int32_t errCode = E_OK; + { + auto connection = connectionPool_->AcquireConnection(false); + if (connection == nullptr) { + return E_CON_OVER_LIMIT; + } - errCode = connection->ExecuteForChangedRowCount(changedRows, sql, tmpBindArgs); - connectionPool->ReleaseConnection(connection); + errCode = connection->ExecuteForChangedRowCount(changedRows, sql, tmpBindArgs); + } if (errCode == E_OK) { DoCloudSync(table); } @@ -644,6 +648,9 @@ int RdbStoreImpl::Delete(int &deletedRows, const std::string &table, const std:: int RdbStoreImpl::Delete(int &deletedRows, const std::string &table, const std::string &whereClause, const std::vector &bindArgs) { + if (config_.GetRoleType() == VISITOR) { + return E_NOT_SUPPORT; + } if (table.empty()) { return E_EMPTY_TABLE_NAME; } @@ -654,13 +661,16 @@ int RdbStoreImpl::Delete(int &deletedRows, const std::string &table, const std:: sql.append(" WHERE ").append(whereClause); } - auto connection = connectionPool->AcquireConnection(false); - if (connection == nullptr) { - return E_CON_OVER_LIMIT; + int errCode = E_OK; + { + auto connection = connectionPool_->AcquireConnection(false); + if (connection == nullptr) { + return E_CON_OVER_LIMIT; + } + + errCode = connection->ExecuteForChangedRowCount(deletedRows, sql, bindArgs); } - int errCode = connection->ExecuteForChangedRowCount(deletedRows, sql, bindArgs); - connectionPool->ReleaseConnection(connection); if (errCode == E_OK) { DoCloudSync(table); } @@ -746,14 +756,14 @@ std::shared_ptr RdbStoreImpl::QuerySql(const std::string &sq { std::vector bindArgs; std::for_each(sqlArgs.begin(), sqlArgs.end(), [&bindArgs](const auto &it) { bindArgs.push_back(ValueObject(it)); }); - return std::make_shared(shared_from_this(), connectionPool, path, sql, bindArgs); + return std::make_shared(connectionPool_, path_, sql, bindArgs); } std::shared_ptr RdbStoreImpl::QuerySql(const std::string &sql, const std::vector &bindArgs) { DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - return std::make_shared(shared_from_this(), connectionPool, path, sql, bindArgs); + return std::make_shared(connectionPool_, path_, sql, bindArgs); } #endif @@ -789,15 +799,21 @@ int RdbStoreImpl::ExecuteSql(const std::string &sql, const std::vectorExecuteSql(sql, bindArgs); - connectionPool->ReleaseConnection(connection); if (errCode != E_OK) { LOG_ERROR("RDB_STORE Execute SQL ERROR."); return errCode; } int sqlType = SqliteUtils::GetSqlStatementType(sql); if (sqlType == SqliteUtils::STATEMENT_DDL) { - LOG_DEBUG("sql ddl execute."); - errCode = connectionPool->ReOpenAvailableReadConnections(); + int64_t version = 0; + connection->ExecuteGetLong(version, "PRAGMA schema_version"); + connection = nullptr; + if (vSchema_ < version) { + LOG_INFO("db:%{public}s exe DDL schema<%{public}" PRIi64 "->%{public}" PRIi64 "> sql:%{public}s.", + name_.c_str(), vSchema_, version, sql.c_str()); + vSchema_ = version; + errCode = connectionPool_->RestartReaders(); + } } if (errCode == E_OK && (sqlType == SqliteUtils::STATEMENT_UPDATE || sqlType == SqliteUtils::STATEMENT_INSERT)) { @@ -854,7 +870,6 @@ int RdbStoreImpl::ExecuteAndGetLong(int64_t &outValue, const std::string &sql, c if (errCode != E_OK) { LOG_ERROR("RDB_STORE ExecuteAndGetLong ERROR is %{public}d.", errCode); } - connectionPool->ReleaseConnection(connection); return errCode; } @@ -867,34 +882,37 @@ int RdbStoreImpl::ExecuteAndGetString( return errCode; } connection->ExecuteGetString(outValue, sql, bindArgs); - connectionPool->ReleaseConnection(connection); return errCode; } int RdbStoreImpl::ExecuteForLastInsertedRowId(int64_t &outValue, const std::string &sql, const std::vector &bindArgs) { - auto connection = connectionPool->AcquireConnection(false); + if (config_.GetRoleType() == VISITOR) { + return E_NOT_SUPPORT; + } + auto connection = connectionPool_->AcquireConnection(false); if (connection == nullptr) { return E_CON_OVER_LIMIT; } int errCode = connection->ExecuteForLastInsertedRowId(outValue, sql, bindArgs); - connectionPool->ReleaseConnection(connection); return errCode; } int RdbStoreImpl::ExecuteForChangedRowCount(int64_t &outValue, const std::string &sql, const std::vector &bindArgs) { + if (config_.GetRoleType() == VISITOR) { + return E_NOT_SUPPORT; + } int changeRow = 0; - auto connection = connectionPool->AcquireConnection(false); + auto connection = connectionPool_->AcquireConnection(false); if (connection == nullptr) { return E_CON_OVER_LIMIT; } int errCode = connection->ExecuteForChangedRowCount(changeRow, sql, bindArgs); - connectionPool->ReleaseConnection(connection); outValue = changeRow; return errCode; } @@ -907,7 +925,7 @@ int RdbStoreImpl::GetDataBasePath(const std::string &databasePath, std::string & } if (ISFILE(databasePath)) { - backupFilePath = ExtractFilePath(path) + databasePath; + backupFilePath = ExtractFilePath(path_) + databasePath; } else { // 2 represents two characters starting from the len - 2 position if (!PathToRealPath(ExtractFilePath(databasePath), backupFilePath) || databasePath.back() == '/' || @@ -918,7 +936,7 @@ int RdbStoreImpl::GetDataBasePath(const std::string &databasePath, std::string & backupFilePath = databasePath; } - if (backupFilePath == path) { + if (backupFilePath == path_) { LOG_ERROR("The backupPath and path should not be same."); return E_INVALID_FILE_PATH; } @@ -936,10 +954,8 @@ int RdbStoreImpl::ExecuteSqlInner(const std::string &sql, const std::vectorExecuteSql(sql, bindArgs); - connectionPool->ReleaseConnection(connection); if (errCode != E_OK) { LOG_ERROR("ExecuteSql ATTACH_BACKUP_SQL error %{public}d", errCode); - return errCode; } return errCode; } @@ -953,10 +969,8 @@ int RdbStoreImpl::ExecuteGetLongInner(const std::string &sql, const std::vector< return errCode; } errCode = connection->ExecuteGetLong(count, sql, bindArgs); - connectionPool->ReleaseConnection(connection); if (errCode != E_OK) { LOG_ERROR("ExecuteSql EXPORT_SQL error %{public}d", errCode); - return errCode; } return errCode; } @@ -966,6 +980,9 @@ int RdbStoreImpl::ExecuteGetLongInner(const std::string &sql, const std::vector< */ int RdbStoreImpl::Backup(const std::string databasePath, const std::vector destEncryptKey) { + if (config_.GetRoleType() == VISITOR) { + return E_NOT_SUPPORT; + } std::string backupFilePath; int ret = GetDataBasePath(databasePath, backupFilePath); if (ret != E_OK) { @@ -992,24 +1009,28 @@ int RdbStoreImpl::Backup(const std::string databasePath, const std::vector destEncryptKey) +int RdbStoreImpl::InnerBackup(const std::string &databasePath, const std::vector &destEncryptKey) { + if (config_.GetRoleType() == VISITOR) { + return E_NOT_SUPPORT; + } + std::vector bindArgs; - bindArgs.push_back(ValueObject(databasePath)); - if (destEncryptKey.size() != 0 && !isEncrypt_) { - bindArgs.push_back(ValueObject(destEncryptKey)); - ExecuteSql(GlobalExpr::CIPHER_DEFAULT_ATTACH_HMAC_ALGO); + bindArgs.emplace_back(databasePath); + if (!destEncryptKey.empty() && !isEncrypt_) { + bindArgs.emplace_back(destEncryptKey); + (static_cast(this))->ExecuteSql(GlobalExpr::CIPHER_DEFAULT_ATTACH_HMAC_ALGO); #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) } else if (isEncrypt_) { RdbPassword rdbPwd = RdbSecurityManager::GetInstance().GetRdbPassword( - rdbStoreConfig.GetPath(), RdbSecurityManager::KeyFileType::PUB_KEY_FILE); + config_.GetPath(), RdbSecurityManager::KeyFileType::PUB_KEY_FILE); std::vector key = std::vector(rdbPwd.GetData(), rdbPwd.GetData() + rdbPwd.GetSize()); - bindArgs.push_back(ValueObject(key)); - ExecuteSql(GlobalExpr::CIPHER_DEFAULT_ATTACH_HMAC_ALGO); + bindArgs.emplace_back(key); + (static_cast(this))->ExecuteSql(GlobalExpr::CIPHER_DEFAULT_ATTACH_HMAC_ALGO); #endif } else { std::string str = ""; - bindArgs.push_back(ValueObject(str)); + bindArgs.emplace_back(str); } int ret = ExecuteSqlInner(GlobalExpr::ATTACH_BACKUP_SQL, bindArgs); @@ -1033,27 +1054,26 @@ int RdbStoreImpl::BeginExecuteSql(const std::string &sql, std::shared_ptrAcquireConnection(assumeReadOnly); + connection = connectionPool_->AcquireConnection(assumeReadOnly); if (connection == nullptr) { return E_CON_OVER_LIMIT; } int errCode = connection->Prepare(sql, isReadOnly); if (errCode != 0) { - connectionPool->ReleaseConnection(connection); return errCode; } if (isReadOnly == connection->IsWriteConnection()) { - connectionPool->ReleaseConnection(connection); - connection = connectionPool->AcquireConnection(isReadOnly); + connection = nullptr; + connection = connectionPool_->AcquireConnection(isReadOnly); if (connection == nullptr) { return E_CON_OVER_LIMIT; } if (!isReadOnly && !connection->IsWriteConnection()) { LOG_ERROR("StoreSession BeginExecutea : read connection can not execute write operation"); - connectionPool->ReleaseConnection(connection); + connection = nullptr; return E_EXECUTE_WRITE_IN_READ_CONNECTION; } } @@ -1062,7 +1082,7 @@ int RdbStoreImpl::BeginExecuteSql(const std::string &sql, std::shared_ptrExecuteGetString(journalMode, sql, std::vector()); if (errCode != E_OK) { - connectionPool->ReleaseConnection(connection); LOG_ERROR("RdbStoreImpl CheckAttach fail to get journal mode : %d", errCode); return errCode; } journalMode = SqliteUtils::StrToUpper(journalMode); if (journalMode == GlobalExpr::DEFAULT_JOURNAL_MODE) { - connectionPool->ReleaseConnection(connection); LOG_ERROR("RdbStoreImpl attach is not supported in WAL mode"); return E_NOT_SUPPORTED_ATTACH_IN_WAL_MODE; } std::vector bindArgs; - bindArgs.push_back(ValueObject(pathName)); - bindArgs.push_back(ValueObject(alias)); - if (destEncryptKey.size() != 0 && !isEncrypt_) { - bindArgs.push_back(ValueObject(destEncryptKey)); - ExecuteSql(GlobalExpr::CIPHER_DEFAULT_ATTACH_HMAC_ALGO); + bindArgs.emplace_back(pathName); + bindArgs.emplace_back(alias); + if (!destEncryptKey.empty() && !isEncrypt_) { + bindArgs.emplace_back(destEncryptKey); + (static_cast(this))->ExecuteSql(GlobalExpr::CIPHER_DEFAULT_ATTACH_HMAC_ALGO); #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) } else if (isEncrypt_) { RdbPassword rdbPwd = - RdbSecurityManager::GetInstance().GetRdbPassword(rdbStoreConfig.GetPath(), + RdbSecurityManager::GetInstance().GetRdbPassword(config_.GetPath(), RdbSecurityManager::KeyFileType::PUB_KEY_FILE); std::vector key = std::vector(rdbPwd.GetData(), rdbPwd.GetData() + rdbPwd.GetSize()); - bindArgs.push_back(ValueObject(key)); - ExecuteSql(GlobalExpr::CIPHER_DEFAULT_ATTACH_HMAC_ALGO); + bindArgs.emplace_back(key); + (static_cast(this))->ExecuteSql(GlobalExpr::CIPHER_DEFAULT_ATTACH_HMAC_ALGO); #endif } else { std::string str = ""; @@ -1113,7 +1131,6 @@ int RdbStoreImpl::Attach(const std::string &alias, const std::string &pathName, } sql = GlobalExpr::ATTACH_SQL; errCode = connection->ExecuteSql(sql, bindArgs); - connectionPool->ReleaseConnection(connection); if (errCode != E_OK) { LOG_ERROR("ExecuteSql ATTACH_SQL error %d", errCode); } @@ -1137,6 +1154,9 @@ int RdbStoreImpl::GetVersion(int &version) */ int RdbStoreImpl::SetVersion(int version) { + if (config_.GetRoleType() == VISITOR) { + return E_NOT_SUPPORT; + } std::string sql = std::string(GlobalExpr::PRAGMA_VERSION) + " = " + std::to_string(version); return ExecuteSql(sql, std::vector()); } @@ -1146,31 +1166,39 @@ int RdbStoreImpl::SetVersion(int version) int RdbStoreImpl::BeginTransaction() { DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - std::lock_guard lockGuard(connectionPool->GetTransactionStackMutex()); + std::lock_guard lockGuard(connectionPool_->GetTransactionStackMutex()); + if (config_.GetRoleType() == VISITOR) { + return E_NOT_SUPPORT; + } + // size + 1 means the number of transactions in process - size_t transactionId = connectionPool->GetTransactionStack().size() + 1; + size_t transactionId = connectionPool_->GetTransactionStack().size() + 1; - auto time = static_cast(duration_cast(system_clock::now().time_since_epoch()).count()); - BaseTransaction transaction(connectionPool->GetTransactionStack().size()); - auto connection = connectionPool->AcquireConnection(false); + auto connection = connectionPool_->AcquireConnection(false); if (connection == nullptr) { - LOG_ERROR("transaction id: %{public}zu, storeName: %{public}s times:%{public}" PRIu64 ".", - transactionId, name.c_str(), time); + LOG_ERROR("transaction id: %{public}zu, storeName: %{public}s", transactionId, name_.c_str()); return E_CON_OVER_LIMIT; } + BaseTransaction transaction(connectionPool_->GetTransactionStack().size()); int errCode = connection->ExecuteSql(transaction.GetTransactionStr()); - connectionPool->ReleaseConnection(connection); if (errCode != E_OK) { - LOG_ERROR("transaction id: %{public}zu, storeName: %{public}s, errCode: %{public}d times:%{public}" PRIu64 ".", - transactionId, name.c_str(), errCode, time); + LOG_ERROR("transaction id: %{public}zu, storeName: %{public}s, errCode: %{public}d", + transactionId, name_.c_str(), errCode); + return errCode; } connection->SetInTransaction(true); - connectionPool->GetTransactionStack().push(transaction); - LOG_INFO("transaction id: %{public}zu, storeName: %{public}s times:%{public}" PRIu64 ".", - transactionId, name.c_str(), time); + + connectionPool_->GetTransactionStack().push(transaction); + + // 1 means the number of transactions in process + if (transactionId > 1) { + LOG_WARN("transaction id: %{public}zu, storeName: %{public}s, errCode: %{public}d", + transactionId, name_.c_str(), errCode); + } + return E_OK; } @@ -1180,37 +1208,38 @@ int RdbStoreImpl::BeginTransaction() int RdbStoreImpl::RollBack() { DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - std::lock_guard lockGuard(connectionPool->GetTransactionStackMutex()); - size_t transactionId = connectionPool->GetTransactionStack().size(); + std::lock_guard lockGuard(connectionPool_->GetTransactionStackMutex()); + if (config_.GetRoleType() == VISITOR) { + return E_NOT_SUPPORT; + } + size_t transactionId = connectionPool_->GetTransactionStack().size(); - auto time = static_cast(duration_cast(system_clock::now().time_since_epoch()).count()); - if (connectionPool->GetTransactionStack().empty()) { - LOG_ERROR("transaction id: %{public}zu, storeName: %{public}s time:%{public}" PRIu64 ".", - transactionId, name.c_str(), time); + if (connectionPool_->GetTransactionStack().empty()) { + LOG_ERROR("transaction id: %{public}zu, storeName: %{public}s", transactionId, name_.c_str()); return E_NO_TRANSACTION_IN_SESSION; } - BaseTransaction transaction = connectionPool->GetTransactionStack().top(); - connectionPool->GetTransactionStack().pop(); - if (transaction.GetType() != TransType::ROLLBACK_SELF && !connectionPool->GetTransactionStack().empty()) { - connectionPool->GetTransactionStack().top().SetChildFailure(true); + BaseTransaction transaction = connectionPool_->GetTransactionStack().top(); + connectionPool_->GetTransactionStack().pop(); + if (transaction.GetType() != TransType::ROLLBACK_SELF && !connectionPool_->GetTransactionStack().empty()) { + connectionPool_->GetTransactionStack().top().SetChildFailure(true); } - auto connection = connectionPool->AcquireConnection(false); + auto connection = connectionPool_->AcquireConnection(false); if (connection == nullptr) { // size + 1 means the number of transactions in process - LOG_ERROR("transaction id: %{public}zu, storeName: %{public}s time:%{public}" PRIu64 ".", - transactionId + 1, name.c_str(), time); + LOG_ERROR("transaction id: %{public}zu, storeName: %{public}s", transactionId + 1, name_.c_str()); return E_CON_OVER_LIMIT; } int errCode = connection->ExecuteSql(transaction.GetRollbackStr()); - connectionPool->ReleaseConnection(connection); - if (connectionPool->GetTransactionStack().empty()) { + if (connectionPool_->GetTransactionStack().empty()) { connection->SetInTransaction(false); } - // size + 1 means the number of transactions in process - LOG_INFO("transaction id: %{public}zu, , storeName: %{public}s, errCode:%{public}d time:%{public}" PRIu64 ".", - transactionId + 1, name.c_str(), errCode, time); + // 1 means the number of transactions in process + if (transactionId > 1) { + LOG_WARN("transaction id: %{public}zu, storeName: %{public}s, errCode: %{public}d", + transactionId, name_.c_str(), errCode); + } return E_OK; } @@ -1220,37 +1249,39 @@ int RdbStoreImpl::RollBack() int RdbStoreImpl::Commit() { DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - std::lock_guard lockGuard(connectionPool->GetTransactionStackMutex()); - size_t transactionId = connectionPool->GetTransactionStack().size(); + std::lock_guard lockGuard(connectionPool_->GetTransactionStackMutex()); + if (config_.GetRoleType() == VISITOR) { + return E_NOT_SUPPORT; + } + size_t transactionId = connectionPool_->GetTransactionStack().size(); - auto time = static_cast(duration_cast(system_clock::now().time_since_epoch()).count()); - if (connectionPool->GetTransactionStack().empty()) { - LOG_ERROR("transaction id: %{public}zu, storeName: %{public}s time:%{public}" PRIu64 ".", - transactionId, name.c_str(), time); + if (connectionPool_->GetTransactionStack().empty()) { + LOG_ERROR("transaction id: %{public}zu, storeName: %{public}s", transactionId, name_.c_str()); return E_OK; } - BaseTransaction transaction = connectionPool->GetTransactionStack().top(); + BaseTransaction transaction = connectionPool_->GetTransactionStack().top(); std::string sqlStr = transaction.GetCommitStr(); if (sqlStr.size() <= 1) { - LOG_INFO("transaction id: %{public}zu, storeName: %{public}s time:%{public}" PRIu64 ".", - transactionId, name.c_str(), time); - connectionPool->GetTransactionStack().pop(); + LOG_INFO("transaction id: %{public}zu, storeName: %{public}s", transactionId, name_.c_str()); + connectionPool_->GetTransactionStack().pop(); return E_OK; } - auto connection = connectionPool->AcquireConnection(false); + auto connection = connectionPool_->AcquireConnection(false); if (connection == nullptr) { - LOG_ERROR("transaction id: %{public}zu, storeName: %{public}s time:%{public}" PRIu64 ".", - transactionId, name.c_str(), time); + LOG_ERROR("transaction id: %{public}zu, storeName: %{public}s", transactionId, name_.c_str()); return E_CON_OVER_LIMIT; } int errCode = connection->ExecuteSql(sqlStr); - connectionPool->ReleaseConnection(connection); connection->SetInTransaction(false); - LOG_INFO("transaction id: %{public}zu, storeName: %{public}s errCode:%{public}d time:%{public}" PRIu64 ".", - transactionId, name.c_str(), errCode, time); - connectionPool->GetTransactionStack().pop(); + + // 1 means the number of transactions in process + if (transactionId > 1) { + LOG_WARN("transaction id: %{public}zu, storeName: %{public}s, errCode: %{public}d", + transactionId, name_.c_str(), errCode); + } + connectionPool_->GetTransactionStack().pop(); return E_OK; } @@ -1259,21 +1290,22 @@ int RdbStoreImpl::FreeTransaction(std::shared_ptr connection, int errCode = connection->ExecuteSql(sql); if (errCode == E_OK) { connection->SetInTransaction(false); - connectionPool->ReleaseTransaction(); + connectionPool_->ReleaseTransaction(); } else { LOG_ERROR("%{public}s with error code %{public}d.", sql.c_str(), errCode); } - connectionPool->ReleaseConnection(connection); return errCode; } bool RdbStoreImpl::IsInTransaction() { + if (config_.GetRoleType() == VISITOR) { + return false; + } bool res = true; - auto connection = connectionPool->AcquireConnection(false); + auto connection = connectionPool_->AcquireConnection(false); if (connection != nullptr) { res = connection->IsInTransaction(); - connectionPool->ReleaseConnection(connection); } return res; } @@ -1292,7 +1324,7 @@ int RdbStoreImpl::CheckAttach(const std::string &sql) return E_OK; } - auto connection = connectionPool->AcquireConnection(false); + auto connection = connectionPool_->AcquireConnection(false); if (connection == nullptr) { return E_CON_OVER_LIMIT; } @@ -1300,7 +1332,6 @@ int RdbStoreImpl::CheckAttach(const std::string &sql) std::string journalMode; int errCode = connection->ExecuteGetString(journalMode, GlobalExpr::PRAGMA_JOUR_MODE_EXP, std::vector()); - connectionPool->ReleaseConnection(connection); if (errCode != E_OK) { LOG_ERROR("RdbStoreImpl CheckAttach fail to get journal mode : %{public}d", errCode); return errCode; @@ -1361,32 +1392,32 @@ bool RdbStoreImpl::PathToRealPath(const std::string &path, std::string &realPath bool RdbStoreImpl::IsOpen() const { - return isOpen; + return isOpen_; } std::string RdbStoreImpl::GetPath() { - return path; + return path_; } std::string RdbStoreImpl::GetOrgPath() { - return orgPath; + return orgPath_; } bool RdbStoreImpl::IsReadOnly() const { - return isReadOnly; + return isReadOnly_; } bool RdbStoreImpl::IsMemoryRdb() const { - return isMemoryRdb; + return isMemoryRdb_; } std::string RdbStoreImpl::GetName() { - return name; + return name_; } void RdbStoreImpl::DoCloudSync(const std::string &table) @@ -1436,37 +1467,35 @@ void RdbStoreImpl::DoCloudSync(const std::string &table) } std::string RdbStoreImpl::GetFileType() { - return fileType; + return fileType_; } -#ifdef RDB_SUPPORT_ICU /** * Sets the database locale. */ -int RdbStoreImpl::ConfigLocale(const std::string localeStr) +int RdbStoreImpl::ConfigLocale(const std::string &localeStr) { - if (isOpen == false) { + if (!isOpen_) { LOG_ERROR("The connection pool has been closed."); return E_ERROR; } - if (connectionPool == nullptr) { - LOG_ERROR("connectionPool is null"); + if (connectionPool_ == nullptr) { + LOG_ERROR("connectionPool_ is null"); return E_ERROR; } - return connectionPool->ConfigLocale(localeStr); + return connectionPool_->ConfigLocale(localeStr); } -#endif int RdbStoreImpl::Restore(const std::string backupPath, const std::vector &newKey) { - if (isOpen == false) { + if (!isOpen_) { LOG_ERROR("The connection pool has been closed."); return E_ERROR; } - if (connectionPool == nullptr) { - LOG_ERROR("The connectionPool is null."); + if (connectionPool_ == nullptr) { + LOG_ERROR("The connectionPool_ is null."); return E_ERROR; } @@ -1481,7 +1510,7 @@ int RdbStoreImpl::Restore(const std::string backupPath, const std::vectorChangeDbFileForRestore(path, backupFilePath, newKey); + return connectionPool_->ChangeDbFileForRestore(path_, backupFilePath, newKey); } /** @@ -1492,12 +1521,12 @@ std::shared_ptr RdbStoreImpl::QueryByStep(const std::string &sql, { std::vector bindArgs; std::for_each(sqlArgs.begin(), sqlArgs.end(), [&bindArgs](const auto &it) { bindArgs.push_back(ValueObject(it)); }); - return std::make_shared(shared_from_this(), connectionPool, sql, bindArgs); + return std::make_shared(connectionPool_, sql, bindArgs); } std::shared_ptr RdbStoreImpl::QueryByStep(const std::string &sql, const std::vector &args) { - return std::make_shared(shared_from_this(), connectionPool, sql, args); + return std::make_shared(connectionPool_, sql, args); } #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) @@ -1595,10 +1624,10 @@ int RdbStoreImpl::InnerSync(const DistributedRdb::RdbService::Option &option, Uri RdbStoreImpl::GetUri(const std::string &event) { std::string rdbUri; - if (rdbStoreConfig.GetDataGroupId().empty()) { - rdbUri = SCHEME_RDB + rdbStoreConfig.GetBundleName() + "/" + path + "/" + event; + if (config_.GetDataGroupId().empty()) { + rdbUri = SCHEME_RDB + config_.GetBundleName() + "/" + path_ + "/" + event; } else { - rdbUri = SCHEME_RDB + rdbStoreConfig.GetDataGroupId() + "/" + path + "/" + event; + rdbUri = SCHEME_RDB + config_.GetDataGroupId() + "/" + path_ + "/" + event; } return Uri(rdbUri); } @@ -1834,12 +1863,7 @@ void RdbStoreImpl::InitDelayNotifier() LOG_ERROR("Init delay notifier failed"); return; } - if (pool_ == nullptr) { - pool_ = TaskExecutor::GetInstance().GetExecutor(); - } - if (pool_ != nullptr) { - delayNotifier_->SetExecutorPool(pool_); - } + delayNotifier_->SetExecutorPool(pool_); delayNotifier_->SetTask([param = syncerParam_](const DistributedRdb::RdbChangedData& rdbChangedData) -> int { auto [errCode, service] = DistributedRdb::RdbManagerImpl::GetInstance().GetRdbService(param); if (errCode != E_OK || service == nullptr) { @@ -1852,28 +1876,29 @@ void RdbStoreImpl::InitDelayNotifier() int RdbStoreImpl::RegisterDataChangeCallback() { - if (!rdbStoreConfig.IsSearchable()) { + if (!config_.IsSearchable()) { return E_OK; } + if (config_.GetRoleType() == VISITOR) { + return E_NOT_SUPPORT; + } InitDelayNotifier(); - auto callBack = [this](ClientChangedData &clientChangedData) { + auto callBack = [delayNotifier = delayNotifier_](ClientChangedData &clientChangedData) { DistributedRdb::RdbChangedData rdbChangedData; for (const auto& entry : clientChangedData.tableData) { DistributedRdb::RdbChangeProperties rdbProperties; rdbProperties.isTrackedDataChange = entry.second.isTrackedDataChange; rdbChangedData.tableData[entry.first] = rdbProperties; } - if (delayNotifier_ != nullptr) { - delayNotifier_->UpdateNotify(rdbChangedData); + if (delayNotifier != nullptr) { + delayNotifier->UpdateNotify(rdbChangedData); } }; - auto connection = connectionPool->AcquireConnection(false); + auto connection = connectionPool_->AcquireConnection(false); if (connection == nullptr) { return E_CON_OVER_LIMIT; } - int code = connection->RegisterCallBackObserver(callBack); - connectionPool->ReleaseConnection(connection); - return code; + return connection->RegisterCallBackObserver(callBack); } bool RdbStoreImpl::ColHasSpecificField(const std::vector &columns) 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 5c6007568562805317a7d219f6831da118e013a8..0e852bcfddb3616960b3c8587a43a1b14c7329dc 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_store_manager.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_store_manager.cpp @@ -56,9 +56,14 @@ RdbStoreManager::RdbStoreManager() std::shared_ptr RdbStoreManager::GetRdbStore(const RdbStoreConfig &config, int &errCode, int version, RdbOpenCallback &openCallback) { - std::string path = config.GetPath(); + std::string path; // TOD this lock should only work on storeCache_, add one more lock for connectionpool std::lock_guard lock(mutex_); + if (config.GetRoleType() == VISITOR) { + path = config.GetVisitorDir(); + } else { + path = config.GetPath(); + } bundleName_ = config.GetBundleName(); if (storeCache_.find(path) != storeCache_.end()) { std::shared_ptr rdbStore = storeCache_[path].lock(); @@ -75,15 +80,19 @@ std::shared_ptr RdbStoreManager::GetRdbStore(const RdbStoreConfig &con return nullptr; } - if (SetSecurityLabel(config) != E_OK) { - LOG_ERROR("RdbHelper set security label fail."); - return nullptr; - } - - errCode = ProcessOpenCallback(*rdbStore, config, version, openCallback); - if (errCode != E_OK) { - LOG_ERROR("RdbHelper GetRdbStore ProcessOpenCallback fail"); - return nullptr; + if (config.GetRoleType() == OWNER) { + errCode = SetSecurityLabel(config); + if (errCode != E_OK) { + LOG_ERROR("fail, storeName:%{public}s security %{public}d errCode:%{public}d", config.GetName().c_str(), + config.GetSecurityLevel(), errCode); + return nullptr; + } + errCode = ProcessOpenCallback(*rdbStore, config, version, openCallback); + if (errCode != E_OK) { + LOG_ERROR("fail, storeName:%{public}s path:%{public}s ProcessOpenCallback errCode:%{public}d", + config.GetName().c_str(), config.GetPath().c_str(), errCode); + return nullptr; + } } storeCache_[path] = rdbStore; diff --git a/relational_store/frameworks/native/rdb/src/sqlite_connection.cpp b/relational_store/frameworks/native/rdb/src/sqlite_connection.cpp index 36e250403c1ca2bb9609e3e32b459c77323c2bce..e158cf310d45b95ecead153903c1467b6a3f1a2b 100644 --- a/relational_store/frameworks/native/rdb/src/sqlite_connection.cpp +++ b/relational_store/frameworks/native/rdb/src/sqlite_connection.cpp @@ -32,6 +32,7 @@ #include "logger.h" #include "raw_data_parser.h" #include "rdb_errno.h" +#include "relational_store_client.h" #include "sqlite_errno.h" #include "sqlite_global_config.h" #include "sqlite_utils.h" @@ -39,7 +40,6 @@ #include "directory_ex.h" #include "rdb_security_manager.h" #include "relational/relational_store_sqlite_ext.h" -#include "relational_store_client.h" #include "share_block.h" #include "shared_block_serializer_info.h" #endif @@ -47,7 +47,6 @@ namespace OHOS { namespace NativeRdb { using namespace OHOS::Rdb; - #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) // error status const int ERROR_STATUS = -1; @@ -81,22 +80,35 @@ SqliteConnection::SqliteConnection(bool isWriteConnection) stepStatement(nullptr), filePath(""), openFlags(0), - inTransaction_(false) + inTransaction_(false), + id_(-1) { } int SqliteConnection::GetDbPath(const RdbStoreConfig &config, std::string &dbPath) { + std::string path; + if (config.GetRoleType() == VISITOR) { + path = config.GetVisitorDir(); + } else { + path = config.GetPath(); + } + if (config.GetStorageMode() == StorageMode::MODE_MEMORY) { + if (config.GetRoleType() == VISITOR) { + LOG_ERROR("not support MODE_MEMORY, storeName:%{public}s, role:%{public}d", config.GetName().c_str(), + config.GetRoleType()); + return E_NOT_SUPPORT; + } dbPath = SqliteGlobalConfig::GetMemoryDbPath(); - } else if (config.GetPath().empty()) { + } else if (path.empty()) { LOG_ERROR("SqliteConnection GetDbPath input empty database path"); return E_EMPTY_FILE_NAME; - } else if (config.GetPath().front() != '/' && config.GetPath().at(1) != ':') { + } else if (path.front() != '/' && path.at(1) != ':') { LOG_ERROR("SqliteConnection GetDbPath input relative path"); return E_RELATIVE_PATH; } else { - dbPath = config.GetPath(); + dbPath = path; } return E_OK; } @@ -223,15 +235,17 @@ int SqliteConnection::Configure(const RdbStoreConfig &config, uint32_t retry, st return E_OK; } + if (config.GetRoleType() == VISITOR) { + return E_OK; + } + auto errCode = RegDefaultFunctions(dbHandle); if (errCode != E_OK) { return errCode; } SetBusyTimeout(DEFAULT_BUSY_TIMEOUT_MS); - if (errCode != E_OK) { - return errCode; - } + LimitPermission(dbPath); errCode = SetPersistWal(); @@ -279,6 +293,11 @@ SqliteConnection::~SqliteConnection() if (stepStatement != nullptr) { stepStatement->Finalize(); } + + if (hasClientObserver_) { + UnRegisterClientObserver(dbHandle); + } + int errCode = sqlite3_close_v2(dbHandle); if (errCode != SQLITE_OK) { LOG_ERROR("SqliteConnection ~SqliteConnection: could not close database err = %{public}d", errCode); @@ -577,6 +596,17 @@ bool SqliteConnection::IsWriteConnection() const return isWriteConnection; } +int32_t SqliteConnection::SetId(uint32_t id) +{ + id_ = id; + return E_OK; +} + +uint32_t SqliteConnection::GetId() const +{ + return id_; +} + int SqliteConnection::Prepare(const std::string &sql, bool &outIsReadOnly) { int errCode = statement.Prepare(dbHandle, sql); @@ -669,12 +699,11 @@ int SqliteConnection::ExecuteForLastInsertedRowId( errCode = statement.Step(); if (errCode == SQLITE_ROW) { - LOG_ERROR("SqliteConnection ExecuteForLastInsertedRowId : Queries can be performed using query or QuerySql " - "methods only"); + LOG_ERROR("failed: %{public}d. sql: %{public}s", errCode, SqliteUtils::Anonymous(sql).c_str()); statement.ResetStatementAndClearBindings(); return E_QUERY_IN_EXECUTE; } else if (errCode != SQLITE_DONE) { - LOG_ERROR("SqliteConnection ExecuteForLastInsertedRowId : failed %{public}d", errCode); + LOG_ERROR("failed: %{public}d. sql: %{public}s", errCode, SqliteUtils::Anonymous(sql).c_str()); statement.ResetStatementAndClearBindings(); return SQLiteError::ErrNo(errCode); } @@ -815,12 +844,14 @@ void LocalizedCollatorDestroy(UCollator *collator) { ucol_close(collator); } +#endif /** * The database locale. */ -int SqliteConnection::ConfigLocale(const std::string localeStr) +int SqliteConnection::ConfigLocale(const std::string& localeStr) { +#ifdef RDB_SUPPORT_ICU std::unique_lock lock(rdbMutex); UErrorCode status = U_ZERO_ERROR; UCollator *collator = ucol_open(localeStr.c_str(), &status); @@ -840,10 +871,9 @@ int SqliteConnection::ConfigLocale(const std::string localeStr) LOG_ERROR("SCreate collator in sqlite3 failed."); return err; } - +#endif return E_OK; } -#endif #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) /** @@ -853,23 +883,25 @@ int SqliteConnection::ExecuteForSharedBlock(int &rowNum, std::string sql, const AppDataFwk::SharedBlock *sharedBlock, int startPos, int requiredPos, bool isCountAllRows) { if (sharedBlock == nullptr) { - LOG_ERROR("ExecuteForSharedBlock:sharedBlock is null."); + LOG_ERROR("sharedBlock null."); return E_ERROR; } SqliteConnectionS connection(this->dbHandle, this->openFlags, this->filePath); int errCode = PrepareAndBind(sql, bindArgs); if (errCode != E_OK) { - LOG_ERROR("PrepareAndBind sql and bindArgs error = %{public}d ", errCode); + LOG_ERROR("error: %{public}d sql: %{public}s startPos: %{public}d requiredPos: %{public}d" + "isCountAllRows: %{public}d", errCode, SqliteUtils::Anonymous(sql).c_str(), + startPos, requiredPos, isCountAllRows); return errCode; } if (ClearSharedBlock(sharedBlock) == ERROR_STATUS) { - LOG_ERROR("ExecuteForSharedBlock:sharedBlock is null."); + LOG_ERROR("failed. %{public}d. sql: %{public}s.", errCode, SqliteUtils::Anonymous(sql).c_str()); return E_ERROR; } sqlite3_stmt *tempSqlite3St = statement.GetSql3Stmt(); int columnNum = sqlite3_column_count(tempSqlite3St); if (SharedBlockSetColumnNum(sharedBlock, columnNum) == ERROR_STATUS) { - LOG_ERROR("ExecuteForSharedBlock:sharedBlock is null."); + LOG_ERROR("failed.columnNum: %{public}d,sql: %{public}s", columnNum, SqliteUtils::Anonymous(sql).c_str()); return E_ERROR; } @@ -887,7 +919,7 @@ int SqliteConnection::ExecuteForSharedBlock(int &rowNum, std::string sql, const } if (!ResetStatement(&sharedBlockInfo)) { - LOG_ERROR("ExecuteForSharedBlock:ResetStatement Failed."); + LOG_ERROR("err.startPos:%{public}d,addedRows:%{public}d", sharedBlockInfo.startPos, sharedBlockInfo.addedRows); return E_ERROR; } sharedBlock->SetStartPos(sharedBlockInfo.startPos); @@ -910,6 +942,7 @@ int SqliteConnection::CleanDirtyData(const std::string &table, uint64_t cursor) int SqliteConnection::RegisterCallBackObserver(const DataChangeCallback &clientChangedData) { if (isWriteConnection && clientChangedData != nullptr) { + hasClientObserver_ = true; int32_t status = RegisterClientObserver(dbHandle, clientChangedData); if (status != E_OK) { LOG_ERROR("RegisterClientObserver error, status:%{public}d", status); @@ -932,6 +965,10 @@ bool SqliteConnection::IsInTransaction() int SqliteConnection::TryCheckPoint() { + if (!isWriteConnection) { + return E_NOT_SUPPORT; + } + std::string walName = sqlite3_filename_wal(sqlite3_db_filename(dbHandle, "main")); int fileSize = SqliteUtils::GetFileSize(walName); if (fileSize <= GlobalExpr::DB_WAL_SIZE_LIMIT_MIN) { diff --git a/relational_store/frameworks/native/rdb/src/sqlite_connection_pool.cpp b/relational_store/frameworks/native/rdb/src/sqlite_connection_pool.cpp index dfb5a068f68518f4cddabf145084c2739fead3d6..9575cdd40cd3d954151d3a7c5a99e1047f75d33a 100644 --- a/relational_store/frameworks/native/rdb/src/sqlite_connection_pool.cpp +++ b/relational_store/frameworks/native/rdb/src/sqlite_connection_pool.cpp @@ -16,12 +16,12 @@ #include "sqlite_connection_pool.h" #include - #include #include #include #include #include +#include #include #include "logger.h" @@ -33,57 +33,52 @@ namespace OHOS { namespace NativeRdb { using namespace OHOS::Rdb; -constexpr std::chrono::seconds TRANSACTION_TIMEOUT(2); +constexpr int32_t TRANSACTION_TIMEOUT(2); -SqliteConnectionPool *SqliteConnectionPool::Create(const RdbStoreConfig &storeConfig, int &errCode) +std::shared_ptr SqliteConnectionPool::Create(const RdbStoreConfig &storeConfig, int &errCode) { - auto pool = new (std::nothrow) SqliteConnectionPool(storeConfig); + std::shared_ptr pool(new (std::nothrow) SqliteConnectionPool(storeConfig)); if (pool == nullptr) { LOG_ERROR("SqliteConnectionPool::Create new failed, pool is nullptr"); return nullptr; } errCode = pool->Init(); if (errCode != E_OK) { - delete pool; return nullptr; } return pool; } -SqliteConnectionPool::SqliteConnectionPool(const RdbStoreConfig &storeConfig) - : config_(storeConfig), writeConnection_(nullptr), writeConnectionUsed_(true), readConnections_(), - readConnectionCount_(0), idleReadConnectionCount_(0), transactionStack_(), transactionUsed_(false) +SqliteConnectionPool::SqliteConnectionPool(const RdbStoreConfig& storeConfig) + : config_(storeConfig), writers_(), readers_(), transactionStack_(), transactionUsed_(false) { } int SqliteConnectionPool::Init() { - int errCode = E_OK; - writeConnection_ = SqliteConnection::Open(config_, true, errCode); - if (writeConnection_ == nullptr) { - return errCode; + if (config_.GetRoleType() == OWNER) { + // write connect count is 1 + auto errCode = writers_.Initialize(1, config_.GetWriteTime(), [this]() { + int32_t errCode = E_OK; + auto conn = SqliteConnection::Open(config_, true, errCode); + return std::pair{ errCode, conn }; + }); + if (errCode != E_OK) { + return errCode; + } } - InitReadConnectionCount(); - + maxReader_ = GetMaxReaders(); // max read connect count is 64 - if (readConnectionCount_ > 64) { + if (maxReader_ > 64) { return E_ARGS_READ_CON_OVERLOAD; } - for (int i = 0; i < readConnectionCount_; i++) { - auto connection = SqliteConnection::Open(config_, false, errCode); - if (connection == nullptr) { - CloseAllConnections(); - return errCode; - } - readConnections_.push_back(connection); - } - writeConnectionUsed_ = false; - idleReadConnectionCount_ = readConnectionCount_; - writeTimeout_ = std::chrono::seconds(config_.GetWriteTime()); - readTimeout_ = std::chrono::seconds(config_.GetReadTime()); - return E_OK; + return readers_.Initialize(maxReader_, config_.GetReadTime(), [this]() { + int32_t errCode = E_OK; + auto conn = SqliteConnection::Open(config_, false, errCode); + return std::pair{ errCode, conn }; + }); } SqliteConnectionPool::~SqliteConnectionPool() @@ -91,69 +86,75 @@ SqliteConnectionPool::~SqliteConnectionPool() CloseAllConnections(); } -void SqliteConnectionPool::InitReadConnectionCount() +int32_t SqliteConnectionPool::GetMaxReaders() { - if (config_.GetStorageMode() == StorageMode::MODE_MEMORY) { - readConnectionCount_ = 0; - } else if (config_.GetJournalMode() == "WAL") { - readConnectionCount_ = config_.GetReadConSize(); + if (config_.GetStorageMode() != StorageMode::MODE_MEMORY && config_.GetJournalMode() == "WAL") { + return config_.GetReadConSize(); } else { - readConnectionCount_ = 0; + return 0; } } void SqliteConnectionPool::CloseAllConnections() { - writeConnection_ = nullptr; - writeConnectionUsed_ = true; - - for (auto &item : readConnections_) { - item = nullptr; - } - readConnections_.clear(); - idleReadConnectionCount_ = 0; + writers_.Clear(); + readers_.Clear(); } std::shared_ptr SqliteConnectionPool::AcquireConnection(bool isReadOnly) { - if (isReadOnly && readConnectionCount_ != 0) { - return AcquireReadConnection(); - } else { - return AcquireWriteConnection(); + Container *container = (isReadOnly && maxReader_ != 0) ? &readers_ : &writers_; + auto node = container->Acquire(); + if (node == nullptr) { + const char *header = (isReadOnly && maxReader_ != 0) ? "readers_" : "writers_"; + container->Dump(header); + return nullptr; } + auto conn = node->GetConnect(); + if (conn == nullptr) { + return nullptr; + } + return std::shared_ptr(conn.get(), [pool = weak_from_this(), node](SqliteConnection*) { + auto realPool = pool.lock(); + if (realPool == nullptr) { + return; + } + realPool->ReleaseNode(node); + }); } -void SqliteConnectionPool::ReleaseConnection(std::shared_ptr connection) +std::shared_ptr SqliteConnectionPool::AcquireByID(int32_t id) { - if (connection == nullptr) { - return; + Container *container = &readers_; + auto node = container->AcquireById(id); + if (node == nullptr) { + container->Dump("readers_"); + return nullptr; } - connection->DesFinalize(); - if (connection == writeConnection_) { - ReleaseWriteConnection(); - connection->TryCheckPoint(); - } else { - ReleaseReadConnection(connection); + auto conn = node->GetConnect(true); + if (conn == nullptr) { + return nullptr; } + return conn; } -std::shared_ptr SqliteConnectionPool::AcquireWriteConnection() +void SqliteConnectionPool::ReleaseNode(std::shared_ptr node) { - std::unique_lock lock(writeMutex_); - if (writeCondition_.wait_for(lock, writeTimeout_, [this] { - return !writeConnectionUsed_; - })) { - writeConnectionUsed_ = true; - return writeConnection_; + if (node == nullptr) { + return; + } + node->Unused(); + if (node->IsWriter()) { + writers_.Release(node); + } else { + readers_.Release(node); } - LOG_WARN("writeConnection_ is %{public}d", writeConnectionUsed_); - return nullptr; } int SqliteConnectionPool::AcquireTransaction() { std::unique_lock lock(transMutex_); - if (transCondition_.wait_for(lock, TRANSACTION_TIMEOUT, [this] { + if (transCondition_.wait_for(lock, std::chrono::seconds(TRANSACTION_TIMEOUT), [this] { return !transactionUsed_; })) { transactionUsed_ = true; @@ -172,125 +173,43 @@ void SqliteConnectionPool::ReleaseTransaction() transCondition_.notify_one(); } -void SqliteConnectionPool::ReleaseWriteConnection() +int SqliteConnectionPool::RestartReaders() { - { - std::unique_lock lock(writeMutex_); - writeConnectionUsed_ = false; - } - writeCondition_.notify_one(); + readers_.Clear(); + return readers_.Initialize(maxReader_, config_.GetReadTime(), [this]() { + int32_t errCode = E_OK; + auto conn = SqliteConnection::Open(config_, false, errCode); + return std::pair{ errCode, conn }; + }); } -/** - * get last element from connectionPool - * @return - */ -std::shared_ptr SqliteConnectionPool::AcquireReadConnection() -{ - std::unique_lock lock(readMutex_); - if (readCondition_.wait_for(lock, readTimeout_, [this] { - return idleReadConnectionCount_ > 0; - })) { - auto connection = readConnections_.back(); - readConnections_.pop_back(); - idleReadConnectionCount_--; - return connection; - } - LOG_WARN("readConnectionCount_ is %{public}d, idleReadConnectionCount_ is %{public}d", readConnectionCount_, - idleReadConnectionCount_); - return nullptr; -} - -/** - * push connection back to last of connectionPool - * @param connection - */ -void SqliteConnectionPool::ReleaseReadConnection(std::shared_ptr connection) -{ - { - std::unique_lock lock(readMutex_); - readConnections_.push_back(connection); - idleReadConnectionCount_++; - } - readCondition_.notify_one(); -} - -int SqliteConnectionPool::InnerReOpenReadConnections() -{ - int errCode = E_OK; - for (auto &item : readConnections_) { - item = nullptr; - } - readConnections_.clear(); - - for (int i = 0; i < readConnectionCount_; i++) { - auto connection = SqliteConnection::Open(config_, false, errCode); - if (connection == nullptr) { - CloseAllConnections(); - return errCode; - } - readConnections_.push_back(connection); - } - - return errCode; -} - -int SqliteConnectionPool::ReOpenAvailableReadConnections() -{ - std::unique_lock lock(readMutex_); - return InnerReOpenReadConnections(); -} - -#ifdef RDB_SUPPORT_ICU /** * The database locale. */ -int SqliteConnectionPool::ConfigLocale(const std::string localeStr) +int SqliteConnectionPool::ConfigLocale(const std::string &localeStr) { - std::unique_lock lock(rdbMutex_); - if (idleReadConnectionCount_ != readConnectionCount_) { - return E_NO_ROW_IN_QUERY; - } - - for (int i = 0; i < idleReadConnectionCount_; i++) { - auto connection = readConnections_[i]; - if (connection == nullptr) { - LOG_ERROR("Read Connection is null."); - return E_ERROR; - } - connection->ConfigLocale(localeStr); - } - - if (writeConnection_ == nullptr) { - LOG_ERROR("Write Connection is null."); - return E_ERROR; - } else { - writeConnection_->ConfigLocale(localeStr); + auto errCode = readers_.ConfigLocale(localeStr); + if (errCode != E_OK) { + return errCode; } - - return E_OK; + return writers_.ConfigLocale(localeStr); } -#endif /** * Rename the backed up database. */ -int SqliteConnectionPool::ChangeDbFileForRestore(const std::string newPath, const std::string backupPath, +int SqliteConnectionPool::ChangeDbFileForRestore(const std::string &newPath, const std::string &backupPath, const std::vector &newKey) { - if (writeConnectionUsed_ == true || idleReadConnectionCount_ != readConnectionCount_) { + if (!writers_.IsFull() || !readers_.IsFull()) { LOG_ERROR("Connection pool is busy now!"); return E_ERROR; } - LOG_ERROR("restore."); CloseAllConnections(); std::string currentPath = config_.GetPath(); - bool ret = SqliteUtils::DeleteFile(currentPath); - if (ret == false) { - LOG_ERROR("DeleteFile error"); - } + SqliteUtils::DeleteFile(currentPath); SqliteUtils::DeleteFile(currentPath + "-shm"); SqliteUtils::DeleteFile(currentPath + "-wal"); SqliteUtils::DeleteFile(currentPath + "-journal"); @@ -320,5 +239,167 @@ std::mutex &SqliteConnectionPool::GetTransactionStackMutex() { return transactionStackMutex_; } + +SqliteConnectionPool::ConnNode::ConnNode(std::shared_ptr conn) : connect_(std::move(conn)) {} + +std::shared_ptr SqliteConnectionPool::ConnNode::GetConnect(bool justHold) +{ + if (!justHold) { + tid_ = gettid(); + time_ = std::chrono::steady_clock::now(); + } + return connect_; +} + +int64_t SqliteConnectionPool::ConnNode::GetUsingTime() const +{ + auto time = std::chrono::steady_clock::now() - time_; + return std::chrono::duration_cast(time).count(); +} + +void SqliteConnectionPool::ConnNode::Unused() +{ + tid_ = 0; + time_ = std::chrono::steady_clock::now(); + if (connect_ != nullptr) { + connect_->DesFinalize(); + connect_->TryCheckPoint(); + } +} + +bool SqliteConnectionPool::ConnNode::IsWriter() const +{ + if (connect_ != nullptr) { + return connect_->IsWriteConnection(); + } + return false; +} + +int32_t SqliteConnectionPool::Container::Initialize(int32_t max, int32_t timeout, Creator creator) +{ + std::unique_lock lock(mutex_); + for (int i = 0; i < max; ++i) { + auto [error, conn] = creator(); + if (conn == nullptr) { + nodes_.clear(); + details_.clear(); + return error; + } + auto node = std::make_shared(conn); + node->id_ = right_++; + conn->SetId(node->id_); + nodes_.push_back(node); + details_.push_back(node); + } + max_ = max; + count_ = max; + timeout_ = std::chrono::seconds(timeout); + return E_OK; +} + +int32_t SqliteConnectionPool::Container::ConfigLocale(const std::string& locale) +{ + std::unique_lock lock(mutex_); + if (max_ != count_) { + return E_NO_ROW_IN_QUERY; + } + for (auto it = details_.begin(); it != details_.end();) { + auto conn = it->lock(); + if (conn == nullptr || conn->connect_ == nullptr) { + it = details_.erase(it); + continue; + } + conn->connect_->ConfigLocale(locale); + } + return E_OK; +} + +std::shared_ptr SqliteConnectionPool::Container::Acquire() +{ + std::unique_lock lock(mutex_); + if (cond_.wait_for(lock, timeout_, [this] { return count_ > 0; })) { + auto node = nodes_.back(); + nodes_.pop_back(); + count_--; + return node; + } + return nullptr; +} + +std::shared_ptr SqliteConnectionPool::Container::AcquireById(int32_t id) +{ + for (auto& detail : details_) { + auto node = detail.lock(); + if (node == nullptr) { + continue; + } + if (node->id_ == id) { + return node; + } + } + return nullptr; +} + +int32_t SqliteConnectionPool::Container::Release(std::shared_ptr node) +{ + { + std::unique_lock lock(mutex_); + if (node->id_ < left_ || node->id_ >= right_) { + return E_OK; + } + nodes_.push_back(node); + count_++; + } + cond_.notify_one(); + return E_OK; +} + +int32_t SqliteConnectionPool::Container::Clear() +{ + std::list> nodes; + std::list> details; + { + std::unique_lock lock(mutex_); + nodes = std::move(nodes_); + details = std::move(details_); + max_ = 0; + count_ = 0; + left_ = right_; + } + nodes.clear(); + details.clear(); + return 0; +} + +bool SqliteConnectionPool::Container::IsFull() +{ + std::unique_lock lock(mutex_); + return max_ == count_; +} + +int32_t SqliteConnectionPool::Container::Dump(const char *header) +{ + std::string info; + for (auto& detail : details_) { + auto node = detail.lock(); + if (node == nullptr) { + continue; + } + info.append("<") + .append(std::to_string(node->id_)) + .append(",") + .append(std::to_string(node->tid_)) + .append(",") + .append(std::to_string(node->GetUsingTime())) + .append(">"); + // 256 represent that limit to info length + if (info.size() > 256) { + LOG_WARN("%{public}s: %{public}s", header, info.c_str()); + info.clear(); + } + } + LOG_WARN("%{public}s: %{public}s", header, info.c_str()); + return 0; +} } // namespace NativeRdb } // namespace OHOS 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 5ca9e793710ae01c6de9f9f296efffafb4154576..f676aca3815b3a9173094fa4ef69c5bd739020da 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 @@ -25,10 +25,10 @@ namespace OHOS { namespace NativeRdb { using namespace OHOS::Rdb; -SqliteSharedResultSet::SqliteSharedResultSet(std::shared_ptr store, SqliteConnectionPool *connectionPool, - std::string path, std::string sql, const std::vector &bindArgs) - : AbsSharedResultSet(path), store_(store), connectionPool_(connectionPool), resultSetBlockCapacity_(0), - rowNum_(NO_COUNT), qrySql_(sql), bindArgs_(std::move(bindArgs)), isOnlyFillResultSetBlock_(false) +SqliteSharedResultSet::SqliteSharedResultSet(std::shared_ptr connectionPool, std::string path, + std::string sql, const std::vector& bindArgs) + : AbsSharedResultSet(path), connectionPool_(connectionPool), resultSetBlockCapacity_(0), rowNum_(NO_COUNT), + qrySql_(sql), bindArgs_(std::move(bindArgs)), isOnlyFillResultSetBlock_(false) { } @@ -63,8 +63,12 @@ int SqliteSharedResultSet::GetAllColumnNames(std::vector &columnNam if (isClosed_) { return E_STEP_RESULT_CLOSED; } + auto pool = connectionPool_; + if (pool == nullptr) { + return E_STEP_RESULT_CLOSED; + } - auto connection = connectionPool_->AcquireConnection(true); + auto connection = pool->AcquireConnection(true); if (connection == nullptr) { return E_CON_OVER_LIMIT; } @@ -72,24 +76,21 @@ int SqliteSharedResultSet::GetAllColumnNames(std::vector &columnNam int errCode = E_OK; std::shared_ptr sqliteStatement = PrepareStep(connection, errCode); if (sqliteStatement == nullptr) { - connectionPool_->ReleaseConnection(connection); return errCode; } int columnCount = 0; // Get the total number of columns errCode = sqliteStatement->GetColumnCount(columnCount); - if (errCode) { - connectionPool_->ReleaseConnection(connection); + if (errCode != E_OK) { return errCode; } - + std::lock_guard lock(columnNamesLock_); for (int i = 0; i < columnCount; i++) { std::string columnName; errCode = sqliteStatement->GetColumnName(i, columnName); - if (errCode) { - connectionPool_->ReleaseConnection(connection); + if (errCode != E_OK) { columnNames_.clear(); return errCode; } @@ -99,8 +100,6 @@ int SqliteSharedResultSet::GetAllColumnNames(std::vector &columnNam columnNames = columnNames_; columnCount_ = static_cast(columnNames_.size()); connection->EndStepQuery(); - connectionPool_->ReleaseConnection(connection); - return E_OK; } @@ -123,7 +122,6 @@ int SqliteSharedResultSet::GetRowCount(int &count) int SqliteSharedResultSet::Close() { AbsSharedResultSet::Close(); - store_.reset(); auto qrySql = std::move(qrySql_); auto bindArgs = std::move(bindArgs_); auto columnNames = std::move(columnNames_); @@ -154,21 +152,23 @@ int SqliteSharedResultSet::PickFillBlockStartPosition(int resultSetPosition, int void SqliteSharedResultSet::FillSharedBlock(int requiredPos) { ClearBlock(); - auto connection = connectionPool_->AcquireConnection(true); + auto pool = connectionPool_; + if (pool == nullptr) { + return; + } + auto connection = pool->AcquireConnection(true); if (connection == nullptr) { return; } AppDataFwk::SharedBlock *sharedBlock = GetBlock(); if (sharedBlock == nullptr) { LOG_ERROR("FillSharedBlock GetBlock failed."); - connectionPool_->ReleaseConnection(connection); return; } if (rowNum_ == NO_COUNT) { auto errCode = connection->ExecuteForSharedBlock(rowNum_, qrySql_, bindArgs_, sharedBlock, requiredPos, requiredPos, true); if (errCode != E_OK) { - connectionPool_->ReleaseConnection(connection); return; } resultSetBlockCapacity_ = static_cast(sharedBlock->GetRowNum()); @@ -183,7 +183,6 @@ void SqliteSharedResultSet::FillSharedBlock(int requiredPos) blockRowNum, requiredPos, sharedBlock->GetStartPos(), sharedBlock->GetLastPos(), sharedBlock->GetBlockPos()); } - connectionPool_->ReleaseConnection(connection); } void SqliteSharedResultSet::SetBlock(AppDataFwk::SharedBlock *block) diff --git a/relational_store/frameworks/native/rdb/src/sqlite_utils.cpp b/relational_store/frameworks/native/rdb/src/sqlite_utils.cpp index 135d6afa2847c339ab5c1ae2726aeb49274b74b7..887b40b22897b1402b2eb1c251db6e0836cce5c9 100644 --- a/relational_store/frameworks/native/rdb/src/sqlite_utils.cpp +++ b/relational_store/frameworks/native/rdb/src/sqlite_utils.cpp @@ -15,14 +15,14 @@ #include "sqlite_utils.h" -#include -#include -#include - #include #include #include #include +#include +#include +#include +#include #include "logger.h" #include "rdb_errno.h" @@ -35,56 +35,31 @@ namespace OHOS { namespace NativeRdb { using namespace OHOS::Rdb; -const int SqliteUtils::STATEMENT_SELECT = 1; -const int SqliteUtils::STATEMENT_UPDATE = 2; -const int SqliteUtils::STATEMENT_ATTACH = 3; -const int SqliteUtils::STATEMENT_DETACH = 4; -const int SqliteUtils::STATEMENT_BEGIN = 5; -const int SqliteUtils::STATEMENT_COMMIT = 6; -const int SqliteUtils::STATEMENT_ROLLBACK = 7; -const int SqliteUtils::STATEMENT_PRAGMA = 8; -const int SqliteUtils::STATEMENT_DDL = 9; -const int SqliteUtils::STATEMENT_INSERT = 10; -const int SqliteUtils::STATEMENT_OTHER = 99; - constexpr int32_t HEAD_SIZE = 3; constexpr int32_t END_SIZE = 3; constexpr int32_t MIN_SIZE = HEAD_SIZE + END_SIZE + 3; constexpr const char *REPLACE_CHAIN = "***"; constexpr const char *DEFAULT_ANONYMOUS = "******"; -const std::map SqliteUtils::SQL_TYPE_MAP = { - { "SEL", SqliteUtils::STATEMENT_SELECT }, - { "INS", SqliteUtils::STATEMENT_INSERT }, - { "UPD", SqliteUtils::STATEMENT_UPDATE }, - { "REP", SqliteUtils::STATEMENT_UPDATE }, - { "DEL", SqliteUtils::STATEMENT_UPDATE }, - { "ATT", SqliteUtils::STATEMENT_ATTACH }, - { "DET", SqliteUtils::STATEMENT_DETACH }, - { "COM", SqliteUtils::STATEMENT_COMMIT }, - { "END", SqliteUtils::STATEMENT_COMMIT }, - { "ROL", SqliteUtils::STATEMENT_ROLLBACK }, - { "BEG", SqliteUtils::STATEMENT_BEGIN }, - { "PRA", SqliteUtils::STATEMENT_PRAGMA }, - { "CRE", SqliteUtils::STATEMENT_DDL }, - { "DRO", SqliteUtils::STATEMENT_DDL }, - { "ALT", SqliteUtils::STATEMENT_DDL }, -}; +constexpr SqliteUtils::SqlType SqliteUtils::SQL_TYPE_MAP[]; +constexpr const char *SqliteUtils::ON_CONFLICT_CLAUSE[]; int SqliteUtils::GetSqlStatementType(const std::string &sql) { - std::string sqlStr = sql; /* the sql string length less than 3 can not be any type sql */ - if (sqlStr.length() < 3) { + if (sql.length() < 3) { return STATEMENT_OTHER; } /* analyze the sql type through first 3 character */ - std::string prefixSql = StrToUpper(sqlStr.substr(0, 3)); - auto iter = SQL_TYPE_MAP.find(prefixSql); - if (iter != SQL_TYPE_MAP.end()) { - return iter->second; + std::string prefixSql = StrToUpper(sql.substr(0, 3)); + SqlType type = { prefixSql.c_str(), STATEMENT_OTHER}; + auto it = std::lower_bound(SQL_TYPE_MAP, SQL_TYPE_MAP + TYPE_SIZE, type, + [](const SqlType& first, const SqlType& second) { + return strcmp(first.sql, second.sql) < 0; + }); + if (it < SQL_TYPE_MAP + TYPE_SIZE) { + return it->type; } - return STATEMENT_OTHER; } @@ -119,23 +94,20 @@ bool SqliteUtils::IsSpecial(int sqlType) return false; } -const std::string SqliteUtils::ON_CONFLICT_CLAUSE[] = { "", " OR ROLLBACK", " OR ABORT", " OR FAIL", " OR IGNORE", - " OR REPLACE" }; -int SqliteUtils::GetConflictClause(int conflictResolution, std::string &conflictClause) +const char *SqliteUtils::GetConflictClause(int conflictResolution) { if (conflictResolution < 0 || conflictResolution >= CONFLICT_CLAUSE_COUNT) { - return E_INVALID_CONFLICT_FLAG; + return nullptr; } - conflictClause = ON_CONFLICT_CLAUSE[conflictResolution]; - return E_OK; + return ON_CONFLICT_CLAUSE[conflictResolution]; } -bool SqliteUtils::DeleteFile(const std::string filePath) +bool SqliteUtils::DeleteFile(const std::string &filePath) { return remove(filePath.c_str()) == 0; } -int SqliteUtils::RenameFile(const std::string srcFile, const std::string destFile) +int SqliteUtils::RenameFile(const std::string &srcFile, const std::string &destFile) { return rename(srcFile.c_str(), destFile.c_str()); } @@ -153,7 +125,7 @@ std::string SqliteUtils::Anonymous(const std::string &srcFile) return (srcFile.substr(0, HEAD_SIZE) + REPLACE_CHAIN + srcFile.substr(srcFile.length() - END_SIZE, END_SIZE)); } -int SqliteUtils::GetFileSize(const std::string fileName) +int SqliteUtils::GetFileSize(const std::string &fileName) { if (fileName.empty() || access(fileName.c_str(), F_OK) != 0) { return 0; 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 9b2e359d036777bcf3426b335f4a8fc1afd878c8..fe421e7d6844fd2a1b9d021cc43c4bfe0417de69 100644 --- a/relational_store/frameworks/native/rdb/src/step_result_set.cpp +++ b/relational_store/frameworks/native/rdb/src/step_result_set.cpp @@ -29,10 +29,10 @@ namespace OHOS { namespace NativeRdb { using namespace OHOS::Rdb; -StepResultSet::StepResultSet(std::shared_ptr rdb_, SqliteConnectionPool *connectionPool, - const std::string &sql_, const std::vector &selectionArgs) - : rdb_(rdb_), sqliteStatement_(nullptr), args_(std::move(selectionArgs)), sql_(sql_), - connectionPool_(connectionPool), rowCount_(INIT_POS), isAfterLast_(false) +StepResultSet::StepResultSet(std::shared_ptr connectionPool, const std::string& sql_, + const std::vector& selectionArgs) + : sqliteStatement_(nullptr), args_(std::move(selectionArgs)), sql_(sql_), + connectionPool_(std::move(connectionPool)), rowCount_(INIT_POS), isAfterLast_(false), connId_(INIT_POS) { int errCode = PrepareStep(); if (errCode) { @@ -43,7 +43,6 @@ StepResultSet::StepResultSet(std::shared_ptr rdb_, SqliteConnectio StepResultSet::~StepResultSet() { Close(); - rdb_.reset(); } int StepResultSet::GetAllColumnNames(std::vector &columnNames) @@ -63,9 +62,13 @@ int StepResultSet::GetAllColumnNames(std::vector &columnNames) LOG_ERROR("get all column names Step ret %{public}d", errCode); return errCode; } - + auto [statement, connection] = GetStatement(); + if (statement == nullptr) { + LOG_ERROR("resultSet closed"); + return E_STEP_RESULT_CLOSED; + } int columnCount = 0; - errCode = sqliteStatement_->GetColumnCount(columnCount); + errCode = statement->GetColumnCount(columnCount); if (errCode) { LOG_ERROR("GetColumnCount ret %{public}d", errCode); return errCode; @@ -74,7 +77,7 @@ int StepResultSet::GetAllColumnNames(std::vector &columnNames) columnNames.clear(); for (int i = 0; i < columnCount; i++) { std::string columnName; - errCode = sqliteStatement_->GetColumnName(i, columnName); + errCode = statement->GetColumnName(i, columnName); if (errCode) { columnNames.clear(); LOG_ERROR("GetColumnName ret %{public}d", errCode); @@ -88,7 +91,8 @@ int StepResultSet::GetAllColumnNames(std::vector &columnNames) int StepResultSet::GetColumnType(int columnIndex, ColumnType &columnType) { - if (isClosed_) { + auto [statement, conn] = GetStatement(); + if (statement == nullptr) { LOG_ERROR("resultSet closed"); return E_STEP_RESULT_CLOSED; } @@ -97,12 +101,9 @@ int StepResultSet::GetColumnType(int columnIndex, ColumnType &columnType) LOG_ERROR("query not executed."); return E_STEP_RESULT_QUERY_NOT_EXECUTED; } - if (sqliteStatement_ == nullptr) { - LOG_ERROR("sqliteStatement_ init failed!"); - return E_CON_OVER_LIMIT; - } + int sqliteType; - int errCode = sqliteStatement_->GetColumnType(columnIndex, sqliteType); + int errCode = statement->GetColumnType(columnIndex, sqliteType); if (errCode) { LOG_ERROR("GetColumnType ret %{public}d", errCode); return errCode; @@ -198,8 +199,14 @@ int StepResultSet::GoToNextRow() return errCode; } + auto [statement, conn] = GetStatement(); + if (statement == nullptr) { + LOG_ERROR("resultSet closed"); + return E_STEP_RESULT_CLOSED; + } + int retryCount = 0; - errCode = sqliteStatement_->Step(); + errCode = statement->Step(); while (errCode == SQLITE_LOCKED || errCode == SQLITE_BUSY) { // The table is locked, retry @@ -209,7 +216,7 @@ int StepResultSet::GoToNextRow() } else { // Sleep to give the thread holding the lock a chance to finish usleep(STEP_QUERY_RETRY_INTERVAL); - errCode = sqliteStatement_->Step(); + errCode = statement->Step(); retryCount++; } } @@ -236,9 +243,9 @@ int StepResultSet::Close() if (isClosed_) { return E_OK; } - rdb_.reset(); auto args = std::move(args_); - sqliteStatement_.reset(); + sqliteStatement_ = nullptr; + connId_ = -1; auto columnNames = std::move(columnNames_); isClosed_ = true; return FinishStep(); @@ -258,24 +265,31 @@ int StepResultSet::PrepareStep() return E_EXECUTE_IN_STEP_QUERY; } - auto connection = connectionPool_->AcquireConnection(true); + auto pool = connectionPool_; + if (pool == nullptr) { + return E_STEP_RESULT_CLOSED; + } + + auto connection = pool->AcquireConnection(true); if (connection == nullptr) { LOG_ERROR("connectionPool_ AcquireConnection failed!"); return E_CON_OVER_LIMIT; } - sqliteStatement_ = SqliteStatement::CreateStatement(connection, sql_); - connectionPool_->ReleaseConnection(connection); - if (sqliteStatement_ == nullptr) { + auto statement = SqliteStatement::CreateStatement(connection, sql_); + if (statement == nullptr) { return E_STATEMENT_NOT_PREPARED; } - int errCode = sqliteStatement_->BindArguments(args_); + int errCode = statement->BindArguments(args_); if (errCode != E_OK) { LOG_ERROR("Bind arg faild! Ret is %{public}d", errCode); - sqliteStatement_->ResetStatementAndClearBindings(); - sqliteStatement_ = nullptr; + statement->ResetStatementAndClearBindings(); + statement = nullptr; return errCode; } + sqliteStatement_ = std::move(statement); + connId_ = connection->GetId(); + conn_ = pool->AcquireByID(connection->GetId()); return E_OK; } @@ -284,9 +298,13 @@ int StepResultSet::PrepareStep() */ int StepResultSet::FinishStep() { - if (sqliteStatement_ != nullptr) { - sqliteStatement_->ResetStatementAndClearBindings(); + auto [statement, connection] = GetStatement(); + if (statement != nullptr) { + statement->ResetStatementAndClearBindings(); sqliteStatement_ = nullptr; + conn_ = nullptr; + connId_ = -1; + connection = nullptr; } rowPos_ = INIT_POS; return E_OK; @@ -331,20 +349,23 @@ int StepResultSet::IsAtFirstRow(bool &result) const int StepResultSet::GetBlob(int columnIndex, std::vector &blob) { - if (isClosed_) { + auto [statement, conn] = GetStatement(); + if (statement == nullptr) { + LOG_ERROR("resultSet closed"); return E_STEP_RESULT_CLOSED; } if (rowPos_ == INIT_POS) { LOG_ERROR("query not executed."); return E_STEP_RESULT_QUERY_NOT_EXECUTED; } - - return sqliteStatement_->GetColumnBlob(columnIndex, blob); + return statement->GetColumnBlob(columnIndex, blob); } int StepResultSet::GetString(int columnIndex, std::string &value) { - if (isClosed_) { + auto [statement, conn] = GetStatement(); + if (statement == nullptr) { + LOG_ERROR("resultSet closed"); return E_STEP_RESULT_CLOSED; } @@ -352,7 +373,7 @@ int StepResultSet::GetString(int columnIndex, std::string &value) return E_STEP_RESULT_QUERY_NOT_EXECUTED; } - int errCode = sqliteStatement_->GetColumnString(columnIndex, value); + int errCode = statement->GetColumnString(columnIndex, value); if (errCode != E_OK) { LOG_ERROR("ret is %{public}d", errCode); return errCode; @@ -362,7 +383,9 @@ int StepResultSet::GetString(int columnIndex, std::string &value) int StepResultSet::GetInt(int columnIndex, int &value) { - if (isClosed_) { + auto [statement, conn] = GetStatement(); + if (statement == nullptr) { + LOG_ERROR("resultSet closed"); return E_STEP_RESULT_CLOSED; } if (rowPos_ == INIT_POS) { @@ -370,7 +393,7 @@ int StepResultSet::GetInt(int columnIndex, int &value) } int64_t columnValue; - int errCode = sqliteStatement_->GetColumnLong(columnIndex, columnValue); + int errCode = statement->GetColumnLong(columnIndex, columnValue); if (errCode != E_OK) { LOG_ERROR("ret is %{public}d", errCode); return errCode; @@ -381,13 +404,15 @@ int StepResultSet::GetInt(int columnIndex, int &value) int StepResultSet::GetLong(int columnIndex, int64_t &value) { - if (isClosed_) { + auto [statement, conn] = GetStatement(); + if (statement == nullptr) { + LOG_ERROR("resultSet closed"); return E_STEP_RESULT_CLOSED; } if (rowPos_ == INIT_POS) { return E_STEP_RESULT_QUERY_NOT_EXECUTED; } - int errCode = sqliteStatement_->GetColumnLong(columnIndex, value); + int errCode = statement->GetColumnLong(columnIndex, value); if (errCode != E_OK) { LOG_ERROR("ret is %{public}d", errCode); return errCode; @@ -397,13 +422,15 @@ int StepResultSet::GetLong(int columnIndex, int64_t &value) int StepResultSet::GetDouble(int columnIndex, double &value) { - if (isClosed_) { + auto [statement, conn] = GetStatement(); + if (statement == nullptr) { + LOG_ERROR("resultSet closed"); return E_STEP_RESULT_CLOSED; } if (rowPos_ == INIT_POS) { return E_STEP_RESULT_QUERY_NOT_EXECUTED; } - int errCode = sqliteStatement_->GetColumnDouble(columnIndex, value); + int errCode = statement->GetColumnDouble(columnIndex, value); if (errCode != E_OK) { LOG_ERROR("ret is %{public}d", errCode); return errCode; @@ -428,14 +455,16 @@ int StepResultSet::Get(int32_t col, ValueObject &value) int StepResultSet::GetModifyTime(std::string &modifyTime) { - if (isClosed_) { + auto [statement, conn] = GetStatement(); + if (statement == nullptr) { + LOG_ERROR("resultSet closed"); return E_STEP_RESULT_CLOSED; } if (rowPos_ == INIT_POS) { return E_STEP_RESULT_QUERY_NOT_EXECUTED; } auto index = std::find(columnNames_.begin(), columnNames_.end(), "modifyTime"); - int errCode = sqliteStatement_->GetColumnString(index - columnNames_.begin(), modifyTime); + int errCode = statement->GetColumnString(index - columnNames_.begin(), modifyTime); if (errCode != E_OK) { LOG_ERROR("ret is %{public}d", errCode); return errCode; @@ -445,12 +474,18 @@ int StepResultSet::GetModifyTime(std::string &modifyTime) int StepResultSet::GetSize(int columnIndex, size_t &size) { + auto [statement, conn] = GetStatement(); + if (statement == nullptr) { + LOG_ERROR("resultSet closed"); + return E_STEP_RESULT_CLOSED; + } + if (rowPos_ == INIT_POS) { size = 0; return E_STEP_RESULT_QUERY_NOT_EXECUTED; } - return sqliteStatement_->GetSize(columnIndex, size); + return statement->GetSize(columnIndex, size); } int StepResultSet::IsColumnNull(int columnIndex, bool &isNull) @@ -487,7 +522,8 @@ int StepResultSet::GetValue(int32_t col, T &value) std::pair StepResultSet::GetValueObject(int32_t col, size_t index) { - if (isClosed_) { + auto [statement, conn] = GetStatement(); + if (statement == nullptr) { return { E_STEP_RESULT_CLOSED, ValueObject() }; } @@ -496,11 +532,19 @@ std::pair StepResultSet::GetValueObject(int32_t col, size_t in } ValueObject value; - auto ret = sqliteStatement_->GetColumn(col, value); + auto ret = statement->GetColumn(col, value); if (index < ValueObject::TYPE_MAX && value.value.index() != index) { return { E_INVALID_COLUMN_TYPE, ValueObject() }; } return { ret, std::move(value) }; } + +std::pair, std::shared_ptr> StepResultSet::GetStatement() +{ + if (isClosed_) { + return { nullptr, nullptr }; + } + return {sqliteStatement_, conn_}; +} } // namespace NativeRdb } // namespace OHOS \ No newline at end of file diff --git a/relational_store/interfaces/inner_api/cloud_data/include/cloud_service.h b/relational_store/interfaces/inner_api/cloud_data/include/cloud_service.h index ed5687e0f86492220525c2a2297e1dec52ac946d..2ceb2857e68b9644b935c4eb03d16249185bd683 100644 --- a/relational_store/interfaces/inner_api/cloud_data/include/cloud_service.h +++ b/relational_store/interfaces/inner_api/cloud_data/include/cloud_service.h @@ -20,6 +20,7 @@ #include #include #include "cloud_types.h" +#include "common_types.h" #include "rdb_types.h" #include "values_bucket.h" namespace OHOS { @@ -28,13 +29,18 @@ class CloudService { public: enum TransId : int32_t { TRANS_HEAD, - TRANS_ENABLE_CLOUD = TRANS_HEAD, + TRANS_CONFIG_HEAD = TRANS_HEAD, + TRANS_ENABLE_CLOUD = TRANS_CONFIG_HEAD, TRANS_DISABLE_CLOUD, TRANS_CHANGE_APP_SWITCH, TRANS_CLEAN, TRANS_NOTIFY_DATA_CHANGE, TRANS_NOTIFY_DATA_CHANGE_EXT, - TRANS_ALLOC_RESOURCE_AND_SHARE, + TRANS_QUERY_STATISTICS, + TRANS_SET_GLOBAL_CLOUD_STRATEGY, + TRANS_CONFIG_BUTT, + TRANS_SHARE_HEAD = TRANS_CONFIG_BUTT, + TRANS_ALLOC_RESOURCE_AND_SHARE = TRANS_SHARE_HEAD, TRANS_SHARE, TRANS_UNSHARE, TRANS_EXIT, @@ -43,7 +49,11 @@ public: TRANS_QUERY_BY_INVITATION, TRANS_CONFIRM_INVITATION, TRANS_CHANGE_CONFIRMATION, - TRANS_BUTT, + TRANS_SHARE_BUTT, + TRANS_CLIENT_HEAD = TRANS_SHARE_BUTT, + TRANS_SET_CLOUD_STRATEGY = TRANS_CLIENT_HEAD, + TRANS_CLIENT_BUTT, + TRANS_BUTT = TRANS_CLIENT_BUTT, }; enum Action : int32_t { CLEAR_CLOUD_INFO, @@ -80,6 +90,9 @@ public: virtual int32_t Clean(const std::string &id, const std::map &actions) = 0; virtual int32_t NotifyDataChange(const std::string &id, const std::string &bundleName) = 0; virtual int32_t NotifyDataChange(const std::string &eventId, const std::string &extraData, int32_t userId) = 0; + virtual std::pair> QueryStatistics(const std::string &id, + const std::string &bundleName, const std::string &storeId) = 0; + virtual int32_t SetGlobalCloudStrategy(Strategy strategy, const std::vector& values) = 0; virtual std::pair> AllocResourceAndShare(const std::string &storeId, const DistributedRdb::PredicatesMemo &predicates, const std::vector &columns, @@ -96,6 +109,8 @@ public: virtual int32_t ChangeConfirmation(const std::string &sharingRes, int32_t confirmation, std::pair &result) = 0; + virtual int32_t SetCloudStrategy(Strategy strategy, const std::vector& values) = 0; + inline static constexpr const char *SERVICE_NAME = "cloud"; }; } // namespace CloudData diff --git a/relational_store/interfaces/inner_api/cloud_data/include/cloud_types.h b/relational_store/interfaces/inner_api/cloud_data/include/cloud_types.h index 0d70732101a192241a0dae29eb6d4b2067891823..57c80f1da177727ec8631943a29d61758ed0d873 100644 --- a/relational_store/interfaces/inner_api/cloud_data/include/cloud_types.h +++ b/relational_store/interfaces/inner_api/cloud_data/include/cloud_types.h @@ -17,6 +17,8 @@ #define OHOS_DISTRIBUTED_DATA_CLOUD_CLOUD_TYPES_H #include +#include +#include namespace OHOS::CloudData { enum Role : int32_t { @@ -51,6 +53,14 @@ struct Participant { std::string attachInfo; }; +struct StatisticInfo { + std::string table; + int32_t inserted = 0; + int32_t updated = 0; + int32_t normal = 0; +}; + +using StatisticInfos = std::vector; using Participants = std::vector; using Results = std::tuple>>; using QueryResults = std::tuple; @@ -131,5 +141,17 @@ enum SharingCode : int32_t { */ CUSTOM_ERROR = 1000, }; + +enum Strategy : uint32_t { + STRATEGY_HEAD, + STRATEGY_NETWORK = STRATEGY_HEAD, + STRATEGY_BUTT +}; + +enum NetWorkStrategy : uint32_t { + WIFI = 0x01, + CELLULAR = 0x02, + NETWORK_STRATEGY_BUTT +}; } // namespace OHOS::CloudData #endif // OHOS_DISTRIBUTED_DATA_CLOUD_CLOUD_TYPES_H diff --git a/relational_store/interfaces/inner_api/common_type/include/common_types.h b/relational_store/interfaces/inner_api/common_type/include/common_types.h index 4895819bedaee1cb18b3bc8738d3ac9c4cb8eefc..f7fbc7c98f91d63ee3e47088ba3af8041df47b0f 100644 --- a/relational_store/interfaces/inner_api/common_type/include/common_types.h +++ b/relational_store/interfaces/inner_api/common_type/include/common_types.h @@ -18,6 +18,7 @@ #include #include #include +#include namespace OHOS::CommonType { struct AssetValue { enum Status : int32_t { diff --git a/relational_store/interfaces/inner_api/rdb/BUILD.gn b/relational_store/interfaces/inner_api/rdb/BUILD.gn index 4a9c785aa60384465dc3cf48d1b152c0f1172049..13a5376b327f9c960f52035212c37a26886ded3a 100644 --- a/relational_store/interfaces/inner_api/rdb/BUILD.gn +++ b/relational_store/interfaces/inner_api/rdb/BUILD.gn @@ -38,6 +38,11 @@ base_sources = [ "${relational_store_native_path}/rdb/src/values_bucket.cpp", ] +if (!is_ohos) { + base_sources += + [ "${relational_store_mock_path}/frameworks/native/rdb/mock.cpp" ] +} + if (is_ohos && !build_ohos_sdk) { config("native_rdb_config") { visibility = [ ":*" ] @@ -210,6 +215,7 @@ if (is_ohos && !build_ohos_sdk) { visibility = [ ":*" ] include_dirs = [ + "${relational_store_mock_path}/frameworks/native/rdb", "mock/include", "${relational_store_common_path}/include", "${relational_store_native_path}/rdb/mock/include", @@ -220,6 +226,7 @@ if (is_ohos && !build_ohos_sdk) { "//third_party/libuv/src/win", ] + cflags = [ "-includemock.h" ] defines = [ "RELATIONAL_STORE", "SQLITE_HAS_CODEC", @@ -273,6 +280,7 @@ if (is_ohos && !build_ohos_sdk) { "//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog_windows", "//third_party/sqlite:sqlite_sdk", ] + cflags_cc = [ "-std=c++17" ] public_configs = [ ":native_rdb_public_config" ] @@ -307,6 +315,7 @@ if (is_ohos && !build_ohos_sdk) { visibility = [ ":*" ] include_dirs = [ + "${relational_store_mock_path}/frameworks/native/rdb", "mock/include", "${relational_store_common_path}/include", "${relational_store_native_path}/rdb/mock/include", @@ -316,6 +325,7 @@ if (is_ohos && !build_ohos_sdk) { "${relational_store_native_path}/rdb/include", ] + cflags = [ "-includemock.h" ] defines = [ "RELATIONAL_STORE", "SQLITE_HAS_CODEC", @@ -399,6 +409,7 @@ if (is_ohos && !build_ohos_sdk) { visibility = [ ":*" ] include_dirs = [ + "${relational_store_mock_path}/frameworks/native/rdb", "${distributedfile_path}/mod_securitylabel", "${relational_store_common_path}/include", "${relational_store_innerapi_path}/rdb/mock/include", @@ -407,6 +418,7 @@ if (is_ohos && !build_ohos_sdk) { "${relational_store_native_path}/rdb/include", ] + cflags = [ "-includemock.h" ] defines = [ "RELATIONAL_STORE", "SQLITE_HAS_CODEC", @@ -466,6 +478,7 @@ if (is_ohos && !build_ohos_sdk) { visibility = [ ":*" ] include_dirs = [ + "${relational_store_mock_path}/frameworks/native/rdb", "${distributedfile_path}/mod_securitylabel", "${relational_store_common_path}/include", "${relational_store_innerapi_path}/rdb/mock/include", @@ -474,6 +487,7 @@ if (is_ohos && !build_ohos_sdk) { "${relational_store_native_path}/rdb/include", ] + cflags = [ "-includemock.h" ] defines = [ "RELATIONAL_STORE", "SQLITE_HAS_CODEC", 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 32d187884f50f3cacb56840da2d5f7174b560616..5013fe7fd0137aac325f5ffb3db33916cf069563 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 @@ -110,6 +110,17 @@ enum class SecurityLevel : int32_t { LAST }; +enum RoleType : uint32_t { + /** + * The user has administrative rights. + */ + OWNER = 0, + /** + * The user has read-only permission. + */ + VISITOR, +}; + /** * @brief The constant indicates the database default page size. */ @@ -471,6 +482,17 @@ public: */ std::string GetCustomDir() const; + + /** + * @brief Sets the visitorDir for the object. + */ + API_EXPORT void SetVisitorDir(const std::string &visitorDir); + + /** + * @brief Obtains the visitorDir in this {@code StoreConfig} object. + */ + API_EXPORT std::string GetVisitorDir() const; + /** * @brief Overload the line number operator. */ @@ -535,6 +557,10 @@ public: */ void SetReadTime(int timeout); + void SetRoleType(RoleType role); + + uint32_t GetRoleType() const; + private: void ClearEncryptKey(); @@ -574,6 +600,9 @@ private: bool isSearchable_ = false; int writeTimeout_ = 2; // seconds int readTimeout_ = 1; // seconds + + RoleType role_ = OWNER; + std::string visitorDir_; }; } // namespace OHOS::NativeRdb 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 0bec84c0c0950926f9686d3f8891c9c56731f017..2f1ba47c7060d509656bb052becbd0da3e5b8a0a 100644 --- a/relational_store/interfaces/inner_api/rdb/include/rdb_types.h +++ b/relational_store/interfaces/inner_api/rdb/include/rdb_types.h @@ -42,6 +42,7 @@ struct RdbSyncerParam { int32_t area_ = 0; int32_t level_ = 0; int32_t type_ = RDB_DEVICE_COLLABORATION; + uint32_t roleType_ = 0; bool isEncrypt_ = false; bool isAutoClean_ = true; bool isSearchable_ = false; @@ -96,6 +97,7 @@ enum ProgressCode { LOCKED_BY_OTHERS, RECORD_LIMIT_EXCEEDED, NO_SPACE_FOR_ASSET, + BLOCKED_BY_NETWORK_STRATEGY, }; struct Statistic { 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 e7599dd0ff25ea4f16a91829de86ebb6d5f2f83f..676cd6749b195b81705554f0b3f23b7cf5b3a536 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 @@ -58,6 +58,11 @@ enum class SecurityLevel : int32_t { LAST }; +enum RoleType : uint32_t { + OWNER = 0, + VISITOR, +}; + 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"; @@ -149,6 +154,10 @@ public: void SetWriteTime(int timeout); int GetReadTime() const; void SetReadTime(int timeout); + void SetVisitorDir(const std::string &visitorDir); + std::string GetVisitorDir() const; + void SetRoleType(RoleType role); + uint32_t GetRoleType() const; bool operator==(const RdbStoreConfig &config) const { @@ -216,6 +225,9 @@ private: bool isSearchable_ = false; int writeTimeout_ = 2; // seconds int readTimeout_ = 1; // seconds + + RoleType role_ = OWNER; + std::string visitorDir_; }; } // namespace OHOS::NativeRdb diff --git a/relational_store/rdbmock/frameworks/native/rdb/mock.cpp b/relational_store/rdbmock/frameworks/native/rdb/mock.cpp new file mode 100644 index 0000000000000000000000000000000000000000..289b22cf540cc09f3cac134fa3349889d01a6d01 --- /dev/null +++ b/relational_store/rdbmock/frameworks/native/rdb/mock.cpp @@ -0,0 +1,25 @@ +/* + * 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 "mock.h" + +namespace OHOS { +namespace NativeRdb { +__attribute__((visibility("default"))) int gettid() +{ + return 0; +} +} +} \ No newline at end of file diff --git a/relational_store/rdbmock/frameworks/native/rdb/mock.h b/relational_store/rdbmock/frameworks/native/rdb/mock.h new file mode 100644 index 0000000000000000000000000000000000000000..85d8123385291dc311fdcba1ac4e7258109152ce --- /dev/null +++ b/relational_store/rdbmock/frameworks/native/rdb/mock.h @@ -0,0 +1,25 @@ +/* + * 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 DISTRIBUTEDDATAMGR_RELATIONAL_STORE_MOCK_H +#define DISTRIBUTEDDATAMGR_RELATIONAL_STORE_MOCK_H + +namespace OHOS { +namespace NativeRdb { +__attribute__((visibility("default"))) int gettid(); +} +} + +#endif //DISTRIBUTEDDATAMGR_RELATIONAL_STORE_MOCK_H diff --git a/relational_store/rdbmock/frameworks/native/rdb/relational_store_client.h b/relational_store/rdbmock/frameworks/native/rdb/relational_store_client.h new file mode 100644 index 0000000000000000000000000000000000000000..a0f7213210efd46eb17a79713baf782fe7d80e09 --- /dev/null +++ b/relational_store/rdbmock/frameworks/native/rdb/relational_store_client.h @@ -0,0 +1,37 @@ +/* + * 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_RELATIONAL_STORE_CLIENT_H +#define RELATIONAL_STORE_RELATIONAL_STORE_CLIENT_H + +#include "sqlite3sym.h" + +namespace OHOS { +namespace NativeRdb { +namespace DistributedDB { +enum DBStatus { + DB_ERROR = -1, + OK = 0, +}; +} + +DistributedDB::DBStatus UnRegisterClientObserver(sqlite3 *db) +{ + return DistributedDB::DBStatus::OK; +}; +} +} + +#endif //RELATIONAL_STORE_RELATIONAL_STORE_CLIENT_H diff --git a/relational_store/relational_store.gni b/relational_store/relational_store.gni index e94b5ea858457096e13abac7ad0b5b8928a6b7d9..7562c03943a719db63abb86be0fb447b644bee34 100644 --- a/relational_store/relational_store.gni +++ b/relational_store/relational_store.gni @@ -20,6 +20,8 @@ distributeddata_base_path = "//foundation/distributeddatamgr" relational_store_base_path = "//foundation/distributeddatamgr/relational_store" +relational_store_mock_path = "${relational_store_base_path}/rdbmock" + relational_store_js_common_path = "${relational_store_base_path}/frameworks/js/napi/common" diff --git a/relational_store/test/js/clouddata/unittest/src/CloudClientTest.js b/relational_store/test/js/clouddata/unittest/src/CloudClientTest.js new file mode 100644 index 0000000000000000000000000000000000000000..a5f0dcbcfae8e07da0a1acf1329bc3b09e4658f2 --- /dev/null +++ b/relational_store/test/js/clouddata/unittest/src/CloudClientTest.js @@ -0,0 +1,219 @@ +/* + * 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 cloudData from '@ohos.data.cloudData'; + +const TAG = "[CLOUD_CLIENT_JSKITS_TEST]" +describe('CloudClientTest', function () { + + /** + * @tc.number SUB_DDM_CLOUD_CLIENT_0010 + * @tc.name setCloudStrategyTest001 + * @tc.desc Test Js Api setCloudStrategy with invalid args. + */ + it('setCloudStrategyTest001', 0, async function (done) { + console.log(TAG + "************* setCloudStrategyTest001 start *************"); + try { + cloudData.setCloudStrategy().then(() => { + expect(null).assertFail(); + }).catch(err => { + console.error(TAG + `setCloudStrategyTest001, errcode:${JSON.stringify(err)}.`); + expect(null).assertFail(); + }); + } catch (err) { + console.error(TAG + `setCloudStrategyTest001, errcode:${JSON.stringify(err)}.`); + expect(err.code == 401).assertTrue(); + } + done() + console.log(TAG + "************* setCloudStrategyTest001 end *************"); + }) + + /** + * @tc.number SUB_DDM_CLOUD_CLIENT_0010 + * @tc.name setCloudStrategyTest002 + * @tc.desc Test Js Api setCloudStrategy with invalid args. + */ + it('setCloudStrategyTest002', 0, async function (done) { + console.log(TAG + "************* setCloudStrategyTest002 start *************"); + try { + cloudData.setCloudStrategy(undefined).then(() => { + expect(null).assertFail(); + }).catch(err => { + console.error(TAG + `setCloudStrategyTest002, errcode:${JSON.stringify(err)}.`); + expect(null).assertFail(); + }); + } catch (err) { + console.error(TAG + `setCloudStrategyTest002, errcode:${JSON.stringify(err)}.`); + expect(err.code == 401).assertTrue(); + } + done() + console.log(TAG + "************* setCloudStrategyTest002 end *************"); + }) + + /** + * @tc.number SUB_DDM_CLOUD_CLIENT_0010 + * @tc.name setCloudStrategyTest003 + * @tc.desc Test Js Api setCloudStrategy with invalid args. + */ + it('setCloudStrategyTest003', 0, async function (done) { + console.log(TAG + "************* setCloudStrategyTest003 start *************"); + try { + cloudData.setCloudStrategy(cloudData.StrategyType.NETWORK, [undefined, "test"]).then(() => { + expect(null).assertFail(); + }).catch(err => { + console.error(TAG + `setCloudStrategyTest003, errcode:${JSON.stringify(err)}.`); + expect(null).assertFail(); + }); + } catch (err) { + console.error(TAG + `setCloudStrategyTest003, errcode:${JSON.stringify(err)}.`); + expect(err.code == 401).assertTrue(); + } + done() + console.log(TAG + "************* setCloudStrategyTest003 end *************"); + }) + + /** + * @tc.number SUB_DDM_CLOUD_CLIENT_0010 + * @tc.name setCloudStrategyTest004 + * @tc.desc Test Js Api setCloudStrategy with invalid args. + */ + it('setCloudStrategyTest004', 0, async function (done) { + console.log(TAG + "************* setCloudStrategyTest004 start *************"); + try { + cloudData.setCloudStrategy(cloudData.StrategyType.NETWORK, [cloudData.NetWorkStrategy.WIFI, "test"]).then(() => { + expect(null).assertFail(); + }).catch(err => { + console.error(TAG + `setCloudStrategyTest004, errcode:${JSON.stringify(err)}.`); + expect(null).assertFail(); + }); + } catch (err) { + console.error(TAG + `setCloudStrategyTest004, errcode:${JSON.stringify(err)}.`); + expect(err.code == 401).assertTrue(); + } + done() + console.log(TAG + "************* setCloudStrategyTest004 end *************"); + }) + + /** + * @tc.number SUB_DDM_CLOUD_CLIENT_0010 + * @tc.name setCloudStrategyTest005 + * @tc.desc Test Js Api setCloudStrategy with valid args. + */ + it('setCloudStrategyTest005', 0, async function (done) { + console.log(TAG + "************* setCloudStrategyTest005 start *************"); + try { + await cloudData.setCloudStrategy(cloudData.StrategyType.NETWORK, [cloudData.NetWorkStrategy.WIFI]).then(() => { + expect(true).assertTrue(); + }).catch(err => { + console.error(TAG + `setCloudStrategyTest005, errcode:${JSON.stringify(err)}.`); + expect(null).assertFail(); + }); + } catch (err) { + console.error(TAG + `setCloudStrategyTest005, errcode:${JSON.stringify(err)}.`); + expect(null).assertFail(); + } + done() + console.log(TAG + "************* setCloudStrategyTest005 end *************"); + }) + + /** + * @tc.number SUB_DDM_CLOUD_CLIENT_0010 + * @tc.name setCloudStrategyTest006 + * @tc.desc Test Js Api setCloudStrategy with valid args. + */ + it('setCloudStrategyTest006', 0, async function (done) { + console.log(TAG + "************* setCloudStrategyTest006 start *************"); + try { + await cloudData.setCloudStrategy(cloudData.StrategyType.NETWORK, [cloudData.NetWorkStrategy.CELLULAR, cloudData.NetWorkStrategy.WIFI]).then(() => { + expect(true).assertTrue(); + }).catch(err => { + console.error(TAG + `setCloudStrategyTest006, errcode:${JSON.stringify(err)}.`); + expect(null).assertFail(); + }); + } catch (err) { + console.error(TAG + `setCloudStrategyTest006, errcode:${JSON.stringify(err)}.`); + expect(null).assertFail(); + } + done() + console.log(TAG + "************* setCloudStrategyTest006 end *************"); + }) + + /** + * @tc.number SUB_DDM_CLOUD_CLIENT_0010 + * @tc.name setCloudStrategyTest007 + * @tc.desc Test Js Api setCloudStrategy with valid args. + */ + it('setCloudStrategyTest007', 0, async function (done) { + console.log(TAG + "************* setCloudStrategyTest007 start *************"); + try { + await cloudData.setCloudStrategy(cloudData.StrategyType.NETWORK).then(() => { + expect(true).assertTrue(); + }).catch(err => { + console.error(TAG + `setCloudStrategyTest007, errcode:${JSON.stringify(err)}.`); + expect(null).assertFail(); + }); + } catch (err) { + console.error(TAG + `setCloudStrategyTest007, errcode:${JSON.stringify(err)}.`); + expect(null).assertFail(); + } + done() + console.log(TAG + "************* setCloudStrategyTest007 end *************"); + }) + + /** + * @tc.number SUB_DDM_CLOUD_CLIENT_0010 + * @tc.name setCloudStrategyTest008 + * @tc.desc Test Js Api setCloudStrategy with valid args. + */ + it('setCloudStrategyTest008', 0, async function (done) { + console.log(TAG + "************* setCloudStrategyTest008 start *************"); + try { + await cloudData.setCloudStrategy(cloudData.StrategyType.NETWORK, undefined).then(() => { + expect(true).assertTrue(); + }).catch(err => { + console.error(TAG + `setCloudStrategyTest008, errcode:${JSON.stringify(err)}.`); + expect(null).assertFail(); + }); + } catch (err) { + console.error(TAG + `setCloudStrategyTest008, errcode:${JSON.stringify(err)}.`); + expect(null).assertFail(); + } + done() + console.log(TAG + "************* setCloudStrategyTest008 end *************"); + }) + + /** + * @tc.number SUB_DDM_CLOUD_CLIENT_0010 + * @tc.name setCloudStrategyTest009 + * @tc.desc Test Js Api setCloudStrategy with valid args. + */ + it('setCloudStrategyTest009', 0, async function (done) { + console.log(TAG + "************* setCloudStrategyTest009 start *************"); + try { + await cloudData.setCloudStrategy(cloudData.StrategyType.NETWORK, null).then(() => { + expect(true).assertTrue(); + }).catch(err => { + console.error(TAG + `setCloudStrategyTest009, errcode:${JSON.stringify(err)}.`); + expect(null).assertFail(); + }); + } catch (err) { + console.error(TAG + `setCloudStrategyTest009, errcode:${JSON.stringify(err)}.`); + expect(null).assertFail(); + } + done() + console.log(TAG + "************* setCloudStrategyTest009 end *************"); + }) +}) \ No newline at end of file diff --git a/relational_store/test/js/clouddata/unittest/src/CloudSyncConfigPromise.js b/relational_store/test/js/clouddata/unittest/src/CloudSyncConfigPromise.js index 4eb98d4242d04052587bbdaa82ccd0f73ab995ca..e08a8e2cab3d28808949401ee59c369333cba01b 100644 --- a/relational_store/test/js/clouddata/unittest/src/CloudSyncConfigPromise.js +++ b/relational_store/test/js/clouddata/unittest/src/CloudSyncConfigPromise.js @@ -17,6 +17,7 @@ import {describe, beforeAll, beforeEach, afterEach, afterAll, it, expect} from 'deccjsunit/index' import cloudData from '@ohos.data.cloudData'; +const TAG = "[CLOUD_CONFIG_JSKITS_TEST]" describe('CloudConfigPromiseTest', function () { /** * @tc.name EnabledCloudInvalidArgsTest @@ -308,4 +309,367 @@ describe('CloudConfigPromiseTest', function () { done(); }) + /** + * @tc.name queryStatisticsTest + * @tc.desc Test Js Api queryStatistics which parameters number are less + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('queryStatisticsTest1', 0, async function (done) { + console.info('queryStatisticsTest1'); + try { + await cloudData.Config.queryStatistics().then((etc) => { + console.info('queryStatisticsTest1 success' + `, info is ${JSON.stringify(etc)}`); + expect(null).assertFail(); + }).catch((error) => { + console.error('queryStatisticsTest1 fail' + `, error code is ${error.code}, message is ${error.message}`); + expect(null).assertFail(); + }); + } catch (e) { + console.error('queryStatisticsTest1 fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 401).assertTrue(); + } + done(); + }) + + /** + * @tc.name queryStatisticsTest + * @tc.desc Test Js Api queryStatistics with effective args + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('queryStatisticsTest2', 0, async function (done) { + console.info('queryStatisticsTest2'); + try { + const accountId = "test_id"; + await cloudData.Config.queryStatistics(accountId).then((etc) => { + console.info('queryStatisticsTest2 success' + `, info is ${JSON.stringify(etc)}`); + expect(null).assertFail(); + }).catch((error) => { + console.error('queryStatisticsTest2 fail' + `, error code is ${error.code}, message is ${error.message}`); + expect(null).assertFail(); + }); + } catch (e) { + console.error('queryStatisticsTest2 fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 401).assertTrue(); + } + done(); + }) + + /** + * @tc.name queryStatisticsTest + * @tc.desc Test Js Api queryStatistics with effective args + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('queryStatisticsTest3', 0, async function (done) { + console.info('queryStatisticsTest3'); + try { + const accountId = 123; + const bundleName = "bundleName"; + await cloudData.Config.queryStatistics(accountId, bundleName).then((etc) => { + console.info('queryStatisticsTest3 success' + `, info is ${JSON.stringify(etc)}`); + expect(null).assertFail(); + }).catch((error) => { + console.error('queryStatisticsTest3 fail' + `, error code is ${error.code}, message is ${error.message}`); + expect(null).assertFail(); + }); + } catch (e) { + console.error('queryStatisticsTest3 fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 401).assertTrue(); + } + done(); + }) + + /** + * @tc.name queryStatisticsTest + * @tc.desc Test Js Api queryStatistics with effective args + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('queryStatisticsTest4', 0, async function (done) { + console.info('queryStatisticsTest4'); + try { + const accountId = "accountId"; + const bundleName = "bundleName"; + await cloudData.Config.queryStatistics(accountId, bundleName).then((etc) => { + console.info('queryStatisticsTest4 success' + `, info is ${JSON.stringify(etc)}`); + expect(etc != null).assertTrue(); + }).catch((error) => { + console.error('queryStatisticsTest4 fail' + `, error code is ${error.code}, message is ${error.message}`); + expect(null).assertFail(); + }); + } catch (e) { + console.error('queryStatisticsTest4 fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 201).assertTrue(); + } + done(); + }) + + /** + * @tc.name queryStatisticsTest + * @tc.desc Test Js Api queryStatistics with effective args + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('queryStatisticsTest5', 0, async function (done) { + console.info('queryStatisticsTest5'); + try { + const accountId = "accountId"; + const bundleName = "bundleName"; + await cloudData.Config.queryStatistics(accountId, bundleName, null).then((etc) => { + console.info('queryStatisticsTest5 success' + `, info is ${JSON.stringify(etc)}`); + expect(etc != null).assertTrue(); + }).catch((error) => { + console.error('queryStatisticsTest5 fail' + `, error code is ${error.code}, message is ${error.message}`); + expect(null).assertFail(); + }); + } catch (e) { + console.error('queryStatisticsTest5 fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 201).assertTrue(); + } + done(); + }) + + /** + * @tc.name queryStatisticsTest + * @tc.desc Test Js Api queryStatistics with effective args + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('queryStatisticsTest6', 0, async function (done) { + console.info('queryStatisticsTest6'); + try { + const accountId = "accountId"; + const bundleName = "bundleName"; + await cloudData.Config.queryStatistics(accountId, bundleName, undefined).then((etc) => { + console.info('queryStatisticsTest6 success' + `, info is ${JSON.stringify(etc)}`); + expect(etc != null).assertTrue(); + }).catch((error) => { + console.error('queryStatisticsTest6 fail' + `, error code is ${error.code}, message is ${error.message}`); + expect(null).assertFail(); + }); + } catch (e) { + console.error('queryStatisticsTest6 fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 201).assertTrue(); + } + done(); + }) + + /** + * @tc.name queryStatisticsTest + * @tc.desc Test Js Api queryStatistics with effective args + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('queryStatisticsTest7', 0, async function (done) { + console.info('queryStatisticsTest7'); + try { + const accountId = "accountId"; + const bundleName = "bundleName"; + const storeId = "storeId"; + await cloudData.Config.queryStatistics(accountId, bundleName, storeId).then((etc) => { + console.info('queryStatisticsTest7 success' + `, info is ${JSON.stringify(etc)}`); + expect(etc != null).assertTrue(); + }).catch((error) => { + console.error('queryStatisticsTest7 fail' + `, error code is ${error.code}, message is ${error.message}`); + expect(null).assertFail(); + }); + } catch (e) { + console.error('queryStatisticsTest7 fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 201).assertTrue(); + } + done(); + }) + + /** + * @tc.number SUB_DDM_CLOUD_CONFIG_SetGlobalCloudStrategy + * @tc.name setGlobalCloudStrategyTest001 + * @tc.desc Test Js Api setGlobalCloudStrategy with invalid args. + */ + it('setGlobalCloudStrategyTest001', 0, async function (done) { + console.log(TAG + "************* setGlobalCloudStrategyTest001 start *************"); + try { + cloudData.Config.setGlobalCloudStrategy().then(() => { + expect(null).assertFail(); + }).catch(err => { + expect(null).assertFail(); + }); + } catch (err) { + expect(err.code == 401).assertTrue(); + } + done() + console.log(TAG + "************* setGlobalCloudStrategyTest001 end *************"); + }) + + /** + * @tc.number SUB_DDM_CLOUD_CONFIG_SetGlobalCloudStrategy + * @tc.name setGlobalCloudStrategyTest002 + * @tc.desc Test Js Api setGlobalCloudStrategy with invalid args. + */ + it('setGlobalCloudStrategyTest002', 0, async function (done) { + console.log(TAG + "************* setGlobalCloudStrategyTest002 start *************"); + try { + cloudData.Config.setGlobalCloudStrategy(undefined).then(() => { + expect(null).assertFail(); + }).catch(err => { + expect(null).assertFail(); + }); + } catch (err) { + expect(err.code == 401).assertTrue(); + } + done() + console.log(TAG + "************* setGlobalCloudStrategyTest002 end *************"); + }) + + /** + * @tc.number SUB_DDM_CLOUD_CONFIG_SetGlobalCloudStrategy + * @tc.name setGlobalCloudStrategyTest003 + * @tc.desc Test Js Api setGlobalCloudStrategy with invalid args. + */ + it('setGlobalCloudStrategyTest003', 0, async function (done) { + console.log(TAG + "************* setGlobalCloudStrategyTest003 start *************"); + try { + cloudData.Config.setGlobalCloudStrategy(cloudData.StrategyType.NETWORK, [undefined, "test"]).then(() => { + expect(null).assertFail(); + }).catch(err => { + expect(null).assertFail(); + }); + } catch (err) { + expect(err.code == 401).assertTrue(); + } + done() + console.log(TAG + "************* setGlobalCloudStrategyTest003 end *************"); + }) + + /** + * @tc.number SUB_DDM_CLOUD_CONFIG_SetGlobalCloudStrategy + * @tc.name setGlobalCloudStrategyTest004 + * @tc.desc Test Js Api setGlobalCloudStrategy with invalid args. + */ + it('setGlobalCloudStrategyTest004', 0, async function (done) { + console.log(TAG + "************* setGlobalCloudStrategyTest004 start *************"); + try { + cloudData.Config.setGlobalCloudStrategy(cloudData.StrategyType.NETWORK, [cloudData.NetWorkStrategy.WIFI, "test"]).then(() => { + expect(null).assertFail(); + }).catch(err => { + expect(null).assertFail(); + }); + } catch (err) { + expect(err.code == 401).assertTrue(); + } + done() + console.log(TAG + "************* setGlobalCloudStrategyTest004 end *************"); + }) + + /** + * @tc.number SUB_DDM_CLOUD_CONFIG_SetGlobalCloudStrategy + * @tc.name setGlobalCloudStrategyTest005 + * @tc.desc Test Js Api setGlobalCloudStrategy with valid args. + */ + it('setGlobalCloudStrategyTest005', 0, async function (done) { + console.log(TAG + "************* setGlobalCloudStrategyTest005 start *************"); + try { + await cloudData.Config.setGlobalCloudStrategy(cloudData.StrategyType.NETWORK, [cloudData.NetWorkStrategy.WIFI]).then(() => { + expect(null).assertFail(); + }).catch(err => { + console.error(TAG + `setGlobalCloudStrategyTest005, errcode:${JSON.stringify(err)}.`); + expect(err.code == 201).assertTrue(); + }); + } catch (err) { + console.error(TAG + `setGlobalCloudStrategyTest005, errcode:${JSON.stringify(err)}.`); + expect(err.code == 201).assertTrue(); + } + done() + console.log(TAG + "************* setGlobalCloudStrategyTest005 end *************"); + }) + + /** + * @tc.number SUB_DDM_CLOUD_CONFIG_SetGlobalCloudStrategy + * @tc.name setGlobalCloudStrategyTest006 + * @tc.desc Test Js Api setGlobalCloudStrategy with valid args. + */ + it('setGlobalCloudStrategyTest006', 0, async function (done) { + console.log(TAG + "************* setGlobalCloudStrategyTest006 start *************"); + try { + await cloudData.Config.setGlobalCloudStrategy(cloudData.StrategyType.NETWORK, [cloudData.NetWorkStrategy.CELLULAR, cloudData.NetWorkStrategy.WIFI]).then(() => { + expect(null).assertFail(); + }).catch(err => { + console.error(TAG + `setGlobalCloudStrategyTest006, errcode:${JSON.stringify(err)}.`); + expect(err.code == 201).assertTrue(); + }); + } catch (err) { + console.error(TAG + `setGlobalCloudStrategyTest006, errcode:${JSON.stringify(err)}.`); + expect(err.code == 201).assertTrue(); + } + done() + console.log(TAG + "************* setGlobalCloudStrategyTest006 end *************"); + }) + + /** + * @tc.number SUB_DDM_CLOUD_CONFIG_SetGlobalCloudStrategy + * @tc.name setGlobalCloudStrategyTest007 + * @tc.desc Test Js Api setGlobalCloudStrategy with valid args. + */ + it('setGlobalCloudStrategyTest007', 0, async function (done) { + console.log(TAG + "************* setGlobalCloudStrategyTest007 start *************"); + try { + await cloudData.Config.setGlobalCloudStrategy(cloudData.StrategyType.NETWORK).then(() => { + expect(null).assertFail(); + }).catch(err => { + console.error(TAG + `setGlobalCloudStrategyTest007, errcode:${JSON.stringify(err)}.`); + expect(err.code == 201).assertTrue(); + }); + } catch (err) { + console.error(TAG + `setGlobalCloudStrategyTest007, errcode:${JSON.stringify(err)}.`); + expect(err.code == 201).assertTrue(); + } + done() + console.log(TAG + "************* setGlobalCloudStrategyTest007 end *************"); + }) + + /** + * @tc.number SUB_DDM_CLOUD_CONFIG_SetGlobalCloudStrategy + * @tc.name setGlobalCloudStrategyTest008 + * @tc.desc Test Js Api setGlobalCloudStrategy with valid args. + */ + it('setGlobalCloudStrategyTest008', 0, async function (done) { + console.log(TAG + "************* setGlobalCloudStrategyTest008 start *************"); + try { + await cloudData.Config.setGlobalCloudStrategy(cloudData.StrategyType.NETWORK, undefined).then(() => { + expect(null).assertFail(); + }).catch(err => { + console.error(TAG + `setGlobalCloudStrategyTest008, errcode:${JSON.stringify(err)}.`); + expect(err.code == 201).assertTrue(); + }); + } catch (err) { + console.error(TAG + `setGlobalCloudStrategyTest008, errcode:${JSON.stringify(err)}.`); + expect(err.code == 201).assertTrue(); + } + done() + console.log(TAG + "************* setGlobalCloudStrategyTest008 end *************"); + }) + + /** + * @tc.number SUB_DDM_CLOUD_CONFIG_SetGlobalCloudStrategy + * @tc.name setGlobalCloudStrategyTest009 + * @tc.desc Test Js Api setGlobalCloudStrategy with valid args. + */ + it('setGlobalCloudStrategyTest009', 0, async function (done) { + console.log(TAG + "************* setGlobalCloudStrategyTest009 start *************"); + try { + await cloudData.Config.setGlobalCloudStrategy(cloudData.StrategyType.NETWORK, null).then(() => { + expect(null).assertFail(); + }).catch(err => { + console.error(TAG + `setGlobalCloudStrategyTest009, errcode:${JSON.stringify(err)}.`); + expect(err.code == 201).assertTrue(); + }); + } catch (err) { + console.error(TAG + `setGlobalCloudStrategyTest009, errcode:${JSON.stringify(err)}.`); + expect(err.code == 201).assertTrue(); + } + done() + console.log(TAG + "************* setGlobalCloudStrategyTest009 end *************"); + }) + }) diff --git a/relational_store/test/js/relationalstore/unittest/src/RdbStoreQueryByStep.test.js b/relational_store/test/js/relationalstore/unittest/src/RdbStoreQueryByStep.test.js new file mode 100644 index 0000000000000000000000000000000000000000..52cf22b85c90d6e119441fea9ac77a49880b6937 --- /dev/null +++ b/relational_store/test/js/relationalstore/unittest/src/RdbStoreQueryByStep.test.js @@ -0,0 +1,312 @@ +/* + * 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 relationalStore from '@ohos.data.relationalStore'; +import ability_featureAbility from '@ohos.ability.featureAbility' + +const TAG = "[RELATIONAL_STORE_JSKITS_TEST] " + +const STORE_NAME = "queryByStep_rdb.db" +let rdbStore = null; +let context = ability_featureAbility.getContext() + +const asset1 = { + name: "name1", + uri: "uri1", + createTime: "createTime1", + modifyTime: "modifyTime1", + size: "size1", + path: "path1", + status: relationalStore.AssetStatus.ASSET_NORMAL, +} + +const asset2 = { + name: "name2", + uri: "uri2", + createTime: "createTime2", + modifyTime: "modifyTime2", + size: "size2", + path: "path2", + status: relationalStore.AssetStatus.ASSET_NORMAL, +} + +describe('rdbStoreQueryByStepTest', function () { + beforeAll(async function () { + console.info(TAG + 'beforeAll') + try { + const config = { + "name": STORE_NAME, + securityLevel: relationalStore.SecurityLevel.S1, + } + rdbStore = await relationalStore.getRdbStore(context, config); + } catch (err) { + console.error(TAG + `create database failed, err code:${err.code}, message:${err.message}`) + expect().assertFail() + } + + try { + let sqlForCreateTable = "CREATE TABLE IF NOT EXISTS test (" + + "id INTEGER PRIMARY KEY AUTOINCREMENT, " + + "name TEXT, age INTEGER, salary REAL, blobType BLOB, data1 asset, data2 assets)"; + await rdbStore.executeSql(sqlForCreateTable); + } catch (err) { + console.error(TAG + `create table test failed, err code:${err.code}, message:${err.message}`) + expect().assertFail() + } + + try { + await InsertTest(); + } catch (err) { + console.error(TAG + `insert data into table test failed, err code:${err.code}, message:${err.message}`) + expect().assertFail() + } + }) + + beforeEach(async function () { + console.info(TAG + 'beforeEach'); + }) + + afterEach(async function () { + console.info(TAG + 'afterEach'); + }) + + afterAll(async function () { + console.info(TAG + 'afterAll'); + await rdbStore.deleteRdbStore(context, STORE_NAME); + rdbStore = null; + }) + + async function InsertTest() { + console.info(TAG, "insertTest data start"); + let u8 = new Uint8Array([1, 2, 3]); + const assets1 = [asset1, asset2]; + let valuesBucket1 = { + "name": "lisi", + "age": 15, + "salary": 153.3, + "blobType": u8, + "data1": asset1, + "data2": assets1, + } + await rdbStore.insert("test", valuesBucket1); + + let valuesBucket2 = { + "name": "tom", + "age": 56, + "salary": 1503.3, + } + await rdbStore.insert("test", valuesBucket2); + + let valuesBucket3 = { + "age": 116, + "salary": 5503.3, + } + await rdbStore.insert("test", valuesBucket3); + console.info(TAG, "insertTest data end"); + } + + console.info(TAG + "*************Unit Test Begin*************"); + + /** + * @tc.number testRdbStoreQueryByStep0001 + * @tc.name Normal test case of queryByStep, query all data + * @tc.desc 1. Execute queryByStep, sql is 'select * from test' + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 2 + */ + it('testRdbStoreQueryByStep0001', 0, async function (done) { + console.info(TAG + "************* testRdbStoreQueryByStep0001 start *************"); + try { + let resultSet = await rdbStore.queryByStep('select * from test'); + // resultSet.rowCount is 3 + expect(3).assertEqual(resultSet.rowCount); + resultSet. + resultSet.close(); + } catch (err) { + console.error(TAG + `query failed, err code:${err.code}, message:${err.message}`) + } + + console.info(TAG + "************* testRdbStoreQueryByStep0001 end *************"); + done(); + }) + + /** + * @tc.number testRdbStoreQueryByStep0002 + * @tc.name Normal test case of queryByStep, query specified data + * @tc.desc 1. Query data for age > 50 + * 2. Execute queryByStep + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 2 + */ + it('testRdbStoreQueryByStep0002', 0, async function (done) { + console.info(TAG + "************* testRdbStoreQueryByStep0002 start *************"); + try { + let resultSet = await rdbStore.queryByStep('select * from test where age > ?', [50]); + // resultSet.rowCount is 2 + expect(2).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (err) { + console.error(TAG + `query failed, err code:${err.code}, message:${err.message}`) + } + + console.info(TAG + "************* testRdbStoreQueryByStep0002 end *************"); + done(); + }) + + /** + * @tc.number testRdbStoreQueryByStep0003 + * @tc.name Normal test case of queryByStep, query specified data + * @tc.desc 1. Query data for age > 50 and salary < 5000 + * 2. Execute queryByStep + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 2 + */ + it('testRdbStoreQueryByStep0003', 0, async function (done) { + console.info(TAG + "************* testRdbStoreQueryByStep0003 start *************"); + try { + let resultSet = await rdbStore.queryByStep('select * from test where age > ? and salary < ?', [50, 5000]); + // resultSet.rowCount is 1 + expect(1).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (err) { + console.error(TAG + `query failed, err code:${err.code}, message:${err.message}`) + } + + console.info(TAG + "************* testRdbStoreQueryByStep0003 end *************"); + done(); + }) + + /** + * @tc.number testRdbStoreQueryByStep0004 + * @tc.name Normal test case of queryByStep, query specified data + * @tc.desc 1. Query data for age > 50 or salary < 5000 + * 2. Execute queryByStep + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 2 + */ + it('testRdbStoreQueryByStep0004', 0, async function (done) { + console.info(TAG + "************* testRdbStoreQueryByStep0004 start *************"); + try { + let resultSet = await rdbStore.queryByStep('select * from test where age > ? or salary < ?', [50, 5000]); + // resultSet.rowCount is 3 + expect(3).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (err) { + console.error(TAG + `query failed, err code:${err.code}, message:${err.message}`) + } + + console.info(TAG + "************* testRdbStoreQueryByStep0004 end *************"); + done(); + }) + + /** + * @tc.number testRdbStoreQueryByStep0005 + * @tc.name AbNormal test case of queryByStep, if param is '' + * @tc.desc 1. Execute queryByStep + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 2 + */ + it('testRdbStoreQueryByStep0005', 0, async function (done) { + console.info(TAG + "************* testRdbStoreQueryByStep0005 start *************"); + try { + let resultSet = await rdbStore.queryByStep(''); + resultSet.close(); + } catch (err) { + // err.code is 401 + expect("401").assertEqual(err.code) + console.error(TAG + `query failed, err code:${err.code}, message:${err.message}`) + } + + console.info(TAG + "************* testRdbStoreQueryByStep0005 end *************"); + done(); + }) + + /** + * @tc.number testRdbStoreQueryByStep0006 + * @tc.name AbNormal test case of queryByStep, if param is null + * @tc.desc 1. Execute queryByStep + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 2 + */ + it('testRdbStoreQueryByStep0006', 0, async function (done) { + console.info(TAG + "************* testRdbStoreQueryByStep0006 start *************"); + try { + let resultSet = await rdbStore.queryByStep(null); + resultSet.close(); + } catch (err) { + // err.code is 401 + expect("401").assertEqual(err.code) + console.error(TAG + `query failed, err code:${err.code}, message:${err.message}`) + } + + console.info(TAG + "************* testRdbStoreQueryByStep0006 end *************"); + done(); + }) + + /** + * @tc.number testRdbStoreQueryByStep0007 + * @tc.name AbNormal test case of queryByStep, if param is null + * @tc.desc 1. Execute queryByStep + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 2 + */ + it('testRdbStoreQueryByStep0007', 0, async function (done) { + console.info(TAG + "************* testRdbStoreQueryByStep0007 start *************"); + try { + let resultSet = await rdbStore.queryByStep(undefined); + resultSet.close(); + } catch (err) { + // err.code is 401 + expect("401").assertEqual(err.code) + console.error(TAG + `query failed, err code:${err.code}, message:${err.message}`) + } + + console.info(TAG + "************* testRdbStoreQueryByStep0007 end *************"); + done(); + }) + + /** + * @tc.number testRdbStoreQueryByStep0008 + * @tc.name AbNormal test case of queryByStep, if args is [] + * @tc.desc 1. Execute queryByStep + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 2 + */ + it('testRdbStoreQueryByStep0008', 0, async function (done) { + console.info(TAG + "************* testRdbStoreQueryByStep0008 start *************"); + try { + let resultSet = await rdbStore.queryByStep('select * from test where age > ?', []); + // resultSet.rowCount is 0 + expect(0).assertEqual(resultSet.rowCount); + resultSet.close(); + } catch (err) { + console.error(TAG + `query failed, err code:${err.code}, message:${err.message}`) + } + + console.info(TAG + "************* testRdbStoreQueryByStep0008 end *************"); + done(); + }) + + console.info(TAG + "*************Unit Test End*************"); +}) diff --git a/relational_store/test/native/rdb/unittest/rdb_step_result_set_test.cpp b/relational_store/test/native/rdb/unittest/rdb_step_result_set_test.cpp index 9e40b13bffd0d825fc3b8b25eba112dbfc9b3499..4c96346f1b90951fc67f1654bdc9753e7ce6b61c 100644 --- a/relational_store/test/native/rdb/unittest/rdb_step_result_set_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_step_result_set_test.cpp @@ -1375,6 +1375,9 @@ HWTEST_F(RdbStepResultSetTest, testSqlStep014, TestSize.Level1) EXPECT_EQ(E_OK, resultSet5->GoToRow(1)); EXPECT_EQ(E_OK, resultSet1->Close()); + + EXPECT_EQ(E_OK, resultSet5->GoToRow(1)); + EXPECT_EQ(E_OK, resultSet2->Close()); EXPECT_EQ(E_OK, resultSet3->Close()); EXPECT_EQ(E_OK, resultSet4->Close()); @@ -1412,7 +1415,7 @@ HWTEST_F(RdbStepResultSetTest, testSqlStep016, TestSize.Level1) EXPECT_NE(resultSet, nullptr); size_t size; - EXPECT_EQ(E_STEP_RESULT_QUERY_NOT_EXECUTED, resultSet->GetSize(2, size)); + EXPECT_EQ(E_STEP_RESULT_CLOSED, resultSet->GetSize(2, size)); EXPECT_EQ(E_OK, resultSet->Close()); EXPECT_EQ(true, resultSet->IsClosed()); 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 d9ec7f609189a44f526b84985bf6b96e55151765..6dbb3ffdc907494d37f88f70dd357428eb17c03b 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 @@ -58,6 +58,23 @@ int ConfigTestOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVe return E_OK; } +class ConfigTestVisitorOpenCallback : public RdbOpenCallback { +public: + int OnCreate(RdbStore &store) override; + int OnUpgrade(RdbStore &store, int oldVersion, int newVersion) override; + static const std::string CREATE_TABLE_TEST; +}; + +int ConfigTestVisitorOpenCallback::OnCreate(RdbStore &store) +{ + return E_OK; +} + +int ConfigTestVisitorOpenCallback::OnUpgrade(RdbStore &store, int oldVersion, int newVersion) +{ + return E_OK; +} + void RdbStoreConfigTest::SetUpTestCase(void) { RdbHelper::DeleteRdbStore(RDB_TEST_PATH + "config_test.db"); @@ -893,4 +910,45 @@ HWTEST_F(RdbStoreConfigTest, RdbStoreConfig_029, TestSize.Level1) bool autoClean = false; config.SetAutoClean(autoClean); EXPECT_EQ(autoClean, config.GetAutoClean()); +} + +/** + * @tc.name: RdbStoreConfigVisitor_001 + * @tc.desc: test RdbStoreConfigVisitor + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreConfigTest, RdbStoreConfigVisitor_001, TestSize.Level1) +{ + int errCode = E_OK; + const std::string dbPath = RDB_TEST_PATH + "config_test.db"; + RdbStoreConfig config(dbPath, StorageMode::MODE_DISK, false); + ConfigTestOpenCallback helper; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); + EXPECT_EQ(errCode, E_OK); + + const std::string visitorDir = RDB_TEST_PATH + "config_test.db"; + RdbStoreConfig visitorConfig("", StorageMode::MODE_DISK, true); + ConfigTestVisitorOpenCallback visitorHelper; + visitorConfig.SetRoleType(OHOS::NativeRdb::VISITOR); + visitorConfig.SetVisitorDir(visitorDir); + visitorConfig.SetCreateNecessary(false); + std::shared_ptr visitorStore = RdbHelper::GetRdbStore(visitorConfig, 1, visitorHelper, errCode); + EXPECT_NE(visitorStore, nullptr); + EXPECT_EQ(errCode, E_OK); + + 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 = visitorStore->Insert(id, "test", values); + EXPECT_NE(ret, E_OK); + + store = nullptr; + visitorStore = nullptr; + ret = RdbHelper::DeleteRdbStore(dbPath); + EXPECT_EQ(ret, E_OK); } \ No newline at end of file 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 87397a450f0bf03a464790d7b7c8d9659d485ffb..2326f241f4f2b3b942d24b554b3a499069db4ec5 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 @@ -404,7 +404,6 @@ HWTEST_F(RdbStoreImplTest, Rdb_SqlitConnectionTest_001, TestSize.Level2) EXPECT_NE(nullptr, tmp); } -#ifdef RDB_SUPPORT_ICU /* * * @tc.name: Rdb_SqlitConnectionPoolTest_001 * @tc.desc: Abnormal testCase for ConfigLocale @@ -422,11 +421,7 @@ HWTEST_F(RdbStoreImplTest, Rdb_SqlitConnectionPoolTest_001, TestSize.Level2) std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); EXPECT_EQ(E_OK, errCode); - // error condition does not affect the current program - errCode = store->ConfigLocale("AbnormalTest"); - EXPECT_EQ(E_OK, errCode); - - SqliteConnectionPool* connectionPool = SqliteConnectionPool::Create(config, errCode); + auto connectionPool = SqliteConnectionPool::Create(config, errCode); EXPECT_NE(nullptr, connectionPool); EXPECT_EQ(E_OK, errCode); @@ -437,10 +432,7 @@ HWTEST_F(RdbStoreImplTest, Rdb_SqlitConnectionPoolTest_001, TestSize.Level2) EXPECT_EQ(OHOS::NativeRdb::E_NO_ROW_IN_QUERY, errCode); RdbHelper::DeleteRdbStore(DATABASE_NAME); - connectionPool->ReleaseConnection(connection); - delete connectionPool; } -#endif /* * * @tc.name: Rdb_SqlitConnectionPoolTest_002 @@ -454,23 +446,21 @@ HWTEST_F(RdbStoreImplTest, Rdb_SqlitConnectionPoolTest_002, TestSize.Level2) RdbStoreConfig config(DATABASE_NAME); config.SetReadConSize(1); config.SetStorageMode(StorageMode::MODE_DISK); - SqliteConnectionPool* connectionPool = SqliteConnectionPool::Create(config, errCode); + auto connectionPool = SqliteConnectionPool::Create(config, errCode); EXPECT_NE(nullptr, connectionPool); EXPECT_EQ(E_OK, errCode); - // repeat AcquireReadConnection without release + // repeat AcquireReader without release auto connection = connectionPool->AcquireConnection(true); EXPECT_NE(nullptr, connection); connection = connectionPool->AcquireConnection(true); EXPECT_EQ(nullptr, connection); - connectionPool->ReleaseConnection(connection); - // repeat AcquireWriteConnection without release + // repeat AcquireWriter without release connection = connectionPool->AcquireConnection(false); EXPECT_NE(nullptr, connection); connection = connectionPool->AcquireConnection(false); EXPECT_EQ(nullptr, connection); - connectionPool->ReleaseConnection(connection); // repeat AcquireTransaction without release errCode = connectionPool->AcquireTransaction(); @@ -478,8 +468,6 @@ HWTEST_F(RdbStoreImplTest, Rdb_SqlitConnectionPoolTest_002, TestSize.Level2) errCode = connectionPool->AcquireTransaction(); EXPECT_NE(E_OK, errCode); connectionPool->ReleaseTransaction(); - - delete connectionPool; } @@ -495,7 +483,7 @@ HWTEST_F(RdbStoreImplTest, Rdb_SqlitConnectionPoolTest_0023, TestSize.Level2) RdbStoreConfig config(DATABASE_NAME); config.SetReadConSize(1); config.SetStorageMode(StorageMode::MODE_DISK); - SqliteConnectionPool* connectionPool = SqliteConnectionPool::Create(config, errCode); + auto connectionPool = SqliteConnectionPool::Create(config, errCode); EXPECT_NE(nullptr, connectionPool); EXPECT_EQ(E_OK, errCode); @@ -508,14 +496,11 @@ HWTEST_F(RdbStoreImplTest, Rdb_SqlitConnectionPoolTest_0023, TestSize.Level2) auto connection = connectionPool->AcquireConnection(false); errCode = connectionPool->ChangeDbFileForRestore(newPath, backupPath, newKey); EXPECT_EQ(E_ERROR, errCode); - connectionPool->ReleaseConnection(connection); // newPath == currentPath, idleReadConnectionCount != readConnectionCount connection = connectionPool->AcquireConnection(true); errCode = connectionPool->ChangeDbFileForRestore(newPath, backupPath, newKey); EXPECT_EQ(E_ERROR, errCode); - connectionPool->ReleaseConnection(connection); - // newPath == currentPath errCode = connectionPool->ChangeDbFileForRestore(newPath, backupPath, newKey); @@ -524,8 +509,6 @@ HWTEST_F(RdbStoreImplTest, Rdb_SqlitConnectionPoolTest_0023, TestSize.Level2) const std::string newPath2 = RDB_TEST_PATH + "tmp.db"; errCode = connectionPool->ChangeDbFileForRestore(newPath2, backupPath, newKey); EXPECT_EQ(E_ERROR, errCode); - - delete connectionPool; } HWTEST_F(RdbStoreImplTest, NotifyDataChangeTest_001, TestSize.Level2) diff --git a/relational_store/test/native/rdb/unittest/rdb_store_rekey_test.cpp b/relational_store/test/native/rdb/unittest/rdb_store_rekey_test.cpp index 7e1db0b820e54fae22175780ed5ee4a85ede7ca9..11108f3bcc3981ce5125de6f96ca65d29bb1819a 100644 --- a/relational_store/test/native/rdb/unittest/rdb_store_rekey_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_store_rekey_test.cpp @@ -102,7 +102,7 @@ void RdbRekeyTest::TearDown() RdbHelper::DeleteRdbStore(RdbRekeyTest::encryptedDatabasePath); } -std::string RdbRekeyTest::RemoveSuffix(const string &name) +std::string RdbRekeyTest::RemoveSuffix(const std::string &name) { std::string suffix(".db"); auto pos = name.rfind(suffix); diff --git a/udmf/framework/common/graph.cpp b/udmf/framework/common/graph.cpp index e9d740fc888a4f83310f0d4299720a2458b6bf02..7ac8a11adbdcc27f9a1d25b8228ca20076990935 100644 --- a/udmf/framework/common/graph.cpp +++ b/udmf/framework/common/graph.cpp @@ -12,7 +12,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include #include "graph.h" namespace OHOS { namespace UDMF { diff --git a/udmf/interfaces/innerkits/client/utd_client.h b/udmf/interfaces/innerkits/client/utd_client.h index 30c5882988f72e1c8ecad9e589b8ea3f25a1a241..0c1bfb7d86117e974f4cee8b53047f811931c7bd 100644 --- a/udmf/interfaces/innerkits/client/utd_client.h +++ b/udmf/interfaces/innerkits/client/utd_client.h @@ -19,7 +19,6 @@ #include #include #include -#include #include "utd_common.h" #include "preset_type_descriptors.h" #include "type_descriptor.h" diff --git a/udmf/interfaces/innerkits/common/error_code.h b/udmf/interfaces/innerkits/common/error_code.h index 9845fcc130c9cfedf413f354955ba32d1e750fdb..75c6eff64af2cb1230f14caedb0d824713718228 100644 --- a/udmf/interfaces/innerkits/common/error_code.h +++ b/udmf/interfaces/innerkits/common/error_code.h @@ -17,7 +17,6 @@ #define UDMF_ERROR_CODE_H #include - #include #include #include