refactor tpl processor so that date is queried once per template

Things like $YEAR, $MONTH required a time() call each.
This commit is contained in:
Rainer Gerhards 2012-10-10 19:20:19 +02:00
parent 2aa16d3b1e
commit 9b4a225c59
5 changed files with 44 additions and 33 deletions

View File

@ -233,11 +233,11 @@ getDefaultBSON(msg_t *pMsg)
gint64 ts_gen, ts_rcv; /* timestamps: generated, received */
int secfrac;
procid = MsgGetProp(pMsg, NULL, PROP_PROGRAMNAME, NULL, &procid_len, &procid_free);
tag = MsgGetProp(pMsg, NULL, PROP_SYSLOGTAG, NULL, &tag_len, &tag_free);
pid = MsgGetProp(pMsg, NULL, PROP_PROCID, NULL, &pid_len, &pid_free);
sys = MsgGetProp(pMsg, NULL, PROP_HOSTNAME, NULL, &sys_len, &sys_free);
msg = MsgGetProp(pMsg, NULL, PROP_MSG, NULL, &msg_len, &msg_free);
procid = MsgGetProp(pMsg, NULL, PROP_PROGRAMNAME, NULL, &procid_len, &procid_free, NULL);
tag = MsgGetProp(pMsg, NULL, PROP_SYSLOGTAG, NULL, &tag_len, &tag_free, NULL);
pid = MsgGetProp(pMsg, NULL, PROP_PROCID, NULL, &pid_len, &pid_free, NULL);
sys = MsgGetProp(pMsg, NULL, PROP_HOSTNAME, NULL, &sys_len, &sys_free, NULL);
msg = MsgGetProp(pMsg, NULL, PROP_MSG, NULL, &msg_len, &msg_free, NULL);
// TODO: move to datetime? Refactor in any case! rgerhards, 2012-03-30
ts_gen = (gint64) datetime.syslogTime2time_t(&pMsg->tTIMESTAMP) * 1000; /* ms! */

View File

