diff options
Diffstat (limited to 'runtime')
-rw-r--r-- | runtime/netstrms.c | 3 | ||||
-rw-r--r-- | runtime/nsd.h | 4 | ||||
-rw-r--r-- | runtime/nsd_ptcp.c | 2 | ||||
-rw-r--r-- | runtime/nsdpoll_ptcp.c | 127 | ||||
-rw-r--r-- | runtime/nsdpoll_ptcp.h | 14 | ||||
-rw-r--r-- | runtime/nspoll.c | 18 | ||||
-rw-r--r-- | runtime/nspoll.h | 14 | ||||
-rw-r--r-- | runtime/nssel.c | 1 | ||||
-rw-r--r-- | runtime/rsyslog.h | 4 |
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) */ |