diff --git a/interfaces/kits/js/src/mod_fileio/properties/watcher.cpp b/interfaces/kits/js/src/mod_fileio/properties/watcher.cpp index b822f9a3c6461034cb62979578c32354e451d672..ce477b402e829df365b36e278c511f261aabbe32 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 45c100cb21057e0a0711212df5ec9846985aebaf..4a2d0a9bae26c2330ed5444074726527c18ee9dc 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 0000000000000000000000000000000000000000..db24fa623c252c00dc8baabf095f1775605d25d8 --- /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 new file mode 100644 index 0000000000000000000000000000000000000000..e1d434f4f6f9ff988375607435b62f64e10a6e40 --- /dev/null +++ b/interfaces/kits/js/src/mod_fileio/properties/watcher_observer.cpp @@ -0,0 +1,204 @@ +/* + * 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::map WatcherObserver::watcherFileMaps_; +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("WatcherObserver inotify_init false"); + return false; + } else { + inotifySuccess_ = true; + return true; + } +} + +bool WatcherObserver::StopObserver() +{ + isRunning_ = false; + for (auto fileInfo : watcherFileMaps_) { + if (inotify_rm_watch(inotifyFd_, fileInfo.second.GetWd()) == -1) { + HILOGE("WatcherObserver 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("WatcherObserver 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 : 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) { + watcherFileInfo.first->OnChanged(info.GetPath(), event->mask); + } + } + } + } + } + positionEvent++; + ret -= (int)sizeof(struct inotify_event); + } + return true; +} + +bool WatcherObserver::WatchPathThread() +{ + while (isRunning_) { + if (watcherFileMaps_.size() > 0) { + AddInotifyEvents(inotifyFd_); + } + } + return true; +} + +void WatcherObserver::AddObserver(const std::string &path, + const std::vector &watchEvents, + const WatcherCallbackPtr &callback) +{ + 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); + + WatcherFileInfo fileInfo; + fileInfo.SetWd(wd); + fileInfo.SetPath(path); + fileInfo.SetWatchEvents(watchEvents); + watcherFileMaps_.insert(make_pair(callback,fileInfo)); + } + } + if (!startThread_) { + std::thread watchThread(WatchPathThread); + watchThread.detach(); + startThread_ = true; + } +} + +bool WatcherObserver::IsOnlyWatcherFileInfo(const std::string &path) +{ + int count = 0; + for (auto watcherFileInfo : watcherFileMaps_) { + if (strcmp(path.c_str(), watcherFileInfo.second.GetPath().c_str()) == 0) { + count++; + } + if (count > 1) { + return false; + } + } + if (count == 0) { + return false; + } + return true; +} + +void WatcherObserver::RemoveObserver(const std::string &path, + const std::vector &watchEvents, + const WatcherCallbackPtr &callback) +{ + + bool isOnly = IsOnlyWatcherFileInfo(path); + auto iter = watcherFileMaps_.find(callback); + if (iter != watcherFileMaps_.end()) { + if (isOnly) { + if (inotify_rm_watch(inotifyFd_, iter->second.GetWd()) == -1) { + HILOGE("WatcherObserver StopFileInotify inotify_rm_watch error"); + return; + } + } + watcherFileMaps_.erase(iter); + } + + if (watcherFileMaps_.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 0000000000000000000000000000000000000000..1376ad65e71878f7a1e1e3741def9f0574511c7c --- /dev/null +++ b/interfaces/kits/js/src/mod_fileio/properties/watcher_observer.h @@ -0,0 +1,72 @@ +/* + * 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 "watcher_callback.h" +#include +#include +#include +#include +#include +namespace OHOS { +namespace DistributedFS { +namespace ModuleFileIO { +using WatcherCallbackPtr = std::shared_ptr; + +class WatcherObserver : public Singleton { +public: + 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); + 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::map watcherFileMaps_; + static std::mutex eventLock_; + static int inotifyFd_; + + bool startThread_; + bool inotifySuccess_; +}; +} // namespace ModuleFileIO +} // namespace DistributedFS +} // namespace OHOS +#endif \ No newline at end of file