summaryrefslogtreecommitdiffstats
path: root/runtime/nsdpoll_ptcp.c
diff options
context:
space:
mode:
authorRainer Gerhards <rgerhards@adiscon.com>2009-11-18 18:40:14 +0100
committerRainer Gerhards <rgerhards@adiscon.com>2009-11-18 18:40:14 +0100
commit48ac0ffecdf244d04ed6cb4f4c560aeea5ba7f23 (patch)
tree05b6563cbb3321d725f7c671ce3e27d81807f93e /runtime/nsdpoll_ptcp.c
parentc82f2781d2ed372e918ea5b5529ead57ff95fc2a (diff)
downloadrsyslog-48ac0ffecdf244d04ed6cb4f4c560aeea5ba7f23.tar.gz
rsyslog-48ac0ffecdf244d04ed6cb4f4c560aeea5ba7f23.tar.xz
rsyslog-48ac0ffecdf244d04ed6cb4f4c560aeea5ba7f23.zip
milestone commit: first driver layer call done
... does not really run. We can now call into the epoll driver, but not handle epoll(). The driver also needs more modifications.
Diffstat (limited to 'runtime/nsdpoll_ptcp.c')
-rw-r--r--runtime/nsdpoll_ptcp.c127
1 files changed, 123 insertions, 4 deletions
diff --git a/runtime/nsdpoll_ptcp.c b/runtime/nsdpoll_ptcp.c
index b6b7af77..ed683acc 100644
--- a/runtime/nsdpoll_ptcp.c
+++ b/runtime/nsdpoll_ptcp.c
@@ -28,11 +28,16 @@
#include <assert.h>
#include <errno.h>
#include <string.h>
+#if HAVE_SYS_EPOLL_H
+# include <sys/epoll.h>
+#endif
#include "rsyslog.h"
#include "module-template.h"
#include "obj.h"
#include "errmsg.h"
+#include "srUtils.h"
+#include "nspoll.h"
#include "nsd_ptcp.h"
#include "nsdpoll_ptcp.h"
#include "unlimited_select.h"
@@ -43,9 +48,66 @@ DEFobjCurrIf(errmsg)
DEFobjCurrIf(glbl)
+/* -START------------------------- helpers for event list ------------------------------------ */
+
+/* add new entry to list. We assume that the fd is not already present and DO NOT check this!
+ * Returns newly created entry in pEvtLst.
+ * rgerhards, 2009-11-18
+ */
+static inline rsRetVal
+addEvent(nsdpoll_ptcp_t *pThis, int id, void *pUsr, int mode, nsd_ptcp_t *pSock, nsdpoll_epollevt_lst_t **pEvtLst) {
+ nsdpoll_epollevt_lst_t *pNew;
+ DEFiRet;
+
+ CHKmalloc(pNew = (nsdpoll_epollevt_lst_t*) malloc(sizeof(nsdpoll_epollevt_lst_t)));
+ pNew->id = id;
+ pNew->pUsr = pUsr;
+ pNew->pSock = pSock;
+ pNew->event.events = EPOLLET; /* always use edge-triggered mode */
+ if(mode & NSDPOLL_IN)
+ pNew->event.events |= EPOLLIN;
+ if(mode & NSDPOLL_OUT)
+ pNew->event.events |= EPOLLOUT;
+ pNew->event.data.u64 = (uint64) pNew;
+ pNew->pNext = pThis->pRoot;
+ pThis->pRoot = pNew;
+ *pEvtLst = pNew;
+
+finalize_it:
+ RETiRet;
+}
+
+
+/* remove the entry identified by id/pUsr from the list.
+ * rgerhards, 2009-11-18
+ */
+static inline rsRetVal
+delEvent(nsdpoll_ptcp_t *pThis, int id, void *pUsr) {
+ DEFiRet;
+ // TODO: XXX add code!
+#warning delEvent implementation is missing!
+ RETiRet;
+}
+
+
+/* -END--------------------------- helpers for event list ------------------------------------ */
+
+
/* Standard-Constructor
*/
BEGINobjConstruct(nsdpoll_ptcp) /* be sure to specify the object type also in END macro! */
+# if defined(EPOLL_CLOEXEC) && defined(HAVE_EPOLL_CREATE1)
+ DBGPRINTF("imudp uses epoll_create1()\n");
+ pThis->efd = epoll_create1(EPOLL_CLOEXEC);
+# else
+ DBGPRINTF("imudp uses epoll_create()\n");
+ pThis->efd = epoll_create(NUM_EPOLL_EVENTS);
+# endif
+ if(pThis->efd < 0) {
+ DBGPRINTF("epoll_create1() could not create fd\n");
+ ABORT_FINALIZE(RS_RET_IO_ERROR);
+ }
+finalize_it:
ENDobjConstruct(nsdpoll_ptcp)
@@ -55,19 +117,76 @@ CODESTARTobjDestruct(nsdpoll_ptcp)
ENDobjDestruct(nsdpoll_ptcp)
-/* Add a socket to the select set */
+/* Modify socket set */
static rsRetVal
-Ctl(nsdpoll_t *pThis, int fd, int op, epoll_event_t *event) {
+Ctl(nsdpoll_t *pNsdpoll, nsd_t *pNsd, int id, void *pUsr, int mode) {
+ nsdpoll_ptcp_t *pThis = (nsdpoll_ptcp_t*) pNsdpoll;
+ nsd_ptcp_t *pSock = (nsd_ptcp_t*) pNsd;
+ nsdpoll_epollevt_lst_t *pEventLst;
+ int errSave;
+ char errStr[512];
DEFiRet;
+
+ if(mode == NSDPOLL_ADD) {
+ dbgprintf("adding nsdpoll entry %d/%p\n", id, pUsr);
+ CHKiRet(addEvent(pThis, id, pUsr, mode, pSock, &pEventLst));
+ if(epoll_ctl(pThis->efd, EPOLL_CTL_ADD, pSock->sock, &pEventLst->event) < 0) {
+ errSave = errno;
+ rs_strerror_r(errSave, errStr, sizeof(errStr));
+ errmsg.LogError(errSave, RS_RET_ERR_EPOLL_CTL,
+ "epoll_ctl failed on fd %d, id %d/%p, op %d with %s\n",
+ pSock->sock, id, pUsr, mode, errStr);
+ }
+ } else if(mode == NSDPOLL_DEL) {
+ // TODO: XXX : code missing!
+ dbgprintf("removing nsdpoll entry %d/%p\n", id, pUsr);
+ } else {
+ dbgprintf("program error: invalid NSDPOLL_mode %d - ignoring request\n", mode);
+ ABORT_FINALIZE(RS_RET_ERR);
+ }
+
+finalize_it:
RETiRet;
}
-/* Wait for io to become ready.
+/* Wait for io to become ready. After the successful call, idRdy contains the
+ * id set by the caller for that i/o event, ppUsr is a pointer to a location
+ * where the user pointer shall be stored.
+ * TODO: this is a trivial implementation that only polls one event at a time. We
+ * may later extend it to poll for multiple events, what would cause less
+ * overhead.
+ * rgerhards, 2009-11-18
*/
static rsRetVal
-Wait(nsdpoll_t *pThis, epoll_event_t *events, int maxevents, int timeout) {
+Wait(nsdpoll_t *pNsdpoll, int timeout, int *idRdy, void **ppUsr) {
+ nsdpoll_ptcp_t *pThis = (nsdpoll_ptcp_t*) pNsdpoll;
+ nsdpoll_epollevt_lst_t *pOurEvt;
+ struct epoll_event event;
+ int nfds;
DEFiRet;
+
+ assert(idRdy != NULL);
+ assert(ppUsr != NULL);
+
+ nfds = epoll_wait(pThis->efd, &event, 1, timeout);
+ if(nfds == -1) {
+ if(errno == EINTR) {
+ ABORT_FINALIZE(RS_RET_EINTR);
+ } else {
+ DBGPRINTF("epoll() returned with error code %d\n", errno);
+ ABORT_FINALIZE(RS_RET_ERR_EPOLL);
+ }
+ } else if(nfds == 0) {
+ ABORT_FINALIZE(RS_RET_TIMEOUT);
+ }
+
+ /* we got a valid event, so tell the caller... */
+ pOurEvt = (nsdpoll_epollevt_lst_t*) event.data.u64;
+ *idRdy = pOurEvt->id;
+ *ppUsr = pOurEvt->pUsr;
+
+finalize_it:
RETiRet;
}