diff --git a/adapter/cloud_adapter_example/include/dk_container.h b/adapter/cloud_adapter_example/include/dk_container.h index 4c6c9340915714367f1f00e658cc7f727b67c22e..f5b909164e83208d2cb00bd5dfe348aa8cf718b8 100644 --- a/adapter/cloud_adapter_example/include/dk_container.h +++ b/adapter/cloud_adapter_example/include/dk_container.h @@ -68,9 +68,9 @@ public: containerName_ = containerName; driveKit_ = driveKit; if (driveKit_) { - publicDatabase_ = std::make_shared(shared_from_this()); - privateDatabase_ = std::make_shared(shared_from_this()); - sharedDatabase_ = std::make_shared(shared_from_this()); + publicDatabase_ = std::make_shared(); + privateDatabase_ = std::make_shared(); + sharedDatabase_ = std::make_shared(); } } ~DKContainer() = default; diff --git a/adapter/cloud_adapter_example/include/dk_database.h b/adapter/cloud_adapter_example/include/dk_database.h index 245d1b05a0dcb8c9cb763e7656f49a0a3355969d..64fcc3b6c837292216cdf48c32e2cfd264acc08e 100644 --- a/adapter/cloud_adapter_example/include/dk_database.h +++ b/adapter/cloud_adapter_example/include/dk_database.h @@ -85,8 +85,8 @@ using DKQueryCursor = std::string; class DKContainer; class DKDatabase : public std::enable_shared_from_this { public: - DKDatabase(std::shared_ptr container) : container_(container) {} - ~DKDatabase() {} + DKDatabase() = default; + ~DKDatabase() = default; using SaveRecordsCallback = std::function, std::shared_ptr, @@ -182,7 +182,6 @@ public: NewAssetReadSession(DKRecordType recordType, DKRecordId recordId, DKFieldKey assetKey, DKAssetPath assetPath); private: - std::shared_ptr container_; DKContainerName containerName_; }; } // namespace DriveKit diff --git a/adapter/cloud_adapter_example/src/dk_database.cpp b/adapter/cloud_adapter_example/src/dk_database.cpp index 5d07979413cbe809f03467d3a6d8e47ed1386c2e..0e3432ad0897a7ac4f7a6165396946a04b88f774 100644 --- a/adapter/cloud_adapter_example/src/dk_database.cpp +++ b/adapter/cloud_adapter_example/src/dk_database.cpp @@ -15,6 +15,7 @@ #include #include +#include #include "dk_context.h" #include "dk_database.h" @@ -25,6 +26,21 @@ DKLocalErrorCode DKDatabase::SaveRecords(std::shared_ptr context, DKSavePolicy policy, SaveRecordsCallback callback) { + /* mock */ + auto result = std::make_shared>(); + srand(time(nullptr)); + for (auto &record : records) { + DKRecordId recordId = std::to_string(rand() + 1); + DKRecordOperResult operResult; + operResult.SetDKRecord(record); + (*result)[recordId] = operResult; + } + + DKError err; + std::thread ([=]() { + callback(context, this->shared_from_this(), result, err); + }).detach(); + return DKLocalErrorCode::NO_ERROR; } DKLocalErrorCode DKDatabase::SaveRecord(std::shared_ptr context, diff --git a/services/cloudsyncservice/BUILD.gn b/services/cloudsyncservice/BUILD.gn index be1963d67c4a5a055a21454973f8e320a279748c..af26f34b53fcbf0b0d6a490d98be9421b94bf88a 100644 --- a/services/cloudsyncservice/BUILD.gn +++ b/services/cloudsyncservice/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright (C) 2022 Huawei Device Co., Ltd. +# Copyright (C) 2023 Huawei Device Co., Ltd. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at @@ -15,11 +15,30 @@ import("//build/ohos.gni") import("//foundation/filemanagement/dfs_service/distributedfile.gni") ohos_shared_library("cloudsync_sa") { - sources = [ + include_dirs = [ + "include", + "include/data_sync", + "include/data_sync/gallery_data_sync", + "../../adapter/cloud_adapter_example/include", + ] + + data_sync = [ "src/data_sync/data_sync_manager.cpp", - "src/data_sync/data_syncer.cpp", - "src/data_sync/gallery/gallery_data_syncer.cpp", "src/data_sync/sync_state_manager.cpp", + "src/data_sync/data_provider.cpp", + "src/data_sync/data_syncer.cpp", + "src/data_sync/task.cpp", + "src/data_sync/sdk_helper.cpp", + ] + + gallery_data_sync = [ + "src/data_sync/gallery_data_sync/gallery_data_syncer.cpp", + "src/data_sync/gallery_data_sync/file_data_provider.cpp", + "src/data_sync/gallery_data_sync/album_data_provider.cpp", + "src/data_sync/gallery_data_sync/data_convertor.cpp", + ] + + sources = [ "src/ipc/cloud_sync_callback_manager.cpp", "src/ipc/cloud_sync_callback_proxy.cpp", "src/ipc/cloud_sync_service.cpp", @@ -30,20 +49,23 @@ ohos_shared_library("cloudsync_sa") { "src/sync_rule/network_status.cpp", ] + sources += data_sync + sources += gallery_data_sync + defines = [ "LOG_DOMAIN=0xD004307", "LOG_TAG=\"CLOUDSYNC_SA\"", ] - include_dirs = [ "include" ] - deps = [ "${utils_path}:libdistributedfileutils" ] external_deps = [ "dfs_service:cloudsync_kit_inner", "init:libbegetutil", "ipc:ipc_core", + "media_library:cloud_sync_header", "netmanager_base:net_conn_manager_if", + "relational_store:native_rdb", "safwk:system_ability_fwk", "samgr:samgr_proxy", ] diff --git a/services/cloudsyncservice/include/data_sync/data_provider.h b/services/cloudsyncservice/include/data_sync/data_provider.h new file mode 100644 index 0000000000000000000000000000000000000000..21f3b624ae59345fa4a6cbcd14e1f250bce584ef --- /dev/null +++ b/services/cloudsyncservice/include/data_sync/data_provider.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DATA_PROVIDER_H +#define DATA_PROVIDER_H + +#include +#include + +#include "rdb_helper.h" +#include "values_bucket.h" +#include "result_set.h" +#include "abs_rdb_predicates.h" + +#include "sdk_helper.h" + +namespace OHOS { +namespace FileManagement { +namespace CloudSync { +class DataProvider { +public: + /* download */ + virtual int32_t GetFetchCondition() = 0; + virtual int32_t OnFetchRecords(const std::vector &records) = 0; + + /* upload */ + virtual int32_t GetCreatedRecords(std::vector &records) = 0; + virtual int32_t GetDeletedRecords(std::vector &records) = 0; + virtual int32_t GetModifiedRecords(std::vector &records) = 0; + + /* upload callback */ + virtual int32_t OnCreateRecords(const std::map &map) = 0; + virtual int32_t OnDeleteRecords(const std::map &map) = 0; + virtual int32_t OnModifyRecords(const std::map &map) = 0; + + /* cursor */ + virtual int32_t SetCursor(); + virtual int32_t GetCursor(); + + /* file */ + virtual int32_t DownloadFiles(); + virtual int32_t OnDownloadFiles(); +}; + +class RdbProvider : public DataProvider { +protected: + /* init */ + RdbProvider(const std::string &table, std::shared_ptr rdb) : + rdb_(rdb), tableName_(table) {} + virtual ~RdbProvider() = default; + + /* insert, delete, update, query */ + virtual int32_t Insert(int64_t &outRowId, const NativeRdb::ValuesBucket &initialValues); + virtual int32_t Update(int &changedRows, const NativeRdb::ValuesBucket &values, + const std::string &whereClause = "", + const std::vector &whereArgs = std::vector()); + virtual int32_t Delete(int &deletedRows, const std::string &whereClause = "", + const std::vector &whereArgs = std::vector()); + virtual std::unique_ptr Query( + const NativeRdb::AbsRdbPredicates &predicates,const std::vector &columns); + +private: + std::shared_ptr rdb_; + std::string tableName_; +}; +} // namespace CloudSync +} // namespace FileManagement +} // namespace OHOS +#endif // DATA_PROVIDER_H \ No newline at end of file diff --git a/services/cloudsyncservice/include/data_sync/data_syncer.h b/services/cloudsyncservice/include/data_sync/data_syncer.h index 2e5ca6a329b62c57d38a173b9f1ce91487d23983..8ead771ff5b9a0f86b5c3a6366bb65e4b13c320b 100644 --- a/services/cloudsyncservice/include/data_sync/data_syncer.h +++ b/services/cloudsyncservice/include/data_sync/data_syncer.h @@ -16,39 +16,119 @@ #ifndef OHOS_FILEMGMT_DATA_SYNCER_H #define OHOS_FILEMGMT_DATA_SYNCER_H -#include +#include +#include +#include +#include +#include "sdk_helper.h" +#include "data_provider.h" +#include "task.h" #include "cloud_sync_constants.h" #include "data_sync/sync_state_manager.h" -namespace OHOS::FileManagement::CloudSync { +namespace OHOS { +namespace FileManagement { +namespace CloudSync { enum class SyncTriggerType : int32_t { APP_TRIGGER, CLOUD_TRIGGER, PENDING_TRIGGER, }; + class DataSyncer { public: DataSyncer(const std::string appPackageName, const int32_t userId); - virtual ~DataSyncer(){}; + virtual ~DataSyncer() = default; + + /* sync */ + virtual int32_t StartSync(bool forceFlag, SyncTriggerType triggerType); + virtual int32_t StopSync(SyncTriggerType triggerType); - virtual void StartSync(bool forceFlag, SyncTriggerType triggerType) = 0; - virtual void StopSync(SyncTriggerType triggerType) = 0; + /* properties */ std::string GetAppPackageName() const; int32_t GetUserId() const; protected: - void OnSyncComplete(const int32_t code, const SyncType type); - std::shared_ptr GetSyncStateManager(); + /* init */ + int32_t Init(const std::string &name); + + /* download */ + int32_t Pull(std::shared_ptr provider); + + /* upload */ + int32_t Push(std::shared_ptr provider); + + /* schedule */ + virtual void Schedule() = 0; + void Abort(); + + /* notify */ + void CompletePull(); + void CompletePush(); + void CompleteAll(const int32_t code, const SyncType type); + void SyncStateChangedNotify(const SyncType type, const SyncPromptState state); private: + /* download */ + void PullRecords(std::shared_ptr context); + + /* dowload callback */ + void OnFetchRecords(const std::shared_ptr context, + const std::shared_ptr> records); + + /* upload */ + void CreateRecords(std::shared_ptr context); + void DeleteRecords(std::shared_ptr context); + void ModifyRecords(std::shared_ptr context); + + /* upload callback */ + void OnCreateRecords(std::shared_ptr, + std::shared_ptr, + std::shared_ptr>, + const DriveKit::DKError &); + void OnDeleteRecords(std::shared_ptr, + std::shared_ptr, + std::shared_ptr>, + const DriveKit::DKError &); + void OnModifyRecords(std::shared_ptr, + std::shared_ptr, + std::shared_ptr>, + const DriveKit::DKError &); + + /* task */ + int32_t CommitTask(std::shared_ptr t); + int32_t AddTask(std::shared_ptr t); + int32_t StartTask(std::shared_ptr t, TaskAction action); + void CompleteTask(std::shared_ptr t); + + void BeginTransaction(); + void EndTransaction(); + + /* async task wrapper */ + int32_t AsyncRun(std::shared_ptr context, + void(DataSyncer::*f)(std::shared_ptr)); + template + std::function AsyncCallback(RET(T::*f)(ARGS...)); + + /* prompt state */ SyncPromptState GetSyncPromptState(const int32_t code); + /* identifier */ const std::string appPackageName_; const int32_t userId_; - std::shared_ptr syncStateManager_; -}; -} // namespace OHOS::FileManagement::CloudSync -#endif // OHOS_FILEMGMT_DATA_SYNCER_H \ No newline at end of file + /* state management */ + SyncStateManager syncStateManager_; + + /* task management */ + std::shared_ptr taskManager_; + + /* sdk */ + SdkHelper sdkHelper_; +}; +} // namespace CloudSync +} // namespace FileManagement +} // namespace OHOS +#endif // OHOS_FILEMGMT_DATA_SYNCER_H diff --git a/services/cloudsyncservice/include/data_sync/gallery_data_sync/album_data_provider.h b/services/cloudsyncservice/include/data_sync/gallery_data_sync/album_data_provider.h new file mode 100644 index 0000000000000000000000000000000000000000..d7f79a42a36beada70ef620e5c26d170d96db6f0 --- /dev/null +++ b/services/cloudsyncservice/include/data_sync/gallery_data_sync/album_data_provider.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ALBUM_DATA_PROVIDER_H +#define ALBUM_DATA_PROVIDER_H + +#include "data_provider.h" +#include "data_convertor.h" + +namespace OHOS { +namespace FileManagement { +namespace CloudSync { +class AlbumDataProvider : public RdbProvider { +public: + AlbumDataProvider(std::shared_ptr rdb); + virtual ~AlbumDataProvider() = default; + + /* download */ + virtual int32_t OnFetchRecords(const std::vector &records) override; + virtual int32_t GetFetchCondition() override; + + /* upload */ + virtual int32_t GetCreatedRecords(std::vector &records) override; + virtual int32_t GetDeletedRecords(std::vector &records) override; + virtual int32_t GetModifiedRecords(std::vector &records) override; + + virtual int32_t OnCreateRecords(const std::map &map) override; + virtual int32_t OnDeleteRecords(const std::map &map) override; + virtual int32_t OnModifyRecords(const std::map &map) override; + +private: + const std::string tableName_ = "albums"; +}; +} // namespace CloudSync +} // namespace FileManagement +} // namespace OHOS +#endif // ALBUM_DATA_PROVIDER_H \ No newline at end of file diff --git a/services/cloudsyncservice/include/data_sync/gallery_data_sync/data_convertor.h b/services/cloudsyncservice/include/data_sync/gallery_data_sync/data_convertor.h new file mode 100644 index 0000000000000000000000000000000000000000..234d5df08089622afce64d232c0f200b2c119d1b --- /dev/null +++ b/services/cloudsyncservice/include/data_sync/gallery_data_sync/data_convertor.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DATA_CONVERTOR_H +#define DATA_CONVERTOR_H + +#include + +#include "values_bucket.h" +#include "result_set.h" + +#include "sdk_helper.h" + +namespace OHOS { +namespace FileManagement { +namespace CloudSync { +enum DataType : int32_t { + INT, + LONG, + STRING, + DOUBLE, + BOOL, + BLOB, + ASSET +}; + +class DataConvertor { +public: + DataConvertor(const std::vector localColumns, + const std::vector cloudColumns, + const std::vector types, int32_t size) : localColumns_(localColumns), + cloudColumns_(cloudColumns), types_(types), size_(size) {} + virtual ~DataConvertor() = default; + + int32_t ResultSetToRecords(const std::unique_ptr resultSet, + std::vector &records) const; + int32_t RecordToValueBucket(const DriveKit::DKRecord &record, + NativeRdb::ValuesBucket &valueBucket) const; + int32_t RecordsToValueBuckets(const std::vector &records, + std::vector &valueBuckets) const; + + const std::vector &GetLocalColumns() const + { + return localColumns_; + } + + const std::vector &GetCloudColumns() const + { + return cloudColumns_; + } + + const std::vector &GetTypes() const + { + return types_; + } + + int32_t GetSize() const + { + return size_; + } + +private: + const std::vector localColumns_; + const std::vector cloudColumns_; + const std::vector types_; + const int32_t size_; +}; +} // namespace CloudSync +} // namespace FileManagement +} // namespace OHOS +#endif // DATA_CONVERTOR_H \ No newline at end of file diff --git a/services/cloudsyncservice/include/data_sync/gallery_data_sync/file_data_provider.h b/services/cloudsyncservice/include/data_sync/gallery_data_sync/file_data_provider.h new file mode 100644 index 0000000000000000000000000000000000000000..dc2799959a15d89898e70cd5f5a02abae70e3954 --- /dev/null +++ b/services/cloudsyncservice/include/data_sync/gallery_data_sync/file_data_provider.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FILE_DATA_PROVIDER_H +#define FILE_DATA_PROVIDER_H + +#include "data_provider.h" +#include "data_convertor.h" + +namespace OHOS { +namespace FileManagement { +namespace CloudSync { +class FileDataProvider : public RdbProvider { +public: + FileDataProvider(std::shared_ptr rdb); + virtual ~FileDataProvider() = default; + + /* download */ + int32_t GetFetchCondition() override; + int32_t OnFetchRecords(const std::vector &records) override; + + /* upload */ + int32_t GetCreatedRecords(std::vector &records) override; + int32_t GetDeletedRecords(std::vector &records) override; + int32_t GetModifiedRecords(std::vector &records) override; + + /* callback */ + int32_t OnCreateRecords(const std::map &map) override; + int32_t OnDeleteRecords(const std::map &map) override; + int32_t OnModifyRecords(const std::map &map) override; + + /* reset */ + void Reset(); + +private: + static const std::string TABLE_NAME; + static const int32_t LIMIT_SIZE; + + /* create */ + int32_t createOffset_ = 0; + const DataConvertor createConvertor_ = { + { "file_id", "data", "size", "data" }, + { "file_id", "data", "size", "asset" }, + { INT, STRING, INT, ASSET }, + 3 + }; + const DataConvertor onCreateConvertor_ = { + { "file_id", "data", "size" }, + { "file_id", "data", "size" }, + { INT, STRING, INT }, + 3 + }; + + /* delete */ + int32_t deleteOffset_ = 0; + const DataConvertor deleteConvertor_ = { + { "file_id", "data", "size" }, + { "id", "path", "size" }, + { INT, STRING, INT }, + 3 + }; + const DataConvertor onDeleteConvertor_ = { + { "file_id", "data", "size" }, + { "id", "path", "size" }, + { INT, STRING, INT }, + 3 + }; + + /* update */ + int32_t updateOffset_ = 0; + const DataConvertor updateConvertor_ = { + { "file_id", "data", "size" }, + { "id", "path", "size" }, + { INT, STRING, INT }, + 3 + }; + const DataConvertor onUpdateConvertor_ = { + { "file_id", "data", "size" }, + { "id", "path", "size" }, + { INT, STRING, INT }, + 3 + }; + + /* fetch */ +}; +} // namespace CloudSync +} // namespace FileManagement +} // namespace OHOS +#endif // FILE_DATA_PROVIDER_H \ No newline at end of file diff --git a/services/cloudsyncservice/include/data_sync/gallery_data_sync/gallery_data_syncer.h b/services/cloudsyncservice/include/data_sync/gallery_data_sync/gallery_data_syncer.h new file mode 100644 index 0000000000000000000000000000000000000000..ef3e7fec9569ad1409ec4a42c65476e180aa0d21 --- /dev/null +++ b/services/cloudsyncservice/include/data_sync/gallery_data_sync/gallery_data_syncer.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef GALLERY_DATA_SYNCER_H +#define GALLERY_DATA_SYNCER_H + +#include "data_syncer.h" + +#include "functional" + +#include "file_data_provider.h" + +namespace OHOS { +namespace FileManagement { +namespace CloudSync { +class GalleryDataSyncer : public DataSyncer, std::enable_shared_from_this { +public: + GalleryDataSyncer(const std::string appPackageName, const int32_t userId); + virtual ~GalleryDataSyncer() = default; + + virtual void Schedule() override; + +private: + enum { + BEGIN, + PREPARE, + DOWNLOADALBUM, + DOWNLOADFILE, + UPLOADALBUM, + UPLOADFILE, + WAIT, + END + }; + + int32_t Prepare(); + int32_t DownloadAlbum(); + int32_t DownloadFile(); + int32_t UploadAlbum(); + int32_t UploadFile(); + int32_t Wait(); + int32_t Complete(); + + /* stage */ + int32_t stage_ = BEGIN; + + /* rdb */ + const std::string DATA_APP_EL2= "/data/app/el2/"; + const std::string DATABASE_DIR = "/database/com.ohos.medialibrary.medialibrarydata/rdb/"; + const std::string DATABASE_NAME = "media_library.db"; + const std::string BUNDLE_NAME = "com.ohos.medialibrary.medialibrarydata"; + const int32_t CONNECT_SIZE = 10; + std::shared_ptr rdb_; + + /* provider */ + std::shared_ptr fileProvider_; +}; + +class RdbCallback : public NativeRdb::RdbOpenCallback { +public: + virtual int32_t OnCreate(NativeRdb::RdbStore &r) override + { + return 0; + } + + virtual int32_t OnUpgrade(NativeRdb::RdbStore &r, int32_t oldVersion, + int32_t newVersion) override + { + return 0; + } +}; +} // namespace CloudSync +} // namespace FileManagement +} // namespace OHOS +#endif // GALLERY_DATA_SYNCER_H diff --git a/services/cloudsyncservice/include/data_sync/sdk_helper.h b/services/cloudsyncservice/include/data_sync/sdk_helper.h new file mode 100644 index 0000000000000000000000000000000000000000..b02af271d2c98322a9a55e6067ce9607675f3223 --- /dev/null +++ b/services/cloudsyncservice/include/data_sync/sdk_helper.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SDK_HELPER_H +#define SDK_HELPER_H + +#include +#include + +#include "drive_kit.h" +#include "dk_database.h" + +namespace OHOS { +namespace FileManagement { +namespace CloudSync { + +class SdkHelper { +public: + SdkHelper(int32_t userId, std::string appPackageName); + ~SdkHelper() = default; + + /* record download */ + int32_t FetchRecords(std::shared_ptr context, + std::function context, + std::shared_ptr>)> callback); + + /* record upload */ + int32_t CreateRecords(std::shared_ptr context, + std::vector &records, + std::function, + std::shared_ptr, + std::shared_ptr>, + const DriveKit::DKError &)> callback + ); + + int32_t DeleteRecords(std::shared_ptr context, + std::vector &records, + std::function, + std::shared_ptr, + std::shared_ptr>, + const DriveKit::DKError &)> callback + ); + + int32_t ModifyRecords(std::shared_ptr context, + std::vector &records, + std::function, + std::shared_ptr, + std::shared_ptr>, + const DriveKit::DKError &)> callback + ); + + /* asset download */ + int32_t DownloadAssets(std::shared_ptr context, + std::vector recordIds, int32_t id, + std::function context, + std::shared_ptr>)> resultCallback); + + int32_t CancelDownloadAssets(int32_t id); + +private: + std::shared_ptr database_; +}; +} // namespace CloudSync +} // namespace FileManagement +} // namespace OHOS +#endif // SDK_HELPER_H diff --git a/services/cloudsyncservice/include/data_sync/task.h b/services/cloudsyncservice/include/data_sync/task.h new file mode 100644 index 0000000000000000000000000000000000000000..70b9d346fdd381775dd182df1a7b3f901e242d74 --- /dev/null +++ b/services/cloudsyncservice/include/data_sync/task.h @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef TASK_H +#define TASK_H + +#include +#include +#include +#include +#include + +#include "thread_pool.h" + +#include "sdk_helper.h" +#include "data_provider.h" + +namespace OHOS { +namespace FileManagement { +namespace CloudSync { +class TaskContext : public DriveKit::DKContext { +public: + TaskContext(std::shared_ptr provider) : provider_(provider) + {} + + std::shared_ptr GetProvider() + { + return provider_; + } + +private: + std::shared_ptr provider_; +}; + +constexpr int32_t INVALID_ID = -1; + +using TaskAction = std::function)>; + +class Task { +public: + Task(std::shared_ptr context, TaskAction action) : context_(context), + action_(action) {} + virtual ~Task() = default; + + virtual void Run() + { + action_(context_); + } + + void SetAction(TaskAction action) + { + action_ = action; + } + + void SetId(int32_t id) + { + id_ = id; + } + + int32_t GetId() + { + return id_; + } + +private: + int32_t id_; + std::shared_ptr context_; + TaskAction action_; +}; + +class TaskManager { +public: + TaskManager(std::function callback); + virtual ~TaskManager(); + + int32_t AddTask(std::shared_ptr t); + int32_t StartTask(std::shared_ptr t, TaskAction action); + int32_t CommitTask(std::shared_ptr t); + void CompleteTask(int32_t id); + + /* dummy */ + void CommitDummyTask(); + void CompleteDummyTask(); + + /* reset and stop */ + void Reset(); + bool StopAndWaitFor(); + +private: + int32_t GenerateTaskId(); + + /* thread pool */ + ThreadPool pool_ = ThreadPool("TaskManager"); + const int32_t MAX_THREAD_NUM = 4; + const int32_t WAIT_FOR_SECOND = 30; + + /* stop */ + bool stopFlag_ = false; + + /* id */ + std::atomic currentId_ = 0; + + /* task list */ + std::shared_mutex mutex_; + std::list> taskList_; + /* specific cv for shared_mutex */ + std::condition_variable_any cv_; + + /* callback */ + std::function callback_; +}; +} // namespace CloudSync +} // namespace FileManagement +} // namespace OHOS +#endif // TASK_H diff --git a/services/cloudsyncservice/include/ipc/cloud_sync_callback_manager.h b/services/cloudsyncservice/include/ipc/cloud_sync_callback_manager.h index 7b7302189128e2fcad049253c472e3779b70064d..48999960c362aca94b57bb3091f88badac9b5e65 100644 --- a/services/cloudsyncservice/include/ipc/cloud_sync_callback_manager.h +++ b/services/cloudsyncservice/include/ipc/cloud_sync_callback_manager.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/services/cloudsyncservice/include/ipc/cloud_sync_callback_proxy.h b/services/cloudsyncservice/include/ipc/cloud_sync_callback_proxy.h index 8623056724f15794e6e64cf5b680406795a01f4d..a60e251c53d9f12fb566d35bf2f58a99377d8e23 100644 --- a/services/cloudsyncservice/include/ipc/cloud_sync_callback_proxy.h +++ b/services/cloudsyncservice/include/ipc/cloud_sync_callback_proxy.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/services/cloudsyncservice/include/ipc/cloud_sync_service.h b/services/cloudsyncservice/include/ipc/cloud_sync_service.h index e6bdcabeed0ae19fc7fcb52e05d45891fe1b9fe7..7a8235b9bc8835bc9fd51cba2f50ebcee9e9df93 100644 --- a/services/cloudsyncservice/include/ipc/cloud_sync_service.h +++ b/services/cloudsyncservice/include/ipc/cloud_sync_service.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/services/cloudsyncservice/include/ipc/cloud_sync_service_stub.h b/services/cloudsyncservice/include/ipc/cloud_sync_service_stub.h index f2f7dfbe04f233418e3ff1b376929f3235df4ad2..58dccc59d64b92dd243a650ef1603949b134c8f7 100644 --- a/services/cloudsyncservice/include/ipc/cloud_sync_service_stub.h +++ b/services/cloudsyncservice/include/ipc/cloud_sync_service_stub.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/services/cloudsyncservice/include/data_sync/gallery/gallery_data_syncer.h b/services/cloudsyncservice/src/data_sync/data_provider.cpp similarity index 33% rename from services/cloudsyncservice/include/data_sync/gallery/gallery_data_syncer.h rename to services/cloudsyncservice/src/data_sync/data_provider.cpp index 6283ea63a5470ca5253185e96e019725bf79dfe3..1c12d83b19e628db806fdb360e662e462832307f 100644 --- a/services/cloudsyncservice/include/data_sync/gallery/gallery_data_syncer.h +++ b/services/cloudsyncservice/src/data_sync/data_provider.cpp @@ -13,24 +13,58 @@ * limitations under the License. */ -#ifndef OHOS_FILEMGMT_GALLERY_DATA_SYNCER_H -#define OHOS_FILEMGMT_GALLERY_DATA_SYNCER_H +#include "data_provider.h" -#include "data_sync/data_syncer.h" +#include "dfs_error.h" +#include "utils_log.h" -namespace OHOS::FileManagement::CloudSync { -class GalleryDataSyncer final : public DataSyncer { -public: - GalleryDataSyncer(const std::string appPackageName, const int32_t userId) : DataSyncer(appPackageName, userId) {} - ~GalleryDataSyncer() = default; +namespace OHOS { +namespace FileManagement { +namespace CloudSync { +using namespace std; +using namespace NativeRdb; - void StartSync(bool forceFlag, SyncTriggerType triggerType) override; - void StopSync(SyncTriggerType triggerType) override; +int32_t DataProvider::SetCursor() +{ + return 0; +} - int32_t UploadFile(bool forceFlag); +int32_t DataProvider::GetCursor() +{ + return 0; +} -private: -}; -} // namespace OHOS::FileManagement::CloudSync +int32_t DataProvider::DownloadFiles() +{ + return 0; +} -#endif // OHOS_FILEMGMT_GALLERY_DATA_SYNCER_H \ No newline at end of file +int32_t DataProvider::OnDownloadFiles() +{ + return 0; +} + +int32_t RdbProvider::Insert(int64_t &outRowId, const ValuesBucket &initiavalues) +{ + return rdb_->Insert(outRowId, tableName_, initiavalues); +} + +int32_t RdbProvider::Update(int &changedRows, const ValuesBucket &values, + const string &whereClause, const vector &whereArgs) +{ + return rdb_->Update(changedRows, tableName_, values, whereClause, whereArgs); +} + +int32_t RdbProvider::Delete(int &deletedRows, const string &whereClause, const vector &whereArgs) +{ + return rdb_->Delete(deletedRows, tableName_, whereClause, whereArgs); +} + +unique_ptr RdbProvider::Query( + const NativeRdb::AbsRdbPredicates &predicates, const std::vector &columns) +{ + return rdb_->Query(predicates, columns); +} +} // namespace CloudSync +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/services/cloudsyncservice/src/data_sync/data_sync_manager.cpp b/services/cloudsyncservice/src/data_sync/data_sync_manager.cpp index 1e58722281e79fe31b2c140b12b7c7622a94d0b0..d5bd680bf69a57bf07b0f2a2d0ebb190477bb2c7 100644 --- a/services/cloudsyncservice/src/data_sync/data_sync_manager.cpp +++ b/services/cloudsyncservice/src/data_sync/data_sync_manager.cpp @@ -17,7 +17,7 @@ #include -#include "data_sync/gallery/gallery_data_syncer.h" +#include "gallery_data_syncer.h" #include "dfs_error.h" #include "ipc/cloud_sync_callback_manager.h" #include "sync_rule/battery_status.h" diff --git a/services/cloudsyncservice/src/data_sync/data_syncer.cpp b/services/cloudsyncservice/src/data_sync/data_syncer.cpp index 3a93e1a8213cd98e4fbf163df07f71ad7e731651..c4c25f6382b0d8f6d7d47ad2d7a9a2b9d497d476 100644 --- a/services/cloudsyncservice/src/data_sync/data_syncer.cpp +++ b/services/cloudsyncservice/src/data_sync/data_syncer.cpp @@ -12,21 +12,455 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include "data_sync/data_syncer.h" -#include +#include "data_syncer.h" + +#include #include "dfs_error.h" +#include "utils_log.h" +#include "sdk_helper.h" #include "ipc/cloud_sync_callback_manager.h" #include "sync_rule/battery_status.h" -#include "utils_log.h" -namespace OHOS::FileManagement::CloudSync { +namespace OHOS { +namespace FileManagement { +namespace CloudSync { using namespace std; +using namespace placeholders; +using namespace DriveKit; + DataSyncer::DataSyncer(const std::string appPackageName, const int32_t userId) - : appPackageName_(appPackageName), userId_(userId) + : appPackageName_(appPackageName), userId_(userId), sdkHelper_(userId, appPackageName) +{ + taskManager_ = make_shared(bind(&DataSyncer::Schedule, this)); + if (taskManager_ == nullptr) { + LOGE("init task manager err"); + } +} + +int32_t DataSyncer::AsyncRun(std::shared_ptr context, + void(DataSyncer::*f)(std::shared_ptr)) +{ + shared_ptr task = make_shared(context, + [this, f](shared_ptr ctx) { + (this->*f)(ctx); + } + ); + if (task == nullptr) { + LOGE("async run alloc task fail"); + return E_MEMORY; + } + + int32_t ret = CommitTask(task); + if (ret != E_OK) { + LOGE("async run commit task err %{public}d", ret); + return ret; + } + + return E_OK; +} + +/* + * About ARGS... + * <1> async execute requires value-copy or shared_ptr like input parameters, + * but no reference for lifecycle consideration. + * <2> In addition, [=] requires the wrapped function with const parameters. + */ +template +function DataSyncer::AsyncCallback(RET(T::*f)(ARGS...)) +{ + shared_ptr task = make_shared(nullptr, nullptr); + if (task == nullptr) { + LOGE("async callback alloc task err"); + return nullptr; + } + + int32_t ret = AddTask(task); + if (ret != E_OK) { + LOGE("async callback add task err %{public}d", ret); + return nullptr; + } + + return [this, f, task](ARGS... args) -> RET { + int32_t ret = StartTask(task, [this, f, args...](shared_ptr) { + (this->*f)(args...); + }); + if (ret != E_OK) { + LOGE("async callback start task err %{public}d", ret); + } + }; +} + +int32_t DataSyncer::StartSync(bool forceFlag, SyncTriggerType triggerType) +{ + LOGI("%{private}d %{public}s starts sync, isforceSync %{public}d, triggerType %{public}d", + userId_, appPackageName_.c_str(), forceFlag, triggerType); + + /* only one specific data sycner running at a time */ + if (syncStateManager_.IsPendingSync(forceFlag)) { + LOGI("syncing, pending sync"); + return E_PENDING; + } + + /* notify sync state */ + SyncStateChangedNotify(SyncType::ALL, SyncPromptState::SYNC_STATE_SYNCING); + + /* start data sync */ + Schedule(); + + return E_OK; +} + +int32_t DataSyncer::StopSync(SyncTriggerType triggerType) +{ + LOGI("%{private}d %{public}s stops sync, trigger stop sync, type:%{public}d", + userId_, appPackageName_.c_str(), triggerType); + + syncStateManager_.SetStopSyncFlag(); + Abort(); + + return E_OK; +} + +void DataSyncer::Abort() +{ + LOGI("%{private}d %{private}s aborts", userId_, appPackageName_.c_str()); + + /* stop all the tasks and wait for tasks' termination */ + if (!taskManager_->StopAndWaitFor()) { + LOGE("wait for tasks stop fail"); + } + + /* call the syncer manager's callback for notification */ +} + +int32_t DataSyncer::Pull(shared_ptr provider) +{ + LOGI("%{private}d %{private}s pull", userId_, appPackageName_.c_str()); + + shared_ptr context = make_shared(provider); + if (context == nullptr) { + LOGE("pull alloc context fail"); + return E_MEMORY; + } + + int32_t ret = AsyncRun(context, &DataSyncer::PullRecords); + if (ret != E_OK) { + LOGE("asyn run pull records err %{public}d", ret); + return ret; + } + + return E_OK; +} + +/* + * Although records from the cloud should be all pulled down before + * uploading the local change, conflicts might be rare in most cases, + * and the syncer would just move on. + */ +void DataSyncer::PullRecords(shared_ptr context) +{ + LOGI("%{private}d %{private}s pull records", userId_, appPackageName_.c_str()); + + /* get query condition */ + /* auto condition = provider->GetCondition(); */ + + auto callback = AsyncCallback(&DataSyncer::OnFetchRecords); + if (callback == nullptr) { + LOGE("wrap on fetch records fail"); + return; + } + int32_t ret = sdkHelper_.FetchRecords(context, callback); + if (ret != E_OK) { + LOGE("sdk fetch records err %{public}d", ret); + } +} + +void DataSyncer::OnFetchRecords(const shared_ptr context, + const shared_ptr> records) +{ + LOGI("%{private}d %{private}s on fetch records", userId_, appPackageName_.c_str()); + + auto ctx = static_pointer_cast(context); + + /* no more records */ + if (records->size() == 0) { + return; + } + + /* update local */ + auto provider = ctx->GetProvider(); + if (provider == nullptr) { + LOGE("context get provider err"); + return; + } + int32_t ret = provider->OnFetchRecords(*records); + if (ret != E_OK) { + LOGE("provider on fetch records err %{public}d", ret); + return; + } + + /* pull more */ + ret = AsyncRun(ctx, &DataSyncer::PullRecords); + if (ret != E_OK) { + LOGE("asyn run pull records err %{public}d", ret); + return; + } +} + +int32_t DataSyncer::Push(shared_ptr provider) +{ + /* + * Although unlikely, if the first callback finds no more records available + * and tries to schedule before following tasks commited, the data syncer + * will directly schedule to the next stage, while following tasks would be + * commited to the next stage mistakenly. + * One possible solution: commit dummy task in the beginning and complete + * dummy task in the end. + */ + shared_ptr context = make_shared(provider); + if (context == nullptr) { + LOGE("alloc context fail"); + return E_MEMORY; + } + + /* commit a dummy task */ + BeginTransaction(); + + int32_t ret = AsyncRun(context, &DataSyncer::CreateRecords); + if (ret != E_OK) { + LOGE("async run create records err %{public}d", ret); + return ret; + } + + ret = AsyncRun(context, &DataSyncer::DeleteRecords); + if (ret != E_OK) { + LOGE("async run delete records err %{public}d", ret); + return ret; + } + + ret = AsyncRun(context, &DataSyncer::ModifyRecords); + if (ret != E_OK) { + LOGE("async run modify records err %{public}d", ret); + return ret; + } + + /* complete the dummy task */ + EndTransaction(); + + return E_OK; +} + +void DataSyncer::CreateRecords(shared_ptr context) +{ + LOGI("%{private}d %{private}s creates records", userId_, appPackageName_.c_str()); + + auto provider = context->GetProvider(); + if (provider == nullptr) { + LOGE("context get provider err"); + return; + } + + /* query local */ + vector records; + int32_t ret = provider->GetCreatedRecords(records); + if (ret != E_OK) { + LOGE("provider get created records err %{public}d", ret); + return; + } + + /* no need upload */ + if (records.size() == 0) { + return; + } + + /* upload */ + auto callback = AsyncCallback(&DataSyncer::OnCreateRecords); + if (callback == nullptr) { + LOGE("wrap on create records fail"); + return; + } + ret = sdkHelper_.CreateRecords(context, records, callback); + if (ret != E_OK) { + LOGE("sdk create records err %{public}d", ret); + return; + } +} + +void DataSyncer::DeleteRecords(shared_ptr context) +{ + LOGI("%{private}d %{private}s deletes records", userId_, appPackageName_.c_str()); + + auto provider = context->GetProvider(); + if (provider == nullptr) { + LOGE("context get provider err"); + return; + } + + /* query local */ + vector records; + int32_t ret = provider->GetDeletedRecords(records); + if (ret != E_OK) { + LOGE("provider get deleted records err %{public}d", ret); + return; + } + + /* no need upload */ + if (records.size() == 0) { + return; + } + + /* upload */ + auto callback = AsyncCallback(&DataSyncer::OnDeleteRecords); + if (callback == nullptr) { + LOGE("wrap on delete records fail"); + return; + } + ret = sdkHelper_.DeleteRecords(context, records, callback); + if (ret != E_OK) { + LOGE("sdk delete records err %{public}d", ret); + } +} + +void DataSyncer::ModifyRecords(shared_ptr context) +{ + LOGI("%{private}d %{private}s modifies records", userId_, appPackageName_.c_str()); + + auto provider = context->GetProvider(); + if (provider == nullptr) { + LOGE("context get provider err"); + return; + } + + /* query local */ + vector records; + int32_t ret = provider->GetModifiedRecords(records); + if (ret != E_OK) { + LOGE("provider get modified records err %{public}d", ret); + return; + } + + /* no need upload */ + if (records.size() == 0) { + return; + } + + /* upload */ + auto callback = AsyncCallback(&DataSyncer::OnModifyRecords); + if (callback == nullptr) { + LOGE("wrap on modify records fail"); + return; + } + ret = sdkHelper_.ModifyRecords(context, records, callback); + if (ret != E_OK) { + LOGE("sdk modify records err %{public}d", ret); + } +} + +void DataSyncer::OnCreateRecords(shared_ptr context, + shared_ptr database, + shared_ptr> map, const DKError &err) +{ + LOGI("%{private}d %{private}s on create records %{public}d", userId_, + appPackageName_.c_str(), map->size()); + + auto ctx = static_pointer_cast(context); + + /* update local */ + auto provider = ctx->GetProvider(); + int32_t ret = provider->OnCreateRecords(*map); + if (ret != E_OK) { + LOGE("provider on create records err %{public}d", ret); + return; + } + + /* push more */ + ret = AsyncRun(ctx, &DataSyncer::CreateRecords); + if (ret != E_OK) { + LOGE("async run create records err %{public}d", ret); + return; + } +} + +void DataSyncer::OnDeleteRecords(shared_ptr context, + shared_ptr database, + shared_ptr> map, const DKError &err) +{ + LOGI("%{private}d %{private}s on create records %{public}d", userId_, + appPackageName_.c_str(), map->size()); + + auto ctx = static_pointer_cast(context); + + /* update local */ + auto provider = ctx->GetProvider(); + int32_t ret = provider->OnDeleteRecords(*map); + if (ret != E_OK) { + LOGE("provider on delete records err %{public}d", ret); + return; + } + + /* push more */ + ret = AsyncRun(ctx, &DataSyncer::DeleteRecords); + if (ret != E_OK) { + LOGE("async run delete records err %{public}d", ret); + return; + } +} + +void DataSyncer::OnModifyRecords(shared_ptr context, + shared_ptr database, + shared_ptr> map, const DKError &err) +{ + LOGI("%{private}d %{private}s on create records %{public}d", userId_, + appPackageName_.c_str(), map->size()); + + auto ctx = static_pointer_cast(context); + + /* update local */ + auto provider = ctx->GetProvider(); + int32_t ret = provider->OnModifyRecords(*map); + if (ret != E_OK) { + LOGE("provider on modify records err %{public}d", ret); + return; + } + + /* push more */ + ret = AsyncRun(ctx, &DataSyncer::ModifyRecords); + if (ret != E_OK) { + LOGE("async run modify records err %{public}d", ret); + return; + } +} + +int32_t DataSyncer::CommitTask(shared_ptr t) +{ + return taskManager_->CommitTask(t); +} + +int32_t DataSyncer::AddTask(shared_ptr t) +{ + return taskManager_->AddTask(t); +} + +int32_t DataSyncer::StartTask(shared_ptr t, TaskAction action) +{ + return taskManager_->StartTask(t, action); +} + +void DataSyncer::CompleteTask(shared_ptr t) +{ + taskManager_->CompleteTask(t->GetId()); +} + +void DataSyncer::BeginTransaction() +{ + taskManager_->CommitDummyTask(); +} + +void DataSyncer::EndTransaction() { - syncStateManager_ = std::make_shared(); + taskManager_->CompleteDummyTask(); } std::string DataSyncer::GetAppPackageName() const @@ -39,8 +473,22 @@ int32_t DataSyncer::GetUserId() const return userId_; } -void DataSyncer::OnSyncComplete(const int32_t code, SyncType type) +void DataSyncer::CompletePull() +{ + LOGI("%{private}d %{private}s completes pull", userId_, appPackageName_.c_str()); + /* call syncer manager callback */ +} + +void DataSyncer::CompletePush() +{ + LOGI("%{private}d %{public}s completes push", userId_, appPackageName_.c_str()); + /* call syncer manager callback */ +} + +void DataSyncer::CompleteAll(const int32_t code, const SyncType type) { + LOGI("%{private}d %{private}s completes all", userId_, appPackageName_.c_str()); + SyncState syncState; if (code == E_OK) { syncState = SyncState::SYNC_SUCCEED; @@ -48,7 +496,7 @@ void DataSyncer::OnSyncComplete(const int32_t code, SyncType type) syncState = SyncState::SYNC_FAILED; } - auto nextAction = syncStateManager_->UpdateSyncState(syncState); + auto nextAction = syncStateManager_.UpdateSyncState(syncState); if (nextAction == Action::START) { StartSync(false, SyncTriggerType::PENDING_TRIGGER); return; @@ -60,20 +508,18 @@ void DataSyncer::OnSyncComplete(const int32_t code, SyncType type) auto state = GetSyncPromptState(code); if (code == E_OK) { - CloudSyncCallbackManager::GetInstance().NotifySyncStateChanged(appPackageName_, userId_, SyncType::ALL, state); + CloudSyncCallbackManager::GetInstance().NotifySyncStateChanged( + appPackageName_, userId_, SyncType::ALL, state); } else { - CloudSyncCallbackManager::GetInstance().NotifySyncStateChanged(appPackageName_, userId_, type, state); + CloudSyncCallbackManager::GetInstance().NotifySyncStateChanged( + appPackageName_, userId_, type, state); } } -std::shared_ptr DataSyncer::GetSyncStateManager() -{ - return syncStateManager_; -} - void DataSyncer::SyncStateChangedNotify(const SyncType type, const SyncPromptState state) { - CloudSyncCallbackManager::GetInstance().NotifySyncStateChanged(appPackageName_, userId_, SyncType::ALL, state); + CloudSyncCallbackManager::GetInstance().NotifySyncStateChanged(appPackageName_, + userId_, SyncType::ALL, state); } SyncPromptState DataSyncer::GetSyncPromptState(const int32_t code) @@ -91,4 +537,6 @@ SyncPromptState DataSyncer::GetSyncPromptState(const int32_t code) return state; } -} // namespace OHOS::FileManagement::CloudSync +} // namespace CloudSync +} // namespace FileManagement +} // namespace OHOS diff --git a/services/cloudsyncservice/src/data_sync/gallery/gallery_data_syncer.cpp b/services/cloudsyncservice/src/data_sync/gallery_data_sync/album_data_provider.cpp similarity index 36% rename from services/cloudsyncservice/src/data_sync/gallery/gallery_data_syncer.cpp rename to services/cloudsyncservice/src/data_sync/gallery_data_sync/album_data_provider.cpp index 5eabd59676661c52d59750a540bc1ea8101fa92c..8649b8940e29d6d2d5405a306125e9abc34704fd 100644 --- a/services/cloudsyncservice/src/data_sync/gallery/gallery_data_syncer.cpp +++ b/services/cloudsyncservice/src/data_sync/gallery_data_sync/album_data_provider.cpp @@ -12,47 +12,66 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include "data_sync/gallery/gallery_data_syncer.h" -#include "cloud_sync_constants.h" + +#include "album_data_provider.h" + +#include "medialibrary_db_const.h" +#include "medialibrary_type_const.h" + #include "dfs_error.h" -#include "sync_rule/battery_status.h" #include "utils_log.h" - -namespace OHOS::FileManagement::CloudSync { +namespace OHOS { +namespace FileManagement { +namespace CloudSync { using namespace std; +using namespace NativeRdb; +using namespace DriveKit; + +AlbumDataProvider::AlbumDataProvider(std::shared_ptr rdb) : + RdbProvider(const_cast(tableName_), rdb) +{ +} + +int32_t AlbumDataProvider::GetFetchCondition() +{ + return E_OK; +} + +int32_t AlbumDataProvider::OnFetchRecords(const vector &records) +{ + return E_OK; +} + +int32_t AlbumDataProvider::GetCreatedRecords(vector &records) +{ + return E_OK; +} + +int32_t AlbumDataProvider::GetDeletedRecords(vector &records) +{ + return E_OK; +} -void GalleryDataSyncer::StartSync(bool forceFlag, SyncTriggerType triggerType) +int32_t AlbumDataProvider::GetModifiedRecords(vector &records) { - LOGI("start sync, isforceSync:%{public}d, triggerType:%{public}d", forceFlag, triggerType); - auto syncStateManager = GetSyncStateManager(); - if (syncStateManager->IsPendingSync(forceFlag)) { - LOGI("syncing, pending sync"); - return; - } + return E_OK; +} - SyncStateChangedNotify(SyncType::ALL, SyncPromptState::SYNC_STATE_SYNCING); - int32_t ret = UploadFile(forceFlag); - OnSyncComplete(ret, SyncType::UPLOAD); +int32_t AlbumDataProvider::OnCreateRecords(const map &map) +{ + return E_OK; } -void GalleryDataSyncer::StopSync(SyncTriggerType triggerType) +int32_t AlbumDataProvider::OnDeleteRecords(const map &map) { - LOGI("trigger stop sync, triggerType:%{public}d", triggerType); - auto syncStateManager = GetSyncStateManager(); - syncStateManager->SetStopSyncFlag(); + return E_OK; } -int32_t GalleryDataSyncer::UploadFile(bool forceFlag) +int32_t AlbumDataProvider::OnModifyRecords(const map &map) { - auto syncStateManager = GetSyncStateManager(); - if (syncStateManager->GetStopSyncFlag()) { - LOGI("trigger stop sync"); - return E_OK; - } - if (!BatteryStatus::IsAllowUpload(forceFlag)) { - return E_SYNC_FAILED_BATTERY_LOW; - } return E_OK; } -} // namespace OHOS::FileManagement::CloudSync \ No newline at end of file +} // namespace CloudSync +} // namespace FileManagement +} // namespace OHOS diff --git a/services/cloudsyncservice/src/data_sync/gallery_data_sync/data_convertor.cpp b/services/cloudsyncservice/src/data_sync/gallery_data_sync/data_convertor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c9a2393b420bdcc8aa7d87d1cac642061964b47d --- /dev/null +++ b/services/cloudsyncservice/src/data_sync/gallery_data_sync/data_convertor.cpp @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "data_convertor.h" + +#include "dfs_error.h" +#include "utils_log.h" +#include "sdk_helper.h" + +namespace OHOS { +namespace FileManagement { +namespace CloudSync { +using namespace std; +using namespace NativeRdb; + +int32_t DataConvertor::ResultSetToRecords(const unique_ptr resultSet, + std::vector &records) const +{ + /* reserve to avoid repeatedly alloc and copy */ + int32_t rowCount = 0; + int ret = resultSet->GetRowCount(rowCount); + if (ret != 0) { + LOGE("result set get row count err %{public}d", ret); + return E_RDB; + } + records.reserve(rowCount); + + auto size = this->GetSize(); + auto &types = this->GetTypes(); + auto &cloudColumns = this->GetCloudColumns(); + + /* iterate all rows */ + while (resultSet->GoToNextRow() == 0) { + DriveKit::DKRecord record; + DriveKit::DKRecordDatas data; + for (int i = 0; i < size; i++) { + DataType type = types[i]; + switch (type) { + case INT: { + int32_t val; + int32_t err = resultSet->GetInt(i, val); + if (err != 0) { + LOGE("result set get int err %{public}d", err); + } + data[cloudColumns[i]] = DriveKit::DKRecordField(val); + break; + } + case LONG: { + int64_t val; + int32_t err = resultSet->GetLong(i, val); + if (err != 0) { + LOGE("result set get long err %{public}d", err); + } + data[cloudColumns[i]] = DriveKit::DKRecordField(val); + break; + } + case STRING: { + string val; + int32_t err = resultSet->GetString(i, val); + if (err != 0) { + LOGE("result set get string err %{public}d", err); + } + data[cloudColumns[i]] = DriveKit::DKRecordField(val); + break; + } + case ASSET: { + string val; + int32_t err = resultSet->GetString(i, val); + if (err != 0) { + LOGE("result set get string err %{public}d", err); + } + struct DriveKit::DKAsset asset = { "", val }; + data[cloudColumns[i]] = DriveKit::DKRecordField(val); + break; + } + default: { + LOGE("invalid data type %{public}d", type); + break; + } + } + } + record.SetRecordDatas(data); + records.emplace_back(move(record)); + } + + return E_OK; +} + +int32_t DataConvertor::RecordToValueBucket(const DriveKit::DKRecord &record, + NativeRdb::ValuesBucket &valueBucket) const +{ + auto size = this->GetSize(); + auto &types = this->GetTypes(); + auto &localColumns = this->GetLocalColumns(); + auto &cloudColumns = this->GetCloudColumns(); + + DriveKit::DKRecordDatas data; + record.GetRecordDatas(data); + for (int32_t j = 0; j < size; j++) { + DataType type = types[j]; + switch (type) { + case INT: { + valueBucket.PutInt(localColumns[j], data[cloudColumns[j]]); + break; + } + case LONG: { + valueBucket.PutLong(localColumns[j], data[cloudColumns[j]]); + break; + } + case STRING: { + valueBucket.PutString(localColumns[j], data[cloudColumns[j]]); + break; + } + default: + break; + } + } + + return E_OK; +} + +int32_t DataConvertor::RecordsToValueBuckets(const std::vector &records, + vector &valueBuckets) const +{ + /* reserve to avoid repeatedly alloc and copy */ + valueBuckets.reserve(records.size()); + + auto size = this->GetSize(); + auto &types = this->GetTypes(); + auto &localColumns = this->GetLocalColumns(); + auto &cloudColumns = this->GetCloudColumns(); + /* iterate records */ + for (uint32_t i = 0; i < records.size(); i++) { + DriveKit::DKRecordDatas data; + records[i].GetRecordDatas(data); + NativeRdb::ValuesBucket v; + for (int32_t j = 0; j < size; j++) { + DataType type = types[j]; + switch (type) { + case INT: { + v.PutInt(localColumns[j], data[cloudColumns[j]]); + break; + } + case LONG: { + v.PutLong(localColumns[j], data[cloudColumns[j]]); + break; + } + case STRING: { + v.PutString(localColumns[j], data[cloudColumns[j]]); + break; + } + default: + break; + } + } + valueBuckets[i] = v; + } + + return E_OK; +} +} // namespace CloudSync +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/services/cloudsyncservice/src/data_sync/gallery_data_sync/file_data_provider.cpp b/services/cloudsyncservice/src/data_sync/gallery_data_sync/file_data_provider.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2ec512a1ec4cb2b888b6b2456e0eaeecce97d83b --- /dev/null +++ b/services/cloudsyncservice/src/data_sync/gallery_data_sync/file_data_provider.cpp @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "file_data_provider.h" + +#include "medialibrary_db_const.h" +#include "medialibrary_type_const.h" + +#include "dfs_error.h" +#include "utils_log.h" + +namespace OHOS { +namespace FileManagement { +namespace CloudSync { +using namespace std; +using namespace NativeRdb; +using namespace DriveKit; + +const string FileDataProvider::TABLE_NAME = "Files"; +const int32_t FileDataProvider::LIMIT_SIZE = 50; + +FileDataProvider::FileDataProvider(std::shared_ptr rdb) : + RdbProvider(TABLE_NAME, rdb) +{ +} + +int32_t FileDataProvider::GetFetchCondition() +{ + return 0; +} + +int32_t FileDataProvider::OnFetchRecords(const vector &records) +{ + return 0; +} + +int32_t FileDataProvider::GetCreatedRecords(vector &records) +{ + /* build predicates */ + NativeRdb::AbsRdbPredicates createPredicates = NativeRdb::AbsRdbPredicates(TABLE_NAME); + createPredicates.SetWhereClause(Media::MEDIA_DATA_DB_DIRTY + " = ? AND " + + Media::MEDIA_DATA_DB_IS_TRASH + " = ?"); + createPredicates.SetWhereArgs({to_string(static_cast(Media::DirtyType::TYPE_NEW)), "0"}); + createPredicates.Offset(createOffset_); + createPredicates.Limit(LIMIT_SIZE); + + /* query */ + auto results = Query(createPredicates, createConvertor_.GetLocalColumns()); + if (results == nullptr) { + LOGE("get nullptr created result"); + return E_RDB; + } + /* update offset */ + createOffset_ += LIMIT_SIZE; + + /* results to records */ + int ret = createConvertor_.ResultSetToRecords(move(results), records); + if (ret != 0) { + LOGE("result set to records err %{public}d", ret); + return ret; + } + + return E_OK; +} + +int32_t FileDataProvider::GetDeletedRecords(vector &records) +{ + /* build predicates */ + NativeRdb::AbsRdbPredicates deletePredicates = NativeRdb::AbsRdbPredicates(TABLE_NAME); + deletePredicates.SetWhereClause(Media::MEDIA_DATA_DB_DIRTY + " = ? AND " + + Media::MEDIA_DATA_DB_IS_TRASH + " = ?"); + deletePredicates.SetWhereArgs({to_string(static_cast(Media::DirtyType::TYPE_DELETED)), "0"}); + deletePredicates.Offset(createOffset_); + deletePredicates.Limit(LIMIT_SIZE); + + /* query */ + auto results = Query(deletePredicates, deleteConvertor_.GetLocalColumns()); + if (results == nullptr) { + LOGE("get nullptr deleted result"); + return E_RDB; + } + /* update offset */ + deleteOffset_ += LIMIT_SIZE; + + /* results to records */ + int ret = deleteConvertor_.ResultSetToRecords(move(results), records); + if (ret != 0) { + LOGE("result set to records err %{public}d", ret); + return ret; + } + + return E_OK; +} + +int32_t FileDataProvider::GetModifiedRecords(vector &records) +{ + /* build predicates */ + NativeRdb::AbsRdbPredicates updatePredicates = NativeRdb::AbsRdbPredicates(TABLE_NAME); + updatePredicates.SetWhereClause(Media::MEDIA_DATA_DB_DIRTY + " = ? AND " + + Media::MEDIA_DATA_DB_IS_TRASH + " = ?"); + updatePredicates.SetWhereArgs({to_string(static_cast(Media::DirtyType::TYPE_FDIRTY)), "0"}); + updatePredicates.Offset(createOffset_); + updatePredicates.Limit(LIMIT_SIZE); + + /* query */ + auto results = Query(updatePredicates, updateConvertor_.GetLocalColumns()); + if (results == nullptr) { + LOGE("get nullptr modified result"); + return E_RDB; + } + /* update offset */ + updateOffset_ += LIMIT_SIZE; + + /* results to records */ + int ret = updateConvertor_.ResultSetToRecords(move(results), records); + if (ret != 0) { + LOGE("result set to records err %{public}d", ret); + return ret; + } + + return E_OK; +} + +int32_t FileDataProvider::OnCreateRecords(const map &map) +{ + for (auto &entry : map) { + auto record = const_cast(entry.second).GetDKRecord(); + + /* record to value bucket */ + ValuesBucket valuesBucket; + int32_t ret = onCreateConvertor_.RecordToValueBucket(record, valuesBucket); + if (ret != E_OK) { + LOGE("record to value bucket err %{public}d", ret); + return ret; + } + valuesBucket.PutString(Media::MEDIA_DATA_DB_GID, entry.first); + valuesBucket.PutInt(Media::MEDIA_DATA_DB_DIRTY, + static_cast(Media::DirtyType::TYPE_SYNCED)); + + DKRecordDatas data; + record.GetRecordDatas(data); + int32_t id = data[Media::MEDIA_DATA_DB_ID]; + /* update local */ + int32_t changedRows; + string whereClause = Media::MEDIA_DATA_DB_ID + " = ?"; + ret = Update(changedRows, valuesBucket, whereClause, { to_string(id) }); + if (ret != 0) { + LOGE("on create records update err %{public}d", ret); + return E_RDB; + } + } + + return E_OK; +} + +int32_t FileDataProvider::OnDeleteRecords(const map &map) +{ + for (auto &entry : map) { + auto record = const_cast(entry.second).GetDKRecord(); + + DKRecordDatas data; + record.GetRecordDatas(data); + string gid = data["gid"]; + /* delete local */ + int32_t deletedRows; + string whereClause = Media::MEDIA_DATA_DB_GID + " = ?"; + int32_t ret = Delete(deletedRows, whereClause, { gid }); + if (ret != 0) { + LOGE("on create records update err %{public}d", ret); + return E_RDB; + } + } + + return E_OK; +} + +int32_t FileDataProvider::OnModifyRecords(const map &map) +{ + for (auto &entry : map) { + auto record = const_cast(entry.second).GetDKRecord(); + + /* record to value bucket */ + ValuesBucket valuesBucket; + int32_t ret = updateConvertor_.RecordToValueBucket(record, valuesBucket); + if (ret != E_OK) { + LOGE("record to value bucket err %{public}d", ret); + return ret; + } + valuesBucket.PutInt(Media::MEDIA_DATA_DB_DIRTY, + static_cast(Media::DirtyType::TYPE_SYNCED)); + + DKRecordDatas data; + record.GetRecordDatas(data); + string gid = data[Media::MEDIA_DATA_DB_GID]; + /* update local */ + int32_t changedRows; + string whereClause = Media::MEDIA_DATA_DB_GID + " = ?"; + ret = Update(changedRows, valuesBucket, whereClause, { gid }); + if (ret != 0) { + LOGE("on create records update err %{public}d", ret); + return E_RDB; + } + } + + return E_OK; +} + +void FileDataProvider::Reset() +{ + createOffset_ = 0; + deleteOffset_ = 0; + updateOffset_ = 0; +} +} // namespace CloudSync +} // namespace FileManagement +} // namespace OHOS \ No newline at end of file diff --git a/services/cloudsyncservice/src/data_sync/gallery_data_sync/gallery_data_syncer.cpp b/services/cloudsyncservice/src/data_sync/gallery_data_sync/gallery_data_syncer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f6ddf1c5c33e98068028d06191fa2b1c32d4cc50 --- /dev/null +++ b/services/cloudsyncservice/src/data_sync/gallery_data_sync/gallery_data_syncer.cpp @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "gallery_data_syncer.h" + +#include "dfs_error.h" +#include "utils_log.h" + +namespace OHOS { +namespace FileManagement { +namespace CloudSync { +using namespace std; + +GalleryDataSyncer::GalleryDataSyncer(const std::string appPackageName, const int32_t userId) : + DataSyncer(appPackageName, userId) +{ + /* rdb config */ + NativeRdb::RdbStoreConfig config(DATABASE_NAME); + config.SetPath(DATA_APP_EL2 + to_string(userId) + DATABASE_DIR + DATABASE_NAME); + config.SetBundleName(BUNDLE_NAME); + config.SetReadConSize(CONNECT_SIZE); + + /* + * Just pass in any value but zero for parameter @version in GetRdbStore, + * since RdbCallback always return 0 in its callbacks. + */ + int32_t err; + RdbCallback cb; + auto rdb_ = NativeRdb::RdbHelper::GetRdbStore(config, 1, cb, err); + if (rdb_ == nullptr) { + LOGE("gallyer data syncer init rdb fail"); + } + + /* init provider */ + fileProvider_ = make_shared(rdb_); +} + +void GalleryDataSyncer::Schedule() +{ + LOGI("schedule to stage %{public}d", ++stage_); + + int32_t ret = E_OK; + switch (stage_) { + case PREPARE : { + ret = Prepare(); + break; + } + case DOWNLOADALBUM: { + ret = DownloadAlbum(); + break; + } + case DOWNLOADFILE: { + ret = DownloadFile(); + break; + } + case UPLOADALBUM: { + ret = UploadAlbum(); + break; + } + case UPLOADFILE: { + ret = UploadFile(); + break; + } + case WAIT: { + ret = Wait(); + break; + } + case END: { + ret = Complete(); + break; + } + default: { + ret = E_SCHEDULE; + LOGE("schedule fail %{public}d", ret); + break; + } + } + + /* reset stage in case one restarts a sync */ + if (stage_ == END) { + stage_ = BEGIN; + } + + if (ret != E_OK) { + stage_ = BEGIN; + Abort(); + } +} + +int32_t GalleryDataSyncer::Prepare() +{ + LOGI("gallery data syncer prepare"); + /* restart a sync might need to update offset, etc */ + fileProvider_->Reset(); + Schedule(); + return E_OK; +} + +int32_t GalleryDataSyncer::DownloadAlbum() +{ + LOGI("gallery data sycner download album"); + Schedule(); + return E_OK; +} + +int32_t GalleryDataSyncer::DownloadFile() +{ + LOGI("gallery data sycner download file"); + int ret = Pull(fileProvider_); + if (ret != E_OK) { + LOGE("gallery data syncer pull file err %{public}d", ret); + } + return ret; +} + +int32_t GalleryDataSyncer::UploadAlbum() +{ + LOGI("gallery data sycner upload album"); + Schedule(); + return E_OK; +} + +int32_t GalleryDataSyncer::UploadFile() +{ + LOGI("gallery data sycner upload file"); + int ret = Push(fileProvider_); + if (ret != E_OK) { + LOGE("gallery data syncer push file err %{public}d", ret); + } + return ret; +} + +/* wait for file download and upload */ +int32_t GalleryDataSyncer::Wait() +{ + LOGI("gallery data syncer wait"); + Schedule(); + return E_OK; +} + +int32_t GalleryDataSyncer::Complete() +{ + LOGI("gallery data syncer complete all"); + CompleteAll(E_OK, SyncType::ALL); + return E_OK; +} +} // namespace CloudSync +} // namespace FileManagement +} // namespace OHOS diff --git a/services/cloudsyncservice/src/data_sync/sdk_helper.cpp b/services/cloudsyncservice/src/data_sync/sdk_helper.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b2a74b63d7eb52c3acbfe44a5b0859fd5b3108b9 --- /dev/null +++ b/services/cloudsyncservice/src/data_sync/sdk_helper.cpp @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "sdk_helper.h" + +#include "dfs_error.h" +#include "utils_log.h" +#include "task.h" + +namespace OHOS { +namespace FileManagement { +namespace CloudSync { +using namespace std; + +SdkHelper::SdkHelper(int32_t userId, string appPackageName) +{ + auto driveKit = DriveKit::DriveKit::getInstance(userId); + if (driveKit == nullptr) { + LOGE("sdk helper get drive kit instance fail"); + return; + } + + auto container = driveKit->GetDefaultContainer(appPackageName); + if (container == nullptr) { + LOGE("sdk helper get drive kit container fail"); + return; + } + + database_ = container->GetPrivateDatabase(); + if (database_ == nullptr) { + LOGE("sdk helper get drive kit database fail"); + } +} + +int32_t SdkHelper::FetchRecords(shared_ptr context, + function context, shared_ptr>)> callback) +{ + auto ret = make_shared>(); + thread ([=]() { + callback(context, ret); + }).detach(); + + return E_OK; +} + +int32_t SdkHelper::CreateRecords(shared_ptr context, + vector &records, + std::function, std::shared_ptr, + std::shared_ptr>, + const DriveKit::DKError &)> callback) +{ + auto err = database_->SaveRecords(context, records, DriveKit::DKSavePolicy::DK_SAVE_IF_UNCHANGED, callback); + if (err != DriveKit::DKLocalErrorCode::NO_ERROR) { + LOGE("drivekit save records err %{public}d", err); + return E_CLOUD_SDK; + } + + return E_OK; +} + +int32_t SdkHelper::DeleteRecords(shared_ptr context, + vector &records, + std::function, std::shared_ptr, + std::shared_ptr>, + const DriveKit::DKError &)> callback) +{ + auto result = std::make_shared>(); + DriveKit::DKError err; + std::thread ([=]() { + callback(context, nullptr, result, err); + }).detach(); + + return E_OK; +} + +int32_t SdkHelper::ModifyRecords(shared_ptr context, + vector &records, + std::function, std::shared_ptr, + std::shared_ptr>, + const DriveKit::DKError &)> callback) +{ + auto result = std::make_shared>(); + DriveKit::DKError err; + std::thread ([=]() { + callback(context, nullptr, result, err); + }).detach(); + + return E_OK; +} + +int32_t SdkHelper::DownloadAssets(shared_ptr context, + vector recordIds, int32_t id, + function context, shared_ptr>)> callback) +{ + thread ([=]() { + callback(context, nullptr); + }).detach(); + + return E_OK; +} + +int32_t SdkHelper::CancelDownloadAssets(int32_t id) +{ + return E_OK; +} +} // namespace CloudSync +} // namespace FileManagement +} // namespace OHOS diff --git a/services/cloudsyncservice/src/data_sync/task.cpp b/services/cloudsyncservice/src/data_sync/task.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3f70a549b6377d2ae5f4929b99fd82552f4111ae --- /dev/null +++ b/services/cloudsyncservice/src/data_sync/task.cpp @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "task.h" + +#include +#include + +#include "dfs_error.h" +#include "utils_log.h" +#include "sdk_helper.h" + +namespace OHOS { +namespace FileManagement { +namespace CloudSync { +using namespace std; + +TaskManager::TaskManager(function callback) : callback_(callback) +{ + pool_.SetMaxTaskNum(MAX_THREAD_NUM); + pool_.Start(0); +} + +TaskManager::~TaskManager() +{ + pool_.Stop(); +} + +int32_t TaskManager:: GenerateTaskId() +{ + return currentId_.fetch_add(1); +} + +int32_t TaskManager::AddTask(shared_ptr t) +{ + unique_lock lock(mutex_); + + /* If stopped, no more tasks can be added */ + if (stopFlag_) { + LOGI("add task fail since stop"); + return E_STOP; + } + + /* insert task */ + t->SetId(GenerateTaskId()); + taskList_.emplace_back(t); + + return E_OK; +} + +int32_t TaskManager::StartTask(shared_ptr t, TaskAction action) +{ + /* If stopped, no more tasks can be executed */ + if (stopFlag_) { + LOGI("start task fail since stop"); + CompleteTask(t->GetId()); + return E_STOP; + } + + t->SetAction(action); + pool_.AddTask([t, this]() { + t->Run(); + this->CompleteTask(t->GetId()); + }); + return E_OK; +} + +int32_t TaskManager::CommitTask(shared_ptr t) +{ + /* add task */ + int32_t ret = AddTask(t); + if (ret != E_OK) { + LOGE("add task err %{public}d", ret); + return ret; + } + + /* launch */ + pool_.AddTask([t, this]() { + t->Run(); + this->CompleteTask(t->GetId()); + }); + + return E_OK; +} + +void TaskManager::CompleteTask(int32_t id) +{ + /* remove task */ + unique_lock lock(mutex_); + for (auto entry = taskList_.begin(); entry != taskList_.end();) { + if (entry->get()->GetId() == id) { + (void)taskList_.erase(entry); + break; + } else { + entry++; + } + } + + if (taskList_.empty()) { + if (stopFlag_) { + /* if it has been stopped, notify the blocking caller */ + cv_.notify_all(); + } else { + lock.unlock(); + Reset(); + /* otherwise just run its callback */ + callback_(); + } + } +} + +bool TaskManager::StopAndWaitFor() +{ + unique_lock lock(mutex_); + LOGI("task manager stop"); + stopFlag_ = true; + + return cv_.wait_for(lock, chrono::seconds(WAIT_FOR_SECOND), [this] { + return taskList_.empty(); + }); +} + +void TaskManager::Reset() +{ + currentId_.store(0); +} + +void TaskManager::CommitDummyTask() +{ + auto task = make_shared(nullptr, nullptr); + task->SetId(INVALID_ID); + + unique_lock lock(mutex_); + taskList_.emplace_back(task); +} + +void TaskManager::CompleteDummyTask() +{ + CompleteTask(INVALID_ID); +} +} // namespace CloudSync +} // namespace FileManagement +} // namespace OHOS diff --git a/services/cloudsyncservice/src/ipc/cloud_sync_callback_manager.cpp b/services/cloudsyncservice/src/ipc/cloud_sync_callback_manager.cpp index d5b92e912c9d1f288b26d1454cd0302b4ae46798..c84324db8a21108b94def43b707e456dfcfec84b 100644 --- a/services/cloudsyncservice/src/ipc/cloud_sync_callback_manager.cpp +++ b/services/cloudsyncservice/src/ipc/cloud_sync_callback_manager.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/services/cloudsyncservice/src/ipc/cloud_sync_callback_proxy.cpp b/services/cloudsyncservice/src/ipc/cloud_sync_callback_proxy.cpp index 3fd68dc9a0503f235e272496efadf87c7b0e7035..297c1c6c4bcfaf0dea9a570be4c31ea2b545fb9f 100644 --- a/services/cloudsyncservice/src/ipc/cloud_sync_callback_proxy.cpp +++ b/services/cloudsyncservice/src/ipc/cloud_sync_callback_proxy.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/services/cloudsyncservice/src/ipc/cloud_sync_service.cpp b/services/cloudsyncservice/src/ipc/cloud_sync_service.cpp index f81fca9440a9c62b4fc0c626a39fdfacd3414451..3649a77b75c1a60e46fcf70b2147fc7e48eb535e 100644 --- a/services/cloudsyncservice/src/ipc/cloud_sync_service.cpp +++ b/services/cloudsyncservice/src/ipc/cloud_sync_service.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/services/cloudsyncservice/src/ipc/cloud_sync_service_stub.cpp b/services/cloudsyncservice/src/ipc/cloud_sync_service_stub.cpp index 921bbf1f8f0f043ecc12ac092e5c6393cbe2dd52..ae5faf89f2225a8d302ab0182f7493e1258c2dd8 100644 --- a/services/cloudsyncservice/src/ipc/cloud_sync_service_stub.cpp +++ b/services/cloudsyncservice/src/ipc/cloud_sync_service_stub.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/services/distributedfile.cfg b/services/distributedfile.cfg index 591bda611712bb6f4e7c664b830b4606b237aeb2..3eb4a09751dc554329f494b97566284bad892de5 100644 --- a/services/distributedfile.cfg +++ b/services/distributedfile.cfg @@ -6,7 +6,7 @@ "name": "distributedfiledaemon", "path": ["/system/bin/sa_main", "/system/profile/distributedfiledaemon.xml"], "uid": "1009", - "gid": ["system", "dfs"], + "gid": ["system", "dfs", "ddms"], "secon": "u:r:distributedfiledaemon:s0", "apl": "system_basic", "permission" : [ diff --git a/services/distributedfiledaemon/include/ipc/daemon.h b/services/distributedfiledaemon/include/ipc/daemon.h index 7843c9bd4c9cc5638bc7d95ef6b51eff26a91dae..c2983f7b4277d96a2491f892c14c194a3f113866 100644 --- a/services/distributedfiledaemon/include/ipc/daemon.h +++ b/services/distributedfiledaemon/include/ipc/daemon.h @@ -64,4 +64,4 @@ private: } // namespace DistributedFile } // namespace Storage } // namespace OHOS -#endif // DAEMON_H \ No newline at end of file +#endif // DAEMON_H diff --git a/test/unittests/cloudsync_sa/data_sync/BUILD.gn b/test/unittests/cloudsync_sa/data_sync/BUILD.gn index 43b28b0a8df5d3d24b0d35590ec366e7313c1824..72739bbb6d72020e26fd193bab551da2280fcda7 100644 --- a/test/unittests/cloudsync_sa/data_sync/BUILD.gn +++ b/test/unittests/cloudsync_sa/data_sync/BUILD.gn @@ -21,16 +21,24 @@ ohos_unittest("data_sync_manager_test") { "${distributedfile_path}/test/unittests/cloudsync_sa/mock/battery_status_mock.cpp", "${distributedfile_path}/test/unittests/cloudsync_sa/mock/cloud_status_mock.cpp", "${distributedfile_path}/test/unittests/cloudsync_sa/mock/cloud_sync_callback_manager_mock.cpp", + "${services_path}/cloudsyncservice/src/data_sync//gallery_data_sync/album_data_provider.cpp", + "${services_path}/cloudsyncservice/src/data_sync//gallery_data_sync/data_convertor.cpp", + "${services_path}/cloudsyncservice/src/data_sync//gallery_data_sync/file_data_provider.cpp", + "${services_path}/cloudsyncservice/src/data_sync//gallery_data_sync/gallery_data_syncer.cpp", + "${services_path}/cloudsyncservice/src/data_sync/data_provider.cpp", "${services_path}/cloudsyncservice/src/data_sync/data_sync_manager.cpp", "${services_path}/cloudsyncservice/src/data_sync/data_syncer.cpp", - "${services_path}/cloudsyncservice/src/data_sync/gallery/gallery_data_syncer.cpp", + "${services_path}/cloudsyncservice/src/data_sync/sdk_helper.cpp", "${services_path}/cloudsyncservice/src/data_sync/sync_state_manager.cpp", + "${services_path}/cloudsyncservice/src/data_sync/task.cpp", "${services_path}/cloudsyncservice/src/sync_rule/network_status.cpp", "data_sync_manager_test.cpp", ] include_dirs = [ "${services_path}/cloudsyncservice/include", + "${services_path}/cloudsyncservice/include/data_sync", + "${services_path}/cloudsyncservice/include/data_sync/gallery_data_sync", "${distributedfile_path}/interfaces/inner_api/native/cloudsync_kit_inner", ] @@ -42,9 +50,19 @@ ohos_unittest("data_sync_manager_test") { external_deps = [ "init:libbegetutil", + "media_library:cloud_sync_header", "netmanager_base:net_conn_manager_if", + "relational_store:native_rdb", ] + if (!dfs_service_feature_enable_cloud_adapter) { + deps += [ + "${distributedfile_path}/adapter/cloud_adapter_example:cloud_adapter", + ] + } else { + external_deps += [ "drivekit_native:drivekit" ] + } + defines = [ "private=public" ] use_exceptions = true diff --git a/test/unittests/cloudsync_sa/ipc/BUILD.gn b/test/unittests/cloudsync_sa/ipc/BUILD.gn index 54b0c003f321dbff43bd8364cbe6672c64dda39c..7127ecf7d2a4ff50d1962686b293740875333134 100644 --- a/test/unittests/cloudsync_sa/ipc/BUILD.gn +++ b/test/unittests/cloudsync_sa/ipc/BUILD.gn @@ -66,10 +66,19 @@ ohos_unittest("cloud_sync_service_test") { "ability_base:want", "dfs_service:cloudsync_kit_inner", "ipc:ipc_core", + "relational_store:native_rdb", "safwk:system_ability_fwk", "samgr:samgr_proxy", ] + if (!dfs_service_feature_enable_cloud_adapter) { + deps += [ + "${distributedfile_path}/adapter/cloud_adapter_example:cloud_adapter", + ] + } else { + external_deps += [ "drivekit_native:drivekit" ] + } + defines = [ "private=public" ] use_exceptions = true } diff --git a/utils/log/include/dfs_error.h b/utils/log/include/dfs_error.h index 226651ae39c7d57ff7cf3d5da13972ed55927ee3..209dbfda7f047cf481eddd9e13b39f52ddc7233d 100644 --- a/utils/log/include/dfs_error.h +++ b/utils/log/include/dfs_error.h @@ -43,7 +43,17 @@ enum CloudSyncServiceErrCode : ErrCode { E_SYNC_FAILED_BATTERY_TOO_LOW, E_SYNC_FAILED_NETWORK_NOT_AVAILABLE, E_GET_NETWORK_MANAGER_FAILED, + + /* data syncer */ + E_CLOUD_SDK, + E_RDB, + E_CONTEXT, + E_MEMORY, + E_STOP, + E_PENDING, + E_SCHEDULE, + E_ASYNC_RUN, }; } // namespace OHOS::FileManagement -#endif // OHOS_FILEMGMT_DFS_ERROR_H \ No newline at end of file +#endif // OHOS_FILEMGMT_DFS_ERROR_H