queue subsystem: .qi file is automically rewritten

previously, a kill -9 during the .qi write could keep the file
in inconsistent state. Now, we first write a temp file, and
(automically) rename it to "the real thing". So if something happens
during writing the .qi, at least the old state still is consistent.

This is inspired by the way the pid file is handled sind v8.19.
This commit is contained in:
Rainer Gerhards 2016-08-18 14:29:49 +02:00
parent 7d0116b7f3
commit 24bab3b108
2 changed files with 21 additions and 1 deletions

View File

@ -2434,7 +2434,9 @@ static rsRetVal
qqueuePersist(qqueue_t *pThis, int bIsCheckpoint)
{
DEFiRet;
char *tmpQIFName = NULL;
strm_t *psQIF = NULL; /* Queue Info File */
char errStr[1024];
ASSERT(pThis != NULL);
@ -2463,11 +2465,15 @@ qqueuePersist(qqueue_t *pThis, int bIsCheckpoint)
FINALIZE; /* nothing left to do, so be happy */
}
const int lentmpQIFName = asprintf((char **)&tmpQIFName, "%s.tmp", pThis->pszQIFNam);
if(tmpQIFName == NULL)
tmpQIFName = (char*)pThis->pszQIFNam;
CHKiRet(strm.Construct(&psQIF));
CHKiRet(strm.SettOperationsMode(psQIF, STREAMMODE_WRITE_TRUNC));
CHKiRet(strm.SetbSync(psQIF, pThis->bSyncQueueFiles));
CHKiRet(strm.SetsType(psQIF, STREAMTYPE_FILE_SINGLE));
CHKiRet(strm.SetFName(psQIF, pThis->pszQIFNam, pThis->lenQIFNam));
CHKiRet(strm.SetFName(psQIF, (uchar*) tmpQIFName, lentmpQIFName));
CHKiRet(strm.ConstructFinalize(psQIF));
/* first, write the property bag for ourselfs
@ -2487,6 +2493,17 @@ qqueuePersist(qqueue_t *pThis, int bIsCheckpoint)
if(pThis->tVars.disk.pReadDel != NULL)
CHKiRet(strm.Serialize(pThis->tVars.disk.pReadDel, psQIF));
strm.Destruct(&psQIF);
if(tmpQIFName != (char*)pThis->pszQIFNam) { /* pointer, not string comparison! */
if(rename(tmpQIFName, (char*)pThis->pszQIFNam) != 0) {
rs_strerror_r(errno, errStr, sizeof(errStr));
DBGOPRINT((obj_t*) pThis,
"FATAL error: renaming temporary .qi file failed: %s\n",
errStr);
ABORT_FINALIZE(RS_RET_RENAME_TMP_QI_ERROR);
}
}
/* tell the input file object that it must not delete the file on close if the queue
* is non-empty - but only if we are not during a simple checkpoint
*/
@ -2501,6 +2518,8 @@ qqueuePersist(qqueue_t *pThis, int bIsCheckpoint)
pThis->bNeedDelQIF = 1;
finalize_it:
if(tmpQIFName != (char*)pThis->pszQIFNam) /* pointer, not string comparison! */
free(tmpQIFName);
if(psQIF != NULL)
strm.Destruct(&psQIF);

View File

@ -454,6 +454,7 @@ enum rsRetVal_ /** return value. All methods return this if not specified oth
RS_RET_ERR_DROP_PRIV = -2432,/**< error droping privileges */
RS_RET_FILE_OPEN_ERROR = -2433, /**< error other than "not found" occured during open() */
RS_RET_FILE_CHOWN_ERROR = -2434, /**< error during chown() */
RS_RET_RENAME_TMP_QI_ERROR = -2435, /**< renaming temporary .qi file failed */
/* RainerScript error messages (range 1000.. 1999) */
RS_RET_SYSVAR_NOT_FOUND = 1001, /**< system variable could not be found (maybe misspelled) */