diff options
author | Rainer Gerhards <rgerhards@adiscon.com> | 2011-05-03 18:02:18 +0200 |
---|---|---|
committer | Rainer Gerhards <rgerhards@adiscon.com> | 2011-05-03 18:02:18 +0200 |
commit | d0d9f823b79c5649dad18cb1d8d7744796ae0907 (patch) | |
tree | 52c7fe67ad47f6395a2974cdeda22736904f2c0c /runtime | |
parent | 3ad873e17adf89de8437aa5638b412e9fc730acf (diff) | |
download | rsyslog-d0d9f823b79c5649dad18cb1d8d7744796ae0907.tar.gz rsyslog-d0d9f823b79c5649dad18cb1d8d7744796ae0907.tar.bz2 rsyslog-d0d9f823b79c5649dad18cb1d8d7744796ae0907.zip |
step: put plumbing in place for new input module config system
Diffstat (limited to 'runtime')
-rw-r--r-- | runtime/conf.c | 34 | ||||
-rw-r--r-- | runtime/module-template.h | 114 | ||||
-rw-r--r-- | runtime/modules.c | 40 | ||||
-rw-r--r-- | runtime/modules.h | 16 | ||||
-rw-r--r-- | runtime/rsconf.c | 104 | ||||
-rw-r--r-- | runtime/rsconf.h | 3 |
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 { |