• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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