diff options
Diffstat (limited to 'src/socketengines/socketengine_epoll.cpp')
-rw-r--r-- | src/socketengines/socketengine_epoll.cpp | 120 |
1 files changed, 41 insertions, 79 deletions
diff --git a/src/socketengines/socketengine_epoll.cpp b/src/socketengines/socketengine_epoll.cpp index 481551289..41f67ebcc 100644 --- a/src/socketengines/socketengine_epoll.cpp +++ b/src/socketengines/socketengine_epoll.cpp @@ -19,107 +19,66 @@ #include <ulimit.h> #include <errno.h> -static long max; static int EngineHandle; -static epoll_event *events; +static std::vector<epoll_event> events; void SocketEngine::Init() { - max = ulimit(4, 0); - - if (max <= 0) - throw SocketException("Can't determine maximum number of open sockets"); - - EngineHandle = epoll_create(max / 4); + EngineHandle = epoll_create(4); if (EngineHandle == -1) throw SocketException("Could not initialize epoll socket engine: " + Anope::LastError()); - - events = new epoll_event[max]; - memset(events, 0, sizeof(epoll_event) * max); + + events.resize(DefaultSize); } void SocketEngine::Shutdown() { - for (std::map<int, Socket *>::const_iterator it = Sockets.begin(), it_end = Sockets.end(); it != it_end;) - { - Socket *s = it->second; - ++it; - delete s; - } - Sockets.clear(); - - delete [] events; -} - -void SocketEngine::AddSocket(Socket *s) -{ - epoll_event ev; - - memset(&ev, 0, sizeof(ev)); - - ev.events = EPOLLIN; - ev.data.fd = s->GetFD(); - - if (epoll_ctl(EngineHandle, EPOLL_CTL_ADD, ev.data.fd, &ev) == -1) - throw SocketException("Unable to add fd " + stringify(ev.data.fd) + " to epoll: " + Anope::LastError()); - - Sockets[ev.data.fd] = s; + while (!Sockets.empty()) + delete Sockets.begin()->second; } -void SocketEngine::DelSocket(Socket *s) +void SocketEngine::Change(Socket *s, bool set, SocketFlag flag) { - epoll_event ev; - - memset(&ev, 0, sizeof(ev)); - - ev.data.fd = s->GetFD(); - - if (epoll_ctl(EngineHandle, EPOLL_CTL_DEL, ev.data.fd, &ev) == -1) - throw SocketException("Unable to remove fd " + stringify(ev.data.fd) + " from epoll: " + Anope::LastError()); - - Sockets.erase(ev.data.fd); -} - -void SocketEngine::MarkWritable(Socket *s) -{ - if (s->HasFlag(SF_WRITABLE)) + if (set == s->HasFlag(flag)) return; - epoll_event ev; + bool before_registered = s->HasFlag(SF_READABLE) || s->HasFlag(SF_WRITABLE); - memset(&ev, 0, sizeof(ev)); - - ev.events = EPOLLIN | EPOLLOUT; - ev.data.fd = s->GetFD(); - - if (epoll_ctl(EngineHandle, EPOLL_CTL_MOD, ev.data.fd, &ev) == -1) - throw SocketException("Unable to mark fd " + stringify(ev.data.fd) + " as writable in epoll: " + Anope::LastError()); - - s->SetFlag(SF_WRITABLE); -} - -void SocketEngine::ClearWritable(Socket *s) -{ - if (!s->HasFlag(SF_WRITABLE)) - return; + if (set) + s->SetFlag(flag); + else + s->UnsetFlag(flag); + + bool now_registered = s->HasFlag(SF_READABLE) || s->HasFlag(SF_WRITABLE); epoll_event ev; memset(&ev, 0, sizeof(ev)); - ev.events = EPOLLIN; + ev.events = (s->HasFlag(SF_READABLE) ? EPOLLIN : 0) | (s->HasFlag(SF_WRITABLE) ? EPOLLOUT : 0); ev.data.fd = s->GetFD(); - if (epoll_ctl(EngineHandle, EPOLL_CTL_MOD, ev.data.fd, &ev) == -1) - throw SocketException("Unable clear mark fd " + stringify(ev.data.fd) + " as writable in epoll: " + Anope::LastError()); - - s->UnsetFlag(SF_WRITABLE); + int mod; + if (!before_registered && now_registered) + mod = EPOLL_CTL_ADD; + else if (before_registered && !now_registered) + mod = EPOLL_CTL_DEL; + else if (before_registered && now_registered) + mod = EPOLL_CTL_MOD; + else + return; + + if (epoll_ctl(EngineHandle, mod, ev.data.fd, &ev) == -1) + throw SocketException("Unable to epoll_ctl() fd " + stringify(ev.data.fd) + " to epoll: " + Anope::LastError()); } void SocketEngine::Process() { - int total = epoll_wait(EngineHandle, events, max - 1, Config->ReadTimeout * 1000); + if (Sockets.size() > events.size()) + events.resize(events.size() * 2); + + int total = epoll_wait(EngineHandle, &events.front(), events.size(), Config->ReadTimeout * 1000); Anope::CurTime = time(NULL); /* EINTR can be given if the read timeout expires */ @@ -132,28 +91,31 @@ void SocketEngine::Process() for (int i = 0; i < total; ++i) { - epoll_event *ev = &events[i]; + epoll_event &ev = events[i]; - std::map<int, Socket *>::iterator it = Sockets.find(ev->data.fd); + std::map<int, Socket *>::iterator it = Sockets.find(ev.data.fd); if (it == Sockets.end()) continue; Socket *s = it->second; - if (ev->events & (EPOLLHUP | EPOLLERR)) + if (ev.events & (EPOLLHUP | EPOLLERR)) { s->ProcessError(); - s->SetFlag(SF_DEAD); delete s; continue; } if (!s->Process()) + { + if (s->HasFlag(SF_DEAD)) + delete s; continue; + } - if ((ev->events & EPOLLIN) && !s->ProcessRead()) + if ((ev.events & EPOLLIN) && !s->ProcessRead()) s->SetFlag(SF_DEAD); - if ((ev->events & EPOLLOUT) && !s->ProcessWrite()) + if ((ev.events & EPOLLOUT) && !s->ProcessWrite()) s->SetFlag(SF_DEAD); if (s->HasFlag(SF_DEAD)) |