]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/socketengine_epoll.cpp
OOPS! We try again, since I'm smoking craq. LF is 0x0a NOT CR.
[user/henk/code/inspircd.git] / src / socketengine_epoll.cpp
index 7a7f46d1b21e7db1e8ce56bd9beef057114ed2e3..4ed68ca57a1f913aadfb0cb85e86fe5d9b3136cd 100644 (file)
@@ -1 +1,157 @@
-/*       +------------------------------------+\r *       | Inspire Internet Relay Chat Daemon |\r *       +------------------------------------+\r *\r *  InspIRCd: (C) 2002-2007 InspIRCd Development Team\r * See: http://www.inspircd.org/wiki/index.php/Credits\r *\r * This program is free but copyrighted software; see\r *            the file COPYING for details.\r *\r * ---------------------------------------------------\r */\r\r#include "inspircd.h"\r#include "exitcodes.h"\r#include <sys/epoll.h>\r#include "socketengine_epoll.h"\r\rEPollEngine::EPollEngine(InspIRCd* Instance) : SocketEngine(Instance)\r{\r      EngineHandle = epoll_create(MAX_DESCRIPTORS);\r\r if (EngineHandle == -1)\r        {\r              ServerInstance->Log(SPARSE,"ERROR: Could not initialize socket engine: %s", strerror(errno));\r          ServerInstance->Log(SPARSE,"ERROR: Your kernel probably does not have the proper features. This is a fatal error, exiting now.");\r              printf("ERROR: Could not initialize socket engine: %s\n", strerror(errno));\r            printf("ERROR: Your kernel probably does not have the proper features. This is a fatal error, exiting now.\n");\r                InspIRCd::Exit(EXIT_STATUS_SOCKETENGINE);\r      }\r      CurrentSetSize = 0;\r}\r\rEPollEngine::~EPollEngine()\r{\r   close(EngineHandle);\r}\r\rbool EPollEngine::AddFd(EventHandler* eh)\r{\r    int fd = eh->GetFd();\r  if ((fd < 0) || (fd > MAX_DESCRIPTORS))\r                return false;\r\r if (GetRemainingFds() <= 1)\r            return false;\r\r if (ref[fd])\r           return false;\r\r ref[fd] = eh;\r  struct epoll_event ev;\r memset(&ev,0,sizeof(struct epoll_event));\r      eh->Readable() ? ev.events = EPOLLIN : ev.events = EPOLLOUT;\r   ev.data.fd = fd;\r       int i = epoll_ctl(EngineHandle, EPOLL_CTL_ADD, fd, &ev);\r       if (i < 0)\r     {\r              return false;\r  }\r\r     ServerInstance->Log(DEBUG,"New file descriptor: %d", fd);\r      CurrentSetSize++;\r      return true;\r}\r\rvoid EPollEngine::WantWrite(EventHandler* eh)\r{\r        /** Use oneshot so that the system removes the writeable\r        * status for us and saves us a call.\r   */\r    struct epoll_event ev;\r memset(&ev,0,sizeof(struct epoll_event));\r      ev.events = EPOLLOUT;\r  ev.data.fd = eh->GetFd();\r      epoll_ctl(EngineHandle, EPOLL_CTL_MOD, eh->GetFd(), &ev);\r}\r\rbool EPollEngine::DelFd(EventHandler* eh, bool force)\r{\r   int fd = eh->GetFd();\r  if ((fd < 0) || (fd > MAX_DESCRIPTORS))\r                return false;\r\r struct epoll_event ev;\r memset(&ev,0,sizeof(struct epoll_event));\r      eh->Readable() ? ev.events = EPOLLIN : ev.events = EPOLLOUT;\r   ev.data.fd = fd;\r       int i = epoll_ctl(EngineHandle, EPOLL_CTL_DEL, fd, &ev);\r\r      if (i < 0 && !force)\r           return false;\r\r CurrentSetSize--;\r      ref[fd] = NULL;\r\r       ServerInstance->Log(DEBUG,"Remove file descriptor: %d", fd);\r   return true;\r}\r\rint EPollEngine::GetMaxFds()\r{\r return MAX_DESCRIPTORS;\r}\r\rint EPollEngine::GetRemainingFds()\r{\r        return MAX_DESCRIPTORS - CurrentSetSize;\r}\r\rint EPollEngine::DispatchEvents()\r{\r        socklen_t codesize;\r    int errcode;\r   int i = epoll_wait(EngineHandle, events, MAX_DESCRIPTORS, 1000);\r       for (int j = 0; j < i; j++)\r    {\r              if (events[j].events & EPOLLHUP)\r               {\r                      if (ref[events[j].data.fd])\r                            ref[events[j].data.fd]->HandleEvent(EVENT_ERROR, 0);\r                   continue;\r              }\r              if (events[j].events & EPOLLERR)\r               {\r                      /* Get error number */\r                 if (getsockopt(events[j].data.fd, SOL_SOCKET, SO_ERROR, &errcode, &codesize) < 0)\r                              errcode = errno;\r                       if (ref[events[j].data.fd])\r                            ref[events[j].data.fd]->HandleEvent(EVENT_ERROR, errcode);\r                     continue;\r              }\r              if (events[j].events & EPOLLOUT)\r               {\r                      struct epoll_event ev;\r                 memset(&ev,0,sizeof(struct epoll_event));\r                      ev.events = EPOLLIN;\r                   ev.data.fd = events[j].data.fd;\r                        epoll_ctl(EngineHandle, EPOLL_CTL_MOD, events[j].data.fd, &ev);\r                        if (ref[events[j].data.fd])\r                            ref[events[j].data.fd]->HandleEvent(EVENT_WRITE);\r              }\r              else\r           {\r                      if (ref[events[j].data.fd])\r                            ref[events[j].data.fd]->HandleEvent(EVENT_READ);\r               }\r      }\r\r     return i;\r}\r\rstd::string EPollEngine::GetName()\r{\r      return "epoll";\r}\r\r
\ No newline at end of file
+/*       +------------------------------------+
+ *       | Inspire Internet Relay Chat Daemon |
+ *       +------------------------------------+
+ *
+ *  InspIRCd: (C) 2002-2007 InspIRCd Development Team
+ * See: http://www.inspircd.org/wiki/index.php/Credits
+ *
+ * This program is free but copyrighted software; see
+ *            the file COPYING for details.
+ *
+ * ---------------------------------------------------
+ */
+
+#include "inspircd.h"
+#include "exitcodes.h"
+#include <sys/epoll.h>
+#include "socketengine_epoll.h"
+
+EPollEngine::EPollEngine(InspIRCd* Instance) : SocketEngine(Instance)
+{
+       EngineHandle = epoll_create(MAX_DESCRIPTORS);
+
+       if (EngineHandle == -1)
+       {
+               ServerInstance->Log(SPARSE,"ERROR: Could not initialize socket engine: %s", strerror(errno));
+               ServerInstance->Log(SPARSE,"ERROR: Your kernel probably does not have the proper features. This is a fatal error, exiting now.");
+               printf("ERROR: Could not initialize socket engine: %s\n", strerror(errno));
+               printf("ERROR: Your kernel probably does not have the proper features. This is a fatal error, exiting now.\n");
+               InspIRCd::Exit(EXIT_STATUS_SOCKETENGINE);
+       }
+       CurrentSetSize = 0;
+}
+
+EPollEngine::~EPollEngine()
+{
+       close(EngineHandle);
+}
+
+bool EPollEngine::AddFd(EventHandler* eh)
+{
+       int fd = eh->GetFd();
+       if ((fd < 0) || (fd > MAX_DESCRIPTORS))
+               return false;
+
+       if (GetRemainingFds() <= 1)
+               return false;
+
+       if (ref[fd])
+               return false;
+
+       ref[fd] = eh;
+       struct epoll_event ev;
+       memset(&ev,0,sizeof(struct epoll_event));
+       eh->Readable() ? ev.events = EPOLLIN : ev.events = EPOLLOUT;
+       ev.data.fd = fd;
+       int i = epoll_ctl(EngineHandle, EPOLL_CTL_ADD, fd, &ev);
+       if (i < 0)
+       {
+               return false;
+       }
+
+       ServerInstance->Log(DEBUG,"New file descriptor: %d", fd);
+       CurrentSetSize++;
+       return true;
+}
+
+void EPollEngine::WantWrite(EventHandler* eh)
+{
+       /** Use oneshot so that the system removes the writeable
+        * status for us and saves us a call.
+        */
+       struct epoll_event ev;
+       memset(&ev,0,sizeof(struct epoll_event));
+       ev.events = EPOLLOUT;
+       ev.data.fd = eh->GetFd();
+       epoll_ctl(EngineHandle, EPOLL_CTL_MOD, eh->GetFd(), &ev);
+}
+
+bool EPollEngine::DelFd(EventHandler* eh, bool force)
+{
+       int fd = eh->GetFd();
+       if ((fd < 0) || (fd > MAX_DESCRIPTORS))
+               return false;
+
+       struct epoll_event ev;
+       memset(&ev,0,sizeof(struct epoll_event));
+       eh->Readable() ? ev.events = EPOLLIN : ev.events = EPOLLOUT;
+       ev.data.fd = fd;
+       int i = epoll_ctl(EngineHandle, EPOLL_CTL_DEL, fd, &ev);
+
+       if (i < 0 && !force)
+               return false;
+
+       CurrentSetSize--;
+       ref[fd] = NULL;
+
+       ServerInstance->Log(DEBUG,"Remove file descriptor: %d", fd);
+       return true;
+}
+
+int EPollEngine::GetMaxFds()
+{
+       return MAX_DESCRIPTORS;
+}
+
+int EPollEngine::GetRemainingFds()
+{
+       return MAX_DESCRIPTORS - CurrentSetSize;
+}
+
+int EPollEngine::DispatchEvents()
+{
+       socklen_t codesize;
+       int errcode;
+       int i = epoll_wait(EngineHandle, events, MAX_DESCRIPTORS, 1000);
+       for (int j = 0; j < i; j++)
+       {
+               if (events[j].events & EPOLLHUP)
+               {
+                       if (ref[events[j].data.fd])
+                               ref[events[j].data.fd]->HandleEvent(EVENT_ERROR, 0);
+                       continue;
+               }
+               if (events[j].events & EPOLLERR)
+               {
+                       /* Get error number */
+                       if (getsockopt(events[j].data.fd, SOL_SOCKET, SO_ERROR, &errcode, &codesize) < 0)
+                               errcode = errno;
+                       if (ref[events[j].data.fd])
+                               ref[events[j].data.fd]->HandleEvent(EVENT_ERROR, errcode);
+                       continue;
+               }
+               if (events[j].events & EPOLLOUT)
+               {
+                       struct epoll_event ev;
+                       memset(&ev,0,sizeof(struct epoll_event));
+                       ev.events = EPOLLIN;
+                       ev.data.fd = events[j].data.fd;
+                       epoll_ctl(EngineHandle, EPOLL_CTL_MOD, events[j].data.fd, &ev);
+                       if (ref[events[j].data.fd])
+                               ref[events[j].data.fd]->HandleEvent(EVENT_WRITE);
+               }
+               else
+               {
+                       if (ref[events[j].data.fd])
+                               ref[events[j].data.fd]->HandleEvent(EVENT_READ);
+               }
+       }
+
+       return i;
+}
+
+std::string EPollEngine::GetName()
+{
+       return "epoll";
+}
+