summaryrefslogtreecommitdiffstats
path: root/runtime
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
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')
-rw-r--r--runtime/netstrms.c3
-rw-r--r--runtime/nsd.h4
-rw-r--r--runtime/nsd_ptcp.c2
-rw-r--r--runtime/nsdpoll_ptcp.c127
-rw-r--r--runtime/nsdpoll_ptcp.h14
-rw-r--r--runtime/nspoll.c18
-rw-r--r--runtime/nspoll.h14
-rw-r--r--runtime/nssel.c1
-rw-r--r--runtime/rsyslog.h4
9 files changed, 171 insertions, 16 deletions
diff --git a/runtime/netstrms.c b/runtime/netstrms.c
index 6b28e7ea..e9ff2568 100644
--- a/runtime/netstrms.c
+++ b/runtime/netstrms.c
@@ -36,6 +36,7 @@
#include "nsd.h"
#include "netstrm.h"
#include "nssel.h"
+#include "nspoll.h"
#include "netstrms.h"
MODULE_TYPE_LIB
@@ -304,6 +305,7 @@ ENDObjClassInit(netstrms)
BEGINmodExit
CODESTARTmodExit
nsselClassExit();
+ nspollClassExit();
netstrmsClassExit();
netstrmClassExit(); /* we use this object, so we must exit it after we are finished */
ENDmodExit
@@ -322,6 +324,7 @@ CODESTARTmodInit
/* Initialize all classes that are in our module - this includes ourselfs */
CHKiRet(netstrmClassInit(pModInfo));
CHKiRet(nsselClassInit(pModInfo));
+ CHKiRet(nspollClassInit(pModInfo));
CHKiRet(netstrmsClassInit(pModInfo));
ENDmodInit
/* vi:set ai:
diff --git a/runtime/nsd.h b/runtime/nsd.h
index bcd5a926..fc34ad6e 100644
--- a/runtime/nsd.h
+++ b/runtime/nsd.h
@@ -91,8 +91,8 @@ ENDinterface(nsdsel)
BEGINinterface(nsdpoll) /* name must also be changed in ENDinterface macro! */
rsRetVal (*Construct)(nsdpoll_t **ppThis);
rsRetVal (*Destruct)(nsdpoll_t **ppThis);
- rsRetVal (*Ctl)(nsdpoll_t *pThis, int fd, int op, epoll_event_t *event);
- rsRetVal (*Wait)(nsdpoll_t *pThis, epoll_event_t *events, int maxevents, int timeout);
+ rsRetVal (*Ctl)(nsdpoll_t *pNsdpoll, nsd_t *pNsd, int id, void *pUsr, int op);
+ rsRetVal (*Wait)(nsdpoll_t *pNsdpoll, int timeout, int *idRdy, void **ppUsr);
ENDinterface(nsdpoll)
#define nsdpollCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */
diff --git a/runtime/nsd_ptcp.c b/runtime/nsd_ptcp.c
index fe31ab40..6feee71d 100644
--- a/runtime/nsd_ptcp.c
+++ b/runtime/nsd_ptcp.c
@@ -821,6 +821,7 @@ ENDObjClassInit(nsd_ptcp)
BEGINmodExit
CODESTARTmodExit
+ nsdpoll_ptcpClassExit();
nsdsel_ptcpClassExit();
nsd_ptcpClassExit();
ENDmodExit
@@ -839,6 +840,7 @@ CODESTARTmodInit
/* Initialize all classes that are in our module - this includes ourselfs */
CHKiRet(nsd_ptcpClassInit(pModInfo)); /* must be done after tcps_sess, as we use it */
CHKiRet(nsdsel_ptcpClassInit(pModInfo)); /* must be done after tcps_sess, as we use it */
+ CHKiRet(nsdpoll_ptcpClassInit(pModInfo)); /* must be done after tcps_sess, as we use it */
ENDmodInit
/* vi:set ai:
*/
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;
}
diff --git a/runtime/nsdpoll_ptcp.h b/runtime/nsdpoll_ptcp.h
index 36d39da7..ccdb87f0 100644
--- a/runtime/nsdpoll_ptcp.h
+++ b/runtime/nsdpoll_ptcp.h
@@ -26,10 +26,24 @@
#include "nsd.h"
typedef nsdpoll_if_t nsdpoll_ptcp_if_t; /* we just *implement* this interface */
+/* a helper object to keep track of the epoll event records
+ * Note that we need to keep track of that list because we need to
+ * free the events when they are no longer needed.
+ */
+typedef struct nsdpoll_epollevt_lst_s nsdpoll_epollevt_lst_t;
+struct nsdpoll_epollevt_lst_s {
+ epoll_event_t event;
+ int id;
+ void *pUsr;
+ nsd_ptcp_t *pSock; /* our associated netstream driver data */
+ nsdpoll_epollevt_lst_t *pNext;
+};
/* the nsdpoll_ptcp object */
struct nsdpoll_ptcp_s {
BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */
+ int efd; /* file descriptor used by epoll */
+ nsdpoll_epollevt_lst_t *pRoot; /* Root of the epoll event list */
};
/* interface is defined in nsd.h, we just implement it! */
diff --git a/runtime/nspoll.c b/runtime/nspoll.c
index ff0b1e92..4413c2c7 100644
--- a/runtime/nspoll.c
+++ b/runtime/nspoll.c
@@ -68,7 +68,7 @@ loadDrvr(nspoll_t *pThis)
pBaseDrvrName = pThis->pBaseDrvrName;
if(pBaseDrvrName == NULL) /* if no drvr name is set, use system default */
pBaseDrvrName = glbl.GetDfltNetstrmDrvr();
- if(snprintf((char*)szDrvrName, sizeof(szDrvrName), "lmnspoll_%s", pBaseDrvrName) == sizeof(szDrvrName))
+ if(snprintf((char*)szDrvrName, sizeof(szDrvrName), "lmnsdpoll_%s", pBaseDrvrName) == sizeof(szDrvrName))
ABORT_FINALIZE(RS_RET_DRVRNAME_TOO_LONG);
CHKmalloc(pThis->pDrvrName = (uchar*) strdup((char*)szDrvrName));
@@ -79,6 +79,7 @@ loadDrvr(nspoll_t *pThis)
* about this hack, but for the time being it is efficient and clean
* enough. -- rgerhards, 2008-04-18
*/
+RUNLOG_VAR("%s", szDrvrName+2);
CHKiRet(obj.UseObj(__FILE__, szDrvrName+2, DONT_LOAD_LIB, (void*) &pThis->Drvr));
finalize_it:
@@ -119,9 +120,11 @@ ConstructFinalize(nspoll_t *pThis)
{
DEFiRet;
ISOBJ_TYPE_assert(pThis, nspoll);
+RUNLOG_STR("trying to load epoll driver\n");
CHKiRet(loadDrvr(pThis));
CHKiRet(pThis->Drvr.Construct(&pThis->pDrvrData));
finalize_it:
+dbgprintf("XXX: done trying to load epoll driver, state %d\n", iRet);
RETiRet;
}
@@ -129,12 +132,11 @@ finalize_it:
/* Carries out the actual wait (all done in lower layers)
*/
static rsRetVal
-Wait(nspoll_t *pThis, epoll_event_t *events, int maxevents, int timeout) {
+Wait(nspoll_t *pThis, int timeout, int *idRdy, void **ppUsr) {
DEFiRet;
ISOBJ_TYPE_assert(pThis, nspoll);
- assert(events != NULL);
- assert(maxevents > 0);
- iRet = pThis->Drvr.Wait(pThis->pDrvrData, events, maxevents, timeout);
+ assert(idRdy != NULL);
+ iRet = pThis->Drvr.Wait(pThis->pDrvrData, timeout, idRdy, ppUsr);
RETiRet;
}
@@ -143,11 +145,10 @@ Wait(nspoll_t *pThis, epoll_event_t *events, int maxevents, int timeout) {
* rgerhards, 2009-11-18
*/
static rsRetVal
-Ctl(nspoll_t *pThis, int fd, int op, epoll_event_t *event) {
+Ctl(nspoll_t *pThis, nsd_t *pNsd, int id, void *pUsr, int op) {
DEFiRet;
ISOBJ_TYPE_assert(pThis, nspoll);
- assert(event != NULL);
- iRet = pThis->Drvr.Ctl(pThis->pDrvrData, fd, op, event);
+ iRet = pThis->Drvr.Ctl(pThis->pDrvrData, pNsd, id, pUsr, op);
RETiRet;
}
@@ -188,6 +189,7 @@ ENDObjClassExit(nspoll)
*/
BEGINObjClassInit(nspoll, 1, OBJ_IS_CORE_MODULE) /* class, version */
/* request objects we use */
+ DBGPRINTF("doing nspollClassInit\n");
CHKiRet(objUse(glbl, CORE_COMPONENT));
/* set our own handlers */
diff --git a/runtime/nspoll.h b/runtime/nspoll.h
index 19efd38b..9d39e017 100644
--- a/runtime/nspoll.h
+++ b/runtime/nspoll.h
@@ -26,6 +26,15 @@
#include "netstrms.h"
+/* some operations to be portable when we do not have epoll() available */
+#define NSDPOLL_ADD 1
+#define NSDPOLL_DEL 2
+
+/* and some mode specifiers for waiting on input/output */
+#define NSDPOLL_IN 1 /* EPOLLIN */
+#define NSDPOLL_OUT 2 /* EPOLLOUT */
+/* next is 4, 8, 16, ... - must be bit values, as they are ored! */
+
/* the nspoll object */
struct nspoll_s {
BEGINobjInstance; /* Data to implement generic object - MUST be the first data element! */
@@ -41,8 +50,9 @@ BEGINinterface(nspoll) /* name must also be changed in ENDinterface macro! */
rsRetVal (*Construct)(nspoll_t **ppThis);
rsRetVal (*ConstructFinalize)(nspoll_t *pThis);
rsRetVal (*Destruct)(nspoll_t **ppThis);
- rsRetVal (*Ctl)(nspoll_t *pThis, int fd, int op, epoll_event_t *event);
- rsRetVal (*Wait)(nspoll_t *pThis, epoll_event_t *events, int maxevents, int timeout);
+ rsRetVal (*Wait)(nspoll_t *pNsdpoll, int timeout, int *idRdy, void **ppUsr);
+ rsRetVal (*Ctl)(nspoll_t *pNsdpoll, nsd_t *pNsd, int id, void *pUsr, int op);
+ rsRetVal (*IsEPollSupported)(void); /* static method */
ENDinterface(nspoll)
#define nspollCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */
diff --git a/runtime/nssel.c b/runtime/nssel.c
index d11d5fe1..7c5be3a9 100644
--- a/runtime/nssel.c
+++ b/runtime/nssel.c
@@ -219,6 +219,7 @@ ENDObjClassExit(nssel)
*/
BEGINObjClassInit(nssel, 1, OBJ_IS_CORE_MODULE) /* class, version */
/* request objects we use */
+ DBGPRINTF("doing nsselClassInit\n");
CHKiRet(objUse(glbl, CORE_COMPONENT));
/* set our own handlers */
diff --git a/runtime/rsyslog.h b/runtime/rsyslog.h
index c5f7a9ea..b8ebafd9 100644
--- a/runtime/rsyslog.h
+++ b/runtime/rsyslog.h
@@ -414,6 +414,10 @@ enum rsRetVal_ /** return value. All methods return this if not specified oth
RS_RET_NO_RULESET= -2158,/**< no ruleset name as specified where one was needed */
RS_RET_PARSER_NOT_FOUND = -2159,/**< parser with the specified name was not found */
RS_RET_COULD_NOT_PARSE = -2160,/**< (this) parser could not parse the message (no error, means try next one) */
+ RS_RET_EINTR = -2161, /**< EINTR occured during a system call (not necessarily an error) */
+ RS_RET_ERR_EPOLL = -2162, /**< epoll() returned with an unexpected error code */
+ RS_RET_ERR_EPOLL_CTL = -2163, /**< epol_ctll() returned with an unexpected error code */
+ RS_RET_TIMEOUT = -2164, /**< timeout occured during operation */
/* RainerScript error messages (range 1000.. 1999) */
RS_RET_SYSVAR_NOT_FOUND = 1001, /**< system variable could not be found (maybe misspelled) */