summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRainer Gerhards <rgerhards@adiscon.com>2009-04-03 12:51:02 +0200
committerRainer Gerhards <rgerhards@adiscon.com>2009-04-03 12:51:02 +0200
commitec0e2c3e7df6addc02431628daddfeae49b92af7 (patch)
tree09377ca7ce8c0d67b7760f3db7680949ff480bc2
parentd747083e54badeeb45f3d46df2916047e60021b4 (diff)
downloadrsyslog-ec0e2c3e7df6addc02431628daddfeae49b92af7.tar.gz
rsyslog-ec0e2c3e7df6addc02431628daddfeae49b92af7.tar.xz
rsyslog-ec0e2c3e7df6addc02431628daddfeae49b92af7.zip
added a new way how output plugins may be passed parameters.
This is more efficient for some outputs. They new can receive fields not only as a single string but rather in an array where each string is seperated.
-rw-r--r--ChangeLog3
-rw-r--r--action.c32
-rw-r--r--action.h2
-rw-r--r--doc/rsyslog_conf_modules.html7
-rw-r--r--plugins/omstdout/omstdout.c80
-rw-r--r--runtime/modules.c2
-rw-r--r--runtime/objomsr.c18
-rw-r--r--runtime/objomsr.h6
-rw-r--r--template.c56
-rw-r--r--template.h1
10 files changed, 197 insertions, 10 deletions
diff --git a/ChangeLog b/ChangeLog
index fc9f807f..7f79271f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -36,6 +36,9 @@ Version 4.1.6 [DEVEL] (rgerhards), 2009-03-??
check for NULL pointers
- improved performance of regexp-based filters
Thanks to Arnaud Cornet for providing the idea and initial patch.
+- added a new way how output plugins may be passed parameters. This is
+ more effcient for some outputs. They new can receive fields not only
+ as a single string but rather in an array where each string is seperated.
---------------------------------------------------------------------------
Version 4.1.5 [DEVEL] (rgerhards), 2009-03-11
- bugfix: parser did not correctly parse fields in UDP-received messages
diff --git a/action.c b/action.c
index 08755c13..03073153 100644
--- a/action.c
+++ b/action.c
@@ -425,6 +425,7 @@ actionCallDoAction(action_t *pAction, msg_t *pMsg)
DEFiRet;
int iRetries;
int i;
+ int iArr;
int iSleepPeriod;
int bCallAction;
int iCancelStateSave;
@@ -439,7 +440,15 @@ actionCallDoAction(action_t *pAction, msg_t *pMsg)
/* here we must loop to process all requested strings */
for(i = 0 ; i < pAction->iNumTpls ; ++i) {
- CHKiRet(tplToString(pAction->ppTpl[i], pMsg, &(ppMsgs[i])));
+ switch(pAction->eParamPassing) {
+ case ACT_STRING_PASSING:
+ CHKiRet(tplToString(pAction->ppTpl[i], pMsg, &(ppMsgs[i])));
+ break;
+ case ACT_ARRAY_PASSING:
+ CHKiRet(tplToArray(pAction->ppTpl[i], pMsg, (uchar***) &(ppMsgs[i])));
+ break;
+ default:assert(0); /* software bug if this happens! */
+ }
}
iRetries = 0;
/* We now must guard the output module against execution by multiple threads. The
@@ -495,7 +504,19 @@ finalize_it:
/* cleanup */
for(i = 0 ; i < pAction->iNumTpls ; ++i) {
if(ppMsgs[i] != NULL) {
- d_free(ppMsgs[i]);
+ switch(pAction->eParamPassing) {
+ case ACT_ARRAY_PASSING:
+ iArr = 0;
+ while(((char **)ppMsgs[i])[iArr] != NULL)
+ d_free(((char **)ppMsgs[i])[iArr++]);
+ d_free(ppMsgs[i]);
+ break;
+ case ACT_STRING_PASSING:
+ d_free(ppMsgs[i]);
+ break;
+ default:
+ assert(0);
+ }
}
}
d_free(ppMsgs);
@@ -905,6 +926,13 @@ addAction(action_t **ppAction, modInfo_t *pMod, void *pModData, omodStringReques
ABORT_FINALIZE(RS_RET_RQD_TPLOPT_MISSING);
}
+ /* set parameter-passing mode */
+ if(iTplOpts & OMSR_TPL_AS_ARRAY) {
+ pAction->eParamPassing = ACT_ARRAY_PASSING;
+ } else {
+ pAction->eParamPassing = ACT_STRING_PASSING;
+ }
+
dbgprintf("template: '%s' assigned\n", pTplName);
}
diff --git a/action.h b/action.h
index dc9bbd74..f2706af6 100644
--- a/action.h
+++ b/action.h
@@ -61,6 +61,8 @@ struct action_s {
short f_ReduceRepeated;/* reduce repeated lines 0 - no, 1 - yes */
int f_prevcount; /* repetition cnt of prevline */
int f_repeatcount; /* number of "repeated" msgs */
+ enum { ACT_STRING_PASSING = 0, ACT_ARRAY_PASSING = 1 }
+ eParamPassing; /* mode of parameter passing to action */
int iNumTpls; /* number of array entries for template element below */
struct template **ppTpl;/* array of template to use - strings must be passed to doAction
* in this order. */
diff --git a/doc/rsyslog_conf_modules.html b/doc/rsyslog_conf_modules.html
index 890a55c8..a281d9e7 100644
--- a/doc/rsyslog_conf_modules.html
+++ b/doc/rsyslog_conf_modules.html
@@ -8,10 +8,9 @@
number of modules. Here is the entry point to their documentation and
what they do (list is currently not complete)</p>
<ul>
-<li><a href="omsnmp.html">omsnmp</a> - SNMP
-trap output module</li>
-<li><a href="omrelp.html">omrelp</a> - RELP
-output module</li>
+<li><a href="omsnmp.html">omsnmp</a> - SNMP trap output module</li>
+<li><a href="omstdout.html">omtdout</a> - stdout output module (mainly a test tool)</li>
+<li><a href="omrelp.html">omrelp</a> - RELP output module</li>
<li>omgssapi - output module for GSS-enabled syslog</li>
<li><a href="ommysql.html">ommysql</a> - output module for MySQL</li>
<li>ompgsql - output module for PostgreSQL</li>
diff --git a/plugins/omstdout/omstdout.c b/plugins/omstdout/omstdout.c
index 6e227ba9..e491005c 100644
--- a/plugins/omstdout/omstdout.c
+++ b/plugins/omstdout/omstdout.c
@@ -49,7 +49,12 @@ MODULE_TYPE_OUTPUT
*/
DEF_OMOD_STATIC_DATA
+/* config variables */
+static int bUseArrayInterface; /* shall action use array instead of string template interface? */
+
+
typedef struct _instanceData {
+ int bUseArrayInterface; /* uses action use array instead of string template interface? */
} instanceData;
BEGINcreateInstance
@@ -79,12 +84,46 @@ CODESTARTtryResume
ENDtryResume
BEGINdoAction
+ char **szParams;
+ char *toWrite;
+ int iParamVal;
+ int iParam;
+ int iBuf;
+ char szBuf[65564];
CODESTARTdoAction
- write(1, (char*)ppString[0], strlen((char*)ppString[0]));
+ if(pData->bUseArrayInterface) {
+ /* if we use array passing, we need to put together a string
+ * ourselves. At this point, please keep in mind that omstdout is
+ * primarily a testing aid. Other modules may do different processing
+ * if they would like to support downlevel versions which do not support
+ * array-passing, but also use that interface on cores who do...
+ * So this code here is also more or less an example of how to do that.
+ * rgerhards, 2009-04-03
+ */
+ szParams = (char**) (ppString[0]);
+ /* In array-passing mode, ppString[] contains a NULL-terminated array
+ * of char *pointers.
+ */
+ iParam = 0;
+ iBuf = 0;
+ while(szParams[iParam] != NULL) {
+ iParamVal = 0;
+ while(szParams[iParam][iParamVal] != '\0' && iBuf < sizeof(szBuf)) {
+ szBuf[iBuf++] = szParams[iParam][iParamVal++];
+ }
+ ++iParam;
+ }
+ szBuf[iBuf] = '\0';
+ toWrite = szBuf;
+ } else {
+ toWrite = (char*) ppString[0];
+ }
+ write(1, toWrite, strlen(toWrite)); /* 1 is stdout! */
ENDdoAction
BEGINparseSelectorAct
+ int iTplOpts;
CODESTARTparseSelectorAct
CODE_STD_STRING_REQUESTparseSelectorAct(1)
/* first check if this config line is actually for us */
@@ -99,7 +138,9 @@ CODE_STD_STRING_REQUESTparseSelectorAct(1)
/* check if a non-standard template is to be applied */
if(*(p-1) == ';')
--p;
- CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, 0, (uchar*) "RSYSLOG_FileFormat"));
+ iTplOpts = (bUseArrayInterface == 0) ? 0 : OMSR_TPL_AS_ARRAY;
+ CHKiRet(cflineParseTemplateName(&p, *ppOMSR, 0, iTplOpts, (uchar*) "RSYSLOG_FileFormat"));
+ pData->bUseArrayInterface = bUseArrayInterface;
CODE_STD_FINALIZERparseSelectorAct
ENDparseSelectorAct
@@ -115,10 +156,45 @@ CODEqueryEtryPt_STD_OMOD_QUERIES
ENDqueryEtryPt
+
+/* Reset config variables for this module to default values.
+ */
+static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
+{
+ DEFiRet;
+ bUseArrayInterface = 0;
+ RETiRet;
+}
+
+
BEGINmodInit()
+ rsRetVal localRet;
+ rsRetVal (*pomsrGetSupportedTplOpts)(unsigned long *pOpts);
+ unsigned long opts;
+ int bArrayPassingSupported; /* does core support template passing as an array? */
CODESTARTmodInit
*ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */
CODEmodInit_QueryRegCFSLineHdlr
+ /* check if the rsyslog core supports parameter passing code */
+ bArrayPassingSupported = 0;
+ localRet = pHostQueryEtryPt((uchar*)"OMSRgetSupportedTplOpts", &pomsrGetSupportedTplOpts);
+ if(localRet == RS_RET_OK) {
+ /* found entry point, so let's see if core supports array passing */
+ CHKiRet((*pomsrGetSupportedTplOpts)(&opts));
+ if(opts & OMSR_TPL_AS_ARRAY)
+ bArrayPassingSupported = 1;
+ } else if(localRet != RS_RET_ENTRY_POINT_NOT_FOUND) {
+ ABORT_FINALIZE(localRet); /* Something else went wrong, what is not acceptable */
+ }
+ DBGPRINTF("omstdout: array-passing is %ssupported by rsyslog core.\n", bArrayPassingSupported ? "" : "not ");
+
+ if(bArrayPassingSupported) {
+ /* enable config comand only if core supports it */
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"actionomstdoutarrayinterface", 0, eCmdHdlrBinary, NULL,
+ &bUseArrayInterface, STD_LOADABLE_MODULE_ID));
+ }
+ CHKiRet(omsdRegCFSLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler,
+ resetConfigVariables, NULL, STD_LOADABLE_MODULE_ID));
ENDmodInit
/* vi:set ai:
diff --git a/runtime/modules.c b/runtime/modules.c
index cef4eac6..9fdb48e7 100644
--- a/runtime/modules.c
+++ b/runtime/modules.c
@@ -225,6 +225,8 @@ static rsRetVal queryHostEtryPt(uchar *name, rsRetVal (**pEtryPoint)())
*pEtryPoint = regCfSysLineHdlr;
} else if(!strcmp((char*) name, "objGetObjInterface")) {
*pEtryPoint = objGetObjInterface;
+ } else if(!strcmp((char*) name, "OMSRgetSupportedTplOpts")) {
+ *pEtryPoint = OMSRgetSupportedTplOpts;
} else {
*pEtryPoint = NULL; /* to be on the safe side */
ABORT_FINALIZE(RS_RET_ENTRY_POINT_NOT_FOUND);
diff --git a/runtime/objomsr.c b/runtime/objomsr.c
index 21d284f3..8dddc4b8 100644
--- a/runtime/objomsr.c
+++ b/runtime/objomsr.c
@@ -141,5 +141,23 @@ int OMSRgetEntry(omodStringRequest_t *pThis, int iEntry, uchar **ppTplName, int
return RS_RET_OK;
}
+
+
+/* return the full set of template options that are supported by this version of
+ * OMSR. They are returned in an unsigned long value. The caller can mask that
+ * value to check on the option he is interested in.
+ * Note that this interface was added in 4.1.6, so a plugin must obtain a pointer
+ * to this interface via queryHostEtryPt().
+ * rgerhards, 2009-04-03
+ */
+rsRetVal
+OMSRgetSupportedTplOpts(unsigned long *pOpts)
+{
+ DEFiRet;
+ assert(pOpts != NULL);
+ *pOpts = OMSR_RQD_TPL_OPT_SQL | OMSR_TPL_AS_ARRAY;
+ RETiRet;
+}
+
/* vim:set ai:
*/
diff --git a/runtime/objomsr.h b/runtime/objomsr.h
index 2255e4f3..75ad0fb8 100644
--- a/runtime/objomsr.h
+++ b/runtime/objomsr.h
@@ -1,6 +1,6 @@
/* Definition of the omsr (omodStringRequest) object.
*
- * Copyright 2007 Rainer Gerhards and Adiscon GmbH.
+ * Copyright 2007, 2009 Rainer Gerhards and Adiscon GmbH.
*
* This file is part of the rsyslog runtime library.
*
@@ -27,7 +27,8 @@
/* define flags for required template options */
#define OMSR_NO_RQD_TPL_OPTS 0
#define OMSR_RQD_TPL_OPT_SQL 1
-/* next option is 2, 4, 8, ... */
+#define OMSR_TPL_AS_ARRAY 2 /* introduced in 4.1.6, 2009-04-03 */
+/* next option is 4, 8, 16, ... */
struct omodStringRequest_s { /* strings requested by output module for doAction() */
int iNumEntries; /* number of array entries for data elements below */
@@ -40,6 +41,7 @@ typedef struct omodStringRequest_s omodStringRequest_t;
rsRetVal OMSRdestruct(omodStringRequest_t *pThis);
rsRetVal OMSRconstruct(omodStringRequest_t **ppThis, int iNumEntries);
rsRetVal OMSRsetEntry(omodStringRequest_t *pThis, int iEntry, uchar *pTplName, int iTplOpts);
+rsRetVal OMSRgetSupportedTplOpts(unsigned long *pOpts);
int OMSRgetEntryCount(omodStringRequest_t *pThis);
int OMSRgetEntry(omodStringRequest_t *pThis, int iEntry, uchar **ppTplName, int *piTplOpts);
diff --git a/template.c b/template.c
index 4f507ff6..4a12aa3b 100644
--- a/template.c
+++ b/template.c
@@ -47,6 +47,8 @@ static struct template *tplRoot = NULL; /* the root of the template list */
static struct template *tplLast = NULL; /* points to the last element of the template list */
static struct template *tplLastStatic = NULL; /* last static element of the template list */
+
+
/* This functions converts a template into a string. It should
* actually be in template.c, but this requires larger re-structuring
* of the code (because all the property-access functions are static
@@ -140,6 +142,60 @@ finalize_it:
RETiRet;
}
+
+/* This functions converts a template into an array of strings.
+ * For further general details, see the very similar funtion
+ * tpltoString().
+ * Instead of a string, an array of string pointers is returned by
+ * thus function. The caller is repsonsible for destroying that array as
+ * well as all of its elements. The array is of fixed size. It's end
+ * is indicated by a NULL pointer.
+ * rgerhards, 2009-04-03
+ */
+rsRetVal tplToArray(struct template *pTpl, msg_t *pMsg, uchar*** ppArr)
+{
+ DEFiRet;
+ struct templateEntry *pTpe;
+ uchar **pArr;
+ int iArr;
+ unsigned short bMustBeFreed;
+ uchar *pVal;
+
+ assert(pTpl != NULL);
+ assert(pMsg != NULL);
+ assert(ppArr != NULL);
+
+ /* 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.
+ */
+
+ CHKmalloc(pArr = calloc(pTpl->tpenElements + 1, sizeof(uchar*)));
+ iArr = 0;
+
+ pTpe = pTpl->pEntryRoot;
+ while(pTpe != NULL) {
+ 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, &bMustBeFreed);
+ if(bMustBeFreed) { /* if it must be freed, it is our own private copy... */
+ pArr[iArr] = pVal; /* ... so we can use it! */
+ } else {
+ CHKmalloc(pArr[iArr] = (uchar*)strdup((char*) pVal));
+ }
+ }
+ iArr++;
+ pTpe = pTpe->pNext;
+ }
+
+finalize_it:
+ *ppArr = (iRet == RS_RET_OK) ? pArr : NULL;
+
+ RETiRet;
+}
+
+
/* Helper to doSQLEscape. This is called if doSQLEscape
* runs out of memory allocating the escaped string.
* Then we are in trouble. We can
diff --git a/template.h b/template.h
index 6ca8dc6c..9d794f66 100644
--- a/template.h
+++ b/template.h
@@ -126,6 +126,7 @@ void tplLastStaticInit(struct template *tpl);
* BEFORE msg.h, even if your code file does not actually need it.
* rgerhards, 2007-08-06
*/
+rsRetVal tplToArray(struct template *pTpl, msg_t *pMsg, uchar*** ppArr);
rsRetVal tplToString(struct template *pTpl, msg_t *pMsg, uchar** ppSz);
rsRetVal doSQLEscape(uchar **pp, size_t *pLen, unsigned short *pbMustBeFreed, int escapeMode);