enh: protect WAL meta by flushing to a tmpfile at first and then renaming
This commit is contained in:
parent
36bf800e15
commit
76865258cf
|
@ -121,7 +121,7 @@ int32_t tdbCommit(TDB *pDb, TXN *pTxn) {
|
||||||
for (pPager = pDb->pgrList; pPager; pPager = pPager->pNext) {
|
for (pPager = pDb->pgrList; pPager; pPager = pPager->pNext) {
|
||||||
ret = tdbPagerCommit(pPager, pTxn);
|
ret = tdbPagerCommit(pPager, pTxn);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
tdbError("failed to commit pager. dbName:%s, txnId:%d", pDb->dbName, pTxn->txnId);
|
tdbError("failed to commit pager since %s. dbName:%s, txnId:%d", tstrerror(terrno), pDb->dbName, pTxn->txnId);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -136,7 +136,7 @@ int32_t tdbAbort(TDB *pDb, TXN *pTxn) {
|
||||||
for (pPager = pDb->pgrList; pPager; pPager = pPager->pNext) {
|
for (pPager = pDb->pgrList; pPager; pPager = pPager->pNext) {
|
||||||
ret = tdbPagerAbort(pPager, pTxn);
|
ret = tdbPagerAbort(pPager, pTxn);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
tdbError("failed to abort pager. dbName:%s, txnId:%d", pDb->dbName, pTxn->txnId);
|
tdbError("failed to abort pager since %s. dbName:%s, txnId:%d", tstrerror(terrno), pDb->dbName, pTxn->txnId);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,8 +35,12 @@ int64_t FORCE_INLINE walGetCommittedVer(SWal* pWal) { return pWal->vers.commitVe
|
||||||
|
|
||||||
int64_t FORCE_INLINE walGetAppliedVer(SWal* pWal) { return pWal->vers.appliedVer; }
|
int64_t FORCE_INLINE walGetAppliedVer(SWal* pWal) { return pWal->vers.appliedVer; }
|
||||||
|
|
||||||
static FORCE_INLINE void walBuildMetaName(SWal* pWal, int metaVer, char* buf) {
|
static FORCE_INLINE int walBuildMetaName(SWal* pWal, int metaVer, char* buf) {
|
||||||
sprintf(buf, "%s/meta-ver%d", pWal->path, metaVer);
|
return sprintf(buf, "%s/meta-ver%d", pWal->path, metaVer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static FORCE_INLINE int walBuildTmpMetaName(SWal* pWal, char* buf) {
|
||||||
|
return sprintf(buf, "%s/meta-ver.tmp", pWal->path);
|
||||||
}
|
}
|
||||||
|
|
||||||
static FORCE_INLINE int64_t walScanLogGetLastVer(SWal* pWal) {
|
static FORCE_INLINE int64_t walScanLogGetLastVer(SWal* pWal) {
|
||||||
|
@ -578,22 +582,51 @@ static int walFindCurMetaVer(SWal* pWal) {
|
||||||
int walSaveMeta(SWal* pWal) {
|
int walSaveMeta(SWal* pWal) {
|
||||||
int metaVer = walFindCurMetaVer(pWal);
|
int metaVer = walFindCurMetaVer(pWal);
|
||||||
char fnameStr[WAL_FILE_LEN];
|
char fnameStr[WAL_FILE_LEN];
|
||||||
walBuildMetaName(pWal, metaVer + 1, fnameStr);
|
char tmpFnameStr[WAL_FILE_LEN];
|
||||||
TdFilePtr pMetaFile = taosOpenFile(fnameStr, TD_FILE_CREATE | TD_FILE_WRITE);
|
int n;
|
||||||
|
|
||||||
|
// flush to a tmpfile
|
||||||
|
n = walBuildTmpMetaName(pWal, tmpFnameStr);
|
||||||
|
ASSERT(n < sizeof(tmpFnameStr) && "Buffer overflow of file name");
|
||||||
|
|
||||||
|
TdFilePtr pMetaFile = taosOpenFile(tmpFnameStr, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_TRUNC);
|
||||||
if (pMetaFile == NULL) {
|
if (pMetaFile == NULL) {
|
||||||
|
wError("failed to open file due to %s. file:%s", strerror(errno), tmpFnameStr);
|
||||||
|
terrno = TAOS_SYSTEM_ERROR(errno);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* serialized = walMetaSerialize(pWal);
|
char* serialized = walMetaSerialize(pWal);
|
||||||
int len = strlen(serialized);
|
int len = strlen(serialized);
|
||||||
if (len != taosWriteFile(pMetaFile, serialized, len)) {
|
if (len != taosWriteFile(pMetaFile, serialized, len)) {
|
||||||
// TODO:clean file
|
// TODO:clean file
|
||||||
|
wError("failed to write file due to %s. file:%s", strerror(errno), tmpFnameStr);
|
||||||
taosCloseFile(&pMetaFile);
|
terrno = TAOS_SYSTEM_ERROR(errno);
|
||||||
taosRemoveFile(fnameStr);
|
goto _err;
|
||||||
return -1;
|
}
|
||||||
|
|
||||||
|
if (taosFsyncFile(pMetaFile) < 0) {
|
||||||
|
wError("failed to sync file due to %s. file:%s", strerror(errno), tmpFnameStr);
|
||||||
|
terrno = TAOS_SYSTEM_ERROR(errno);
|
||||||
|
goto _err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (taosCloseFile(&pMetaFile) < 0) {
|
||||||
|
wError("failed to close file due to %s. file:%s", strerror(errno), tmpFnameStr);
|
||||||
|
terrno = TAOS_SYSTEM_ERROR(errno);
|
||||||
|
goto _err;
|
||||||
|
}
|
||||||
|
|
||||||
|
// rename it
|
||||||
|
n = walBuildMetaName(pWal, metaVer + 1, fnameStr);
|
||||||
|
ASSERT(n < sizeof(fnameStr) && "Buffer overflow of file name");
|
||||||
|
|
||||||
|
if (taosRenameFile(tmpFnameStr, fnameStr) < 0) {
|
||||||
|
wError("failed to rename file due to %s. dest:%s", strerror(errno), fnameStr);
|
||||||
|
terrno = TAOS_SYSTEM_ERROR(errno);
|
||||||
|
goto _err;
|
||||||
}
|
}
|
||||||
|
|
||||||
taosCloseFile(&pMetaFile);
|
|
||||||
// delete old file
|
// delete old file
|
||||||
if (metaVer > -1) {
|
if (metaVer > -1) {
|
||||||
walBuildMetaName(pWal, metaVer, fnameStr);
|
walBuildMetaName(pWal, metaVer, fnameStr);
|
||||||
|
@ -601,6 +634,11 @@ int walSaveMeta(SWal* pWal) {
|
||||||
}
|
}
|
||||||
taosMemoryFree(serialized);
|
taosMemoryFree(serialized);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
_err:
|
||||||
|
taosCloseFile(&pMetaFile);
|
||||||
|
taosMemoryFree(serialized);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int walLoadMeta(SWal* pWal) {
|
int walLoadMeta(SWal* pWal) {
|
||||||
|
|
Loading…
Reference in New Issue