diff options
author | Rainer Gerhards <rgerhards@adiscon.com> | 2008-02-21 11:03:34 +0000 |
---|---|---|
committer | Rainer Gerhards <rgerhards@adiscon.com> | 2008-02-21 11:03:34 +0000 |
commit | 1cc790fae01e4392d4cf96820f6402528f611c44 (patch) | |
tree | 8d1c66f712cd53cf1b8a847dab97556c7c456a2d | |
parent | 3e22b60c70d04d5bce245103de7d2aafc43d3f05 (diff) | |
download | rsyslog-1cc790fae01e4392d4cf96820f6402528f611c44.tar.gz rsyslog-1cc790fae01e4392d4cf96820f6402528f611c44.tar.xz rsyslog-1cc790fae01e4392d4cf96820f6402528f611c44.zip |
first steps in implementing object interfaces (stage work for later dynamic
class loading)
-rw-r--r-- | obj-types.h | 59 | ||||
-rw-r--r-- | rsyslog.h | 1 | ||||
-rw-r--r-- | vmop.c | 37 | ||||
-rw-r--r-- | vmop.h | 24 | ||||
-rw-r--r-- | vmprg.c | 20 |
5 files changed, 123 insertions, 18 deletions
diff --git a/obj-types.h b/obj-types.h index 6fce1f8f..d823af47 100644 --- a/obj-types.h +++ b/obj-types.h @@ -237,6 +237,7 @@ finalize_it: \ * rgerhards, 2008-02-20 */ #define PROTOTYPEObjDebugPrint(obj) rsRetVal obj##DebugPrint(obj##_t *pThis) +#define INTERFACEObjDebugPrint(obj) rsRetVal (*DebugPrint)(obj##_t *pThis) #define BEGINobjDebugPrint(obj) \ rsRetVal obj##DebugPrint(obj##_t *pThis) \ { \ @@ -250,6 +251,64 @@ finalize_it: \ RETiRet; \ } +/* ------------------------------ object loader system ------------------------------ * + * The following code is the early beginning of a dynamic object loader system. The + * root idea is that all objects will become dynamically loadable libraries over time, + * which is necessary to get a clean plug-in interface where every plugin can access + * rsyslog's rich object model via simple and quite portable methods. + * + * To do so, each object defines one or more interfaces. They are essentially structures + * with function (method) pointers. Anyone interested in calling an object must first + * obtain the interface and can then call through it. + * + * The interface data type must always be called <obj>_if_t, as this is expected + * by the macros. Having consitent naming is also easier for the programmer. By default, + * macros create a static variable named like the object in each calling objects + * static data block. + * + * To facilitate moving to this system, I begin to implement some hooks, which + * allows to use interfaces today (when the rest of the infrastructure is not yet + * there). This is in the hope that it will ease migration to the full-fledged system + * once we are ready to work on that. + * rgerhards, 2008-02-21 + */ + +/* this defines the QueryInterface print entry point. Over time, it should be + * present in all objects. + */ +#define PROTOTYPEObjQueryInterface(obj) rsRetVal obj##QueryInterface(obj##_if_t *pThis) +#define BEGINobjQueryInterface(obj) \ + rsRetVal obj##QueryInterface(obj##_if_t *pIf) \ + { \ + DEFiRet; \ + +#define CODESTARTobjQueryInterface(obj) \ + ASSERT(pIf != NULL); + +#define ENDobjQueryInterface(obj) \ + RETiRet; \ + } +/* the base data type for interfaces + * This MUST be in sync with the ifBEGIN macro + */ +typedef struct interface_s { + int ifVersion; /* must be set to version requested */ + objID_t oID; /* our object ID (later dynamically assigned) */ +} interface_t; + +/* defines data that must always be present at the very begin of the interface structure */ +#define ifBEGIN \ + int ifVersion; /* must be set to version requested */ \ + objID_t oID; /* our object ID (later dynamically assigned) */ + + +/* use the following define some place in your static data (suggested right at + * the beginning + */ +#define DEFobjCurrIf(obj) \ + obj##_if_t obj = { .ifVersion = obj##CURR_IF_VERSION }; + +/* ------------------------------ end object loader system ------------------------------ */ #endif /* #ifndef OBJ_TYPES_H_INCLUDED */ @@ -127,6 +127,7 @@ enum rsRetVal_ /** return value. All methods return this if not specified oth RS_RET_SYNTAX_ERROR = -2051, /**< syntax error, eg. during parsing */ RS_RET_INVALID_OCTAL_DIGIT = -2052, /**< invalid octal digit during parsing */ RS_RET_INVALID_HEX_DIGIT = -2053, /**< invalid hex digit during parsing */ + RS_RET_INTERFACE_NOT_SUPPORTED = -2054, /**< interface not supported */ RS_RET_OK_DELETE_LISTENTRY = 1, /**< operation successful, but callee requested the deletion of an entry (special state) */ RS_RET_TERMINATE_NOW = 2, /**< operation successful, function is requested to terminate (mostly used with threads) */ RS_RET_NO_RUN = 3, /**< operation successful, but function does not like to be executed */ @@ -35,6 +35,9 @@ DEFobjStaticHelpers +/* forward definitions */ +static rsRetVal vmopOpcode2Str(vmop_t *pThis, uchar **ppName); + /* Standard-Constructor */ BEGINobjConstruct(vmop) /* be sure to specify the object type also in END macro! */ @@ -73,7 +76,7 @@ ENDobjDebugPrint(vmop) /* set operand (variant case) * rgerhards, 2008-02-20 */ -rsRetVal +static rsRetVal vmopSetVar(vmop_t *pThis, var_t *pVar) { DEFiRet; @@ -87,7 +90,7 @@ vmopSetVar(vmop_t *pThis, var_t *pVar) /* set operation * rgerhards, 2008-02-20 */ -rsRetVal +static rsRetVal vmopSetOpcode(vmop_t *pThis, opcode_t opcode) { DEFiRet; @@ -99,7 +102,7 @@ vmopSetOpcode(vmop_t *pThis, opcode_t opcode) /* a way to turn an opcode into a readable string */ -rsRetVal +static rsRetVal vmopOpcode2Str(vmop_t *pThis, uchar **ppName) { DEFiRet; @@ -175,6 +178,34 @@ vmopOpcode2Str(vmop_t *pThis, uchar **ppName) } +/* queryInterface function + * rgerhards, 2008-02-21 + */ +BEGINobjQueryInterface(vmop) +CODESTARTobjQueryInterface(vmop) + if(pIf->ifVersion != vmopCURR_IF_VERSION) { /* check for current version, increment on each change */ + ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED); + } + + /* ok, we have the right interface, so let's fill it + * Please note that we may also do some backwards-compatibility + * work here (if we can support an older interface version - that, + * of course, also affects the "if" above). + */ + pIf->oID = OBJvmop; + + pIf->Construct = vmopConstruct; + pIf->ConstructFinalize = vmopConstructFinalize; + pIf->Destruct = vmopDestruct; + pIf->DebugPrint = vmopDebugPrint; + pIf->SetOpcode = vmopSetOpcode; + pIf->SetVar = vmopSetVar; + pIf->Opcode2Str = vmopOpcode2Str; +finalize_it: +ENDobjQueryInterface(vmop) + + + /* Initialize the vmop class. Must be called as the very first method * before anything else is called inside this class. * rgerhards, 2008-02-19 @@ -66,14 +66,22 @@ typedef struct vmop_s { } vmop_t; -/* prototypes */ -rsRetVal vmopConstruct(vmop_t **ppThis); -rsRetVal vmopConstructFinalize(vmop_t __attribute__((unused)) *pThis); -rsRetVal vmopDestruct(vmop_t **ppThis); -rsRetVal vmopSetOpcode(vmop_t *pThis, opcode_t opcode); -rsRetVal vmopSetVar(vmop_t *pThis, var_t *pVar); -rsRetVal vmopOpcode2Str(vmop_t *pThis, uchar **ppName); +/* interfaces */ +typedef struct vmop_if_s { + ifBEGIN; /* This MUST always be the first interface member */ + INTERFACEObjDebugPrint(vmop); + rsRetVal (*Construct)(vmop_t **ppThis); + rsRetVal (*ConstructFinalize)(vmop_t __attribute__((unused)) *pThis); + rsRetVal (*Destruct)(vmop_t **ppThis); + rsRetVal (*SetOpcode)(vmop_t *pThis, opcode_t opcode); + rsRetVal (*SetVar)(vmop_t *pThis, var_t *pVar); + rsRetVal (*Opcode2Str)(vmop_t *pThis, uchar **ppName); +} vmop_if_t; + +#define vmopCURR_IF_VERSION 1 /* increment whenever you change the interface structure! */ + +/* the remaining prototypes */ PROTOTYPEObjClassInit(vmop); -PROTOTYPEObjDebugPrint(vmop); +PROTOTYPEObjQueryInterface(vmop); #endif /* #ifndef INCLUDED_VMOP_H */ @@ -32,6 +32,7 @@ /* static data */ DEFobjStaticHelpers +DEFobjCurrIf(vmop) /* Standard-Constructor @@ -60,7 +61,7 @@ CODESTARTobjDestruct(vmprg) for(pOp = pThis->vmopRoot ; pOp != NULL ; ) { pTmp = pOp; pOp = pOp->pNext; - vmopDestruct(&pTmp); + vmop.Destruct(&pTmp); } ENDobjDestruct(vmprg) @@ -71,7 +72,7 @@ BEGINobjDebugPrint(vmprg) /* be sure to specify the object type also in END and CODESTARTobjDebugPrint(vmprg) dbgoprint((obj_t*) pThis, "program contents:\n"); for(pOp = pThis->vmopRoot ; pOp != NULL ; pOp = pOp->pNext) { - vmopDebugPrint(pOp); + vmop.DebugPrint(pOp); } ENDobjDebugPrint(vmprg) @@ -90,12 +91,12 @@ vmprgAddVarOperation(vmprg_t *pThis, opcode_t opcode, var_t *pVar) ISOBJ_TYPE_assert(pThis, vmprg); /* construct and fill vmop */ - CHKiRet(vmopConstruct(&pOp)); - CHKiRet(vmopConstructFinalize(pOp)); - CHKiRet(vmopConstructFinalize(pOp)); - CHKiRet(vmopSetOpcode(pOp, opcode)); + CHKiRet(vmop.Construct(&pOp)); + CHKiRet(vmop.ConstructFinalize(pOp)); + CHKiRet(vmop.ConstructFinalize(pOp)); + CHKiRet(vmop.SetOpcode(pOp, opcode)); if(pVar != NULL) - CHKiRet(vmopSetVar(pOp, pVar)); + CHKiRet(vmop.SetVar(pOp, pVar)); /* and add it to the program */ CHKiRet(vmprgAddOperation(pThis, pOp)); @@ -134,6 +135,11 @@ vmprgAddOperation(vmprg_t *pThis, vmop_t *pOp) * rgerhards, 2008-02-19 */ BEGINObjClassInit(vmprg, 1) /* class, version */ + /* request objects we use */ + //objUse(vmop); + CHKiRet(vmopQueryInterface(&vmop)); + + /* set our own handlers */ OBJSetMethodHandler(objMethod_DEBUGPRINT, vmprgDebugPrint); OBJSetMethodHandler(objMethod_CONSTRUCTION_FINALIZER, vmprgConstructFinalize); ENDObjClassInit(vmprg) |