summaryrefslogtreecommitdiff
path: root/tools/omfile.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/omfile.c')
-rw-r--r--tools/omfile.c317
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));