提交 76865258 编写于 作者: B Benguang Zhao

enh: protect WAL meta by flushing to a tmpfile at first and then renaming

上级 36bf800e
...@@ -121,7 +121,7 @@ int32_t tdbCommit(TDB *pDb, TXN *pTxn) { ...@@ -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) { ...@@ -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 ...@@ -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) { ...@@ -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);
terrno = TAOS_SYSTEM_ERROR(errno);
goto _err;
}
taosCloseFile(&pMetaFile); if (taosFsyncFile(pMetaFile) < 0) {
taosRemoveFile(fnameStr); wError("failed to sync file due to %s. file:%s", strerror(errno), tmpFnameStr);
return -1; 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) { ...@@ -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) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册