@ -2373,40 +2373,38 @@ char *textpri(char *pRes, size_t pResLen, int pri)
*/
typedef enum ENOWType { NOW_NOW, NOW_YEAR, NOW_MONTH, NOW_DAY, NOW_HOUR, NOW_HHOUR, NOW_QHOUR, NOW_MINUTE } eNOWType;
#define tmpBUFSIZE 16 /* size of formatting buffer */
static uchar *getNOW(eNOWType eNow)
static uchar *getNOW(eNOWType eNow, struct syslogTime *t)
{
uchar *pBuf;
struct syslogTime t;
if((pBuf = (uchar*) MALLOC(sizeof(uchar) * tmpBUFSIZE)) == NULL) {
return NULL;
}
datetime.getCurrTime(&t, NULL);
switch(eNow) {
case NOW_NOW:
snprintf((char*) pBuf, tmpBUFSIZE, "%4.4d-%2.2d-%2.2d", t.year, t.month, t.day);
snprintf((char*) pBuf, tmpBUFSIZE, "%4.4d-%2.2d-%2.2d", t->year, t->month, t->day);
break;
case NOW_YEAR:
snprintf((char*) pBuf, tmpBUFSIZE, "%4.4d", t.year);
snprintf((char*) pBuf, tmpBUFSIZE, "%4.4d", t->year);
break;
case NOW_MONTH:
snprintf((char*) pBuf, tmpBUFSIZE, "%2.2d", t.month);
snprintf((char*) pBuf, tmpBUFSIZE, "%2.2d", t->month);
break;
case NOW_DAY:
snprintf((char*) pBuf, tmpBUFSIZE, "%2.2d", t.day);
snprintf((char*) pBuf, tmpBUFSIZE, "%2.2d", t->day);
break;
case NOW_HOUR:
snprintf((char*) pBuf, tmpBUFSIZE, "%2.2d", t.hour);
snprintf((char*) pBuf, tmpBUFSIZE, "%2.2d", t->hour);
break;
case NOW_HHOUR:
snprintf((char*) pBuf, tmpBUFSIZE, "%2.2d", t.minute / 30);
snprintf((char*) pBuf, tmpBUFSIZE, "%2.2d", t->minute / 30);
break;
case NOW_QHOUR:
snprintf((char*) pBuf, tmpBUFSIZE, "%2.2d", t.minute / 15);
snprintf((char*) pBuf, tmpBUFSIZE, "%2.2d", t->minute / 15);
break;
case NOW_MINUTE:
snprintf((char*) pBuf, tmpBUFSIZE, "%2.2d", t.minute);
snprintf((char*) pBuf, tmpBUFSIZE, "%2.2d", t->minute);
break;
}
@ -2673,7 +2671,7 @@ finalize_it:
* Parameter "bMustBeFreed" is set by this function. It tells the
* caller whether or not the string returned must be freed by the
* caller itself. It is is 0, the caller MUST NOT free it. If it is
* 1, the caller MUST free 1. Handling this wrongly leads to either
* 1, the caller MUST free it. Handling this wrongly leads to either
* a memory leak of a program abort (do to double-frees or frees on
* the constant memory pool). So be careful to do it right.
* rgerhards 2004-11-23
@ -2690,7 +2688,7 @@ finalize_it:
return(UCHAR_CONSTANT("**OUT OF MEMORY**"));}
uchar *MsgGetProp(msg_t *pMsg, struct templateEntry *pTpe,
propid_t propid, es_str_t *propName, rs_size_t *pPropLen,
unsigned short *pbMustBeFreed)
unsigned short *pbMustBeFreed, struct syslogTime *ttNow)
{
uchar *pRes; /* result pointer */
rs_size_t bufLen = -1; /* length of string or -1, if not known */
@ -2794,49 +2792,50 @@ uchar *MsgGetProp(msg_t *pMsg, struct templateEntry *pTpe,
pRes = (uchar*)getParseSuccess(pMsg);
break;
case PROP_SYS_NOW:
if((pRes = getNOW(NOW_NOW)) == NULL) {
if((pRes = getNOW(NOW_NOW, ttNow)) == NULL) {
RET_OUT_OF_MEMORY;
} else
*pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */
break;
case PROP_SYS_YEAR:
if((pRes = getNOW(NOW_YEAR)) == NULL) {
if((pRes = getNOW(NOW_YEAR, ttNow)) == NULL) {
RET_OUT_OF_MEMORY;
} else
//TODO set pPropLen!
*pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */
break;
case PROP_SYS_MONTH:
if((pRes = getNOW(NOW_MONTH)) == NULL) {
if((pRes = getNOW(NOW_MONTH, ttNow)) == NULL) {
RET_OUT_OF_MEMORY;
} else
*pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */
break;
case PROP_SYS_DAY:
if((pRes = getNOW(NOW_DAY)) == NULL) {
if((pRes = getNOW(NOW_DAY, ttNow)) == NULL) {
RET_OUT_OF_MEMORY;
} else
*pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */
break;
case PROP_SYS_HOUR:
if((pRes = getNOW(NOW_HOUR)) == NULL) {
if((pRes = getNOW(NOW_HOUR, ttNow)) == NULL) {
RET_OUT_OF_MEMORY;
} else
*pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */
break;
case PROP_SYS_HHOUR:
if((pRes = getNOW(NOW_HHOUR)) == NULL) {
if((pRes = getNOW(NOW_HHOUR, ttNow)) == NULL) {
RET_OUT_OF_MEMORY;
} else
*pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */
break;
case PROP_SYS_QHOUR:
if((pRes = getNOW(NOW_QHOUR)) == NULL) {
if((pRes = getNOW(NOW_QHOUR, ttNow)) == NULL) {
RET_OUT_OF_MEMORY;
} else
*pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */
break;
case PROP_SYS_MINUTE:
if((pRes = getNOW(NOW_MINUTE)) == NULL) {
if((pRes = getNOW(NOW_MINUTE, ttNow)) == NULL) {
RET_OUT_OF_MEMORY;
} else
*pbMustBeFreed = 1; /* all of these functions allocate dyn. memory */
@ -3544,7 +3543,7 @@ msgGetMsgVarNew(msg_t *pThis, uchar *name)
/* always call MsgGetProp() without a template specifier */
/* TODO: optimize propNameToID() call -- rgerhards, 2009-06-26 */
propNameStrToID(name, &propid);
pszProp = (uchar*) MsgGetProp(pThis, NULL, propid, NULL, &propLen, &bMustBeFreed);
pszProp = (uchar*) MsgGetProp(pThis, NULL, propid, NULL, &propLen, &bMustBeFreed, NULL);
estr = es_newStrFromCStr((char*)pszProp, propLen);
if(bMustBeFreed)

View File

@ -173,7 +173,7 @@ void MsgSetRawMsg(msg_t *pMsg, char* pszRawMsg, size_t lenMsg);
rsRetVal MsgReplaceMSG(msg_t *pThis, uchar* pszMSG, int lenMSG);
uchar *MsgGetProp(msg_t *pMsg, struct templateEntry *pTpe,
propid_t propid, es_str_t *propName,
rs_size_t *pPropLen, unsigned short *pbMustBeFreed);
rs_size_t *pPropLen, unsigned short *pbMustBeFreed, struct syslogTime *ttNow);
char *textpri(char *pRes, size_t pResLen, int pri);
rsRetVal msgGetMsgVar(msg_t *pThis, cstr_t *pstrPropName, var_t **ppVar);
es_str_t* msgGetMsgVarNew(msg_t *pThis, uchar *name);

View File

@ -378,7 +378,8 @@ evalPROPFILT(struct cnfstmt *stmt, msg_t *pMsg)
goto done;
pszPropVal = MsgGetProp(pMsg, NULL, stmt->d.s_propfilt.propID,
stmt->d.s_propfilt.propName, &propLen, &pbMustBeFreed);
stmt->d.s_propfilt.propName, &propLen,
&pbMustBeFreed, NULL);
/* Now do the compares (short list currently ;)) */
switch(stmt->d.s_propfilt.operation ) {

View File

@ -45,12 +45,14 @@
#include "strgen.h"
#include "rsconf.h"
#include "msg.h"
#include "datetime.h"
#include "unicode-helper.h"
/* static data */
DEFobjCurrIf(obj)
DEFobjCurrIf(errmsg)
DEFobjCurrIf(strgen)
DEFobjCurrIf(datetime)
/* tables for interfacing with the v6 config system */
static struct cnfparamdescr cnfparamdescr[] = {
@ -149,6 +151,7 @@ rsRetVal tplToString(struct template *pTpl, msg_t *pMsg, uchar **ppBuf, size_t *
unsigned short bMustBeFreed = 0;
uchar *pVal;
rs_size_t iLenVal = 0;
struct syslogTime ttNow;
assert(pTpl != NULL);
assert(pMsg != NULL);
@ -176,6 +179,7 @@ rsRetVal tplToString(struct template *pTpl, msg_t *pMsg, uchar **ppBuf, size_t *
}
/* we have a "regular" template with template entries */
datetime.getCurrTime(&ttNow, NULL); // TODO: query time only if required 2012-10-10 rger
/* loop through the template. We obtain one value
* and copy it over to our dynamic string buffer. Then, we
@ -191,7 +195,8 @@ rsRetVal tplToString(struct template *pTpl, msg_t *pMsg, uchar **ppBuf, size_t *
bMustBeFreed = 0;
} else if(pTpe->eEntryType == FIELD) {
pVal = (uchar*) MsgGetProp(pMsg, pTpe, pTpe->data.field.propid,
pTpe->data.field.propName, &iLenVal, &bMustBeFreed);
pTpe->data.field.propName, &iLenVal,
&bMustBeFreed, &ttNow);
/* 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,
@ -254,6 +259,7 @@ rsRetVal tplToArray(struct template *pTpl, msg_t *pMsg, uchar*** ppArr)
rs_size_t propLen;
unsigned short bMustBeFreed;
uchar *pVal;
struct syslogTime ttNow;
assert(pTpl != NULL);
assert(pMsg != NULL);
@ -273,6 +279,7 @@ rsRetVal tplToArray(struct template *pTpl, msg_t *pMsg, uchar*** ppArr)
FINALIZE;
}
datetime.getCurrTime(&ttNow, NULL); // TODO: query time only if required 2012-10-10 rger
/* loop through the template. We obtain one value, create a
* private copy (if necessary), add it to the string array
* and then on to the next until we have processed everything.
@ -286,7 +293,8 @@ rsRetVal tplToArray(struct template *pTpl, msg_t *pMsg, uchar*** ppArr)
CHKmalloc(pArr[iArr] = (uchar*)strdup((char*) pTpe->data.constant.pConstant));
} else if(pTpe->eEntryType == FIELD) {
pVal = (uchar*) MsgGetProp(pMsg, pTpe, pTpe->data.field.propid,
pTpe->data.field.propName, &propLen, &bMustBeFreed);
pTpe->data.field.propName, &propLen,
&bMustBeFreed, &ttNow);
if(bMustBeFreed) { /* if it must be freed, it is our own private copy... */
pArr[iArr] = pVal; /* ... so we can use it! */
} else {
@ -318,11 +326,12 @@ tplToJSON(struct template *pTpl, msg_t *pMsg, struct json_object **pjson)
uchar *pVal;
struct json_object *json, *jsonf;
rsRetVal localRet;
struct syslogTime ttNow;
DEFiRet;
assert(pTpl != NULL);
assert(pMsg != NULL);
assert(json != NULL);
assert(pjson != NULL);
if(pTpl->subtree != NULL){
localRet = jsonFind(pMsg, pTpl->subtree, pjson);
@ -336,6 +345,7 @@ tplToJSON(struct template *pTpl, msg_t *pMsg, struct json_object **pjson)
}
json = json_object_new_object();
datetime.getCurrTime(&ttNow, NULL); // TODO: query time only if required 2012-10-10 rger
for(pTpe = pTpl->pEntryRoot ; pTpe != NULL ; pTpe = pTpe->pNext) {
if(pTpe->eEntryType == CONSTANT) {
if(pTpe->fieldName == NULL)
@ -357,7 +367,7 @@ tplToJSON(struct template *pTpl, msg_t *pMsg, struct json_object **pjson)
} else {
pVal = (uchar*) MsgGetProp(pMsg, pTpe, pTpe->data.field.propid,
pTpe->data.field.propName, &propLen,
&bMustBeFreed);
&bMustBeFreed, &ttNow);
if(pTpe->data.field.options.bMandatory || propLen > 0) {
jsonf = json_object_new_string_len((char*)pVal, propLen);
json_object_object_add(json, (char*)pTpe->fieldName, jsonf);
@ -2140,6 +2150,7 @@ rsRetVal templateInit()
DEFiRet;
CHKiRet(objGetObjInterface(&obj));
CHKiRet(objUse(errmsg, CORE_COMPONENT));
CHKiRet(objUse(datetime, CORE_COMPONENT));
CHKiRet(objUse(strgen, CORE_COMPONENT));
finalize_it: