summaryrefslogtreecommitdiffstats
path: root/runtime
diff options
context:
space:
mode:
authorRainer Gerhards <rgerhards@adiscon.com>2011-05-03 18:02:18 +0200
committerRainer Gerhards <rgerhards@adiscon.com>2011-05-03 18:02:18 +0200
commitd0d9f823b79c5649dad18cb1d8d7744796ae0907 (patch)
tree52c7fe67ad47f6395a2974cdeda22736904f2c0c /runtime
parent3ad873e17adf89de8437aa5638b412e9fc730acf (diff)
downloadrsyslog-d0d9f823b79c5649dad18cb1d8d7744796ae0907.tar.gz
rsyslog-d0d9f823b79c5649dad18cb1d8d7744796ae0907.tar.xz
rsyslog-d0d9f823b79c5649dad18cb1d8d7744796ae0907.zip
step: put plumbing in place for new input module config system
Diffstat (limited to 'runtime')
-rw-r--r--runtime/conf.c34
-rw-r--r--runtime/module-template.h114
-rw-r--r--runtime/modules.c40
-rw-r--r--runtime/modules.h16
-rw-r--r--runtime/rsconf.c104
-rw-r--r--runtime/rsconf.h3
6 files changed, 258 insertions, 53 deletions
diff --git a/runtime/conf.c b/runtime/conf.c
index ea7102a6..6a2e57fa 100644
--- a/runtime/conf.c
+++ b/runtime/conf.c
@@ -1095,24 +1095,26 @@ finalize_it:
*/
static rsRetVal cflineDoAction(rsconf_t *conf, uchar **p, action_t **ppAction)
{
- DEFiRet;
modInfo_t *pMod;
+ cfgmodules_etry_t *node;
omodStringRequest_t *pOMSR;
action_t *pAction = NULL;
void *pModData;
+ DEFiRet;
ASSERT(p != NULL);
ASSERT(ppAction != NULL);
/* loop through all modules and see if one picks up the line */
- pMod = module.GetNxtCnfType(conf, NULL, eMOD_OUT);
- /* Note: clang static analyzer reports that pMod mybe == NULL. However, this is
+ node = module.GetNxtCnfType(conf, NULL, eMOD_OUT);
+ /* Note: clang static analyzer reports that node maybe == NULL. However, this is
* not possible, because we have the built-in output modules which are always
* present. Anyhow, we guard this by an assert. -- rgerhards, 2010-12-16
*/
- assert(pMod != NULL);
- while(pMod != NULL) {
+ assert(node != NULL);
+ while(node != NULL) {
pOMSR = NULL;
+ pMod = node->pMod;
iRet = pMod->mod.om.parseSelectorAct(p, &pModData, &pOMSR);
dbgprintf("tried selector action for %s: %d\n", module.GetName(pMod), iRet);
if(iRet == RS_RET_OK || iRet == RS_RET_SUSPENDED) {
@@ -1144,7 +1146,7 @@ static rsRetVal cflineDoAction(rsconf_t *conf, uchar **p, action_t **ppAction)
dbgprintf("error %d parsing config line\n", (int) iRet);
break;
}
- pMod = module.GetNxtCnfType(conf, pMod, eMOD_OUT);
+ node = module.GetNxtCnfType(conf, node, eMOD_OUT);
}
*ppAction = pAction;
@@ -1279,17 +1281,17 @@ static inline rsRetVal
setActionScope(void)
{
DEFiRet;
- modInfo_t *pMod;
+ cfgmodules_etry_t *node;
currConfObj = eConfObjAction;
DBGPRINTF("entering action scope\n");
CHKiRet(actionNewScope());
/* now tell each action to start the scope */
- pMod = NULL;
- while((pMod = module.GetNxtCnfType(loadConf, pMod, eMOD_OUT)) != NULL) {
- DBGPRINTF("beginning scope on module %s\n", pMod->pszName);
- pMod->mod.om.newScope();
+ node = NULL;
+ while((node = module.GetNxtCnfType(loadConf, node, eMOD_OUT)) != NULL) {
+ DBGPRINTF("beginning scope on module %s\n", node->pMod->pszName);
+ node->pMod->mod.om.newScope();
}
finalize_it:
@@ -1304,17 +1306,17 @@ static inline rsRetVal
unsetActionScope(void)
{
DEFiRet;
- modInfo_t *pMod;
+ cfgmodules_etry_t *node;
currConfObj = eConfObjAction;
DBGPRINTF("exiting action scope\n");
CHKiRet(actionRestoreScope());
/* now tell each action to restore the scope */
- pMod = NULL;
- while((pMod = module.GetNxtCnfType(loadConf, pMod, eMOD_OUT)) != NULL) {
- DBGPRINTF("exiting scope on module %s\n", pMod->pszName);
- pMod->mod.om.restoreScope();
+ node = NULL;
+ while((node = module.GetNxtCnfType(loadConf, node, eMOD_OUT)) != NULL) {
+ DBGPRINTF("exiting scope on module %s\n", node->pMod->pszName);
+ node->pMod->mod.om.restoreScope();
}
finalize_it:
diff --git a/runtime/module-template.h b/runtime/module-template.h
index 2b0ed593..1ec1d8d2 100644
--- a/runtime/module-template.h
+++ b/runtime/module-template.h
@@ -459,6 +459,16 @@ static rsRetVal queryEtryPt(uchar *name, rsRetVal (**pEtryPoint)())\
*pEtryPoint = willRun;\
} else if(!strcmp((char*) name, "afterRun")) {\
*pEtryPoint = afterRun;\
+ } else if(!strcmp((char*) name, "beginCnfLoad")) {\
+ *pEtryPoint = beginCnfLoad;\
+ } else if(!strcmp((char*) name, "endCnfLoad")) {\
+ *pEtryPoint = endCnfLoad;\
+ } else if(!strcmp((char*) name, "checkCnf")) {\
+ *pEtryPoint = checkCnf;\
+ } else if(!strcmp((char*) name, "activateCnf")) {\
+ *pEtryPoint = activateCnf;\
+ } else if(!strcmp((char*) name, "freeCnf")) {\
+ *pEtryPoint = freeCnf;\
}
/* the following definition is the standard block for queryEtryPt for LIBRARY
@@ -600,6 +610,110 @@ static rsRetVal modExit(void)\
}
+/* beginCnfLoad()
+ * This is a function tells an input module that a new config load begins.
+ * The core passes in a handle to the new module-specific module conf to
+ * the module. -- rgerards, 2011-05-03
+ */
+#define BEGINbeginCnfLoad \
+static rsRetVal beginCnfLoad(modConfData_t **ptr)\
+{\
+ modConfData_t *pModConf; \
+ DEFiRet;
+
+#define CODESTARTbeginCnfLoad \
+ if((pModConf = calloc(1, sizeof(modConfData_t))) == NULL) {\
+ *ptr = NULL;\
+ ENDfunc \
+ return RS_RET_OUT_OF_MEMORY;\
+ }
+
+#define ENDbeginCnfLoad \
+ *ptr = pModConf;\
+ RETiRet;\
+}
+
+
+/* endCnfLoad()
+ * This is a function tells an input module that the current config load ended.
+ * It gets a last chance to make changes to its in-memory config object. After
+ * this call, the config object must no longer be changed.
+ * The pModConf pointer passed into the module must no longer be used.
+ * rgerards, 2011-05-03
+ */
+#define BEGINendCnfLoad \
+static rsRetVal endCnfLoad(modConfData_t *ptr)\
+{\
+ modConfData_t *pModConf = (modConfData_t*) ptr; \
+ DEFiRet;
+
+#define CODESTARTendCnfLoad
+
+#define ENDendCnfLoad \
+ RETiRet;\
+}
+
+
+/* checkCnf()
+ * Check the provided config object for errors, inconsistencies and other things
+ * that do not work out.
+ * NOTE: no part of the config must be activated, so some checks that require
+ * activation can not be done in this entry point. They must be done in the
+ * activateConf() stage, where the caller must also be prepared for error
+ * returns.
+ * rgerhards, 2011-05-03
+ */
+#define BEGINcheckCnf \
+static rsRetVal checkCnf(modConfData_t *ptr)\
+{\
+ modConfData_t *pModConf = (modConfData_t*) ptr; \
+ DEFiRet;
+
+#define CODESTARTcheckCnf
+
+#define ENDcheckCnf \
+ RETiRet;\
+}
+
+
+/* activateCnf()
+ * This activates the provided config, and may report errors if they are detected
+ * during activation.
+ * rgerhards, 2011-05-03
+ */
+#define BEGINactivateCnf \
+static rsRetVal activateCnf(modConfData_t *ptr)\
+{\
+ modConfData_t *pModConf = (modConfData_t*) ptr; \
+ DEFiRet;
+
+#define CODESTARTactivateCnf
+
+#define ENDactivateCnf \
+ RETiRet;\
+}
+
+
+/* freeCnf()
+ * This is a function tells an input module that it must free all data
+ * associated with the passed-in module config.
+ * rgerhards, 2011-05-03
+ */
+#define BEGINfreeCnf \
+static rsRetVal freeCnf(void *ptr)\
+{\
+ modConfData_t *pModConf = (modConfData_t*) ptr; \
+ DEFiRet;
+
+#define CODESTARTfreeCnf
+
+#define ENDfreeCnf \
+ if(pModConf != NULL)\
+ free(pModConf); /* we need to free this in any case */\
+ RETiRet;\
+}
+
+
/* runInput()
* This is the main function for input modules. It is used to gather data from the
* input source and submit it to the message queue. Each runInput() instance has its own
diff --git a/runtime/modules.c b/runtime/modules.c
index 69c89790..67f16e65 100644
--- a/runtime/modules.c
+++ b/runtime/modules.c
@@ -362,12 +362,19 @@ addModToCnfList(modInfo_t *pThis)
}
}
- /* if we reach this point, pLast is the tail pointer */
+ /* if we reach this point, pLast is the tail pointer and this module is new
+ * inside the currently loaded config. So, iff it is an input module, let's
+ * pass it a pointer which it can populate with a pointer to its module conf.
+ */
CHKmalloc(pNew = MALLOC(sizeof(cfgmodules_etry_t)));
pNew->next = NULL;
pNew->pMod = pThis;
+ if(pThis->eType == eMOD_IN) {
+ CHKiRet(pThis->mod.im.beginCnfLoad(&pNew->modCnf));
+ }
+
if(pLast == NULL) {
loadConf->modules.root = pNew;
} else {
@@ -401,31 +408,27 @@ static modInfo_t *GetNxt(modInfo_t *pThis)
/* this function is like GetNxt(), but it returns pointers to
+ * the configmodules entry, which than can be used to obtain the
+ * actual module pointer. Note that it returns those for
* modules of specific type only. Only modules from the provided
* config are returned. Note that processing speed could be improved,
* but this is really not relevant, as config file loading is not really
* something we are concerned about in regard to runtime.
*/
-static modInfo_t *GetNxtCnfType(rsconf_t *cnf, modInfo_t *pThis, eModType_t rqtdType)
+static cfgmodules_etry_t
+*GetNxtCnfType(rsconf_t *cnf, cfgmodules_etry_t *node, eModType_t rqtdType)
{
- cfgmodules_etry_t *node;
-
- if(pThis == NULL) { /* start at beginning of module list */
+ if(node == NULL) { /* start at beginning of module list */
node = cnf->modules.root;
- } else { /* start at last location - then we need to find the module in the config list */
- for(node = cnf->modules.root ; node != NULL && node->pMod != pThis ; node = node->next)
- /*search only, all done in for() */;
- if(node != NULL)
- node = node->next; /* skip to NEXT element in list */
+ } else {
+ node = node->next;
}
-dbgprintf("XXXX: entering node, ptr %p: %s\n", node, (node == NULL)? "":modGetName(node->pMod));
while(node != NULL && node->pMod->eType != rqtdType) {
node = node->next; /* warning: do ... while() */
-dbgprintf("XXXX: in loop, ptr %p: %s\n", node, (node == NULL)? "":modGetName(node->pMod));
}
- return (node == NULL) ? NULL : node->pMod;
+ return node;
}
@@ -518,6 +521,11 @@ doModInit(rsRetVal (*modInit)(int, int*, rsRetVal(**)(), rsRetVal(*)(), modInfo_
/* ... and now the module-specific interfaces */
switch(pNew->eType) {
case eMOD_IN:
+ CHKiRet((*pNew->modQueryEtryPt)((uchar*)"beginCnfLoad", &pNew->mod.im.beginCnfLoad));
+ CHKiRet((*pNew->modQueryEtryPt)((uchar*)"endCnfLoad", &pNew->mod.im.endCnfLoad));
+ CHKiRet((*pNew->modQueryEtryPt)((uchar*)"freeCnf", &pNew->mod.im.freeCnf));
+ CHKiRet((*pNew->modQueryEtryPt)((uchar*)"checkCnf", &pNew->mod.im.checkCnf));
+ CHKiRet((*pNew->modQueryEtryPt)((uchar*)"activateCnf", &pNew->mod.im.activateCnf));
CHKiRet((*pNew->modQueryEtryPt)((uchar*)"runInput", &pNew->mod.im.runInput));
CHKiRet((*pNew->modQueryEtryPt)((uchar*)"willRun", &pNew->mod.im.willRun));
CHKiRet((*pNew->modQueryEtryPt)((uchar*)"afterRun", &pNew->mod.im.afterRun));
@@ -697,6 +705,9 @@ static void modPrintList(void)
break;
case eMOD_IN:
dbgprintf("Input Module Entry Points\n");
+ dbgprintf("\tbeginCnfLoad: 0x%lx\n", (unsigned long) pMod->mod.im.beginCnfLoad);
+ dbgprintf("\tendCnfLoad: 0x%lx\n", (unsigned long) pMod->mod.im.endCnfLoad);
+ dbgprintf("\tfreeCnf: 0x%lx\n", (unsigned long) pMod->mod.im.freeCnf);
dbgprintf("\trunInput: 0x%lx\n", (unsigned long) pMod->mod.im.runInput);
dbgprintf("\twillRun: 0x%lx\n", (unsigned long) pMod->mod.im.willRun);
dbgprintf("\tafterRun: 0x%lx\n", (unsigned long) pMod->mod.im.afterRun);
@@ -928,7 +939,8 @@ Load(uchar *pModName, sbool bConfLoad)
szPath[iPathLen++] = '/';
szPath[iPathLen] = '\0';
} else {
- errmsg.LogError(0, RS_RET_MODULE_LOAD_ERR_PATHLEN, "could not load module '%s', path too long\n", pModName);
+ errmsg.LogError(0, RS_RET_MODULE_LOAD_ERR_PATHLEN,
+ "could not load module '%s', path too long\n", pModName);
ABORT_FINALIZE(RS_RET_MODULE_LOAD_ERR_PATHLEN);
}
}
diff --git a/runtime/modules.h b/runtime/modules.h
index 37a73ecd..759e3350 100644
--- a/runtime/modules.h
+++ b/runtime/modules.h
@@ -110,19 +110,19 @@ struct modInfo_s {
rsRetVal (*modExit)(void); /* called before termination or module unload */
rsRetVal (*modGetID)(void **); /* get its unique ID from module */
rsRetVal (*doHUP)(void *); /* non-restart type HUP handler */
- /* below: parse a configuration line - return if processed
- * or not. If not, must be parsed to next module.
- */
- rsRetVal (*parseConfigLine)(uchar **pConfLine);
/* below: create an instance of this module. Most importantly the module
* can allocate instance memory in this call.
*/
rsRetVal (*createInstance)();
- /* TODO: pass pointer to msg submit function to IM rger, 2007-12-14 */
union {
struct {/* data for input modules */
+ rsRetVal (*beginCnfLoad)(void*newCnf);
+ rsRetVal (*endCnfLoad)(void*Cnf);
+ rsRetVal (*checkCnf)(void*Cnf);
+ rsRetVal (*activateCnf)(void*Cnf); /* make provided config the running conf */
+ rsRetVal (*freeCnf)(void*Cnf);
+/* TODO: remove? */rsRetVal (*willRun)(void); /* check if the current config will be able to run*/
rsRetVal (*runInput)(thrdInfo_t*); /* function to gather input and submit to queue */
- rsRetVal (*willRun)(void); /* function to gather input and submit to queue */
rsRetVal (*afterRun)(thrdInfo_t*); /* function to gather input and submit to queue */
int bCanRun; /* cached value of whether willRun() succeeded */
} im;
@@ -159,7 +159,7 @@ struct modInfo_s {
/* interfaces */
BEGINinterface(module) /* name must also be changed in ENDinterface macro! */
modInfo_t *(*GetNxt)(modInfo_t *pThis);
- modInfo_t *(*GetNxtCnfType)(rsconf_t *cnf, modInfo_t *pThis, eModType_t rqtdType);
+ cfgmodules_etry_t *(*GetNxtCnfType)(rsconf_t *cnf, cfgmodules_etry_t *pThis, eModType_t rqtdType);
uchar *(*GetName)(modInfo_t *pThis);
uchar *(*GetStateName)(modInfo_t *pThis);
rsRetVal (*Use)(char *srcFile, modInfo_t *pThis); /**< must be called before a module is used (ref counting) */
@@ -180,4 +180,6 @@ ENDinterface(module)
/* prototypes */
PROTOTYPEObj(module);
+/* TODO: remove "dirty" calls! */
+rsRetVal addModToCnfList(modInfo_t *pThis);
#endif /* #ifndef MODULES_H_INCLUDED */
diff --git a/runtime/rsconf.c b/runtime/rsconf.c
index 11eea2b7..1e427d42 100644
--- a/runtime/rsconf.c
+++ b/runtime/rsconf.c
@@ -294,25 +294,94 @@ dropPrivileges(rsconf_t *cnf)
}
+/* Tell input modules that the config parsing stage is over. */
+static rsRetVal
+tellInputsConfigLoadDone(void)
+{
+ cfgmodules_etry_t *node;
+
+ BEGINfunc
+ DBGPRINTF("telling inputs that config load for %p is done\n", loadConf);
+ node = module.GetNxtCnfType(loadConf, NULL, eMOD_IN);
+ while(node != NULL) {
+ node->pMod->mod.im.endCnfLoad(node->modCnf);
+ node = module.GetNxtCnfType(runConf, node, eMOD_IN);
+ }
+
+ ENDfunc
+ return RS_RET_OK; /* intentional: we do not care about module errors */
+}
+
+
+/* Tell input modules to verify config object */
+static rsRetVal
+tellInputsCheckConfig(void)
+{
+ cfgmodules_etry_t *node;
+ rsRetVal localRet;
+
+ BEGINfunc
+ DBGPRINTF("telling inputs to check config %p\n", loadConf);
+ node = module.GetNxtCnfType(loadConf, NULL, eMOD_IN);
+ while(node != NULL) {
+ localRet = node->pMod->mod.im.checkCnf(node->modCnf);
+ DBGPRINTF("module %s tells us config can %sbe activated\n",
+ node->pMod->pszName, (localRet == RS_RET_OK) ? "" : "NOT ");
+ if(localRet == RS_RET_OK) {
+ node->canActivate = 1;
+ } else {
+ node->canActivate = 0;
+ }
+ node = module.GetNxtCnfType(runConf, node, eMOD_IN);
+ }
+
+ ENDfunc
+ return RS_RET_OK; /* intentional: we do not care about module errors */
+}
+
+
+/* Tell input modules to activate current running config */
+static rsRetVal
+tellInputsActivateConfig(void)
+{
+ cfgmodules_etry_t *node;
+
+ BEGINfunc
+ DBGPRINTF("telling inputs to activate config %p\n", runConf);
+ node = module.GetNxtCnfType(runConf, NULL, eMOD_IN);
+ while(node != NULL) {
+ if(node->canActivate) {
+ DBGPRINTF("activating config %p for module %s\n",
+ runConf, node->pMod->pszName);
+ node->pMod->mod.im.activateCnf(node->modCnf);
+ }
+ node = module.GetNxtCnfType(runConf, node, eMOD_IN);
+ }
+
+ ENDfunc
+ return RS_RET_OK; /* intentional: we do not care about module errors */
+}
+
+
/* Actually run the input modules. This happens after privileges are dropped,
* if that is requested.
*/
static rsRetVal
runInputModules(void)
{
- modInfo_t *pMod;
+ cfgmodules_etry_t *node;
int bNeedsCancel;
BEGINfunc
- pMod = module.GetNxtCnfType(runConf, NULL, eMOD_IN);
- while(pMod != NULL) {
- if(pMod->mod.im.bCanRun) {
+ node = module.GetNxtCnfType(runConf, NULL, eMOD_IN);
+ while(node != NULL) {
+ if(node->pMod->mod.im.bCanRun) {
/* activate here */
- bNeedsCancel = (pMod->isCompatibleWithFeature(sFEATURENonCancelInputTermination) == RS_RET_OK) ?
+ bNeedsCancel = (node->pMod->isCompatibleWithFeature(sFEATURENonCancelInputTermination) == RS_RET_OK) ?
0 : 1;
- thrdCreate(pMod->mod.im.runInput, pMod->mod.im.afterRun, bNeedsCancel);
+ thrdCreate(node->pMod->mod.im.runInput, node->pMod->mod.im.afterRun, bNeedsCancel);
}
- pMod = module.GetNxtCnfType(runConf, pMod, eMOD_IN);
+ node = module.GetNxtCnfType(runConf, node, eMOD_IN);
}
ENDfunc
@@ -326,16 +395,16 @@ static rsRetVal
startInputModules(void)
{
DEFiRet;
- modInfo_t *pMod;
-
- pMod = module.GetNxtCnfType(runConf, NULL, eMOD_IN);
- while(pMod != NULL) {
- iRet = pMod->mod.im.willRun();
- pMod->mod.im.bCanRun = (iRet == RS_RET_OK);
- if(!pMod->mod.im.bCanRun) {
- DBGPRINTF("module %lx will not run, iRet %d\n", (unsigned long) pMod, iRet);
+ cfgmodules_etry_t *node;
+
+ node = module.GetNxtCnfType(runConf, NULL, eMOD_IN);
+ while(node != NULL) {
+ iRet = node->pMod->mod.im.willRun();
+ node->pMod->mod.im.bCanRun = (iRet == RS_RET_OK);
+ if(!node->pMod->mod.im.bCanRun) {
+ DBGPRINTF("module %lx will not run, iRet %d\n", (unsigned long) node->pMod, iRet);
}
- pMod = module.GetNxtCnfType(runConf, pMod, eMOD_IN);
+ node = module.GetNxtCnfType(runConf, node, eMOD_IN);
}
ENDfunc
@@ -381,6 +450,8 @@ activate(rsconf_t *cnf)
if(ourConf->globals.pszConfDAGFile != NULL)
generateConfigDAG(ourConf->globals.pszConfDAGFile);
# endif
+ tellInputsConfigLoadDone();
+ tellInputsCheckConfig();
/* the output part and the queue is now ready to run. So it is a good time
* to initialize the inputs. Please note that the net code above should be
@@ -390,6 +461,7 @@ activate(rsconf_t *cnf)
* Keep in mind. though, that the outputs already run if the queue was
* persisted to disk. -- rgerhards
*/
+ tellInputsActivateConfig();
startInputModules();
CHKiRet(dropPrivileges(cnf));
diff --git a/runtime/rsconf.h b/runtime/rsconf.h
index 63754e6f..0718566a 100644
--- a/runtime/rsconf.h
+++ b/runtime/rsconf.h
@@ -96,6 +96,9 @@ struct defaults_s {
struct cfgmodules_etry_s {
cfgmodules_etry_t *next;
modInfo_t *pMod;
+ /* the following data is input module specific */
+ void *modCnf; /* pointer to the input module conf */
+ sbool canActivate; /* OK to activate this config? */
};
struct cfgmodules_s {