diff options
author | sangwan.kwon <sangwan.kwon@samsung.com> | 2016-04-04 13:24:17 +0900 |
---|---|---|
committer | sangwan.kwon <sangwan.kwon@samsung.com> | 2016-05-11 10:46:37 +0900 |
commit | 0e0c941196c0dc23eee6247a5182f6851e45ff48 (patch) | |
tree | 26b1c19e09d8b3f3239ac94bfdcacd7f8f49405e /src/common/mainloop.cpp | |
parent | e05626bc306e8cf9d57604fd1e8b9d540b68e6cd (diff) | |
download | cert-checker-ref/for/tizen.tar.gz cert-checker-ref/for/tizen.tar.bz2 cert-checker-ref/for/tizen.zip |
Implement on-demand style about server-sideref/for/tizen
[AS-IS]
* cert-checker was daemon.
[TO-BE]
* Change to on-demand style.
* cert-svc call cert-checker.
* Add common library.
Change-Id: Idab160e6103cf62299b97a5485a767de9831d614
Signed-off-by: sangwan.kwon <sangwan.kwon@samsung.com>
Diffstat (limited to 'src/common/mainloop.cpp')
-rw-r--r-- | src/common/mainloop.cpp | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/src/common/mainloop.cpp b/src/common/mainloop.cpp new file mode 100644 index 0000000..19ff477 --- /dev/null +++ b/src/common/mainloop.cpp @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 + */ +/* + * @file mainloop.cpp + * @author Kyungwook Tak (k.tak@samsung.com) + * @version 1.0 + * @brief Mainloop with epoll + */ +#include "common/mainloop.h" + +#include <exception> +#include <stdexcept> +#include <system_error> +#include <sys/epoll.h> +#include <unistd.h> + +#include <cchecker/log.h> + +namespace CCHECKER { + +Mainloop::Mainloop() : + m_isTimedOut(false), + m_pollfd(::epoll_create1(EPOLL_CLOEXEC)) +{ + if (m_pollfd == -1) + throw std::system_error( + std::error_code(errno, std::generic_category()), + "Failed to epoll_create1"); +} + +Mainloop::~Mainloop() +{ + if (!m_isTimedOut && !m_callbacks.empty()) + throw std::logic_error("mainloop registered callbacks should be empty " + "except timed out case"); + + ::close(m_pollfd); +} + +void Mainloop::run(int timeout) +{ + m_isTimedOut = false; + + while (!m_isTimedOut) { + dispatch(timeout); + } + + LogDebug("Mainloop run stopped"); +} + +void Mainloop::addEventSource(int fd, uint32_t event, Callback &&callback) +{ + /* TODO: use scoped-lock to thread safe on member variables */ + if (m_callbacks.count(fd) != 0) + throw std::logic_error("event source already added!"); + + LogDebug("Add event[" << event << "] source on fd[" << fd << "]"); + + epoll_event e; + + e.events = event; + e.data.fd = fd; + + if (::epoll_ctl(m_pollfd, EPOLL_CTL_ADD, fd, &e) == -1) + throw std::system_error( + std::error_code(errno, std::generic_category()), + "epoll_ctl failed to EPOLL_CTL_ADD."); + + m_callbacks[fd] = std::move(callback); +} + +void Mainloop::removeEventSource(int fd) +{ + /* TODO: use scoped-lock to thread safe on member variables */ + if (m_callbacks.count(fd) == 0) + throw std::logic_error("event source isn't added at all"); + + LogDebug("Remove event source on fd[" << fd << "]"); + + do { + m_callbacks.erase(fd); + + if (::epoll_ctl(m_pollfd, EPOLL_CTL_DEL, fd, nullptr) == -1) { + if (errno == ENOENT) + throw std::logic_error("Tried to delete epoll item which wasn't added"); + else + throw std::system_error( + std::error_code(errno, std::generic_category()), + "epoll_ctl failed to EPOLL_CTL_DEL."); + } + } while (false); +} + +void Mainloop::dispatch(int timeout) +{ + int nfds = -1; + epoll_event event[MAX_EPOLL_EVENTS]; + + LogDebug("Mainloop dispatched with timeout: " << timeout); + + do { + nfds = ::epoll_wait(m_pollfd, event, MAX_EPOLL_EVENTS, timeout); + } while ((nfds == -1) && (errno == EINTR)); + + if (nfds < 0) + throw std::system_error( + std::error_code(errno, std::generic_category()), + "epoll_wait failed!"); + + if (nfds == 0) { + LogDebug("Mainloop timed out!"); + m_isTimedOut = true; + return; + } + + for (int i = 0; i < nfds; i++) { + /* TODO: use scoped-lock to thread safe on member variables */ + int fd = event[i].data.fd; + + if (m_callbacks.count(fd) == 0) + throw std::logic_error("event in, but associated callback isn't exist!"); + + if (event[i].events & (EPOLLHUP | EPOLLRDHUP)) { + LogInfo("peer connection closed on fd[" << fd << "]"); + event[i].events &= ~EPOLLIN; + } + + LogDebug("event[" << event[i].events << "] polled on fd[" << fd << "]"); + + m_callbacks[fd](event[i].events); + } +} + +} // namespace CCHECKER |