From 19cad8b12fa34e05f903c1d55c77453be1bab431 Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Tue, 29 Jan 2008 10:23:10 +0000 Subject: implemented naming for all objects (mostly as a debug aid, but you never know what else it will be good for) --- debug.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- debug.h | 4 ++- msg.c | 2 +- obj-types.h | 19 +++++--------- obj.c | 62 ++++++++++++++++++++++++++++++++++++++++++- obj.h | 6 +++-- queue.c | 11 +++----- syslogd.c | 13 +++------ wtp.c | 1 - 9 files changed, 169 insertions(+), 36 deletions(-) diff --git a/debug.c b/debug.c index 4605eec8..82ed2442 100644 --- a/debug.c +++ b/debug.c @@ -48,6 +48,7 @@ #include "rsyslog.h" #include "debug.h" +#include "obj.h" /* forward definitions */ static void dbgGetThrdName(char *pszBuf, size_t lenBuf, pthread_t thrd, int bIncludeNumID); @@ -684,7 +685,91 @@ sigsegvHdlr(int signum) } -/* print some debug output */ +/* print some debug output when an object is given + * This is mostly a copy of dbgprintf, but I do not know how to combine it + * into a single function as we have variable arguments and I don't know how to call + * from one vararg function into another. I don't dig in this, it is OK for the + * time being. -- rgerhards, 2008-01-29 + */ +void +dbgoprint(obj_t *pObj, char *fmt, ...) +{ + static pthread_t ptLastThrdID = 0; + static int bWasNL = 0; + va_list ap; + static char pszThrdName[64]; /* 64 is to be on the safe side, anything over 20 is bad... */ + static char pszWriteBuf[1024]; + size_t lenWriteBuf; + struct timespec t; + + if(!(Debug && debugging_on)) + return; + + pthread_mutex_lock(&mutdbgprintf); + pthread_cleanup_push(dbgMutexCancelCleanupHdlr, &mutdbgprintf); + + /* The bWasNL handler does not really work. It works if no thread + * switching occurs during non-NL messages. Else, things are messed + * up. Anyhow, it works well enough to provide useful help during + * getting this up and running. It is questionable if the extra effort + * is worth fixing it, giving the limited appliability. + * rgerhards, 2005-10-25 + * I have decided that it is not worth fixing it - especially as it works + * pretty well. + * rgerhards, 2007-06-15 + */ + if(ptLastThrdID != pthread_self()) { + if(!bWasNL) { + fprintf(stddbg, "\n"); + if(altdbg != NULL) fprintf(altdbg, "\n"); + bWasNL = 1; + } + ptLastThrdID = pthread_self(); + } + + /* do not cache the thread name, as the caller might have changed it + * TODO: optimized, invalidate cache when new name is set + */ + dbgGetThrdName(pszThrdName, sizeof(pszThrdName), ptLastThrdID, 0); + + if(bWasNL) { + if(bPrintTime) { + clock_gettime(CLOCK_REALTIME, &t); + fprintf(stddbg, "%4.4ld.%9.9ld:", t.tv_sec % 10000, t.tv_nsec); + if(altdbg != NULL) fprintf(altdbg, "%4.4ld.%9.9ld:", t.tv_sec % 10000, t.tv_nsec); + } + fprintf(stddbg, "%s: ", pszThrdName); + if(altdbg != NULL) fprintf(altdbg, "%s: ", pszThrdName); + /* print object name header if we have an object */ + if(pObj != NULL) { + fprintf(stddbg, "%s: ", objGetName(pObj)); + if(altdbg != NULL) fprintf(altdbg, "%s: ", objGetName(pObj)); + } + } + bWasNL = (*(fmt + strlen(fmt) - 1) == '\n') ? 1 : 0; + va_start(ap, fmt); + lenWriteBuf = vsnprintf(pszWriteBuf, sizeof(pszWriteBuf), fmt, ap); + if(lenWriteBuf >= sizeof(pszWriteBuf)) { + /* if our buffer was too small, we simply truncate. TODO: maybe something better? */ + lenWriteBuf--; + } + va_end(ap); + /* + fprintf(stddbg, "%s", pszWriteBuf); + if(altdbg != NULL) fprintf(altdbg, "%s", pszWriteBuf); + */ + fwrite(pszWriteBuf, lenWriteBuf, 1, stddbg); + if(altdbg != NULL) fwrite(pszWriteBuf, lenWriteBuf, 1, altdbg); + + fflush(stddbg); + if(altdbg != NULL) fflush(altdbg); + pthread_cleanup_pop(1); +} + + +/* print some debug output when no object is given + * WARNING: duplicate code, see dbgoprin above! + */ void dbgprintf(char *fmt, ...) { diff --git a/debug.h b/debug.h index 9c28eca1..df8c3138 100644 --- a/debug.h +++ b/debug.h @@ -26,6 +26,7 @@ #define DEBUG_H_INCLUDED #include +#include "obj-types.h" /* external static data elements (some time to be replaced) */ extern int Debug; /* debug flag - read-only after startup */ @@ -84,7 +85,8 @@ typedef struct dbgCallStack_s { rsRetVal dbgClassInit(void); rsRetVal dbgClassExit(void); void sigsegvHdlr(int signum); -void dbgprintf(char *fmt, ...) __attribute__((format(printf,1, 2))); +void dbgoprint(obj_t *pObj, char *fmt, ...) __attribute__((format(printf, 2, 3))); +void dbgprintf(char *fmt, ...) __attribute__((format(printf, 1, 2))); int dbgMutexLock(pthread_mutex_t *pmut, dbgFuncDB_t *pFuncD, int ln, int iStackPtr); int dbgMutexUnlock(pthread_mutex_t *pmut, dbgFuncDB_t *pFuncD, int ln, int iStackPtr); int dbgCondWait(pthread_cond_t *cond, pthread_mutex_t *pmut, dbgFuncDB_t *pFuncD, int ln, int iStackPtr); diff --git a/msg.c b/msg.c index 3bdc1f92..cc81c109 100644 --- a/msg.c +++ b/msg.c @@ -27,7 +27,6 @@ * A copy of the GPL can be found in the file "COPYING" in this distribution. */ #include "config.h" -#include "rsyslog.h" #include #include #include @@ -36,6 +35,7 @@ #include #include #include +#include "rsyslog.h" #include "syslogd.h" #include "srUtils.h" #include "stringbuf.h" diff --git a/obj-types.h b/obj-types.h index 01842a83..bd0da73e 100644 --- a/obj-types.h +++ b/obj-types.h @@ -29,11 +29,7 @@ #define OBJ_TYPES_H_INCLUDED #include "stringbuf.h" - -/* base object data, present in all objects */ -typedef struct objData_s { - uchar *pName; -} objData_t; +#include "syslogd-types.h" /* property types */ typedef enum { /* do NOT start at 0 to detect uninitialized types after calloc() */ @@ -90,23 +86,22 @@ typedef struct objInfo_s { rsRetVal (*objMethods[OBJ_NUM_METHODS])(); } objInfo_t; -/* TODO: move obj_t at front of struct */ + typedef struct obj { /* the dummy struct that each derived class can be casted to */ objInfo_t *pObjInfo; #ifndef NDEBUG /* this means if debug... */ - objData_t objData; unsigned int iObjCooCKiE; /* must always be 0xBADEFEE for a valid object */ #endif + uchar *pszName; /* the name of *this* specific object instance */ } obj_t; + /* macros which must be gloablly-visible (because they are used during definition of * other objects. */ #ifndef NDEBUG /* this means if debug... */ # define BEGINobjInstance \ - objInfo_t *pObjInfo; \ - objData_t objData; \ - unsigned int iObjCooCKiE; /* prevent name conflict, thus the strange name */ + obj_t objData; # define ISOBJ_assert(pObj) \ do { \ ASSERT((pObj) != NULL); \ @@ -115,11 +110,11 @@ typedef struct obj { /* the dummy struct that each derived class can be casted t # define ISOBJ_TYPE_assert(pObj, objType) \ do { \ ASSERT(pObj != NULL); \ - ASSERT((unsigned) pObj->iObjCooCKiE == (unsigned) 0xBADEFEE); \ + ASSERT((unsigned) ((obj_t*) (pObj))->iObjCooCKiE == (unsigned) 0xBADEFEE); \ ASSERT(objGetObjID(pObj) == OBJ##objType); \ } while(0); #else /* non-debug mode, no checks but much faster */ -# define BEGINobjInstance objInfo_t *pObjInfo; objData_t objData; +# define BEGINobjInstance objInfo_t *objData.pObjInfo; objData_t objData; # define ISOBJ_TYPE_assert(pObj, objType) # define ISOBJ_assert(pObj) #endif diff --git a/obj.c b/obj.c index dfd3edd0..1559628b 100644 --- a/obj.c +++ b/obj.c @@ -1,3 +1,5 @@ +// TODO: we need to be called when the derived object is destructed!!!! + /* obj.c * * This file implements a generic object "class". All other classes can @@ -146,7 +148,7 @@ static rsRetVal objSerializeHeader(strm_t *pStrm, obj_t *pObj, uchar *pszRecType * the object back in */ CHKiRet(strmWriteChar(pStrm, ':')); - CHKiRet(strmWrite(pStrm, objGetName(pObj), strlen((char*)objGetName(pObj)))); + CHKiRet(strmWrite(pStrm, objGetClassName(pObj), strlen((char*)objGetClassName(pObj)))); /* record trailer */ CHKiRet(strmWriteChar(pStrm, ':')); CHKiRet(strmWriteChar(pStrm, '\n')); @@ -764,6 +766,64 @@ finalize_it: /* --------------- end object serializiation / deserialization support --------------- */ + +/* set the object (instance) name + * rgerhards, 2008-01-29 + * TODO: change the naming to a rsCStr obj! (faster) + */ +rsRetVal +objSetName(obj_t *pThis, uchar *pszName) +{ + DEFiRet; + + if(pThis->pszName != NULL) + free(pThis->pszName); + + pThis->pszName = (uchar*) strdup((char*) pszName); + + if(pThis->pszName == NULL) + ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); + +finalize_it: + RETiRet; +} + + +/* get the object (instance) name + * Note that we use a non-standard calling convention. Thus function must never + * fail, else we run into real big problems. So it must make sure that at least someting + * is returned. + * rgerhards, 2008-01-30 + */ +uchar * +objGetName(obj_t *pThis) +{ + uchar *ret; + uchar szName[128]; + + BEGINfunc + ISOBJ_assert(pThis); + + if(pThis->pszName == NULL) { + snprintf((char*)szName, sizeof(szName)/sizeof(uchar), "%s %p", objGetClassName(pThis), pThis); + objSetName(pThis, szName); + /* looks strange, but we NEED to re-check because if there was an + * error in objSetName(), the pointer may still be NULL + */ + if(pThis->pszName == NULL) { + ret = objGetClassName(pThis); + } else { + ret = pThis->pszName; + } + } else { + ret = pThis->pszName; + } + + ENDfunc + return ret; +} + + /* register a classe's info pointer, so that we can reference it later, if needed to * (e.g. for de-serialization support). * rgerhards, 2008-01-07 diff --git a/obj.h b/obj.h index 6b965e10..3eb3f194 100644 --- a/obj.h +++ b/obj.h @@ -66,13 +66,13 @@ #define objSerializePTR(strm, propName, propType) \ CHKiRet(objSerializeProp(strm, (uchar*) #propName, PROPTYPE_##propType, (void*) pThis->propName)); #define DEFobjStaticHelpers static objInfo_t *pObjInfoOBJ = NULL; -#define objGetName(pThis) (((obj_t*) (pThis))->pObjInfo->pszName) +#define objGetClassName(pThis) (((obj_t*) (pThis))->pObjInfo->pszName) #define objGetObjID(pThis) (((obj_t*) (pThis))->pObjInfo->objID) #define objGetVersion(pThis) (((obj_t*) (pThis))->pObjInfo->iObjVers) /* the next macro MUST be called in Constructors: */ #ifndef NDEBUG /* this means if debug... */ # define objConstructSetObjInfo(pThis) \ - assert(pThis->pObjInfo == NULL); \ + ASSERT(((obj_t*) (pThis))->pObjInfo == NULL); \ ((obj_t*) (pThis))->pObjInfo = pObjInfoOBJ; \ ((obj_t*) (pThis))->iObjCooCKiE = 0xBADEFEE #else @@ -95,6 +95,8 @@ rsRetVal objEndSerialize(strm_t *pStrm); rsRetVal objRegisterObj(objID_t oID, objInfo_t *pInfo); rsRetVal objDeserialize(void *ppObj, objID_t objTypeExpected, strm_t *pStrm, rsRetVal (*fFixup)(obj_t*,void*), void *pUsr); rsRetVal objDeserializePropBag(obj_t *pObj, strm_t *pStrm); +rsRetVal objSetName(obj_t *pThis, uchar *pszName); +uchar * objGetName(obj_t *pThis); PROTOTYPEObjClassInit(obj); #endif /* #ifndef OBJ_H_INCLUDED */ diff --git a/queue.c b/queue.c index 39c9639e..c617de75 100644 --- a/queue.c +++ b/queue.c @@ -1106,9 +1106,7 @@ rsRetVal queueConstruct(queue_t **ppThis, queueType_t qType, int iWorkerThreads, } finalize_it: -RUNLOG_VAR("%x", pThis->iObjCooCKiE ); OBJCONSTRUCT_CHECK_SUCCESS_AND_CLEANUP -RUNLOG_VAR("%x", pThis->iObjCooCKiE ); RETiRet; } @@ -1422,26 +1420,25 @@ rsRetVal queueStart(queue_t *pThis) /* this is the ConstructionFinalizer */ * influenced by properties which might have been set after queueConstruct () */ if(pThis->pqParent == NULL) { -dbgprintf("Queue %p: no parent, alloc mutex\n", pThis); pThis->mut = (pthread_mutex_t *) malloc (sizeof (pthread_mutex_t)); pthread_mutex_init(pThis->mut, NULL); } else { /* child queue, we need to use parent's mutex */ + dbgoprint((obj_t*) pThis, "I am a child\n"); pThis->mut = pThis->pqParent->mut; -dbgprintf("Queue %p: I am child, use mutex %p\n", pThis, pThis->pqParent->mut); } pthread_mutex_init(&pThis->mutThrdMgmt, NULL); pthread_cond_init (&pThis->condDAReady, NULL); pthread_cond_init (&pThis->notFull, NULL); pthread_cond_init (&pThis->notEmpty, NULL); -dbgprintf("Queue %p: post mutexes, mut %p\n", pThis, pThis->mut); /* call type-specific constructor */ CHKiRet(pThis->qConstruct(pThis)); /* this also sets bIsDA */ - dbgprintf("Queue 0x%lx: type %d, enq-only %d, disk assisted %d, maxFileSz %ld, qsize %d starting\n", queueGetID(pThis), - pThis->qType, pThis->bEnqOnly, pThis->bIsDA, pThis->iMaxFileSize, pThis->iQueueSize); + dbgoprint((obj_t*) pThis, "type %d, enq-only %d, disk assisted %d, maxFileSz %ld, qsize %d, child %d starting\n", + pThis->qType, pThis->bEnqOnly, pThis->bIsDA, pThis->iMaxFileSize, + pThis->iQueueSize, pThis->pqParent == NULL ? 0 : 1); if(pThis->qType == QUEUETYPE_DIRECT) FINALIZE; /* with direct queues, we are already finished... */ diff --git a/syslogd.c b/syslogd.c index a1e89530..574100a5 100644 --- a/syslogd.c +++ b/syslogd.c @@ -1661,16 +1661,6 @@ int shouldProcessThisMessage(selector_t *f, msg_t *pMsg) } -/* cancellation cleanup handler - frees the action mutex - * rgerhards, 2008-01-14 - */ -static void callActionMutClean(void *arg) -{ - assert(arg != NULL); - pthread_mutex_unlock((pthread_mutex_t*) arg); -} - - /* helper to processMsg(), used to call the configured actions. It is * executed from within llExecFunc() of the action list. * rgerhards, 2007-08-02 @@ -3211,6 +3201,9 @@ init(void) fprintf(stderr, "fatal error %d: could not create message queue - rsyslogd can not run!\n", iRet); exit(1); } + /* name our main queue object (it's not fatal if it fails...) */ + objSetName((obj_t*) pMsgQueue, (uchar*) "main queue"); + /* ... set some properties ... */ # define setQPROP(func, directive, data) \ CHKiRet_Hdlr(func(pMsgQueue, data)) { \ diff --git a/wtp.c b/wtp.c index 63507279..69ca353b 100644 --- a/wtp.c +++ b/wtp.c @@ -616,7 +616,6 @@ wtpSetDbgHdr(wtp_t *pThis, uchar *pszMsg, size_t lenMsg) { DEFiRet; -dbgprintf("objID: %d\n", pThis->pObjInfo->objID); ISOBJ_TYPE_assert(pThis, wtp); assert(pszMsg != NULL); -- cgit