1 /*
2 * Copyright (c) 2023 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
16 #include "utils_log.h"
17 #include "common_event_sys_errors.h"
18 #include "io_event_epoll.h"
19 #include "io_event_reactor.h"
20
21 namespace OHOS {
22 namespace Utils {
23
IOEventReactor()24 IOEventReactor::IOEventReactor()
25 :loopReady_(false), enabled_(false), count_(0), ioHandlers_(INIT_FD_NUMS), backend_(new IOEventEpoll()) {}
26
~IOEventReactor()27 IOEventReactor::~IOEventReactor()
28 {
29 CleanUp();
30 }
31
SetUp()32 ErrCode IOEventReactor::SetUp()
33 {
34 if (backend_ == nullptr) {
35 backend_ = std::make_unique<IOEventEpoll>();
36 }
37
38 ErrCode res = backend_->SetUp();
39 if (res != EVENT_SYS_ERR_OK) {
40 UTILS_LOGE("%{public}s: Backend start failed.", __FUNCTION__);
41 return res;
42 }
43
44 loopReady_ = true;
45 return res;
46 }
47
InsertNodeFront(int fd,IOEventHandler * target)48 void IOEventReactor::InsertNodeFront(int fd, IOEventHandler* target)
49 {
50 IOEventHandler* h = ioHandlers_[fd].head.get();
51 target->next_ = h->next_;
52 target->prev_ = h;
53 if (h->next_ != nullptr) {
54 h->next_->prev_ = target;
55 }
56 h->next_ = target;
57 }
58
RemoveNode(IOEventHandler * target)59 void IOEventReactor::RemoveNode(IOEventHandler* target)
60 {
61 target->prev_->next_ = target->next_;
62
63 if (target->next_ != nullptr) {
64 target->next_->prev_ = target->prev_;
65 }
66
67 target->prev_ = nullptr;
68 target->next_ = nullptr;
69 }
70
AddHandler(IOEventHandler * target)71 ErrCode IOEventReactor::AddHandler(IOEventHandler* target)
72 {
73 if (target == nullptr) {
74 return EVENT_SYS_ERR_NOT_FOUND;
75 }
76
77 if (target->fd_ == -1) {
78 UTILS_LOGE("%{public}s: Failed, Bad fd.", __FUNCTION__);
79 return EVENT_SYS_ERR_BADF;
80 }
81 if (target->prev_!=nullptr) {
82 UTILS_LOGW("%{public}s: Warning, already started.", __FUNCTION__);
83 return EVENT_SYS_ERR_ALREADY_STARTED;
84 }
85
86 std::lock_guard<std::mutex> lock(mutex_);
87 int fd = target->fd_;
88 if (static_cast<size_t>(fd) > ioHandlers_.size() - 1u) {
89 UTILS_LOGD("%{public}s: Resize when fd: %{public}d", __FUNCTION__, fd);
90 ioHandlers_.resize(fd * EXPANSION_COEFF);
91 }
92
93 InsertNodeFront(fd, target);
94
95 if ((ioHandlers_[fd].events & target->events_) != target->events_) {
96 if (backend_ == nullptr || !UpdateToDemultiplexer(target->fd_)) {
97 UTILS_LOGE("%{public}s: Update fd: %{public}d to backend failed.", __FUNCTION__, target->fd_);
98 return EVENT_SYS_ERR_FAILED;
99 }
100 }
101
102 target->enabled_ = true;
103 count_++;
104 return EVENT_SYS_ERR_OK;
105 }
106
UpdateHandler(IOEventHandler * target)107 ErrCode IOEventReactor::UpdateHandler(IOEventHandler* target)
108 {
109 if (target == nullptr) {
110 return EVENT_SYS_ERR_NOT_FOUND;
111 }
112
113 if (target->fd_ == -1) {
114 UTILS_LOGE("%{public}s: Failed, Bad fd.", __FUNCTION__);
115 return EVENT_SYS_ERR_BADF;
116 }
117
118 if (target->prev_!=nullptr) {
119 if (!HasHandler(target)) {
120 UTILS_LOGE("%{public}s: Failed, handler not found.", __FUNCTION__);
121 return EVENT_SYS_ERR_NOT_FOUND;
122 }
123 if (backend_ == nullptr || !UpdateToDemultiplexer(target->fd_)) {
124 UTILS_LOGE("%{public}s: Update fd: %{public}d to backend failed.", __FUNCTION__, target->fd_);
125 return EVENT_SYS_ERR_FAILED;
126 }
127 return EVENT_SYS_ERR_OK;
128 }
129
130 return AddHandler(target);
131 }
132
RemoveHandler(IOEventHandler * target)133 ErrCode IOEventReactor::RemoveHandler(IOEventHandler* target)
134 {
135 if (target == nullptr) {
136 return EVENT_SYS_ERR_NOT_FOUND;
137 }
138
139 if (target->fd_ == -1) {
140 UTILS_LOGE("%{public}s: Failed, Bad fd.", __FUNCTION__);
141 return EVENT_SYS_ERR_BADF;
142 }
143
144 target->enabled_ = false;
145 std::lock_guard<std::mutex> lock(mutex_);
146
147 if (!HasHandler(target)) {
148 UTILS_LOGE("%{public}s Failed. Handler not found.", __FUNCTION__);
149 target->enabled_=true;
150 return EVENT_SYS_ERR_NOT_FOUND;
151 }
152
153 RemoveNode(target);
154
155 if (backend_ == nullptr || !UpdateToDemultiplexer(target->fd_)) {
156 UTILS_LOGE("%{public}s: Update fd: %{public}d to backend failed.", __FUNCTION__, target->fd_);
157 target->enabled_=true;
158 return EVENT_SYS_ERR_FAILED;
159 }
160
161 count_--;
162 return EVENT_SYS_ERR_OK;
163 }
164
HasHandler(IOEventHandler * target)165 bool IOEventReactor::HasHandler(IOEventHandler* target)
166 {
167 for (IOEventHandler* cur = ioHandlers_[target->fd_].head.get(); cur != nullptr; cur = cur->next_) {
168 if (cur == target) {
169 return true;
170 }
171 }
172
173 return false;
174 }
175
FindHandler(IOEventHandler * target)176 ErrCode IOEventReactor::FindHandler(IOEventHandler* target)
177 {
178 if (target == nullptr) {
179 return EVENT_SYS_ERR_NOT_FOUND;
180 }
181
182 if (target->fd_ == -1) {
183 UTILS_LOGD("%{public}s: Failed, Bad fd.", __FUNCTION__);
184 return EVENT_SYS_ERR_BADF;
185 }
186
187 std::lock_guard<std::mutex> lock(mutex_);
188
189 if (!HasHandler(target)) {
190 UTILS_LOGD("%{public}s: Handler not found.", __FUNCTION__);
191 return EVENT_SYS_ERR_NOT_FOUND;
192 }
193
194 return EVENT_SYS_ERR_OK;
195 }
196
UpdateToDemultiplexer(int fd)197 bool IOEventReactor::UpdateToDemultiplexer(int fd)
198 {
199 uint32_t emask = 0u;
200 for (IOEventHandler* cur = ioHandlers_[fd].head.get(); cur != nullptr; cur = cur->next_) {
201 emask |= cur->events_;
202 }
203
204 if (emask == ioHandlers_[fd].events) {
205 UTILS_LOGW("%{public}s: Warning, Interested events not changed.", __FUNCTION__);
206 return true;
207 }
208
209 ErrCode res = backend_->ModifyEvents(fd, emask);
210 if (res != EVENT_SYS_ERR_OK) {
211 UTILS_LOGE("%{public}s: Modify events on backend failed. fd: %{public}d, \
212 new event: %{public}d, error code: %{public}d", __FUNCTION__, fd, emask, res);
213 return false;
214 }
215
216 ioHandlers_[fd].events = emask;
217 return true;
218 }
219
Execute(const std::vector<EventCallback> & tasks)220 void IOEventReactor::Execute(const std::vector<EventCallback>& tasks)
221 {
222 for (const EventCallback& cb : tasks) {
223 cb();
224 }
225 }
226
HandleEvents(int fd,EventId event)227 ErrCode IOEventReactor::HandleEvents(int fd, EventId event)
228 {
229 std::vector<EventCallback> taskQue;
230 {
231 std::lock_guard<std::mutex> lock(mutex_);
232 if (!(ioHandlers_[fd].events & event)) {
233 UTILS_LOGD("%{public}s: Non-interested event: %{public}d with fd: %{public}d, interested events: \
234 %{public}d", __FUNCTION__, event, fd, ioHandlers_[fd].events);
235 return EVENT_SYS_ERR_BADEVENT;
236 }
237
238 for (IOEventHandler* cur = ioHandlers_[fd].head.get()->next_; cur != nullptr; cur = cur->next_) {
239 if (cur->events_ != Events::EVENT_NONE && cur->enabled_ && (cur->events_ & event) && cur->cb_) {
240 taskQue.push_back(cur->cb_);
241 UTILS_LOGD("%{public}s: Handling event success: %{public}d with fd: %{public}d; \
242 handler interested events: %{public}d, active-status: %{public}d", \
243 __FUNCTION__, event, fd, cur->events_, cur->enabled_);
244 } else {
245 UTILS_LOGD("%{public}s: Handling event ignore: %{public}d with fd: %{public}d; \
246 handler interested events: %{public}d, active-status: %{public}d", \
247 __FUNCTION__, event, fd, cur->events_, cur->enabled_);
248 }
249 }
250 }
251
252 Execute(taskQue);
253 return EVENT_SYS_ERR_OK;
254 }
255
HandleAll(const std::vector<std::pair<int,EventId>> & events)256 void IOEventReactor::HandleAll(const std::vector<std::pair<int, EventId>>& events)
257 {
258 for (size_t idx = 0u; idx < events.size(); idx++) {
259 int fd = events[idx].first;
260 EventId event = events[idx].second;
261
262 UTILS_LOGD("%{public}s: Processing. Handling event: %{public}d, with fd: %{public}d.", \
263 __FUNCTION__, event, fd);
264
265 if (HandleEvents(fd, event) == EVENT_SYS_ERR_BADEVENT) {
266 UTILS_LOGD("%{public}s: Received non-interested events-%{public}d.", __FUNCTION__, event);
267 }
268 }
269 }
270
Run(int timeout)271 void IOEventReactor::Run(int timeout)
272 {
273 std::vector<std::pair<int, EventId>> gotEvents;
274 while (loopReady_) {
275 if (!enabled_) {
276 continue;
277 }
278 ErrCode res;
279 if (timeout == -1) {
280 std::lock_guard<std::mutex> lock(mutex_);
281 if (count_ ==0) {
282 continue;
283 }
284 res = backend_->Polling(timeout, gotEvents);
285 } else {
286 res = backend_->Polling(timeout, gotEvents);
287 }
288
289 switch (res) {
290 case EVENT_SYS_ERR_OK:
291 HandleAll(gotEvents);
292 gotEvents.clear();
293 break;
294 case EVENT_SYS_ERR_NOEVENT:
295 UTILS_LOGD("%{public}s: No events captured.", __FUNCTION__);
296 break;
297 case EVENT_SYS_ERR_FAILED:
298 UTILS_LOGE("%{public}s: Backends failed.", __FUNCTION__);
299 break;
300 default:
301 break;
302 }
303 }
304 }
305
DoClean(int fd)306 bool IOEventReactor::DoClean(int fd)
307 {
308 if (ioHandlers_[fd].head->next_ == nullptr) {
309 return true;
310 }
311
312 for (IOEventHandler* cur = ioHandlers_[fd].head->next_; cur != nullptr; cur = cur->next_) {
313 cur->prev_->next_ = nullptr;
314 cur->prev_ = nullptr;
315 cur->enabled_ = false;
316 }
317
318 if (!UpdateToDemultiplexer(fd)) {
319 UTILS_LOGD("%{public}s: Clear handler list success, while updating backend failed.", __FUNCTION__);
320 return false;
321 }
322
323 return true;
324 }
325
CleanUp()326 ErrCode IOEventReactor::CleanUp()
327 {
328 std::lock_guard<std::mutex> lock(mutex_);
329 ErrCode res = EVENT_SYS_ERR_OK;
330 for (size_t fd = 0u; fd < ioHandlers_.size() && fd <= INT_MAX; fd++) {
331 if (!DoClean(fd)) {
332 UTILS_LOGD("%{public}s Failed.", __FUNCTION__);
333 res = EVENT_SYS_ERR_FAILED;
334 }
335 }
336
337 return res;
338 }
339
Clean(int fd)340 ErrCode IOEventReactor::Clean(int fd)
341 {
342 if (fd == -1) {
343 UTILS_LOGD("%{public}s: Failed, bad fd.", __FUNCTION__);
344 return EVENT_SYS_ERR_BADF;
345 }
346
347 std::lock_guard<std::mutex> lock(mutex_);
348 if (!DoClean(fd)) {
349 UTILS_LOGD("%{public}s: Failed.", __FUNCTION__);
350 return EVENT_SYS_ERR_FAILED;
351 }
352
353 return EVENT_SYS_ERR_OK;
354 }
355
356 } // namespace Utils
357 } // namespace OHOS
358