From 1f361c5eb9028e7750a1c84811c9c3ac5cdd0a31 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Fri, 26 Jun 2009 14:22:00 +0200 Subject: some optimization, declared some frequently called small stringbuf functions inline --- runtime/stringbuf.c | 57 ---------------------------------------------- runtime/stringbuf.h | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 62 insertions(+), 60 deletions(-) diff --git a/runtime/stringbuf.c b/runtime/stringbuf.c index f3824831..88f5a3a2 100644 --- a/runtime/stringbuf.c +++ b/runtime/stringbuf.c @@ -343,42 +343,6 @@ uchar* rsCStrGetSzStr(cstr_t *pThis) } -/* Converts the CStr object to a classical sz string and returns that. - * Same restrictions as in cstrGetSzStr() applies (see there!). This - * function here guarantees that a valid string is returned, even if - * the CStr object currently holds a NULL pointer string buffer. If so, - * "" is returned. - * rgerhards 2005-10-19 - * WARNING: The returned pointer MUST NOT be freed, as it may be - * obtained from that constant memory pool (in case of NULL!) - */ -uchar* cstrGetSzStrNoNULL(cstr_t *pThis) -{ - rsCHECKVALIDOBJECT(pThis, OIDrsCStr); - if(pThis->pBuf == NULL) - return (uchar*) ""; - else - return cstrGetSzStr(pThis); -} - -/* Returns the cstr data as a classical C sz string. We use that the - * Finalizer did properly terminate our string (but we may stil be NULL). - * So it is vital that the finalizer is called BEFORe this function here! - * The caller must not free or otherwise manipulate the returned string and must not - * destroy the CStr object as long as the ascii string is used. - * This function may return NULL, if the string is currently NULL. This - * is a feature, not a bug. If you need non-NULL in any case, use - * cstrGetSzStrNoNULL() instead. - * Note that due to the new single-buffer interface this function almost does nothing! - * rgerhards, 2006-09-16 - */ -uchar* cstrGetSzStr(cstr_t *pThis) -{ - rsCHECKVALIDOBJECT(pThis, OIDrsCStr); - return(pThis->pBuf); -} - - /* Converts the CStr object to a classical zero-terminated C string, * returns that string and destroys the CStr object. The returned string * MUST be freed by the caller. The function might return NULL if @@ -426,27 +390,6 @@ finalize_it: } -/* Finalize the string object. This must be called after all data is added to it - * but before that data is used. - * rgerhards, 2009-06-16 - */ -rsRetVal -cstrFinalize(cstr_t *pThis) -{ - DEFiRet; - rsCHECKVALIDOBJECT(pThis, OIDrsCStr); - - if(pThis->iStrLen > 0) { - /* terminate string only if one exists */ - CHKiRet(cstrAppendChar(pThis, '\0')); - --pThis->iStrLen; /* do NOT count the \0 byte */ - } - -finalize_it: - RETiRet; -} - - /* return the length of the current string * 2005-09-09 rgerhards * Please note: this is only a function in a debug build. diff --git a/runtime/stringbuf.h b/runtime/stringbuf.h index 4fbd9a9b..86c7e943 100644 --- a/runtime/stringbuf.h +++ b/runtime/stringbuf.h @@ -74,7 +74,7 @@ void rsCStrDestruct(cstr_t **ppThis); rsRetVal rsCStrExtendBuf(cstr_t *pThis, size_t iMinNeeded); /* our helper, NOT a public interface! */ static inline rsRetVal cstrAppendChar(cstr_t *pThis, uchar c) { - rsRetVal iRet; + rsRetVal iRet = RS_RET_OK; rsCHECKVALIDOBJECT(pThis, OIDrsCStr); @@ -89,6 +89,67 @@ finalize_it: return iRet; } + +/* some inline functions for things that are really frequently called... */ + +/* Finalize the string object. This must be called after all data is added to it + * but before that data is used. + * rgerhards, 2009-06-16 + */ +static inline rsRetVal +cstrFinalize(cstr_t *pThis) +{ + rsRetVal iRet = RS_RET_OK; + rsCHECKVALIDOBJECT(pThis, OIDrsCStr); + + if(pThis->iStrLen > 0) { + /* terminate string only if one exists */ + CHKiRet(cstrAppendChar(pThis, '\0')); + --pThis->iStrLen; /* do NOT count the \0 byte */ + } + +finalize_it: + return iRet; +} + + +/* Returns the cstr data as a classical C sz string. We use that the + * Finalizer did properly terminate our string (but we may stil be NULL). + * So it is vital that the finalizer is called BEFORe this function here! + * The caller must not free or otherwise manipulate the returned string and must not + * destroy the CStr object as long as the ascii string is used. + * This function may return NULL, if the string is currently NULL. This + * is a feature, not a bug. If you need non-NULL in any case, use + * cstrGetSzStrNoNULL() instead. + * Note that due to the new single-buffer interface this function almost does nothing! + * rgerhards, 2006-09-16 + */ +static inline uchar* cstrGetSzStr(cstr_t *pThis) +{ + rsCHECKVALIDOBJECT(pThis, OIDrsCStr); + return(pThis->pBuf); +} + + +/* Converts the CStr object to a classical sz string and returns that. + * Same restrictions as in cstrGetSzStr() applies (see there!). This + * function here guarantees that a valid string is returned, even if + * the CStr object currently holds a NULL pointer string buffer. If so, + * "" is returned. + * rgerhards 2005-10-19 + * WARNING: The returned pointer MUST NOT be freed, as it may be + * obtained from that constant memory pool (in case of NULL!) + */ +static inline uchar* cstrGetSzStrNoNULL(cstr_t *pThis) +{ + rsCHECKVALIDOBJECT(pThis, OIDrsCStr); + if(pThis->pBuf == NULL) + return (uchar*) ""; + else + return cstrGetSzStr(pThis); +} + + /** * Truncate "n" number of characters from the end of the * string. The buffer remains unchanged, just the @@ -148,8 +209,6 @@ rsRetVal rsCStrConvertToBool(cstr_t *pStr, number_t *pBool); /* new calling interface */ rsRetVal cstrFinalize(cstr_t *pThis); rsRetVal cstrConvSzStrAndDestruct(cstr_t *pThis, uchar **ppSz, int bRetNULL); -uchar* cstrGetSzStr(cstr_t *pThis); -uchar* cstrGetSzStrNoNULL(cstr_t *pThis); rsRetVal cstrAppendCStr(cstr_t *pThis, cstr_t *pstrAppend); /* now come inline-like functions */ -- cgit From 7ea63db2f9d6b375dc95696e47357d73927f2d3d Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Fri, 26 Jun 2009 15:31:40 +0200 Subject: optimization: propert names are now internally identified by integers --- runtime/conf.c | 10 +- runtime/msg.c | 356 ++++++++++++++++++++++++++++++++++------------------ runtime/msg.h | 5 +- runtime/rsyslog.h | 41 ++++++ runtime/rule.c | 14 +-- runtime/rule.h | 4 +- runtime/stringbuf.h | 3 - template.c | 16 +-- template.h | 2 +- 9 files changed, 303 insertions(+), 148 deletions(-) diff --git a/runtime/conf.c b/runtime/conf.c index d70bc281..83ed2e9b 100644 --- a/runtime/conf.c +++ b/runtime/conf.c @@ -837,6 +837,7 @@ static rsRetVal cflineProcessPropFilter(uchar **pline, register rule_t *f) { rsParsObj *pPars; cstr_t *pCSCompOp; + cstr_t *pCSPropName; rsRetVal iRet; int iOffset; /* for compare operations */ @@ -856,12 +857,19 @@ static rsRetVal cflineProcessPropFilter(uchar **pline, register rule_t *f) } /* read property */ - iRet = parsDelimCStr(pPars, &f->f_filterData.prop.pCSPropName, ',', 1, 1, 1); + iRet = parsDelimCStr(pPars, &pCSPropName, ',', 1, 1, 1); if(iRet != RS_RET_OK) { errmsg.LogError(0, iRet, "error %d parsing filter property - ignoring selector", iRet); rsParsDestruct(pPars); return(iRet); } + iRet = propNameToID(pCSPropName, &f->f_filterData.prop.propID); + if(iRet != RS_RET_OK) { + errmsg.LogError(0, iRet, "error %d parsing filter property - ignoring selector", iRet); + rsParsDestruct(pPars); + return(iRet); + } + cstrDestruct(&pCSPropName); /* read operation */ iRet = parsDelimCStr(pPars, &pCSCompOp, ',', 1, 1, 1); diff --git a/runtime/msg.c b/runtime/msg.c index 3f69dbcb..c4ba18df 100644 --- a/runtime/msg.c +++ b/runtime/msg.c @@ -1864,10 +1864,9 @@ static uchar *getNOW(eNOWType eNow) * rgerhards 2005-09-15 */ char *MsgGetProp(msg_t *pMsg, struct templateEntry *pTpe, - cstr_t *pCSPropName, size_t *pPropLen, + propid_t propID, size_t *pPropLen, unsigned short *pbMustBeFreed) { - uchar *pName; char *pRes; /* result pointer */ int bufLen = -1; /* length of string or -1, if not known */ char *pBufStart; @@ -1876,132 +1875,155 @@ char *MsgGetProp(msg_t *pMsg, struct templateEntry *pTpe, short iOffs; BEGINfunc + assert(pMsg != NULL); + assert(pbMustBeFreed != NULL); + #ifdef FEATURE_REGEXP /* Variables necessary for regular expression matching */ size_t nmatch = 10; regmatch_t pmatch[10]; #endif - assert(pMsg != NULL); - assert(pbMustBeFreed != NULL); - - if(pCSPropName == NULL) { - assert(pTpe != NULL); - pName = pTpe->data.field.pPropRepl; - } else { - pName = rsCStrGetSzStrNoNULL(pCSPropName); - } *pbMustBeFreed = 0; - /* sometimes there are aliases to the original MonitoWare - * property names. These come after || in the ifs below. */ - if(!strcmp((char*) pName, "msg")) { - pRes = getMSG(pMsg); - bufLen = getMSGLen(pMsg); - } else if(!strcmp((char*) pName, "timestamp") - || !strcmp((char*) pName, "timereported")) { - pRes = getTimeReported(pMsg, pTpe->data.field.eDateFormat); - } else if(!strcmp((char*) pName, "hostname") || !strcmp((char*) pName, "source")) { - pRes = getHOSTNAME(pMsg); - } else if(!strcmp((char*) pName, "syslogtag")) { - pRes = getTAG(pMsg); - } else if(!strcmp((char*) pName, "rawmsg")) { - pRes = getRawMsg(pMsg); - /* enable this, if someone actually uses UxTradMsg, delete after some time has - * passed and nobody complained -- rgerhards, 2009-06-16 - } else if(!strcmp((char*) pName, "uxtradmsg")) { - pRes = getUxTradMsg(pMsg); - */ - } else if(!strcmp((char*) pName, "inputname")) { - pRes = (char*) getInputName(pMsg); - } else if(!strcmp((char*) pName, "fromhost")) { - pRes = (char*) getRcvFrom(pMsg); - } else if(!strcmp((char*) pName, "fromhost-ip")) { - pRes = (char*) getRcvFromIP(pMsg); - } else if(!strcmp((char*) pName, "pri")) { - pRes = getPRI(pMsg); - } else if(!strcmp((char*) pName, "pri-text")) { - pBuf = malloc(20 * sizeof(char)); - if(pBuf == NULL) { - *pbMustBeFreed = 0; - return "**OUT OF MEMORY**"; - } else { - *pbMustBeFreed = 1; - pRes = textpri(pBuf, 20, getPRIi(pMsg)); - } - } else if(!strcmp((char*) pName, "iut")) { - pRes = "1"; /* always 1 for syslog messages (a MonitorWare thing;)) */ - } else if(!strcmp((char*) pName, "syslogfacility")) { - pRes = getFacility(pMsg); - } else if(!strcmp((char*) pName, "syslogfacility-text")) { - pRes = getFacilityStr(pMsg); - } else if(!strcmp((char*) pName, "syslogseverity") || !strcmp((char*) pName, "syslogpriority")) { - pRes = getSeverity(pMsg); - } else if(!strcmp((char*) pName, "syslogseverity-text") || !strcmp((char*) pName, "syslogpriority-text")) { - pRes = getSeverityStr(pMsg); - } else if(!strcmp((char*) pName, "timegenerated")) { - pRes = getTimeGenerated(pMsg, pTpe->data.field.eDateFormat); - } else if(!strcmp((char*) pName, "programname")) { - pRes = getProgramName(pMsg, LOCK_MUTEX); - } else if(!strcmp((char*) pName, "protocol-version")) { - pRes = getProtocolVersionString(pMsg); - } else if(!strcmp((char*) pName, "structured-data")) { - pRes = getStructuredData(pMsg); - } else if(!strcmp((char*) pName, "app-name")) { - pRes = getAPPNAME(pMsg, LOCK_MUTEX); - } else if(!strcmp((char*) pName, "procid")) { - pRes = getPROCID(pMsg, LOCK_MUTEX); - } else if(!strcmp((char*) pName, "msgid")) { - pRes = getMSGID(pMsg); - /* here start system properties (those, that do not relate to the message itself */ - } else if(!strcmp((char*) pName, "$now")) { - if((pRes = (char*) getNOW(NOW_NOW)) == NULL) { - return "***OUT OF MEMORY***"; - } else - *pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */ - } else if(!strcmp((char*) pName, "$year")) { - if((pRes = (char*) getNOW(NOW_YEAR)) == NULL) { - return "***OUT OF MEMORY***"; - } else - *pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */ - } else if(!strcmp((char*) pName, "$month")) { - if((pRes = (char*) getNOW(NOW_MONTH)) == NULL) { - return "***OUT OF MEMORY***"; - } else - *pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */ - } else if(!strcmp((char*) pName, "$day")) { - if((pRes = (char*) getNOW(NOW_DAY)) == NULL) { - return "***OUT OF MEMORY***"; - } else - *pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */ - } else if(!strcmp((char*) pName, "$hour")) { - if((pRes = (char*) getNOW(NOW_HOUR)) == NULL) { - return "***OUT OF MEMORY***"; - } else - *pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */ - } else if(!strcmp((char*) pName, "$hhour")) { - if((pRes = (char*) getNOW(NOW_HHOUR)) == NULL) { - return "***OUT OF MEMORY***"; - } else - *pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */ - } else if(!strcmp((char*) pName, "$qhour")) { - if((pRes = (char*) getNOW(NOW_QHOUR)) == NULL) { - return "***OUT OF MEMORY***"; - } else - *pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */ - } else if(!strcmp((char*) pName, "$minute")) { - if((pRes = (char*) getNOW(NOW_MINUTE)) == NULL) { - return "***OUT OF MEMORY***"; - } else - *pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */ - } else if(!strcmp((char*) pName, "$myhostname")) { - pRes = (char*) glbl.GetLocalHostName(); - } else { - /* there is no point in continuing, we may even otherwise render the - * error message unreadable. rgerhards, 2007-07-10 - */ - dbgprintf("invalid property name: '%s'\n", pName); - return "**INVALID PROPERTY NAME**"; + switch(propID) { + case PROP_MSG: + pRes = getMSG(pMsg); + bufLen = getMSGLen(pMsg); + break; + case PROP_TIMESTAMP: + pRes = getTimeReported(pMsg, pTpe->data.field.eDateFormat); + break; + case PROP_HOSTNAME: + pRes = getHOSTNAME(pMsg); + break; + case PROP_SYSLOGTAG: + pRes = getTAG(pMsg); + break; + case PROP_RAWMSG: + pRes = getRawMsg(pMsg); + break; + /* enable this, if someone actually uses UxTradMsg, delete after some time has + * passed and nobody complained -- rgerhards, 2009-06-16 + case PROP_UXTRADMSG: + pRes = getUxTradMsg(pMsg); + break; + */ + case PROP_INPUTNAME: + pRes = (char*) getInputName(pMsg); + break; + case PROP_FROMHOST: + pRes = (char*) getRcvFrom(pMsg); + break; + case PROP_FROMHOST_IP: + pRes = (char*) getRcvFromIP(pMsg); + break; + case PROP_PRI: + pRes = getPRI(pMsg); + break; + case PROP_PRI_TEXT: + pBuf = malloc(20 * sizeof(char)); + if(pBuf == NULL) { + *pbMustBeFreed = 0; + return "**OUT OF MEMORY**"; + } else { + *pbMustBeFreed = 1; + pRes = textpri(pBuf, 20, getPRIi(pMsg)); + } + break; + case PROP_IUT: + pRes = "1"; /* always 1 for syslog messages (a MonitorWare thing;)) */ + break; + case PROP_SYSLOGFACILITY: + pRes = getFacility(pMsg); + break; + case PROP_SYSLOGFACILITY_TEXT: + pRes = getFacilityStr(pMsg); + break; + case PROP_SYSLOGSEVERITY: + pRes = getSeverity(pMsg); + break; + case PROP_SYSLOGSEVERITY_TEXT: + pRes = getSeverityStr(pMsg); + break; + case PROP_TIMEGENERATED: + pRes = getTimeGenerated(pMsg, pTpe->data.field.eDateFormat); + break; + case PROP_PROGRAMNAME: + pRes = getProgramName(pMsg, LOCK_MUTEX); + break; + case PROP_PROTOCOL_VERSION: + pRes = getProtocolVersionString(pMsg); + break; + case PROP_STRUCTURED_DATA: + pRes = getStructuredData(pMsg); + break; + case PROP_APP_NAME: + pRes = getAPPNAME(pMsg, LOCK_MUTEX); + break; + case PROP_PROCID: + pRes = getPROCID(pMsg, LOCK_MUTEX); + break; + case PROP_MSGID: + pRes = getMSGID(pMsg); + break; + case PROP_SYS_NOW: + if((pRes = (char*) getNOW(NOW_NOW)) == NULL) { + return "***OUT OF MEMORY***"; + } else + *pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */ + break; + case PROP_SYS_YEAR: + if((pRes = (char*) getNOW(NOW_YEAR)) == NULL) { + return "***OUT OF MEMORY***"; + } else + *pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */ + break; + case PROP_SYS_MONTH: + if((pRes = (char*) getNOW(NOW_MONTH)) == NULL) { + return "***OUT OF MEMORY***"; + } else + *pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */ + break; + case PROP_SYS_DAY: + if((pRes = (char*) getNOW(NOW_DAY)) == NULL) { + return "***OUT OF MEMORY***"; + } else + *pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */ + break; + case PROP_SYS_HOUR: + if((pRes = (char*) getNOW(NOW_HOUR)) == NULL) { + return "***OUT OF MEMORY***"; + } else + *pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */ + break; + case PROP_SYS_HHOUR: + if((pRes = (char*) getNOW(NOW_HHOUR)) == NULL) { + return "***OUT OF MEMORY***"; + } else + *pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */ + break; + case PROP_SYS_QHOUR: + if((pRes = (char*) getNOW(NOW_QHOUR)) == NULL) { + return "***OUT OF MEMORY***"; + } else + *pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */ + break; + case PROP_SYS_MINUTE: + if((pRes = (char*) getNOW(NOW_MINUTE)) == NULL) { + return "***OUT OF MEMORY***"; + } else + *pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */ + break; + case PROP_SYS_MYHOSTNAME: + pRes = (char*) glbl.GetLocalHostName(); + break; + default: + /* there is no point in continuing, we may even otherwise render the + * error message unreadable. rgerhards, 2007-07-10 + */ + dbgprintf("invalid property id: '%d'\n", propID); + return "**INVALID PROPERTY NAME**"; } /* If we did not receive a template pointer, we are already done... */ @@ -2587,6 +2609,7 @@ msgGetMsgVar(msg_t *pThis, cstr_t *pstrPropName, var_t **ppVar) size_t propLen; uchar *pszProp = NULL; cstr_t *pstrProp; + propid_t propid; unsigned short bMustBeFreed = 0; ISOBJ_TYPE_assert(pThis, msg); @@ -2598,7 +2621,9 @@ msgGetMsgVar(msg_t *pThis, cstr_t *pstrPropName, var_t **ppVar) CHKiRet(var.ConstructFinalize(pVar)); /* always call MsgGetProp() without a template specifier */ - pszProp = (uchar*) MsgGetProp(pThis, NULL, pstrPropName, &propLen, &bMustBeFreed); + /* TODO: optimize propNameToID() call -- rgerhards, 2009-06-26 */ + propNameToID(pstrPropName, &propid); + pszProp = (uchar*) MsgGetProp(pThis, NULL, propid, &propLen, &bMustBeFreed); /* now create a string object out of it and hand that over to the var */ CHKiRet(rsCStrConstructFromszStr(&pstrProp, pszProp)); @@ -2614,6 +2639,95 @@ finalize_it: RETiRet; } +/* map a property name (string) to a property ID */ +rsRetVal propNameToID(cstr_t *pCSPropName, propid_t *pPropID) +{ + uchar *pName; + DEFiRet; + + assert(pCSPropName != NULL); + assert(pPropID != NULL); + pName = rsCStrGetSzStrNoNULL(pCSPropName); + + /* sometimes there are aliases to the original MonitoWare + * property names. These come after || in the ifs below. */ + if(!strcmp((char*) pName, "msg")) { + *pPropID = PROP_MSG; + } else if(!strcmp((char*) pName, "timestamp") + || !strcmp((char*) pName, "timereported")) { + *pPropID = PROP_TIMESTAMP; + } else if(!strcmp((char*) pName, "hostname") || !strcmp((char*) pName, "source")) { + *pPropID = PROP_HOSTNAME; + } else if(!strcmp((char*) pName, "syslogtag")) { + *pPropID = PROP_SYSLOGTAG; + } else if(!strcmp((char*) pName, "rawmsg")) { + *pPropID = PROP_RAWMSG; + /* enable this, if someone actually uses UxTradMsg, delete after some time has + * passed and nobody complained -- rgerhards, 2009-06-16 + } else if(!strcmp((char*) pName, "uxtradmsg")) { + pRes = getUxTradMsg(pMsg); + */ + } else if(!strcmp((char*) pName, "inputname")) { + *pPropID = PROP_INPUTNAME; + } else if(!strcmp((char*) pName, "fromhost")) { + *pPropID = PROP_FROMHOST; + } else if(!strcmp((char*) pName, "fromhost-ip")) { + *pPropID = PROP_FROMHOST_IP; + } else if(!strcmp((char*) pName, "pri")) { + *pPropID = PROP_PRI; + } else if(!strcmp((char*) pName, "pri-text")) { + *pPropID = PROP_PRI_TEXT; + } else if(!strcmp((char*) pName, "iut")) { + *pPropID = PROP_IUT; + } else if(!strcmp((char*) pName, "syslogfacility")) { + *pPropID = PROP_SYSLOGFACILITY; + } else if(!strcmp((char*) pName, "syslogfacility-text")) { + *pPropID = PROP_SYSLOGFACILITY_TEXT; + } else if(!strcmp((char*) pName, "syslogseverity") || !strcmp((char*) pName, "syslogpriority")) { + *pPropID = PROP_SYSLOGSEVERITY; + } else if(!strcmp((char*) pName, "syslogseverity-text") || !strcmp((char*) pName, "syslogpriority-text")) { + *pPropID = PROP_SYSLOGSEVERITY_TEXT; + } else if(!strcmp((char*) pName, "timegenerated")) { + *pPropID = PROP_TIMEGENERATED; + } else if(!strcmp((char*) pName, "programname")) { + *pPropID = PROP_PROGRAMNAME; + } else if(!strcmp((char*) pName, "protocol-version")) { + *pPropID = PROP_PROTOCOL_VERSION; + } else if(!strcmp((char*) pName, "structured-data")) { + *pPropID = PROP_STRUCTURED_DATA; + } else if(!strcmp((char*) pName, "app-name")) { + *pPropID = PROP_APP_NAME; + } else if(!strcmp((char*) pName, "procid")) { + *pPropID = PROP_PROCID; + } else if(!strcmp((char*) pName, "msgid")) { + *pPropID = PROP_MSGID; + /* here start system properties (those, that do not relate to the message itself */ + } else if(!strcmp((char*) pName, "$now")) { + *pPropID = PROP_SYS_NOW; + } else if(!strcmp((char*) pName, "$year")) { + *pPropID = PROP_SYS_YEAR; + } else if(!strcmp((char*) pName, "$month")) { + *pPropID = PROP_SYS_MONTH; + } else if(!strcmp((char*) pName, "$day")) { + *pPropID = PROP_SYS_DAY; + } else if(!strcmp((char*) pName, "$hour")) { + *pPropID = PROP_SYS_HOUR; + } else if(!strcmp((char*) pName, "$hhour")) { + *pPropID = PROP_SYS_HHOUR; + } else if(!strcmp((char*) pName, "$qhour")) { + *pPropID = PROP_SYS_QHOUR; + } else if(!strcmp((char*) pName, "$minute")) { + *pPropID = PROP_SYS_MINUTE; + } else if(!strcmp((char*) pName, "$myhostname")) { + *pPropID = PROP_SYS_MYHOSTNAME; + } else { + *pPropID = PROP_INVALID; + iRet = RS_RET_VAR_NOT_FOUND; + } + + RETiRet; +} + /* This function can be used as a generic way to set properties. * We have to handle a lot of legacy, so our return value is not always diff --git a/runtime/msg.h b/runtime/msg.h index 56ba5b80..e6b25e6c 100644 --- a/runtime/msg.h +++ b/runtime/msg.h @@ -33,6 +33,7 @@ #include "syslogd-types.h" #include "template.h" + /* rgerhards 2004-11-08: The following structure represents a * syslog message. * @@ -160,7 +161,7 @@ void MsgSetRawMsgWOSize(msg_t *pMsg, char* pszRawMsg); void MsgSetRawMsg(msg_t *pMsg, char* pszRawMsg, size_t lenMsg); rsRetVal MsgReplaceMSG(msg_t *pThis, uchar* pszMSG, int lenMSG); char *MsgGetProp(msg_t *pMsg, struct templateEntry *pTpe, - cstr_t *pCSPropName, size_t *pPropLen, unsigned short *pbMustBeFreed); + propid_t propID, size_t *pPropLen, unsigned short *pbMustBeFreed); char *textpri(char *pRes, size_t pResLen, int pri); rsRetVal msgGetMsgVar(msg_t *pThis, cstr_t *pstrPropName, var_t **ppVar); rsRetVal MsgEnableThreadSafety(void); @@ -177,6 +178,8 @@ int getHOSTNAMELen(msg_t *pM); char *getProgramName(msg_t *pM, bool bLockMutex); int getProgramNameLen(msg_t *pM, bool bLockMutex); uchar *getRcvFrom(msg_t *pM); +rsRetVal propNameToID(cstr_t *pCSPropName, propid_t *pPropID); + /* The MsgPrepareEnqueue() function is a macro for performance reasons. * It needs one global variable to work. This is acceptable, as it gains diff --git a/runtime/rsyslog.h b/runtime/rsyslog.h index c2fb9383..4e0f6e6c 100644 --- a/runtime/rsyslog.h +++ b/runtime/rsyslog.h @@ -111,6 +111,7 @@ typedef long long int64; typedef long long unsigned uint64; typedef int64 number_t; /* type to use for numbers - TODO: maybe an autoconf option? */ typedef char intTiny; /* 0..127! */ +typedef uchar uintTiny; /* 0..255! */ #ifdef __hpux typedef unsigned int u_int32_t; /* TODO: is this correct? */ @@ -156,6 +157,45 @@ struct multi_submit_s { #define _PATH_CONSOLE "/dev/console" #endif +/* properties are now encoded as (tiny) integers. I do not use an enum as I would like + * to keep the memory footprint small (and thus cache hits high). + * rgerhards, 2009-06-26 + */ +typedef uintTiny propid_t; +#define PROP_INVALID 0 +#define PROP_MSG 1 +#define PROP_TIMESTAMP 2 +#define PROP_HOSTNAME 3 +#define PROP_SYSLOGTAG 4 +#define PROP_RAWMSG 5 +#define PROP_INPUTNAME 6 +#define PROP_FROMHOST 7 +#define PROP_FROMHOST_IP 8 +#define PROP_PRI 9 +#define PROP_PRI_TEXT 10 +#define PROP_IUT 11 +#define PROP_SYSLOGFACILITY 12 +#define PROP_SYSLOGFACILITY_TEXT 13 +#define PROP_SYSLOGSEVERITY 14 +#define PROP_SYSLOGSEVERITY_TEXT 15 +#define PROP_TIMEGENERATED 16 +#define PROP_PROGRAMNAME 17 +#define PROP_PROTOCOL_VERSION 18 +#define PROP_STRUCTURED_DATA 19 +#define PROP_APP_NAME 20 +#define PROP_PROCID 21 +#define PROP_MSGID 22 +#define PROP_SYS_NOW 150 +#define PROP_SYS_YEAR 151 +#define PROP_SYS_MONTH 152 +#define PROP_SYS_DAY 153 +#define PROP_SYS_HOUR 154 +#define PROP_SYS_HHOUR 155 +#define PROP_SYS_QHOUR 156 +#define PROP_SYS_MINUTE 157 +#define PROP_SYS_MYHOSTNAME 158 + + /* The error codes below are orginally "borrowed" from * liblogging. As such, we reserve values up to -2999 * just in case we need to borrow something more ;) @@ -325,6 +365,7 @@ enum rsRetVal_ /** return value. All methods return this if not specified oth RS_RET_STREAM_DISABLED = -2127, /**< a file has been disabled (e.g. by size limit restriction) */ RS_RET_FILENAME_INVALID = -2140, /**< filename invalid, not found, no access, ... */ RS_RET_ZLIB_ERR = -2141, /**< error during zlib call */ + RS_RET_VAR_NOT_FOUND = -2142, /**< variable not found */ /* RainerScript error messages (range 1000.. 1999) */ RS_RET_SYSVAR_NOT_FOUND = 1001, /**< system variable could not be found (maybe misspelled) */ diff --git a/runtime/rule.c b/runtime/rule.c index 221368e6..ce19146b 100644 --- a/runtime/rule.c +++ b/runtime/rule.c @@ -179,8 +179,7 @@ shouldProcessThisMessage(rule_t *pRule, msg_t *pMsg, int *bProcessMsg) bRet = (pResult->val.num) ? 1 : 0; } else { assert(pRule->f_filter_type == FILTER_PROP); /* assert() just in case... */ - pszPropVal = MsgGetProp(pMsg, NULL, pRule->f_filterData.prop.pCSPropName, &propLen, &pbMustBeFreed); - // TODO: optimize, we now have the length of the property! + pszPropVal = MsgGetProp(pMsg, NULL, pRule->f_filterData.prop.propID, &propLen, &pbMustBeFreed); /* Now do the compares (short list currently ;)) */ switch(pRule->f_filterData.prop.operation ) { @@ -220,9 +219,8 @@ shouldProcessThisMessage(rule_t *pRule, msg_t *pMsg, int *bProcessMsg) bRet = (bRet == 1) ? 0 : 1; if(Debug) { - dbgprintf("Filter: check for property '%s' (value '%s') ", - rsCStrGetSzStrNoNULL(pRule->f_filterData.prop.pCSPropName), - pszPropVal); + dbgprintf("Filter: check for property '%d' (value '%s') ", + pRule->f_filterData.prop.propID, pszPropVal); if(pRule->f_filterData.prop.isNegated) dbgprintf("NOT "); dbgprintf("%s '%s': %s\n", @@ -308,8 +306,6 @@ CODESTARTobjDestruct(rule) rsCStrDestruct(&pThis->pCSProgNameComp); if(pThis->f_filter_type == FILTER_PROP) { - if(pThis->f_filterData.prop.pCSPropName != NULL) - rsCStrDestruct(&pThis->f_filterData.prop.pCSPropName); if(pThis->f_filterData.prop.pCSCompValue != NULL) rsCStrDestruct(&pThis->f_filterData.prop.pCSCompValue); if(pThis->f_filterData.prop.regex_cache != NULL) @@ -377,8 +373,8 @@ CODESTARTobjDebugPrint(rule) dbgprintf("EXPRESSION-BASED Filter: can currently not be displayed"); } else { dbgprintf("PROPERTY-BASED Filter:\n"); - dbgprintf("\tProperty.: '%s'\n", - rsCStrGetSzStrNoNULL(pThis->f_filterData.prop.pCSPropName)); + dbgprintf("\tProperty.: '%d'\n", pThis->f_filterData.prop.propID); +// TODO: XXXX ADD idtostring()! dbgprintf("\tOperation: "); if(pThis->f_filterData.prop.isNegated) dbgprintf("NOT "); diff --git a/runtime/rule.h b/runtime/rule.h index 38b11c63..99ac44e7 100644 --- a/runtime/rule.h +++ b/runtime/rule.h @@ -44,11 +44,11 @@ struct rule_s { union { u_char f_pmask[LOG_NFACILITIES+1]; /* priority mask */ struct { - cstr_t *pCSPropName; fiop_t operation; regex_t *regex_cache; /* cache for compiled REs, if such are used */ cstr_t *pCSCompValue; /* value to "compare" against */ - char isNegated; /* actually a boolean ;) */ + bool isNegated; + propid_t propID; /* ID of the requested property */ } prop; expr_t *f_expr; /* expression object */ } f_filterData; diff --git a/runtime/stringbuf.h b/runtime/stringbuf.h index 86c7e943..400c74eb 100644 --- a/runtime/stringbuf.h +++ b/runtime/stringbuf.h @@ -76,8 +76,6 @@ static inline rsRetVal cstrAppendChar(cstr_t *pThis, uchar c) { rsRetVal iRet = RS_RET_OK; - rsCHECKVALIDOBJECT(pThis, OIDrsCStr); - if(pThis->iStrLen >= pThis->iBufSize) { CHKiRet(rsCStrExtendBuf(pThis, 1)); /* need more memory! */ } @@ -100,7 +98,6 @@ static inline rsRetVal cstrFinalize(cstr_t *pThis) { rsRetVal iRet = RS_RET_OK; - rsCHECKVALIDOBJECT(pThis, OIDrsCStr); if(pThis->iStrLen > 0) { /* terminate string only if one exists */ diff --git a/template.c b/template.c index 704f0b19..832183b0 100644 --- a/template.c +++ b/template.c @@ -105,7 +105,7 @@ rsRetVal tplToString(struct template *pTpl, msg_t *pMsg, uchar **ppBuf, size_t * iLenVal = pTpe->data.constant.iLenConstant; bMustBeFreed = 0; } else if(pTpe->eEntryType == FIELD) { - pVal = (uchar*) MsgGetProp(pMsg, pTpe, NULL, &iLenVal, &bMustBeFreed); + pVal = (uchar*) MsgGetProp(pMsg, pTpe, pTpe->data.field.propid, &iLenVal, &bMustBeFreed); /* we now need to check if we should use SQL option. In this case, * we must go over the generated string and escape '\'' characters. * rgerhards, 2005-09-22: the option values below look somewhat misplaced, @@ -173,7 +173,7 @@ rsRetVal tplToArray(struct template *pTpl, msg_t *pMsg, uchar*** ppArr) if(pTpe->eEntryType == CONSTANT) { CHKmalloc(pArr[iArr] = (uchar*)strdup((char*) pTpe->data.constant.pConstant)); } else if(pTpe->eEntryType == FIELD) { - pVal = (uchar*) MsgGetProp(pMsg, pTpe, NULL, &propLen, &bMustBeFreed); + pVal = (uchar*) MsgGetProp(pMsg, pTpe, pTpe->data.field.propid, &propLen, &bMustBeFreed); if(bMustBeFreed) { /* if it must be freed, it is our own private copy... */ pArr[iArr] = pVal; /* ... so we can use it! */ } else { @@ -561,11 +561,11 @@ static int do_Parameter(unsigned char **pp, struct template *pTpl) ++p; /* do NOT do this in tolower()! */ } - /* got the name*/ + /* got the name */ cstrFinalize(pStrB); - if(cstrConvSzStrAndDestruct(pStrB, &pTpe->data.field.pPropRepl, 0) != RS_RET_OK) + + if(propNameToID(pStrB, &pTpe->data.field.propid) != RS_RET_OK) return 1; -// TODO: another optimization: map name to integer id OPT /* Check frompos, if it has an R, then topos should be a regex */ if(*p == ':') { @@ -1004,8 +1004,6 @@ void tplDeleteAll(void) regexp.regfree(&(pTpeDel->data.field.re)); } } - /*dbgprintf("(FIELD), value: '%s'", pTpeDel->data.field.pPropRepl);*/ - free(pTpeDel->data.field.pPropRepl); break; } /*dbgprintf("\n");*/ @@ -1061,8 +1059,6 @@ void tplDeleteNew(void) regexp.regfree(&(pTpeDel->data.field.re)); } } - /*dbgprintf("(FIELD), value: '%s'", pTpeDel->data.field.pPropRepl);*/ - free(pTpeDel->data.field.pPropRepl); break; } /*dbgprintf("\n");*/ @@ -1111,7 +1107,7 @@ void tplPrintList(void) pTpe->data.constant.pConstant); break; case FIELD: - dbgprintf("(FIELD), value: '%s' ", pTpe->data.field.pPropRepl); + dbgprintf("(FIELD), value: '%d' ", pTpe->data.field.propid); switch(pTpe->data.field.eDateFormat) { case tplFmtDefault: break; diff --git a/template.h b/template.h index 73ed0f84..271e8271 100644 --- a/template.h +++ b/template.h @@ -63,7 +63,7 @@ struct templateEntry { int iLenConstant; /* its length */ } constant; struct { - uchar *pPropRepl; /* pointer to property replacer string */ + propid_t propid; /* property to be used */ unsigned iFromPos; /* for partial strings only chars from this position ... */ unsigned iToPos; /* up to that one... */ #ifdef FEATURE_REGEXP -- cgit