diff options
author | Rainer Gerhards <rgerhards@adiscon.com> | 2007-11-21 16:34:48 +0000 |
---|---|---|
committer | Rainer Gerhards <rgerhards@adiscon.com> | 2007-11-21 16:34:48 +0000 |
commit | 3bb7ad8246bca95c89d68a8b0402b8482489c877 (patch) | |
tree | 798656b4722649346cbd43a0a328041832666237 /linkedlist.c | |
parent | bb6bfca3dfa6a5d3500e51459b38bb6d0ca6a4b2 (diff) | |
download | rsyslog-3bb7ad8246bca95c89d68a8b0402b8482489c877.tar.gz rsyslog-3bb7ad8246bca95c89d68a8b0402b8482489c877.tar.xz rsyslog-3bb7ad8246bca95c89d68a8b0402b8482489c877.zip |
- added an identifier to command handler table - need to identify which
command handler entries need to be removed when module is unloaded
- added support so that linkedlist key can be used for owner handle
- enhanced llExecFunc to support deletion of list elements (on behalf of
user function being called, slight interface change)
- enhanced linkedlist class so that list elements can now be deleted based
on the key value they have
- created entry point so that CfSysLine handlers are removed on modExit()
Diffstat (limited to 'linkedlist.c')
-rw-r--r-- | linkedlist.c | 120 |
1 files changed, 112 insertions, 8 deletions
diff --git a/linkedlist.c b/linkedlist.c index b9239b48..bea2cb90 100644 --- a/linkedlist.c +++ b/linkedlist.c @@ -229,36 +229,124 @@ finalize_it: } -/* find a user element based on the provided key +/* unlink a requested element. As we have singly-linked lists, the + * caller also needs to pass in the previous element (or NULL, if it is the + * root element). + * rgerhards, 2007-11-21 */ -rsRetVal llFind(linkedList_t *pThis, void *pKey, void **ppData) +static rsRetVal llUnlinkElt(linkedList_t *pThis, llElt_t *pElt, llElt_t *pEltPrev) +{ + assert(pElt != NULL); + + if(pEltPrev == NULL) { /* root element? */ + pThis->pRoot = pElt->pNext; + } else { /* regular element */ + pEltPrev->pNext = pElt->pNext; + } + + if(pElt == pThis->pLast) + pThis->pLast = pEltPrev; + + return RS_RET_OK; +} + + +/* unlinks and immediately deletes an element. Previous element must + * be given (or zero if the root element is to be deleted). + * rgerhards, 2007-11-21 + */ +static rsRetVal llUnlinkAndDelteElt(linkedList_t *pThis, llElt_t *pElt, llElt_t *pEltPrev) +{ + DEFiRet; + + assert(pElt != NULL); + + CHKiRet(llUnlinkElt(pThis, pElt, pEltPrev)); + CHKiRet(llDestroyElt(pThis, pElt)); + +finalize_it: + return iRet; +} + +/* find a user element based on the provided key - this is the + * internal variant, which also tracks the last element pointer + * before the found element. This is necessary to delete elements. + * NULL means there is no element in front of it, aka the found elt + * is the root elt. + * rgerhards, 2007-11-21 + */ +static rsRetVal llFindElt(linkedList_t *pThis, void *pKey, llElt_t **ppElt, llElt_t **ppEltPrev) { DEFiRet; llElt_t *pElt; + llElt_t *pEltPrev = NULL; int bFound = 0; assert(pThis != NULL); assert(pKey != NULL); - assert(ppData != NULL); + assert(ppElt != NULL); + assert(ppEltPrev != NULL); pElt = pThis->pRoot; while(pElt != NULL && bFound == 0) { if(pThis->cmpOp(pKey, pElt->pKey) == 0) bFound = 1; - else + else { + pEltPrev = pElt; pElt = pElt->pNext; + } } if(bFound == 1) { - *ppData = pElt->pData; - } else { + *ppElt = pElt; + *ppEltPrev = pEltPrev; + } else iRet = RS_RET_NOT_FOUND; - } return iRet; } +/* find a user element based on the provided key + */ +rsRetVal llFind(linkedList_t *pThis, void *pKey, void **ppData) +{ + DEFiRet; + llElt_t *pElt; + llElt_t *pEltPrev; + + CHKiRet(llFindElt(pThis, pKey, &pElt, &pEltPrev)); + + /* if we reach this point, we have found the element */ + *ppData = pElt->pData; + +finalize_it: + return iRet; +} + + +/* find a delete an element based on user-provided key. The element is + * delete, the caller does not receive anything. If we need to receive + * the element before destruction, we may implement an llFindAndUnlink() + * at that time. + * rgerhards, 2007-11-21 + */ +rsRetVal llFindAndDelete(linkedList_t *pThis, void *pKey) +{ + DEFiRet; + llElt_t *pElt; + llElt_t *pEltPrev; + + CHKiRet(llFindElt(pThis, pKey, &pElt, &pEltPrev)); + + /* if we reach this point, we have found an element */ + CHKiRet(llUnlinkAndDelteElt(pThis, pElt, pEltPrev)); + +finalize_it: + return iRet; +} + + /* provide the count of linked list elements */ rsRetVal llGetNumElts(linkedList_t *pThis, int *piCnt) @@ -279,6 +367,9 @@ rsRetVal llGetNumElts(linkedList_t *pThis, int *piCnt) * or a pointer to a structure with more data. If the user-supplied * function does not return RS_RET_OK, this function here terminates. * rgerhards, 2007-08-02 + * rgerhards, 2007-11-21: added functionality to delete a list element. + * If the called user function returns RS_RET_OK_DELETE_LISTENTRY the current element + * is deleted. */ rsRetVal llExecFunc(linkedList_t *pThis, rsRetVal (*pFunc)(void*, void*), void* pParam) { @@ -286,12 +377,25 @@ rsRetVal llExecFunc(linkedList_t *pThis, rsRetVal (*pFunc)(void*, void*), void* rsRetVal iRetLL; void *pData; linkedListCookie_t llCookie = NULL; + linkedListCookie_t llCookiePrev = NULL; /* previous list element (needed for deletion, NULL = at root) */ assert(pThis != NULL); assert(pFunc != NULL); while((iRetLL = llGetNextElt(pThis, &llCookie, (void**)&pData)) == RS_RET_OK) { - CHKiRet(pFunc(pData, pParam)); + iRet = pFunc(pData, pParam); + if(iRet == RS_RET_OK_DELETE_LISTENTRY) { + /* delete element */ + CHKiRet(llUnlinkAndDelteElt(pThis, llCookie, llCookiePrev)); + /* we need to revert back, as we have just deleted the current element. + * So the actual current element is the one before it, which happens to be + * stored in llCookiePrev. -- rgerhards, 2007-11-21 + */ + llCookie = llCookiePrev; + } else if (iRet != RS_RET_OK) { + goto finalize_it; + } + llCookiePrev = llCookie; } if(iRetLL != RS_RET_END_OF_LINKEDLIST) |