diff --git a/interfaces/kits/js/BUILD.gn b/interfaces/kits/js/BUILD.gn index a52d641898f90fdcd7670c65cd3934a345a374a8..41eb97824db535d4fd732510478d78607a7de1a8 100644 --- a/interfaces/kits/js/BUILD.gn +++ b/interfaces/kits/js/BUILD.gn @@ -153,6 +153,7 @@ ohos_shared_library("fs") { cflags_cc = [ "-std=c++17" ] deps = [ + "${file_api_path}/interfaces/kits/native:task_signal_native", "${utils_path}/filemgmt_libhilog:filemgmt_libhilog", "${utils_path}/filemgmt_libn:filemgmt_libn", ] @@ -167,6 +168,7 @@ ohos_shared_library("fs") { } external_deps = [ + "dfs_service:distributed_file_daemon_kit_inner", "hilog:libhilog", "napi:ace_napi", ] @@ -188,6 +190,8 @@ ohos_shared_library("fs") { "src/mod_fs/class_readeriterator/readeriterator_n_exporter.cpp", "src/mod_fs/class_stream/flush.cpp", "src/mod_fs/class_stream/stream_n_exporter.cpp", + "src/mod_fs/class_tasksignal/task_signal_entity.cpp", + "src/mod_fs/class_tasksignal/task_signal_n_exporter.cpp", "src/mod_fs/class_watcher/watcher_entity.cpp", "src/mod_fs/class_watcher/watcher_n_exporter.cpp", "src/mod_fs/properties/copy.cpp", diff --git a/interfaces/kits/js/src/mod_fs/class_tasksignal/task_signal_entity.cpp b/interfaces/kits/js/src/mod_fs/class_tasksignal/task_signal_entity.cpp index 96071dd110a4cf861ff6767ded411c13150d106b..a3aac6c05e63565f655d00e6a929d6ef0d620feb 100644 --- a/interfaces/kits/js/src/mod_fs/class_tasksignal/task_signal_entity.cpp +++ b/interfaces/kits/js/src/mod_fs/class_tasksignal/task_signal_entity.cpp @@ -22,11 +22,11 @@ TaskSignalEntity::~TaskSignalEntity() {} void TaskSignalEntity::OnCancel(const std::string &path) { uv_loop_s *loop = nullptr; - if (!callbackContext) { + if (!callbackContext_) { return; } - auto env = callbackContext->env_; - callbackContext->filePath_ = path; + auto env = callbackContext_->env_; + callbackContext_->filePath_ = path; napi_get_uv_event_loop(env, &loop); if (loop == nullptr) { return; @@ -35,7 +35,7 @@ void TaskSignalEntity::OnCancel(const std::string &path) if (work == nullptr) { return; } - work->data = reinterpret_cast(callbackContext.get()); + work->data = reinterpret_cast(callbackContext_.get()); int ret = uv_queue_work_with_qos(loop, work, [](uv_work_t *work) {}, [](uv_work_t *work, int status) { JSCallbackContext *callbackContext = reinterpret_cast(work->data); @@ -52,7 +52,7 @@ void TaskSignalEntity::OnCancel(const std::string &path) } napi_env env = callbackContext->env_; napi_value jsCallback = callbackContext->ref_.Deref(env).val_; - napi_value filePath = LibN::NVal::CreateUTF8String(env, callbackContext->filePath).val_; + napi_value filePath = LibN::NVal::CreateUTF8String(env, callbackContext->filePath_).val_; napi_value retVal = nullptr; ret = napi_call_function(env, nullptr, jsCallback, 1, &filePath, &retVal); if (ret != napi_ok) { @@ -66,7 +66,7 @@ void TaskSignalEntity::OnCancel(const std::string &path) delete work; }, uv_qos_user_initiated); if (ret != 0) { - delete callbackContext; + HILOGE("Failed to uv_queue_work_with_qos, ret: %{public}d", ret); delete work; } } diff --git a/interfaces/kits/js/src/mod_fs/module.cpp b/interfaces/kits/js/src/mod_fs/module.cpp index 2322aad76e4c861ee2702f292180e8767eb3d3ee..ad976623b653e89424e083caeb7602d3145745bf 100644 --- a/interfaces/kits/js/src/mod_fs/module.cpp +++ b/interfaces/kits/js/src/mod_fs/module.cpp @@ -24,6 +24,7 @@ #include "class_randomaccessfile/randomaccessfile_n_exporter.h" #include "class_readeriterator/readeriterator_n_exporter.h" #include "class_stream/stream_n_exporter.h" +#include "class_tasksignal/task_signal_n_exporter.h" #include "class_watcher/watcher_n_exporter.h" #endif #include "filemgmt_libhilog.h" @@ -48,6 +49,7 @@ static napi_value Export(napi_env env, napi_value exports) products.emplace_back(make_unique(env, exports)); products.emplace_back(make_unique(env, exports)); products.emplace_back(make_unique(env, exports)); + products.emplace_back(make_unique(env, exports)); #endif for (auto &&product : products) { #ifdef WIN_PLATFORM diff --git a/interfaces/kits/js/src/mod_fs/properties/copy.cpp b/interfaces/kits/js/src/mod_fs/properties/copy.cpp index 6bc6aa29c2abaadeccf897449dc89058769abb92..3b1cdea117c2789997588e3eab4ee100a75a58da 100644 --- a/interfaces/kits/js/src/mod_fs/properties/copy.cpp +++ b/interfaces/kits/js/src/mod_fs/properties/copy.cpp @@ -30,6 +30,7 @@ #include #include +#include "../class_tasksignal/task_signal_n_exporter.h" #include "file_uri.h" #include "file_utils.h" #include "filemgmt_libhilog.h" @@ -88,6 +89,21 @@ tuple Copy::GetListenerFromOptionArg(napi_env env, const NFuncArg &f return { true, NVal() }; } +tuple Copy::GetCopySignalFromOptionArg(napi_env env, const NFuncArg &funcArg) +{ + if (funcArg.GetArgc() >= NARG_CNT::THREE) { + NVal op(env, funcArg[NARG_POS::THIRD]); + if (op.HasProp("copySignal") && !op.GetProp("copySignal").TypeIs(napi_undefined)) { + if (!op.GetProp("copySignal").TypeIs(napi_object)) { + HILOGE("Illegal options.CopySignal type"); + return { false, NVal() }; + } + return { true, op.GetProp("copySignal") }; + } + } + return { true, NVal() }; +} + bool Copy::IsRemoteUri(const std::string &uri) { // NETWORK_PARA @@ -139,7 +155,7 @@ void Copy::CheckOrCreatePath(const std::string &destPath) } } -int Copy::CopyFile(const string &src, const string &dest) +int Copy::CopyFile(const string &src, const string &dest, std::shared_ptr infos) { HILOGD("src = %{public}s, dest = %{public}s", src.c_str(), dest.c_str()); auto srcFd = open(src.c_str(), O_RDONLY); @@ -173,6 +189,11 @@ int Copy::CopyFile(const string &src, const string &dest) HILOGE("Failed to sendfile by errno : %{public}d", errno); return errno; } + if (infos != nullptr && infos->taskSignal != nullptr) { + if (infos->taskSignal->CheckCancelIfNeed(src)) { + return E_CANCELED; + } + } offset += static_cast(ret); size -= static_cast(ret); if (ret == 0) { @@ -321,7 +342,7 @@ int Copy::RecurCopyDir(const string &srcPath, const string &destPath, std::share ret = CopySubDir(src, dest, infos); } else { infos->filePaths.insert(dest); - ret = CopyFile(src, dest); + ret = CopyFile(src, dest, infos); } if (ret != ERRNO_NOERR) { return ret; @@ -691,7 +712,7 @@ std::string Copy::ConvertUriToPath(const std::string &uri) } tuple> Copy::CreateFileInfos( - const std::string &srcUri, const std::string &destUri, const NVal &listener) + const std::string &srcUri, const std::string &destUri, const NVal &listener, NVal copySignal) { auto infos = CreateSharedPtr(); if (infos == nullptr) { @@ -701,6 +722,8 @@ tuple> Copy::CreateFileInfos( infos->srcUri = srcUri; infos->destUri = destUri; infos->listener = listener; + infos->env = listener.env_; + infos->copySignal = copySignal; infos->srcPath = ConvertUriToPath(infos->srcUri); infos->destPath = ConvertUriToPath(infos->destUri); infos->srcPath = GetRealPath(infos->srcPath); @@ -709,6 +732,12 @@ tuple> Copy::CreateFileInfos( if (listener) { infos->hasListener = true; } + if (infos->copySignal) { + auto taskSignalEntity = NClass::GetEntityOf(infos->env, infos->copySignal.val_); + if (taskSignalEntity != nullptr) { + infos->taskSignal = taskSignalEntity->taskSignal_; + } + } return { ERRNO_NOERR, infos }; } @@ -725,7 +754,7 @@ int Copy::ExecCopy(std::shared_ptr infos) { if (IsFile(infos->srcPath) && IsFile(infos->destPath)) { // copyFile - return CopyFile(infos->srcPath, infos->destPath); + return CopyFile(infos->srcPath, infos->destPath, infos); } if (IsDirectory(infos->srcPath) && IsDirectory(infos->destPath)) { if (infos->srcPath.back() != '/') { @@ -748,12 +777,13 @@ int Copy::ParseJsParam(napi_env env, NFuncArg &funcArg, std::shared_ptr callback) void Copy::CopyComplete(std::shared_ptr infos, std::shared_ptr callback) { - if (callback != nullptr) { + if (callback != nullptr && infos->hasListener) { callback->progressSize = callback->totalSize; OnFileReceive(infos); } @@ -793,8 +823,13 @@ napi_value Copy::Async(napi_env env, napi_callback_info info) return nullptr; } auto cbExec = [infos, callback]() -> NError { + if (infos->taskSignal != nullptr) { + infos->taskSignal->MarkRemoteTask(); + } if (IsRemoteUri(infos->srcUri)) { - return TransListener::CopyFileFromSoftBus(infos->srcUri, infos->destUri, std::move(callback)); + auto ret = TransListener::CopyFileFromSoftBus(infos->srcUri, infos->destUri, + infos, std::move(callback)); + return ret; } auto result = Copy::ExecLocal(infos, callback); CloseNotifyFd(infos, callback); diff --git a/interfaces/kits/js/src/mod_fs/properties/copy.h b/interfaces/kits/js/src/mod_fs/properties/copy.h index a30c42710e404316ddfcc40321f765df98fe9b65..f655095e95a6da8aee9eb0bdead9b0c0bec86dc3 100644 --- a/interfaces/kits/js/src/mod_fs/properties/copy.h +++ b/interfaces/kits/js/src/mod_fs/properties/copy.h @@ -25,6 +25,8 @@ #include "common_func.h" #include "filemgmt_libn.h" #include "n_async/n_ref.h" +#include "task_signal.h" +#include "class_tasksignal/task_signal_entity.h" namespace OHOS { namespace FileManagement { @@ -32,6 +34,7 @@ namespace ModuleFileIO { using namespace std; using namespace OHOS::FileManagement::LibN; using namespace OHOS::AppExecFwk; +using namespace DistributedFS::ModuleTaskSignal; struct ReceiveInfo { std::string path; // dir name std::map fileList; // filename, proceededSize @@ -82,6 +85,9 @@ struct FileInfos { bool hasListener = false; napi_env env; NVal listener; + NVal copySignal; + int32_t sessionId = -1; + std::shared_ptr taskSignal = nullptr; std::set filePaths; int exceptionCode = ERRNO_NOERR; // notify copy thread or listener thread has exceptions. bool operator==(const FileInfos &infos) const @@ -120,6 +126,7 @@ private: // operator of napi static tuple ParseJsOperand(napi_env env, NVal pathOrFdFromJsArg); static tuple GetListenerFromOptionArg(napi_env env, const NFuncArg &funcArg); + static tuple GetCopySignalFromOptionArg(napi_env env, const NFuncArg &funcArg); static void CheckOrCreatePath(const std::string &destPath); static int ParseJsParam(napi_env env, NFuncArg &funcArg, std::shared_ptr &fileInfos); @@ -142,12 +149,12 @@ private: static int RecurCopyDir(const string &srcPath, const string &destPath, std::shared_ptr infos); static tuple GetFileSize(const std::string &path); static uint64_t GetDirSize(std::shared_ptr infos, const std::string &path); - static int CopyFile(const string &src, const string &dest); + static int CopyFile(const string &src, const string &dest, std::shared_ptr infos); static int MakeDir(const string &path); static int CopySubDir(const string &srcPath, const string &destPath, std::shared_ptr infos); static int CopyDirFunc(const string &src, const string &dest, std::shared_ptr infos); static tuple> CreateFileInfos( - const std::string &srcUri, const std::string &destUri, const NVal &listener); + const std::string &srcUri, const std::string &destUri, const NVal &listener, NVal copySignal); static int ExecCopy(std::shared_ptr infos); // operator of file size diff --git a/interfaces/kits/js/src/mod_fs/properties/copy_listener/trans_listener.cpp b/interfaces/kits/js/src/mod_fs/properties/copy_listener/trans_listener.cpp index 36f199f852ac0b130c30666b240b0ddfc39bb24a..6a7a8ddd6802d0f8e0f56f88e44a6c9e3a3e4eb8 100644 --- a/interfaces/kits/js/src/mod_fs/properties/copy_listener/trans_listener.cpp +++ b/interfaces/kits/js/src/mod_fs/properties/copy_listener/trans_listener.cpp @@ -57,7 +57,7 @@ std::string TransListener::CreateDfsCopyPath() } NError TransListener::CopyFileFromSoftBus(const std::string &srcUri, const std::string &destUri, - std::shared_ptr callback) + std::shared_ptr fileInfos, std::shared_ptr callback) { sptr transListener = new (std::nothrow) TransListener(); if (transListener == nullptr) { @@ -71,18 +71,14 @@ NError TransListener::CopyFileFromSoftBus(const std::string &srcUri, const std:: std::string tmpDir; std::string disSandboxPath; - if (authority != FILE_MANAGER_AUTHORITY && authority != MEDIA_AUTHORITY) { - tmpDir = CreateDfsCopyPath(); - disSandboxPath = DISTRIBUTED_PATH + tmpDir; - if (!std::filesystem::create_directory(disSandboxPath)) { - HILOGE("Create dir failed"); - return NError(EIO); - } + auto ret = CreateDirectory(authority, tmpDir, disSandboxPath); + if (ret != ERRNO_NOERR) { + return NError(EIO); } - + Storage::DistributedFile::HmdfsInfo info{.copyPath = tmpDir}; auto networkId = GetNetworkIdFromUri(srcUri); - auto ret = Storage::DistributedFile::DistributedFileDaemonManager::GetInstance().PrepareSession(srcUri, destUri, - networkId, transListener, tmpDir); + ret = Storage::DistributedFile::DistributedFileDaemonManager::GetInstance().PrepareSession(srcUri, destUri, + networkId, transListener, info); if (ret != ERRNO_NOERR) { HILOGE("PrepareSession failed, ret = %{public}d.", ret); if (authority != FILE_MANAGER_AUTHORITY && authority != MEDIA_AUTHORITY) { @@ -90,6 +86,9 @@ NError TransListener::CopyFileFromSoftBus(const std::string &srcUri, const std:: } return NError(EIO); } + if (fileInfos->taskSignal != nullptr) { + fileInfos->taskSignal->SetFileInfoOfRemoteTask(info.sessionName, fileInfos->srcPath); + } std::unique_lock lock(transListener->cvMutex_); transListener->cv_.wait(lock, [&transListener]() { return transListener->copyEvent_ == SUCCESS || transListener->copyEvent_ == FAILED; }); @@ -113,6 +112,19 @@ NError TransListener::CopyFileFromSoftBus(const std::string &srcUri, const std:: return NError(ERRNO_NOERR); } +int32_t TransListener::CreateDirectory(const std::string& authority, std::string& tmpDir, + std::string& disSandboxPath) +{ + if (authority != FILE_MANAGER_AUTHORITY && authority != MEDIA_AUTHORITY) { + tmpDir = CreateDfsCopyPath(); + disSandboxPath = DISTRIBUTED_PATH + tmpDir; + if (!std::filesystem::create_directory(disSandboxPath)) { + return EIO; + } + } + return ERRNO_NOERR; +} + int32_t TransListener::CopyToSandBox(const std::string &srcUri, const std::string &disSandboxPath, const std::string &sandboxPath) { diff --git a/interfaces/kits/js/src/mod_fs/properties/copy_listener/trans_listener.h b/interfaces/kits/js/src/mod_fs/properties/copy_listener/trans_listener.h index be483971ef0c925be60c6db5b032888a0cc0cb50..dbe582cad5c39217ddbdc279ec8d9b4a47783a16 100644 --- a/interfaces/kits/js/src/mod_fs/properties/copy_listener/trans_listener.h +++ b/interfaces/kits/js/src/mod_fs/properties/copy_listener/trans_listener.h @@ -35,6 +35,7 @@ public: int32_t OnFailed(const std::string &sessionName) override; static NError CopyFileFromSoftBus(const std::string &srcUri, const std::string &destUri, + std::shared_ptr fileInfos, std::shared_ptr callback); private: @@ -44,8 +45,9 @@ private: static std::string CreateDfsCopyPath(); static std::string GetFileName(const std::string &path); static int32_t CopyToSandBox(const std::string &srcUri, const std::string &disSandboxPath, - const std::string &sandboxPath); - + const std::string &sandboxPath); + static int32_t CreateDirectory(const std::string& authority, std::string& tmpDir, + std::string& disSandboxPath); std::mutex cvMutex_; std::condition_variable cv_; int copyEvent_ = NONE; diff --git a/interfaces/kits/native/BUILD.gn b/interfaces/kits/native/BUILD.gn index ceeb70833828000cd4643c701ccf3d7126aaad47..26ebb9a5b7d5df57227d5bee7be68ace1cecdc00 100644 --- a/interfaces/kits/native/BUILD.gn +++ b/interfaces/kits/native/BUILD.gn @@ -22,6 +22,14 @@ config("remote_uri_config") { ] } +config("task_signal_config") { + visibility = [ ":*" ] + include_dirs = [ + "include", + "task_signal", + ] +} + ohos_shared_library("remote_uri_native") { if (!use_mingw_win && !use_mac) { stack_protector_ret = true @@ -51,6 +59,36 @@ ohos_shared_library("remote_uri_native") { subsystem_name = "filemanagement" } +ohos_shared_library("task_signal_native") { + if (!use_mingw_win && !use_mac) { + stack_protector_ret = true + sanitize = { + integer_overflow = true + ubsan = true + boundary_sanitize = true + cfi = true + cfi_cross_dso = true + debug = false + } + } + + sources = [ "task_signal/task_signal.cpp" ] + + public_configs = [ ":task_signal_config" ] + + deps = [ "${utils_path}/filemgmt_libhilog:filemgmt_libhilog" ] + + external_deps = [ + "c_utils:utils", + "dfs_service:distributed_file_daemon_kit_inner", + "hilog:libhilog", + ] + + innerapi_tags = [ "platformsdk" ] + part_name = "file_api" + subsystem_name = "filemanagement" +} + config("environment_config") { visibility = [ ":*" ] include_dirs = [ "environment" ] @@ -120,5 +158,6 @@ group("build_kits_native") { ":environment_native", ":fileio_native", ":remote_uri_native", + ":task_signal_native", ] } diff --git a/interfaces/kits/native/task_signal/task_signal.cpp b/interfaces/kits/native/task_signal/task_signal.cpp index c99b0edd759f808188212cf9c7f36a37a3b9ac4f..8e10163c129c55771e4bb8165581f2a1e0fbac90 100644 --- a/interfaces/kits/native/task_signal/task_signal.cpp +++ b/interfaces/kits/native/task_signal/task_signal.cpp @@ -78,9 +78,9 @@ void TaskSignal::MarkRemoteTask() remoteTask_.store(true); } -void TaskSignal::SetSessionIdOfRemoteTask(const std::string &sessionName, const std::string &filePath) +void TaskSignal::SetFileInfoOfRemoteTask(const std::string &sessionName, const std::string &filePath) { - HILOGD("SetSessionIdOfRemoteTask sessionName = %{public}s", sessionName.c_str()); + HILOGD("SetFileInfoOfRemoteTask sessionName = %{public}s", sessionName.c_str()); sessionName_ = sessionName; filePath_ = filePath; } diff --git a/interfaces/kits/native/task_signal/task_signal.h b/interfaces/kits/native/task_signal/task_signal.h index 2d06d073204be9740ac747c8fa2248c165a0cd44..4d1f96df2d1f89da93a0e59339daee10a685723e 100644 --- a/interfaces/kits/native/task_signal/task_signal.h +++ b/interfaces/kits/native/task_signal/task_signal.h @@ -35,7 +35,7 @@ public: void OnCancel(const std::string &path); void SetTaskSignalListener(std::shared_ptr signalListener); void MarkRemoteTask(); - void SetSessionIdOfRemoteTask(const std::string &sessionName, const std::string &filePath); + void SetFileInfoOfRemoteTask(const std::string &sessionName, const std::string &filePath); std::atomic_bool needCancel_{ false }; std::atomic_bool remoteTask_{ false }; std::string sessionName_ = std::string(""); diff --git a/utils/filemgmt_libn/include/n_error.h b/utils/filemgmt_libn/include/n_error.h index 18d4a7384e874c4f8e4d51fd6083b37d5c4a7916..1289a4f8c89378f93d586a4ce41c0e3fdb88d6d9 100644 --- a/utils/filemgmt_libn/include/n_error.h +++ b/utils/filemgmt_libn/include/n_error.h @@ -36,6 +36,8 @@ constexpr int ERESTART = 85; constexpr int EDQUOT = 122; #endif constexpr int UNKROWN_ERR = -1; +constexpr int NO_TASK_ERR = -2; +constexpr int CANCEL_ERR = -3; constexpr int ERRNO_NOERR = 0; constexpr int STORAGE_SERVICE_SYS_CAP_TAG = 13600000; constexpr int FILEIO_SYS_CAP_TAG = 13900000; @@ -89,6 +91,9 @@ enum ErrCodeSuffixOfFileIO { E_DQUOT, E_UKERR, E_NOLCK, + E_NOTASK, + E_UNCANCELED, + E_CANCELED, E_NETUNREACH }; @@ -196,6 +201,7 @@ static inline std::unordered_map uvCode2ErrCodeTable { { "EBADFD", EBADFD }, { "ERESTART", ERESTART }, { "EDQUOT", EDQUOT }, + { "ECANCELED", ECANCELED }, { "ENETUNREACH", ENETUNREACH }, }; @@ -243,6 +249,9 @@ static inline std::unordered_map> errCodeTa { ERESTART, { FILEIO_SYS_CAP_TAG + E_RESTART, "Interrupted system call should be restarted" } }, { EDQUOT, { FILEIO_SYS_CAP_TAG + E_DQUOT, "Quota exceeded" } }, { UNKROWN_ERR, { FILEIO_SYS_CAP_TAG + E_UKERR, "Unknown error" } }, + { NO_TASK_ERR, { FILEIO_SYS_CAP_TAG + E_NOTASK, "No task can be canceled" } }, + { CANCEL_ERR, { FILEIO_SYS_CAP_TAG + E_UNCANCELED, "Failed to cancel" } }, + { ECANCELED, { FILEIO_SYS_CAP_TAG + E_CANCELED, "Operation canceled" } }, { ENOLCK, { FILEIO_SYS_CAP_TAG + E_NOLCK, "No record locks available" } }, { ENETUNREACH, { FILEIO_SYS_CAP_TAG + E_NETUNREACH, "Network is unreachable" } }, { FILEIO_SYS_CAP_TAG + E_PERM, { FILEIO_SYS_CAP_TAG + E_PERM, "Operation not permitted" } },