From b726cb89e57c6eb4e8b5742f6351db3ddb09bd10 Mon Sep 17 00:00:00 2001 From: Cao Chuan Date: Wed, 11 Jan 2023 13:39:50 +0800 Subject: [PATCH 1/3] add watchFileObserver Signed-off-by: Cao Chuan --- .../properties/watcher_observer.cpp | 199 ++++++++++++++++++ .../mod_fileio/properties/watcher_observer.h | 63 ++++++ 2 files changed, 262 insertions(+) create mode 100644 interfaces/kits/js/src/mod_fileio/properties/watcher_observer.cpp create mode 100644 interfaces/kits/js/src/mod_fileio/properties/watcher_observer.h diff --git a/interfaces/kits/js/src/mod_fileio/properties/watcher_observer.cpp b/interfaces/kits/js/src/mod_fileio/properties/watcher_observer.cpp new file mode 100644 index 000000000..18abab0d0 --- /dev/null +++ b/interfaces/kits/js/src/mod_fileio/properties/watcher_observer.cpp @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "watcher_observer.h" +#include "../../log.h" +#include +#include +#include +#include +namespace OHOS { +namespace DistributedFS { +namespace ModuleFileIO { +using namespace std; +bool WatcherObserver::isRunning_ = false; +int WatcherObserver::inotifyFd_ = 0; +std::mutex WatcherObserver::eventLock_; +std::vector WatcherObserver::watcherFileInfos_; +const int BUF_SIZE = 1024; + +void WatcherObserver::WatcherFileInfo::SetPath(const std::string &path) +{ + path_ = path; +} + +std::string WatcherObserver::WatcherFileInfo::GetPath() +{ + return path_; +} + +void WatcherObserver::WatcherFileInfo::SetWd(const int &wd) +{ + wd_ = wd; +} + +int WatcherObserver::WatcherFileInfo::GetWd() +{ + return wd_; +} + +void WatcherObserver::WatcherFileInfo::SetWatchEvents(const std::vector &events) +{ + events_.assign(events.begin(), events.end()); +} + +std::vector WatcherObserver::WatcherFileInfo::GetWatchEvents() +{ + return events_; +} + +bool WatcherObserver::StartObserver() +{ + isRunning_ = true; + inotifyFd_ = inotify_init(); + if (inotifyFd_ == -1) { + HILOGE("MtpFileObserver inotify_init false"); + return false; + } else { + inotifySuccess_ = true; + return true; + } +} + +bool WatcherObserver::StopObserver() +{ + isRunning_ = false; + for (auto fileInfo : watcherFileInfos_) { + if (inotify_rm_watch(inotifyFd_, fileInfo.GetWd()) == -1) { + HILOGE("MtpFileObserver StopFileInotify inotify_rm_watch error"); + return false; + } + } + close(inotifyFd_); + startThread_ = false; + inotifySuccess_ = false; + inotifyFd_ = 0; + return true; +} + +bool WatcherObserver::AddInotifyEvents(const int &inotifyFd) +{ + char eventBuf[BUF_SIZE] = {0}; + + int ret = read(inotifyFd, eventBuf, sizeof(eventBuf)); + if (ret < (int)sizeof(struct inotify_event)) { + HILOGE("MtpFileObserver AddInotifyEvents no event"); + return false; + } + + struct inotify_event *positionEvent = (struct inotify_event *)eventBuf; + struct inotify_event *event; + while (ret >= (int)sizeof(struct inotify_event)) { + lock_guard lock(eventLock_); + event = positionEvent; + if (event->len) { + for (auto watcherFileInfo : watcherFileInfos_) { + if (watcherFileInfo.GetWd() == event->wd) { + vector events = watcherFileInfo.GetWatchEvents(); + for (auto iter = events.begin(); iter != events.end(); ++iter) { + if (event->mask == *iter) { + // todo添加回调 + } + } + } + } + } + positionEvent++; + ret -= (int)sizeof(struct inotify_event); + } + return true; +} + +bool WatcherObserver::WatchPathThread() +{ + while (isRunning_) { + if (watcherFileInfos_.size() > 0) { + AddInotifyEvents(inotifyFd_); + } + } + return true; +} + +// todo 参数添加回调 +void WatcherObserver::AddObserver(const std::string &path, const std::vector &watchEvents) +{ + if (!inotifySuccess_) { + StartObserver(); + } + if (inotifySuccess_) { + if (!path.empty() && watchEvents.size() > 0) { + uint32_t event = 0; + for (auto watchEvent : watchEvents) { + event = event | watchEvent; + } + int wd = inotify_add_watch(inotifyFd_, path.c_str(), event); + + WatcherObserver::WatcherFileInfo fileInfo; + fileInfo.SetWd(wd); + fileInfo.SetPath(path); + fileInfo.SetWatchEvents(watchEvents); + watcherFileInfos_.push_back(fileInfo); + } + } + if (!startThread_) { + std::thread watchThread(WatchPathThread); + watchThread.detach(); + startThread_ = true; + } +} + +bool WatcherObserver::IsOnlyWatcherFileInfo(const std::string &path) +{ + int count = 0; + for (auto watcherFileInfo : watcherFileInfos_) { + if (strcmp(path.c_str(), watcherFileInfo.GetPath().c_str()) == 0) { + count++; + } + if (count > 1) { + return false; + } + } + if (count == 0) { + return false; + } + return true; +} + +// todo 参数添加回调 +void WatcherObserver::RemoveObserver(const std::string &path, const std::vector &watchEvents) +{ + + bool isOnly = IsOnlyWatcherFileInfo(path); + for (auto iter = watcherFileInfos_.begin(); iter != watcherFileInfos_.end(); ++iter) { + if (isOnly) { + if (inotify_rm_watch(inotifyFd_, iter->GetWd()) == -1) { + HILOGE("MtpFileObserver StopFileInotify inotify_rm_watch error"); + return; + } + } + watcherFileInfos_.erase(iter); + } + + if (watcherFileInfos_.size() == 0) { + StopObserver(); + } +} +} // namespace ModuleFileIO +} // namespace DistributedFS +} // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fileio/properties/watcher_observer.h b/interfaces/kits/js/src/mod_fileio/properties/watcher_observer.h new file mode 100644 index 000000000..68ba4c61d --- /dev/null +++ b/interfaces/kits/js/src/mod_fileio/properties/watcher_observer.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef WATCHER_OBSERVER_H +#define WATCHER_OBSERVER_H +#include "singleton.h" +#include +#include +#include +namespace OHOS { +namespace DistributedFS { +namespace ModuleFileIO { +class WatcherObserver : public Singleton { +public: + // todo 添加回调 + void AddObserver(const std::string &path, const std::vector &watchEvents); + void RemoveObserver(const std::string &path, const std::vector &watchEvents); + class WatcherFileInfo { + public: + void SetWd(const int &wd); + int32_t GetWd(); + + void SetPath(const std::string &path); + std::string GetPath(); + + void SetWatchEvents(const std::vector &events); + std::vector GetWatchEvents(); + + private: + int wd_; + std::string path_; + std::vector events_; + }; + +private: + bool StartObserver(); + bool StopObserver(); + bool IsOnlyWatcherFileInfo(const std::string &path); + static bool AddInotifyEvents(const int &inotifyFd); + static bool WatchPathThread(); + static bool isRunning_; + static std::vector watcherFileInfos_; + static std::mutex eventLock_; + static int inotifyFd_; + + bool startThread_; + bool inotifySuccess_; +}; +} // namespace ModuleFileIO +} // namespace DistributedFS +} // namespace OHOS +#endif \ No newline at end of file -- Gitee From 327fafd41b3f2fa2de5647ba45dc9989ddb78d55 Mon Sep 17 00:00:00 2001 From: Cao Chuan Date: Wed, 11 Jan 2023 13:52:01 +0800 Subject: [PATCH 2/3] modify log Signed-off-by: Cao Chuan --- .../js/src/mod_fileio/properties/watcher_observer.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/interfaces/kits/js/src/mod_fileio/properties/watcher_observer.cpp b/interfaces/kits/js/src/mod_fileio/properties/watcher_observer.cpp index 18abab0d0..4da9ddb61 100644 --- a/interfaces/kits/js/src/mod_fileio/properties/watcher_observer.cpp +++ b/interfaces/kits/js/src/mod_fileio/properties/watcher_observer.cpp @@ -63,7 +63,7 @@ bool WatcherObserver::StartObserver() isRunning_ = true; inotifyFd_ = inotify_init(); if (inotifyFd_ == -1) { - HILOGE("MtpFileObserver inotify_init false"); + HILOGE("WatcherObserver inotify_init false"); return false; } else { inotifySuccess_ = true; @@ -76,7 +76,7 @@ bool WatcherObserver::StopObserver() isRunning_ = false; for (auto fileInfo : watcherFileInfos_) { if (inotify_rm_watch(inotifyFd_, fileInfo.GetWd()) == -1) { - HILOGE("MtpFileObserver StopFileInotify inotify_rm_watch error"); + HILOGE("WatcherObserver StopFileInotify inotify_rm_watch error"); return false; } } @@ -93,7 +93,7 @@ bool WatcherObserver::AddInotifyEvents(const int &inotifyFd) int ret = read(inotifyFd, eventBuf, sizeof(eventBuf)); if (ret < (int)sizeof(struct inotify_event)) { - HILOGE("MtpFileObserver AddInotifyEvents no event"); + HILOGE("WatcherObserver AddInotifyEvents no event"); return false; } @@ -183,7 +183,7 @@ void WatcherObserver::RemoveObserver(const std::string &path, const std::vector< for (auto iter = watcherFileInfos_.begin(); iter != watcherFileInfos_.end(); ++iter) { if (isOnly) { if (inotify_rm_watch(inotifyFd_, iter->GetWd()) == -1) { - HILOGE("MtpFileObserver StopFileInotify inotify_rm_watch error"); + HILOGE("WatcherObserver StopFileInotify inotify_rm_watch error"); return; } } -- Gitee From 672b151eac050c96fef9ef561c8b6c3bd7446066 Mon Sep 17 00:00:00 2001 From: Cao Chuan Date: Thu, 12 Jan 2023 09:33:32 +0800 Subject: [PATCH 3/3] add callback Signed-off-by: Cao Chuan --- .../js/src/mod_fileio/properties/watcher.cpp | 8 +++- .../js/src/mod_fileio/properties/watcher.h | 9 ++++ .../mod_fileio/properties/watcher_callback.h | 24 ++++++++++ .../properties/watcher_observer.cpp | 45 ++++++++++--------- .../mod_fileio/properties/watcher_observer.h | 17 +++++-- 5 files changed, 77 insertions(+), 26 deletions(-) create mode 100644 interfaces/kits/js/src/mod_fileio/properties/watcher_callback.h diff --git a/interfaces/kits/js/src/mod_fileio/properties/watcher.cpp b/interfaces/kits/js/src/mod_fileio/properties/watcher.cpp index b822f9a3c..ce477b402 100644 --- a/interfaces/kits/js/src/mod_fileio/properties/watcher.cpp +++ b/interfaces/kits/js/src/mod_fileio/properties/watcher.cpp @@ -36,8 +36,8 @@ using namespace std; void Watcher::RunCommand(uv_fs_event_t *handle, const char *filename, int events, int status) { WatcherInforArg *information = (WatcherInforArg *)handle->data; - uint32_t eventsFirst { events }; - uint32_t eventsSecond { information->events }; + uint32_t eventsFirst{events}; + uint32_t eventsSecond{information->events}; if (eventsFirst & eventsSecond) { napi_handle_scope scope = nullptr; napi_open_handle_scope(information->env, &scope); @@ -101,6 +101,10 @@ napi_value Watcher::CreateWatcher(napi_env env, napi_callback_info info) return objWatcher; } + +void WatcherEventCallback::OnChanged(const std::string &path, const uint32_t &event) { + //todo 添加napi +} } // namespace ModuleFileIO } // namespace DistributedFS } // namespace OHOS \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fileio/properties/watcher.h b/interfaces/kits/js/src/mod_fileio/properties/watcher.h index 45c100cb2..4a2d0a9ba 100644 --- a/interfaces/kits/js/src/mod_fileio/properties/watcher.h +++ b/interfaces/kits/js/src/mod_fileio/properties/watcher.h @@ -18,6 +18,7 @@ #include #include "../../common/napi/n_val.h" +#include "watcher_callback.h" namespace OHOS { namespace DistributedFS { @@ -29,6 +30,14 @@ public: private: static void RunCommand(uv_fs_event_t *handle, const char *filename, int events, int status); }; + +class WatcherEventCallback : public WatcherCallback +{ +public: + void OnChanged(const std::string &path, const uint32_t &event); +private: + +}; } // namespace ModuleFileIO } // namespace DistributedFS } // namespace OHOS diff --git a/interfaces/kits/js/src/mod_fileio/properties/watcher_callback.h b/interfaces/kits/js/src/mod_fileio/properties/watcher_callback.h new file mode 100644 index 000000000..db24fa623 --- /dev/null +++ b/interfaces/kits/js/src/mod_fileio/properties/watcher_callback.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef WATCHER_CALLBACK_H +#define WATCHER_CALLBACK_H +#include +class WatcherCallback +{ +public: + virtual ~WatcherCallback() = default; + virtual void OnChanged(const std::string &path, const uint32_t &event) = 0; +}; +#endif \ No newline at end of file diff --git a/interfaces/kits/js/src/mod_fileio/properties/watcher_observer.cpp b/interfaces/kits/js/src/mod_fileio/properties/watcher_observer.cpp index 4da9ddb61..e1d434f4f 100644 --- a/interfaces/kits/js/src/mod_fileio/properties/watcher_observer.cpp +++ b/interfaces/kits/js/src/mod_fileio/properties/watcher_observer.cpp @@ -22,10 +22,11 @@ namespace OHOS { namespace DistributedFS { namespace ModuleFileIO { using namespace std; + bool WatcherObserver::isRunning_ = false; int WatcherObserver::inotifyFd_ = 0; std::mutex WatcherObserver::eventLock_; -std::vector WatcherObserver::watcherFileInfos_; +std::map WatcherObserver::watcherFileMaps_; const int BUF_SIZE = 1024; void WatcherObserver::WatcherFileInfo::SetPath(const std::string &path) @@ -74,8 +75,8 @@ bool WatcherObserver::StartObserver() bool WatcherObserver::StopObserver() { isRunning_ = false; - for (auto fileInfo : watcherFileInfos_) { - if (inotify_rm_watch(inotifyFd_, fileInfo.GetWd()) == -1) { + for (auto fileInfo : watcherFileMaps_) { + if (inotify_rm_watch(inotifyFd_, fileInfo.second.GetWd()) == -1) { HILOGE("WatcherObserver StopFileInotify inotify_rm_watch error"); return false; } @@ -103,12 +104,13 @@ bool WatcherObserver::AddInotifyEvents(const int &inotifyFd) lock_guard lock(eventLock_); event = positionEvent; if (event->len) { - for (auto watcherFileInfo : watcherFileInfos_) { - if (watcherFileInfo.GetWd() == event->wd) { - vector events = watcherFileInfo.GetWatchEvents(); + for (auto watcherFileInfo : watcherFileMaps_) { + WatcherObserver::WatcherFileInfo info = watcherFileInfo.second; + if (info.GetWd() == event->wd) { + vector events = info.GetWatchEvents(); for (auto iter = events.begin(); iter != events.end(); ++iter) { if (event->mask == *iter) { - // todo添加回调 + watcherFileInfo.first->OnChanged(info.GetPath(), event->mask); } } } @@ -123,15 +125,16 @@ bool WatcherObserver::AddInotifyEvents(const int &inotifyFd) bool WatcherObserver::WatchPathThread() { while (isRunning_) { - if (watcherFileInfos_.size() > 0) { + if (watcherFileMaps_.size() > 0) { AddInotifyEvents(inotifyFd_); } } return true; } -// todo 参数添加回调 -void WatcherObserver::AddObserver(const std::string &path, const std::vector &watchEvents) +void WatcherObserver::AddObserver(const std::string &path, + const std::vector &watchEvents, + const WatcherCallbackPtr &callback) { if (!inotifySuccess_) { StartObserver(); @@ -144,11 +147,11 @@ void WatcherObserver::AddObserver(const std::string &path, const std::vector 1) { @@ -175,22 +178,24 @@ bool WatcherObserver::IsOnlyWatcherFileInfo(const std::string &path) return true; } -// todo 参数添加回调 -void WatcherObserver::RemoveObserver(const std::string &path, const std::vector &watchEvents) +void WatcherObserver::RemoveObserver(const std::string &path, + const std::vector &watchEvents, + const WatcherCallbackPtr &callback) { bool isOnly = IsOnlyWatcherFileInfo(path); - for (auto iter = watcherFileInfos_.begin(); iter != watcherFileInfos_.end(); ++iter) { + auto iter = watcherFileMaps_.find(callback); + if (iter != watcherFileMaps_.end()) { if (isOnly) { - if (inotify_rm_watch(inotifyFd_, iter->GetWd()) == -1) { + if (inotify_rm_watch(inotifyFd_, iter->second.GetWd()) == -1) { HILOGE("WatcherObserver StopFileInotify inotify_rm_watch error"); return; } } - watcherFileInfos_.erase(iter); + watcherFileMaps_.erase(iter); } - if (watcherFileInfos_.size() == 0) { + if (watcherFileMaps_.size() == 0) { StopObserver(); } } diff --git a/interfaces/kits/js/src/mod_fileio/properties/watcher_observer.h b/interfaces/kits/js/src/mod_fileio/properties/watcher_observer.h index 68ba4c61d..1376ad65e 100644 --- a/interfaces/kits/js/src/mod_fileio/properties/watcher_observer.h +++ b/interfaces/kits/js/src/mod_fileio/properties/watcher_observer.h @@ -15,17 +15,26 @@ #ifndef WATCHER_OBSERVER_H #define WATCHER_OBSERVER_H #include "singleton.h" +#include "watcher_callback.h" +#include +#include #include #include #include namespace OHOS { namespace DistributedFS { namespace ModuleFileIO { +using WatcherCallbackPtr = std::shared_ptr; + class WatcherObserver : public Singleton { public: - // todo 添加回调 - void AddObserver(const std::string &path, const std::vector &watchEvents); - void RemoveObserver(const std::string &path, const std::vector &watchEvents); + void AddObserver(const std::string &path, + const std::vector &watchEvents, + const WatcherCallbackPtr &callback); + void RemoveObserver(const std::string &path, + const std::vector &watchEvents, + const WatcherCallbackPtr &callback); + class WatcherFileInfo { public: void SetWd(const int &wd); @@ -50,7 +59,7 @@ private: static bool AddInotifyEvents(const int &inotifyFd); static bool WatchPathThread(); static bool isRunning_; - static std::vector watcherFileInfos_; + static std::map watcherFileMaps_; static std::mutex eventLock_; static int inotifyFd_; -- Gitee