1 /*
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include "watcher_data_cache.h"
16
17 #include "filemgmt_libhilog.h"
18
19 namespace OHOS::FileManagement::ModuleFileIO {
20
AddWatcherInfo(std::shared_ptr<WatcherInfo> info)21 bool WatcherDataCache::AddWatcherInfo(std::shared_ptr<WatcherInfo> info)
22 {
23 std::lock_guard<std::mutex> lock(cacheMutex_);
24 for (auto &iter : watcherInfoCache_) {
25 if (iter->fileName == info->fileName && iter->events == info->events) {
26 bool isSame = iter->callback->IsStrictEquals(info->callback);
27 if (isSame) {
28 HILOGE("Failed to add watcher, fileName:%{private}s the callback is same", info->fileName.c_str());
29 return false;
30 }
31 }
32 }
33 watcherInfoCache_.push_back(info);
34 wdFileNameCache_[info->fileName] = std::make_pair(info->wd, info->events);
35 return true;
36 }
37
RemoveWatcherInfo(std::shared_ptr<WatcherInfo> info)38 uint32_t WatcherDataCache::RemoveWatcherInfo(std::shared_ptr<WatcherInfo> info)
39 {
40 std::lock_guard<std::mutex> lock(cacheMutex_);
41 auto it = std::find(watcherInfoCache_.begin(), watcherInfoCache_.end(), info);
42 if (it != watcherInfoCache_.end()) {
43 watcherInfoCache_.erase(it);
44 }
45
46 uint32_t remainingEvents = 0;
47 for (const auto &iter : watcherInfoCache_) {
48 if (iter->fileName == info->fileName && iter->wd > 0) {
49 remainingEvents |= iter->events;
50 }
51 }
52
53 return remainingEvents;
54 }
55
RemoveFileWatcher(const std::string & fileName)56 bool WatcherDataCache::RemoveFileWatcher(const std::string &fileName)
57 {
58 std::lock_guard<std::mutex> lock(cacheMutex_);
59
60 auto iter = wdFileNameCache_.find(fileName);
61 if (iter == wdFileNameCache_.end()) {
62 HILOGE("Failed to find fileName");
63 return false;
64 }
65 wdFileNameCache_.erase(iter);
66
67 watcherInfoCache_.erase(std::remove_if(watcherInfoCache_.begin(), watcherInfoCache_.end(),
68 [&fileName](const std::shared_ptr<WatcherInfo> &info) {
69 return info->fileName == fileName;
70 }), watcherInfoCache_.end());
71
72 return true;
73 }
74
FindWatchedWd(const std::string & fileName,uint32_t event)75 std::tuple<bool, int32_t> WatcherDataCache::FindWatchedWd(const std::string &fileName, uint32_t event)
76 {
77 std::lock_guard<std::mutex> lock(cacheMutex_);
78
79 int32_t wd = -1;
80 auto iter = wdFileNameCache_.find(fileName);
81 if (iter == wdFileNameCache_.end()) {
82 return { false, wd };
83 }
84
85 wd = iter->second.first;
86 if ((iter->second.second & event) == event) {
87 return { true, wd };
88 }
89
90 return { false, wd };
91 }
92
UpdateWatchedEvents(const std::string & fileName,int32_t wd,uint32_t events)93 bool WatcherDataCache::UpdateWatchedEvents(const std::string &fileName, int32_t wd, uint32_t events)
94 {
95 std::lock_guard<std::mutex> lock(cacheMutex_);
96 auto iter = wdFileNameCache_.find(fileName);
97 if (iter == wdFileNameCache_.end()) {
98 return false;
99 }
100
101 iter->second = std::make_pair(wd, events);
102 return true;
103 }
104
CheckIncludeEvent(uint32_t mask,uint32_t event)105 static bool CheckIncludeEvent(uint32_t mask, uint32_t event)
106 {
107 return (mask & event) > 0;
108 }
109
FindWatcherInfos(int32_t wd,uint32_t eventMask)110 std::tuple<bool, std::string, std::vector<std::shared_ptr<WatcherInfo>>> WatcherDataCache::FindWatcherInfos(
111 int32_t wd, uint32_t eventMask)
112 {
113 std::lock_guard<std::mutex> lock(cacheMutex_);
114 std::string fileName;
115 bool found = false;
116 for (const auto &[key, val] : wdFileNameCache_) {
117 if (val.first == wd) {
118 fileName = key;
119 found = true;
120 break;
121 }
122 }
123
124 if (!found) {
125 return { false, "", {} };
126 }
127
128 std::vector<std::shared_ptr<WatcherInfo>> matchedInfos;
129 for (const auto &info : watcherInfoCache_) {
130 uint32_t watchEvent = 0;
131 if ((info->fileName == fileName) && (info->wd > 0)) {
132 watchEvent = info->events;
133 }
134 if (CheckIncludeEvent(eventMask, watchEvent)) {
135 matchedInfos.push_back(info);
136 }
137 }
138 return { !matchedInfos.empty(), fileName, matchedInfos };
139 }
140
GetFileEvents(const std::string & fileName)141 uint32_t WatcherDataCache::GetFileEvents(const std::string &fileName)
142 {
143 std::lock_guard<std::mutex> lock(cacheMutex_);
144 auto iter = wdFileNameCache_.find(fileName);
145 if (iter == wdFileNameCache_.end()) {
146 return 0;
147 }
148 return iter->second.second;
149 }
150
HasWatcherInfo() const151 bool WatcherDataCache::HasWatcherInfo() const
152 {
153 std::lock_guard<std::mutex> lock(cacheMutex_);
154 return !watcherInfoCache_.empty();
155 }
156
ClearCache()157 void WatcherDataCache::ClearCache()
158 {
159 std::lock_guard<std::mutex> lock(cacheMutex_);
160 watcherInfoCache_.clear();
161 wdFileNameCache_.clear();
162 }
163
164 } // namespace OHOS::FileManagement::ModuleFileIO