diff options
Diffstat (limited to 'tools/omfile.c')
-rw-r--r-- | tools/omfile.c | 317 |
1 files changed, 236 insertions, 81 deletions
diff --git a/tools/omfile.c b/tools/omfile.c index ba9f7f7..39c0173 100644 --- a/tools/omfile.c +++ b/tools/omfile.c @@ -17,7 +17,7 @@ * pipes. These have been moved to ompipe, to reduced the entanglement * between the two different functionalities. -- rgerhards * - * Copyright 2007-2013 Adiscon GmbH. + * Copyright 2007-2014 Adiscon GmbH. * * This file is part of rsyslog. * @@ -71,6 +71,7 @@ #include "statsobj.h" #include "sigprov.h" #include "cryprov.h" +#include "janitor.h" MODULE_TYPE_OUTPUT MODULE_TYPE_NOKEEP @@ -95,7 +96,7 @@ DEFobjCurrIf(statsobj) * That should be sufficient (and even than, there would no really bad effect ;)). * The variable below is the global counter/clock. */ -#if HAVE_ATOMIC_BUILTINS_64BIT +#if HAVE_ATOMIC_BUILTINS64 static uint64 clockFileAccess = 0; #else static unsigned clockFileAccess = 0; @@ -107,7 +108,7 @@ static pthread_mutex_t mutClock; static inline uint64 getClockFileAccess(void) { -#if HAVE_ATOMIC_BUILTINS_64BIT +#if HAVE_ATOMIC_BUILTINS64 return ATOMIC_INC_AND_FETCH_uint64(&clockFileAccess, &mutClock); #else return ATOMIC_INC_AND_FETCH_unsigned(&clockFileAccess, &mutClock); @@ -122,6 +123,7 @@ struct s_dynaFileCacheEntry { strm_t *pStrm; /* our output stream */ void *sigprovFileData; /* opaque data ptr for provider use */ uint64 clkTickAccessed;/* for LRU - based on clockFileAccess */ + short nInactive; /* number of minutes not writen - for close timeout */ }; typedef struct s_dynaFileCacheEntry dynaFileCacheEntry; @@ -133,14 +135,17 @@ typedef struct s_dynaFileCacheEntry dynaFileCacheEntry; typedef struct _instanceData { - uchar *f_fname; /* file or template name (display only) */ + pthread_mutex_t mutWrite; /* guard against multiple instances writing to single file */ + uchar *fname; /* file or template name (display only) */ uchar *tplName; /* name of assigned template */ strm_t *pStrm; /* our output stream */ + short nInactive; /* number of minutes not writen (STATIC files only) */ char bDynamicName; /* 0 - static name, 1 - dynamic name (with properties) */ int fCreateMode; /* file creation mode for open() */ int fDirCreateMode; /* creation mode for mkdir() */ int bCreateDirs; /* auto-create directories? */ int bSyncFile; /* should the file by sync()'ed? 1- yes, 0- no */ + uint8_t iNumTpls; /* number of tpls we use */ uid_t fileUID; /* IDs for creation */ uid_t dirUID; gid_t fileGID; @@ -155,7 +160,6 @@ typedef struct _instanceData { uchar *cryprovName; /* crypto provider */ uchar *cryprovNameFull;/* full internal crypto provider name */ void *cryprovData; /* opaque data ptr for provider use */ - void *cryprovFileData;/* opaque data ptr for file instance */ cryprov_if_t cryprov; /* ptr to crypto provider interface */ sbool useCryprov; /* quicker than checkig ptr (1 vs 8 bytes!) */ int iCurrElt; /* currently active cache element (-1 = none) */ @@ -171,6 +175,7 @@ typedef struct _instanceData { int iZipLevel; /* zip mode to use for this selector */ int iIOBufSize; /* size of associated io buffer */ int iFlushInterval; /* how fast flush buffer on inactivity? */ + short iCloseTimeout; /* after how many *minutes* shall the file be closed if inactive? */ sbool bFlushOnTXEnd; /* flush write buffers when transaction has ended? */ sbool bUseAsyncWriter; /* use async stream writer? */ sbool bVeryRobustZip; @@ -180,9 +185,16 @@ typedef struct _instanceData { STATSCOUNTER_DEF(ctrEvict, mutCtrEvict); STATSCOUNTER_DEF(ctrMiss, mutCtrMiss); STATSCOUNTER_DEF(ctrMax, mutCtrMax); + STATSCOUNTER_DEF(ctrCloseTimeouts, mutCtrCloseTimeouts); + char janitorID[128]; /* holds ID for janitor calls */ } instanceData; +typedef struct wrkrInstanceData { + instanceData *pData; +} wrkrInstanceData_t; + + typedef struct configSettings_s { int iDynaFileCacheSize; /* max cache for dynamic files */ int fCreateMode; /* mode to use when creating files */ @@ -207,6 +219,12 @@ uchar *pszFileDfltTplName; /* name of the default template to use */ struct modConfData_s { rsconf_t *pConf; /* our overall config object */ uchar *tplName; /* default template */ + int fCreateMode; /* default mode to use when creating files */ + int fDirCreateMode; /* default mode to use when creating files */ + uid_t fileUID; /* default IDs for creation */ + uid_t dirUID; + gid_t fileGID; + gid_t dirGID; }; static modConfData_t *loadModConf = NULL;/* modConf ptr to use for the current load process */ @@ -216,6 +234,16 @@ static modConfData_t *runModConf = NULL;/* modConf ptr to use for the current ex /* module-global parameters */ static struct cnfparamdescr modpdescr[] = { { "template", eCmdHdlrGetWord, 0 }, + { "dircreatemode", eCmdHdlrFileCreateMode, 0 }, + { "filecreatemode", eCmdHdlrFileCreateMode, 0 }, + { "dirowner", eCmdHdlrUID, 0 }, + { "dirownernum", eCmdHdlrInt, 0 }, + { "dirgroup", eCmdHdlrGID, 0 }, + { "dirgroupnum", eCmdHdlrInt, 0 }, + { "fileowner", eCmdHdlrUID, 0 }, + { "fileownernum", eCmdHdlrInt, 0 }, + { "filegroup", eCmdHdlrGID, 0 }, + { "filegroupnum", eCmdHdlrInt, 0 }, }; static struct cnfparamblk modpblk = { CNFPARAMBLK_VERSION, @@ -233,9 +261,13 @@ static struct cnfparamdescr actpdescr[] = { { "flushontxend", eCmdHdlrBinary, 0 }, /* legacy: omfileflushontxend */ { "iobuffersize", eCmdHdlrSize, 0 }, /* legacy: omfileiobuffersize */ { "dirowner", eCmdHdlrUID, 0 }, /* legacy: dirowner */ + { "dirownernum", eCmdHdlrInt, 0 }, /* legacy: dirownernum */ { "dirgroup", eCmdHdlrGID, 0 }, /* legacy: dirgroup */ + { "dirgroupnum", eCmdHdlrInt, 0 }, /* legacy: dirgroupnum */ { "fileowner", eCmdHdlrUID, 0 }, /* legacy: fileowner */ + { "fileownernum", eCmdHdlrInt, 0 }, /* legacy: fileownernum */ { "filegroup", eCmdHdlrGID, 0 }, /* legacy: filegroup */ + { "filegroupnum", eCmdHdlrInt, 0 }, /* legacy: filegroupnum */ { "dircreatemode", eCmdHdlrFileCreateMode, 0 }, /* legacy: dircreatemode */ { "filecreatemode", eCmdHdlrFileCreateMode, 0 }, /* legacy: filecreatemode */ { "failonchownfailure", eCmdHdlrBinary, 0 }, /* legacy: failonchownfailure */ @@ -245,6 +277,7 @@ static struct cnfparamdescr actpdescr[] = { { "dynafile", eCmdHdlrString, 0 }, /* "dynafile" MUST be present */ { "sig.provider", eCmdHdlrGetWord, 0 }, { "cry.provider", eCmdHdlrGetWord, 0 }, + { "closetimeout", eCmdHdlrPositiveInt, 0 }, { "template", eCmdHdlrGetWord, 0 } }; static struct cnfparamblk actpblk = @@ -287,11 +320,11 @@ CODESTARTdbgPrintInstInfo if(pData->bDynamicName) { dbgprintf("[dynamic]\n"); } else { /* regular file */ - dbgprintf("%s%s\n", pData->f_fname, + dbgprintf("%s%s\n", pData->fname, (pData->pStrm == NULL) ? " (closed)" : ""); } - dbgprintf("\ttemplate='%s'\n", pData->f_fname); + dbgprintf("\ttemplate='%s'\n", pData->fname); dbgprintf("\tuse async writer=%d\n", pData->bUseAsyncWriter); dbgprintf("\tflush on TX end=%d\n", pData->bFlushOnTXEnd); dbgprintf("\tflush interval=%d\n", pData->iFlushInterval); @@ -411,7 +444,7 @@ static rsRetVal cflineParseOutchannel(instanceData *pData, uchar* p, omodStringR } /* OK, we finally got a correct template. So let's use it... */ - pData->f_fname = ustrdup(pOch->pszFileTemplate); + pData->fname = ustrdup(pOch->pszFileTemplate); pData->iSizeLimit = pOch->uSizeLimit; /* WARNING: It is dangerous "just" to pass the pointer. As we * never rebuild the output channel description, this is acceptable here. @@ -433,7 +466,7 @@ finalize_it: * if the entry should be d_free()ed and 0 if not. */ static rsRetVal -dynaFileDelCacheEntry(instanceData *pData, int iEntry, int bFreeEntry) +dynaFileDelCacheEntry(instanceData *__restrict__ const pData, const int iEntry, const int bFreeEntry) { dynaFileCacheEntry **pCache = pData->dynCache; DEFiRet; @@ -473,7 +506,7 @@ finalize_it: * rgerhards, 2008-10-23 */ static inline void -dynaFileFreeCacheEntries(instanceData *pData) +dynaFileFreeCacheEntries(instanceData *__restrict__ const pData) { register int i; ASSERT(pData != NULL); @@ -489,7 +522,7 @@ dynaFileFreeCacheEntries(instanceData *pData) /* This function frees the dynamic file name cache. */ -static void dynaFileFreeCache(instanceData *pData) +static void dynaFileFreeCache(instanceData *__restrict__ const pData) { ASSERT(pData != NULL); @@ -503,7 +536,7 @@ static void dynaFileFreeCache(instanceData *pData) /* close current file */ static rsRetVal -closeFile(instanceData *pData) +closeFile(instanceData *__restrict__ const pData) { DEFiRet; if(pData->useSigprov) { @@ -517,7 +550,7 @@ closeFile(instanceData *pData) /* This prepares the signature provider to process a file */ static rsRetVal -sigprovPrepare(instanceData *pData, uchar *fn) +sigprovPrepare(instanceData *__restrict__ const pData, uchar *__restrict__ const fn) { DEFiRet; pData->sigprov.OnFileOpen(pData->sigprovData, fn, &pData->sigprovFileData); @@ -531,7 +564,7 @@ sigprovPrepare(instanceData *pData, uchar *fn) * changed to iRet interface - 2009-03-19 */ static rsRetVal -prepareFile(instanceData *pData, uchar *newFileName) +prepareFile(instanceData *__restrict__ const pData, const uchar *__restrict__ const newFileName) { int fd; DEFiRet; @@ -633,7 +666,7 @@ finalize_it: * This is a helper to writeFile(). rgerhards, 2007-07-03 */ static inline rsRetVal -prepareDynFile(instanceData *pData, uchar *newFileName, unsigned iMsgOpts) +prepareDynFile(instanceData *__restrict__ const pData, const uchar *__restrict__ const newFileName) { uint64 ctOldest; /* "timestamp" of oldest element */ int iOldest; @@ -727,16 +760,10 @@ prepareDynFile(instanceData *pData, uchar *newFileName, unsigned iMsgOpts) /* check if we had an error */ if(localRet != RS_RET_OK) { - /* do not report anything if the message is an internally-generated - * message. Otherwise, we could run into a never-ending loop. The bad - * news is that we also lose errors on startup messages, but so it is. + /* We do no longer care about internal messages. The errmsg rate limiter + * will take care of too-frequent error messages. */ - if(iMsgOpts & INTERNAL_MSG) { - DBGPRINTF("Could not open dynaFile '%s', state %d, discarding message\n", - newFileName, localRet); - } else { - errmsg.LogError(0, localRet, "Could not open dynamic file '%s' [state %d] - discarding message", newFileName, localRet); - } + errmsg.LogError(0, localRet, "Could not open dynamic file '%s' [state %d] - discarding message", newFileName, localRet); ABORT_FINALIZE(localRet); } @@ -752,6 +779,7 @@ prepareDynFile(instanceData *pData, uchar *newFileName, unsigned iMsgOpts) DBGPRINTF("Added new entry %d for file cache, file '%s'.\n", iFirstFree, newFileName); finalize_it: + pCache[pData->iCurrElt]->nInactive = 0; RETiRet; } @@ -762,13 +790,14 @@ finalize_it: * rgerhards, 2009-06-03 */ static rsRetVal -doWrite(instanceData *pData, uchar *pszBuf, int lenBuf) +doWrite(instanceData *__restrict__ const pData, uchar *__restrict__ const pszBuf, const int lenBuf) { DEFiRet; ASSERT(pData != NULL); ASSERT(pszBuf != NULL); - DBGPRINTF("write to stream, pData->pStrm %p, lenBuf %d\n", pData->pStrm, lenBuf); + DBGPRINTF("omfile: write to stream, pData->pStrm %p, lenBuf %d, strt data %.128s\n", + pData->pStrm, lenBuf, pszBuf); if(pData->pStrm != NULL){ CHKiRet(strm.Write(pData->pStrm, pszBuf, lenBuf)); if(pData->useSigprov) { @@ -783,27 +812,34 @@ finalize_it: /* rgerhards 2004-11-11: write to a file output. */ static rsRetVal -writeFile(uchar **ppString, unsigned iMsgOpts, instanceData *pData) +writeFile(instanceData *__restrict__ const pData, + const actWrkrIParams_t *__restrict__ const pParam, + const int iMsg) { DEFiRet; - ASSERT(pData != NULL); - + STATSCOUNTER_INC(pData->ctrRequests, pData->mutCtrRequests); /* first check if we have a dynamic file name and, if so, * check if it still is ok or a new file needs to be created */ if(pData->bDynamicName) { - CHKiRet(prepareDynFile(pData, ppString[1], iMsgOpts)); + DBGPRINTF("omfile: file to log to: %s\n", + actParam(pParam, pData->iNumTpls, iMsg, 1).param); + CHKiRet(prepareDynFile(pData, actParam(pParam, pData->iNumTpls, iMsg, 1).param)); } else { /* "regular", non-dynafile */ if(pData->pStrm == NULL) { - CHKiRet(prepareFile(pData, pData->f_fname)); + CHKiRet(prepareFile(pData, pData->fname)); if(pData->pStrm == NULL) { - errmsg.LogError(0, RS_RET_NO_FILE_ACCESS, "Could no open output file '%s'", pData->f_fname); + errmsg.LogError(0, RS_RET_NO_FILE_ACCESS, + "Could not open output file '%s'", pData->fname); } } + pData->nInactive = 0; } - CHKiRet(doWrite(pData, ppString[0], strlen(CHAR_CONVERT(ppString[0])))); + CHKiRet(doWrite(pData, + actParam(pParam, pData->iNumTpls, iMsg, 0).param, + actParam(pParam, pData->iNumTpls, iMsg, 0).lenStr)); finalize_it: RETiRet; @@ -815,6 +851,12 @@ CODESTARTbeginCnfLoad loadModConf = pModConf; pModConf->pConf = pConf; pModConf->tplName = NULL; + pModConf->fCreateMode = 0644; + pModConf->fDirCreateMode = 0700; + pModConf->fileUID = -1; + pModConf->dirUID = -1; + pModConf->fileGID = -1; + pModConf->dirGID = -1; ENDbeginCnfLoad BEGINsetModCnf @@ -834,8 +876,10 @@ CODESTARTsetModCnf } for(i = 0 ; i < modpblk.nParams ; ++i) { - if(!pvals[i].bUsed) + if(!pvals[i].bUsed) { continue; + } + if(!strcmp(modpblk.descr[i].name, "template")) { loadModConf->tplName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); if(pszFileDfltTplName != NULL) { @@ -843,6 +887,26 @@ CODESTARTsetModCnf "was already set via legacy directive - may lead to inconsistent " "results."); } + } else if(!strcmp(modpblk.descr[i].name, "dircreatemode")) { + loadModConf->fDirCreateMode = (int) pvals[i].val.d.n; + } else if(!strcmp(modpblk.descr[i].name, "filecreatemode")) { + loadModConf->fCreateMode = (int) pvals[i].val.d.n; + } else if(!strcmp(modpblk.descr[i].name, "dirowner")) { + loadModConf->dirUID = (int) pvals[i].val.d.n; + } else if(!strcmp(modpblk.descr[i].name, "dirownernum")) { + loadModConf->dirUID = (int) pvals[i].val.d.n; + } else if(!strcmp(modpblk.descr[i].name, "dirgroup")) { + loadModConf->dirGID = (int) pvals[i].val.d.n; + } else if(!strcmp(modpblk.descr[i].name, "dirgroupnum")) { + loadModConf->dirGID = (int) pvals[i].val.d.n; + } else if(!strcmp(modpblk.descr[i].name, "fileowner")) { + loadModConf->fileUID = (int) pvals[i].val.d.n; + } else if(!strcmp(modpblk.descr[i].name, "fileownernum")) { + loadModConf->fileUID = (int) pvals[i].val.d.n; + } else if(!strcmp(modpblk.descr[i].name, "filegroup")) { + loadModConf->fileGID = (int) pvals[i].val.d.n; + } else if(!strcmp(modpblk.descr[i].name, "filegroupnum")) { + loadModConf->fileGID = (int) pvals[i].val.d.n; } else { dbgprintf("omfile: program error, non-handled " "param '%s' in beginCnfLoad\n", modpblk.descr[i].name); @@ -853,6 +917,54 @@ finalize_it: cnfparamvalsDestruct(pvals, &modpblk); ENDsetModCnf +/* This function checks dynafile cache for janitor action */ +static inline void +janitorChkDynaFiles(instanceData *__restrict__ const pData) +{ + int i; + dynaFileCacheEntry **pCache = pData->dynCache; + + for(i = 0 ; i < pData->iCurrCacheSize ; ++i) { + if(pCache[i] == NULL) + continue; + DBGPRINTF("omfile janitor: checking dynafile %d:%s, inactive since %d\n", i, + pCache[i]->pName == NULL ? UCHAR_CONSTANT("[OPEN FAILED]") : pCache[i]->pName, + (int) pCache[i]->nInactive); + if(pCache[i]->nInactive >= pData->iCloseTimeout) { + STATSCOUNTER_INC(pData->ctrCloseTimeouts, pData->mutCtrCloseTimeouts); + dynaFileDelCacheEntry(pData, i, 1); + if(pData->iCurrElt == i) + pData->iCurrElt = -1; /* no longer available! */ + } else { + pCache[i]->nInactive += janitorInterval; + } + } +} + +/* callback for the janitor. This cleans out files (if so configured) */ +void +janitorCB(void *pUsr) +{ + instanceData *__restrict__ const pData = (instanceData *) pUsr; + pthread_mutex_lock(&pData->mutWrite); + if(pData->bDynamicName) { + janitorChkDynaFiles(pData); + } else { + if(pData->pStrm != NULL) { + DBGPRINTF("omfile janitor: checking file %s, inactive since %d\n", + pData->fname, pData->nInactive); + if(pData->nInactive >= pData->iCloseTimeout) { + STATSCOUNTER_INC(pData->ctrCloseTimeouts, pData->mutCtrCloseTimeouts); + closeFile(pData); + } else { + pData->nInactive += janitorInterval; + } + } + } + pthread_mutex_unlock(&pData->mutWrite); +} + + BEGINendCnfLoad CODESTARTendCnfLoad loadModConf = NULL; /* done loading */ @@ -879,13 +991,21 @@ ENDfreeCnf BEGINcreateInstance CODESTARTcreateInstance pData->pStrm = NULL; + pthread_mutex_init(&pData->mutWrite, NULL); ENDcreateInstance +BEGINcreateWrkrInstance +CODESTARTcreateWrkrInstance +ENDcreateWrkrInstance + + BEGINfreeInstance CODESTARTfreeInstance free(pData->tplName); - free(pData->f_fname); + free(pData->fname); + if(pData->iCloseTimeout > 0) + janitorDelEtry(pData->janitorID); if(pData->bDynamicName) { dynaFileFreeCache(pData); } else if(pData->pStrm != NULL) @@ -904,9 +1024,15 @@ CODESTARTfreeInstance free(pData->cryprovName); free(pData->cryprovNameFull); } + pthread_mutex_destroy(&pData->mutWrite); ENDfreeInstance +BEGINfreeWrkrInstance +CODESTARTfreeWrkrInstance +ENDfreeWrkrInstance + + BEGINtryResume CODESTARTtryResume ENDtryResume @@ -917,8 +1043,15 @@ CODESTARTbeginTransaction ENDbeginTransaction -BEGINendTransaction -CODESTARTendTransaction +BEGINcommitTransaction + instanceData *__restrict__ const pData = pWrkrData->pData; + unsigned i; +CODESTARTcommitTransaction + pthread_mutex_lock(&pData->mutWrite); + + for(i = 0 ; i < nParams ; ++i) { + writeFile(pData, pParams, i); + } /* Note: pStrm may be NULL if there was an error opening the stream */ if(pData->bFlushOnTXEnd && pData->pStrm != NULL) { /* if we have an async writer, it controls the flush via @@ -929,38 +1062,23 @@ CODESTARTendTransaction CHKiRet(strm.Flush(pData->pStrm)); } finalize_it: -ENDendTransaction - - -BEGINdoAction -CODESTARTdoAction - DBGPRINTF("file to log to: %s\n", - (pData->bDynamicName) ? ppString[1] : pData->f_fname); - DBGPRINTF("omfile: start of data: '%.128s'\n", ppString[0]); - STATSCOUNTER_INC(pData->ctrRequests, pData->mutCtrRequests); - CHKiRet(writeFile(ppString, iMsgOpts, pData)); - if(!bCoreSupportsBatching && pData->bFlushOnTXEnd) { - CHKiRet(strm.Flush(pData->pStrm)); - } -finalize_it: - if(iRet == RS_RET_OK) - iRet = RS_RET_DEFER_COMMIT; -ENDdoAction + pthread_mutex_unlock(&pData->mutWrite); +ENDcommitTransaction static inline void -setInstParamDefaults(instanceData *pData) +setInstParamDefaults(instanceData *__restrict__ const pData) { - pData->f_fname = NULL; + pData->fname = NULL; pData->tplName = NULL; - pData->fileUID = -1; - pData->fileGID = -1; - pData->dirUID = -1; - pData->dirGID = -1; + pData->fileUID = loadModConf->fileUID; + pData->fileGID = loadModConf->fileGID; + pData->dirUID = loadModConf->dirUID; + pData->dirGID = loadModConf->dirGID; pData->bFailOnChown = 1; pData->iDynaFileCacheSize = 10; - pData->fCreateMode = 0644; - pData->fDirCreateMode = 0700; + pData->fCreateMode = loadModConf->fCreateMode; + pData->fDirCreateMode = loadModConf->fDirCreateMode; pData->bCreateDirs = 1; pData->bSyncFile = 0; pData->iZipLevel = 0; @@ -973,11 +1091,12 @@ setInstParamDefaults(instanceData *pData) pData->cryprovName = NULL; pData->useSigprov = 0; pData->useCryprov = 0; + pData->iCloseTimeout = -1; } static rsRetVal -setupInstStatsCtrs(instanceData *pData) +setupInstStatsCtrs(instanceData *__restrict__ const pData) { uchar ctrName[512]; DEFiRet; @@ -987,25 +1106,28 @@ setupInstStatsCtrs(instanceData *pData) } /* support statistics gathering */ - snprintf((char*)ctrName, sizeof(ctrName), "dynafile cache %s", pData->f_fname); + snprintf((char*)ctrName, sizeof(ctrName), "dynafile cache %s", pData->fname); ctrName[sizeof(ctrName)-1] = '\0'; /* be on the save side */ CHKiRet(statsobj.Construct(&(pData->stats))); CHKiRet(statsobj.SetName(pData->stats, ctrName)); STATSCOUNTER_INIT(pData->ctrRequests, pData->mutCtrRequests); CHKiRet(statsobj.AddCounter(pData->stats, UCHAR_CONSTANT("requests"), - ctrType_IntCtr, &(pData->ctrRequests))); + ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pData->ctrRequests))); STATSCOUNTER_INIT(pData->ctrLevel0, pData->mutCtrLevel0); CHKiRet(statsobj.AddCounter(pData->stats, UCHAR_CONSTANT("level0"), - ctrType_IntCtr, &(pData->ctrLevel0))); + ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pData->ctrLevel0))); STATSCOUNTER_INIT(pData->ctrMiss, pData->mutCtrMiss); CHKiRet(statsobj.AddCounter(pData->stats, UCHAR_CONSTANT("missed"), - ctrType_IntCtr, &(pData->ctrMiss))); + ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pData->ctrMiss))); STATSCOUNTER_INIT(pData->ctrEvict, pData->mutCtrEvict); CHKiRet(statsobj.AddCounter(pData->stats, UCHAR_CONSTANT("evicted"), - ctrType_IntCtr, &(pData->ctrEvict))); + ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pData->ctrEvict))); STATSCOUNTER_INIT(pData->ctrMax, pData->mutCtrMax); CHKiRet(statsobj.AddCounter(pData->stats, UCHAR_CONSTANT("maxused"), - ctrType_IntCtr, &(pData->ctrMax))); + ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pData->ctrMax))); + STATSCOUNTER_INIT(pData->ctrCloseTimeouts, pData->mutCtrCloseTimeouts); + CHKiRet(statsobj.AddCounter(pData->stats, UCHAR_CONSTANT("closetimeouts"), + ctrType_IntCtr, CTR_FLAG_RESETTABLE, &(pData->ctrCloseTimeouts))); CHKiRet(statsobj.ConstructFinalize(pData->stats)); finalize_it: @@ -1013,7 +1135,7 @@ finalize_it: } static inline void -initSigprov(instanceData *pData, struct nvlst *lst) +initSigprov(instanceData *__restrict__ const pData, struct nvlst *lst) { uchar szDrvrName[1024]; @@ -1055,7 +1177,7 @@ done: return; } static inline rsRetVal -initCryprov(instanceData *pData, struct nvlst *lst) +initCryprov(instanceData *__restrict__ const pData, struct nvlst *lst) { uchar szDrvrName[1024]; DEFiRet; @@ -1089,7 +1211,7 @@ initCryprov(instanceData *pData, struct nvlst *lst) szDrvrName); ABORT_FINALIZE(RS_RET_CRYPROV_ERR); } - CHKiRet(pData->cryprov.SetCnfParam(pData->cryprovData, lst)); + CHKiRet(pData->cryprov.SetCnfParam(pData->cryprovData, lst, CRYPROV_PARAMTYPE_REGULAR)); dbgprintf("loaded crypto provider %s, data instance at %p\n", szDrvrName, pData->cryprovData); @@ -1139,12 +1261,20 @@ CODESTARTnewActInst pData->iIOBufSize = (int) pvals[i].val.d.n; } else if(!strcmp(actpblk.descr[i].name, "dirowner")) { pData->dirUID = (int) pvals[i].val.d.n; + } else if(!strcmp(actpblk.descr[i].name, "dirownernum")) { + pData->dirUID = (int) pvals[i].val.d.n; } else if(!strcmp(actpblk.descr[i].name, "dirgroup")) { pData->dirGID = (int) pvals[i].val.d.n; + } else if(!strcmp(actpblk.descr[i].name, "dirgroupnum")) { + pData->dirGID = (int) pvals[i].val.d.n; } else if(!strcmp(actpblk.descr[i].name, "fileowner")) { pData->fileUID = (int) pvals[i].val.d.n; + } else if(!strcmp(actpblk.descr[i].name, "fileownernum")) { + pData->fileUID = (int) pvals[i].val.d.n; } else if(!strcmp(actpblk.descr[i].name, "filegroup")) { pData->fileGID = (int) pvals[i].val.d.n; + } else if(!strcmp(actpblk.descr[i].name, "filegroupnum")) { + pData->fileGID = (int) pvals[i].val.d.n; } else if(!strcmp(actpblk.descr[i].name, "dircreatemode")) { pData->fDirCreateMode = (int) pvals[i].val.d.n; } else if(!strcmp(actpblk.descr[i].name, "filecreatemode")) { @@ -1156,11 +1286,11 @@ CODESTARTnewActInst } else if(!strcmp(actpblk.descr[i].name, "createdirs")) { pData->bCreateDirs = (int) pvals[i].val.d.n; } else if(!strcmp(actpblk.descr[i].name, "file")) { - pData->f_fname = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); + pData->fname = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); CODE_STD_STRING_REQUESTnewActInst(1) pData->bDynamicName = 0; } else if(!strcmp(actpblk.descr[i].name, "dynafile")) { - pData->f_fname = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); + pData->fname = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); CODE_STD_STRING_REQUESTnewActInst(2) pData->bDynamicName = 1; } else if(!strcmp(actpblk.descr[i].name, "template")) { @@ -1169,13 +1299,15 @@ CODESTARTnewActInst pData->sigprovName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); } else if(!strcmp(actpblk.descr[i].name, "cry.provider")) { pData->cryprovName = (uchar*)es_str2cstr(pvals[i].val.d.estr, NULL); + } else if(!strcmp(actpblk.descr[i].name, "closetimeout")) { + pData->iCloseTimeout = (int) pvals[i].val.d.n; } else { dbgprintf("omfile: program error, non-handled " "param '%s'\n", actpblk.descr[i].name); } } - if(pData->f_fname == NULL) { + if(pData->fname == NULL) { errmsg.LogError(0, RS_RET_MISSING_CNFPARAMS, "omfile: either the \"file\" or " "\"dynfile\" parameter must be given"); ABORT_FINALIZE(RS_RET_MISSING_CNFPARAMS); @@ -1191,12 +1323,14 @@ CODESTARTnewActInst tplToUse = ustrdup((pData->tplName == NULL) ? getDfltTpl() : pData->tplName); CHKiRet(OMSRsetEntry(*ppOMSR, 0, tplToUse, OMSR_NO_RQD_TPL_OPTS)); + pData->iNumTpls = 1; if(pData->bDynamicName) { /* "filename" is actually a template name, we need this as string 1. So let's add it * to the pOMSR. -- rgerhards, 2007-07-27 */ - CHKiRet(OMSRsetEntry(*ppOMSR, 1, ustrdup(pData->f_fname), OMSR_NO_RQD_TPL_OPTS)); + CHKiRet(OMSRsetEntry(*ppOMSR, 1, ustrdup(pData->fname), OMSR_NO_RQD_TPL_OPTS)); + pData->iNumTpls = 2; // TODO: create unified code for this (legacy+v6 system) /* we now allocate the cache table */ CHKmalloc(pData->dynCache = (dynaFileCacheEntry**) @@ -1206,6 +1340,17 @@ CODESTARTnewActInst // TODO: add pData->iSizeLimit = 0; /* default value, use outchannels to configure! */ setupInstStatsCtrs(pData); + if(pData->iCloseTimeout == -1) { /* unset? */ + pData->iCloseTimeout = (pData->bDynamicName) ? 10 : 0; + } + + snprintf(pData->janitorID, sizeof(pData->janitorID), "omfile:%sfile:%s:%p", + (pData->bDynamicName) ? "dyna" : "", pData->fname, pData); + pData->janitorID[sizeof(pData->janitorID)-1] = '\0'; /* just in case... */ + + if(pData->iCloseTimeout > 0) + janitorAddEtry(janitorCB, pData->janitorID, pData); + CODE_STD_FINALIZERnewActInst cnfparamvalsDestruct(pvals, &actpblk); ENDnewActInst @@ -1238,6 +1383,7 @@ CODESTARTparseSelectorAct switch(*p) { case '$': CODE_STD_STRING_REQUESTparseSelectorAct(1) + pData->iNumTpls = 1; /* rgerhards 2005-06-21: this is a special setting for output-channel * definitions. In the long term, this setting will probably replace * anything else, but for the time being we must co-exist with the @@ -1253,15 +1399,16 @@ CODESTARTparseSelectorAct * a template name. rgerhards, 2007-07-03 */ CODE_STD_STRING_REQUESTparseSelectorAct(2) + pData->iNumTpls = 2; ++p; /* eat '?' */ CHKiRet(cflineParseFileName(p, fname, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS, getDfltTpl())); - pData->f_fname = ustrdup(fname); + pData->fname = ustrdup(fname); pData->bDynamicName = 1; pData->iCurrElt = -1; /* no current element */ /* "filename" is actually a template name, we need this as string 1. So let's add it * to the pOMSR. -- rgerhards, 2007-07-27 */ - CHKiRet(OMSRsetEntry(*ppOMSR, 1, ustrdup(pData->f_fname), OMSR_NO_RQD_TPL_OPTS)); + CHKiRet(OMSRsetEntry(*ppOMSR, 1, ustrdup(pData->fname), OMSR_NO_RQD_TPL_OPTS)); /* we now allocate the cache table */ CHKmalloc(pData->dynCache = (dynaFileCacheEntry**) calloc(cs.iDynaFileCacheSize, sizeof(dynaFileCacheEntry*))); @@ -1270,8 +1417,9 @@ CODESTARTparseSelectorAct case '/': case '.': CODE_STD_STRING_REQUESTparseSelectorAct(1) + pData->iNumTpls = 1; CHKiRet(cflineParseFileName(p, fname, *ppOMSR, 0, OMSR_NO_RQD_TPL_OPTS, getDfltTpl())); - pData->f_fname = ustrdup(fname); + pData->fname = ustrdup(fname); pData->bDynamicName = 0; break; default: @@ -1294,6 +1442,7 @@ CODESTARTparseSelectorAct pData->iFlushInterval = cs.iFlushInterval; pData->bUseAsyncWriter = cs.bUseAsyncWriter; pData->bVeryRobustZip = 0; /* cannot be specified via legacy conf */ + pData->iCloseTimeout = 0; /* cannot be specified via legacy conf */ setupInstStatsCtrs(pData); CODE_STD_FINALIZERparseSelectorAct ENDparseSelectorAct @@ -1327,6 +1476,7 @@ static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __a BEGINdoHUP CODESTARTdoHUP + pthread_mutex_lock(&pData->mutWrite); if(pData->bDynamicName) { dynaFileFreeCacheEntries(pData); } else { @@ -1334,6 +1484,7 @@ CODESTARTdoHUP closeFile(pData); } } + pthread_mutex_unlock(&pData->mutWrite); ENDdoHUP @@ -1348,11 +1499,11 @@ ENDmodExit BEGINqueryEtryPt CODESTARTqueryEtryPt -CODEqueryEtryPt_STD_OMOD_QUERIES +CODEqueryEtryPt_STD_OMODTX_QUERIES +CODEqueryEtryPt_STD_OMOD8_QUERIES CODEqueryEtryPt_STD_CONF2_QUERIES CODEqueryEtryPt_STD_CONF2_setModCnf_QUERIES CODEqueryEtryPt_STD_CONF2_OMOD_QUERIES -CODEqueryEtryPt_TXIF_OMOD_QUERIES /* we support the transactional interface! */ CODEqueryEtryPt_doHUP ENDqueryEtryPt @@ -1377,9 +1528,13 @@ INITLegCnfVars CHKiRet(omsdRegCFSLineHdlr((uchar *)"omfileflushontxend", 0, eCmdHdlrBinary, NULL, &cs.bFlushOnTXEnd, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"omfileiobuffersize", 0, eCmdHdlrSize, NULL, &cs.iIOBufSize, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"dirowner", 0, eCmdHdlrUID, NULL, &cs.dirUID, STD_LOADABLE_MODULE_ID)); + CHKiRet(omsdRegCFSLineHdlr((uchar *)"dirownernum", 0, eCmdHdlrInt, NULL, &cs.dirUID, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"dirgroup", 0, eCmdHdlrGID, NULL, &cs.dirGID, STD_LOADABLE_MODULE_ID)); + CHKiRet(omsdRegCFSLineHdlr((uchar *)"dirgroupnum", 0, eCmdHdlrInt, NULL, &cs.dirGID, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"fileowner", 0, eCmdHdlrUID, NULL, &cs.fileUID, STD_LOADABLE_MODULE_ID)); + CHKiRet(omsdRegCFSLineHdlr((uchar *)"fileownernum", 0, eCmdHdlrInt, NULL, &cs.fileUID, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"filegroup", 0, eCmdHdlrGID, NULL, &cs.fileGID, STD_LOADABLE_MODULE_ID)); + CHKiRet(omsdRegCFSLineHdlr((uchar *)"filegroupnum", 0, eCmdHdlrInt, NULL, &cs.fileGID, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"dircreatemode", 0, eCmdHdlrFileCreateMode, NULL, &cs.fDirCreateMode, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"filecreatemode", 0, eCmdHdlrFileCreateMode, NULL, &cs.fCreateMode, STD_LOADABLE_MODULE_ID)); CHKiRet(omsdRegCFSLineHdlr((uchar *)"createdirs", 0, eCmdHdlrBinary, NULL, &cs.bCreateDirs, STD_LOADABLE_MODULE_ID)); |