704 lines
17 KiB
C
704 lines
17 KiB
C
/*
|
|
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
|
*
|
|
* This program is free software: you can use, redistribute, and/or modify
|
|
* it under the terms of the GNU Affero General Public License, version 3
|
|
* or later ("AGPL"), as published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE.
|
|
*
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "tsdb.h"
|
|
|
|
// =================================================================================================
|
|
static int32_t tPutFSState(uint8_t *p, STsdbFSState *pState) {
|
|
int32_t n = 0;
|
|
int8_t hasDel = pState->pDelFile ? 1 : 0;
|
|
uint32_t nDFileSet = taosArrayGetSize(pState->aDFileSet);
|
|
|
|
// SDelFile
|
|
n += tPutI8(p ? p + n : p, hasDel);
|
|
if (hasDel) {
|
|
n += tPutDelFile(p ? p + n : p, pState->pDelFile);
|
|
}
|
|
|
|
// SArray<SDFileSet>
|
|
n += tPutU32v(p ? p + n : p, nDFileSet);
|
|
for (uint32_t iDFileSet = 0; iDFileSet < nDFileSet; iDFileSet++) {
|
|
n += tPutDFileSet(p ? p + n : p, (SDFileSet *)taosArrayGet(pState->aDFileSet, iDFileSet));
|
|
}
|
|
|
|
return n;
|
|
}
|
|
|
|
static int32_t tGetFSState(uint8_t *p, STsdbFSState *pState) {
|
|
int32_t n = 0;
|
|
int8_t hasDel;
|
|
uint32_t nDFileSet;
|
|
SDFileSet *pSet = &(SDFileSet){0};
|
|
|
|
// SDelFile
|
|
n += tGetI8(p + n, &hasDel);
|
|
if (hasDel) {
|
|
pState->pDelFile = &pState->delFile;
|
|
n += tGetDelFile(p + n, pState->pDelFile);
|
|
} else {
|
|
pState->pDelFile = NULL;
|
|
}
|
|
|
|
// SArray<SDFileSet>
|
|
taosArrayClear(pState->aDFileSet);
|
|
n += tGetU32v(p + n, &nDFileSet);
|
|
for (uint32_t iDFileSet = 0; iDFileSet < nDFileSet; iDFileSet++) {
|
|
n += tGetDFileSet(p + n, pSet);
|
|
taosArrayPush(pState->aDFileSet, pSet);
|
|
}
|
|
|
|
return n;
|
|
}
|
|
|
|
static int32_t tsdbGnrtCurrent(const char *fname, STsdbFSState *pState) {
|
|
int32_t code = 0;
|
|
int64_t n;
|
|
int64_t size;
|
|
uint8_t *pData;
|
|
TdFilePtr pFD = NULL;
|
|
|
|
// to binary
|
|
size = tPutFSState(NULL, pState) + sizeof(TSCKSUM);
|
|
pData = taosMemoryMalloc(size);
|
|
if (pData == NULL) {
|
|
code = TSDB_CODE_OUT_OF_MEMORY;
|
|
goto _err;
|
|
}
|
|
n = tPutFSState(pData, pState);
|
|
ASSERT(n + sizeof(TSCKSUM) == size);
|
|
taosCalcChecksumAppend(0, pData, size);
|
|
|
|
// create and write
|
|
pFD = taosOpenFile(fname, TD_FILE_WRITE | TD_FILE_CREATE);
|
|
if (pFD == NULL) {
|
|
code = TAOS_SYSTEM_ERROR(errno);
|
|
goto _err;
|
|
}
|
|
|
|
n = taosWriteFile(pFD, pData, size);
|
|
if (n < 0) {
|
|
code = TAOS_SYSTEM_ERROR(errno);
|
|
goto _err;
|
|
}
|
|
|
|
if (taosFsyncFile(pFD) < 0) {
|
|
code = TAOS_SYSTEM_ERROR(errno);
|
|
goto _err;
|
|
}
|
|
|
|
taosCloseFile(&pFD);
|
|
|
|
if (pData) taosMemoryFree(pData);
|
|
return code;
|
|
|
|
_err:
|
|
tsdbError("tsdb gnrt current failed since %s", tstrerror(code));
|
|
if (pData) taosMemoryFree(pData);
|
|
return code;
|
|
}
|
|
|
|
static int32_t tsdbLoadCurrentState(STsdbFS *pFS, STsdbFSState *pState) {
|
|
int32_t code = 0;
|
|
int64_t size;
|
|
int64_t n;
|
|
char fname[TSDB_FILENAME_LEN];
|
|
uint8_t *pData = NULL;
|
|
TdFilePtr pFD;
|
|
|
|
snprintf(fname, TSDB_FILENAME_LEN - 1, "%s%s%s%sCURRENT", tfsGetPrimaryPath(pFS->pTsdb->pVnode->pTfs), TD_DIRSEP,
|
|
pFS->pTsdb->path, TD_DIRSEP);
|
|
|
|
if (!taosCheckExistFile(fname)) {
|
|
// create an empry CURRENT file if not exists
|
|
code = tsdbGnrtCurrent(fname, pState);
|
|
if (code) goto _err;
|
|
} else {
|
|
// open the file and load
|
|
pFD = taosOpenFile(fname, TD_FILE_READ);
|
|
if (pFD == NULL) {
|
|
code = TAOS_SYSTEM_ERROR(errno);
|
|
goto _err;
|
|
}
|
|
|
|
if (taosFStatFile(pFD, &size, NULL) < 0) {
|
|
code = TAOS_SYSTEM_ERROR(errno);
|
|
goto _err;
|
|
}
|
|
|
|
pData = taosMemoryMalloc(size);
|
|
if (pData == NULL) {
|
|
code = TSDB_CODE_OUT_OF_MEMORY;
|
|
goto _err;
|
|
}
|
|
|
|
n = taosReadFile(pFD, pData, size);
|
|
if (n < 0) {
|
|
code = TAOS_SYSTEM_ERROR(errno);
|
|
goto _err;
|
|
}
|
|
|
|
if (!taosCheckChecksumWhole(pData, size)) {
|
|
code = TSDB_CODE_FILE_CORRUPTED;
|
|
goto _err;
|
|
}
|
|
|
|
taosCloseFile(&pFD);
|
|
|
|
// decode
|
|
tGetFSState(pData, pState);
|
|
}
|
|
|
|
if (pData) taosMemoryFree(pData);
|
|
return code;
|
|
|
|
_err:
|
|
tsdbError("vgId:%d tsdb load current state failed since %s", TD_VID(pFS->pTsdb->pVnode), tstrerror(code));
|
|
if (pData) taosMemoryFree(pData);
|
|
return code;
|
|
}
|
|
|
|
static int32_t tsdbApplyDFileSetChange(STsdbFS *pFS, SDFileSet *pFrom, SDFileSet *pTo) {
|
|
int32_t code = 0;
|
|
char fname[TSDB_FILENAME_LEN];
|
|
|
|
if (pFrom && pTo) {
|
|
// head
|
|
if (tsdbFileIsSame(pFrom, pTo, TSDB_HEAD_FILE)) {
|
|
ASSERT(pFrom->fHead.size == pTo->fHead.size);
|
|
ASSERT(pFrom->fHead.offset == pTo->fHead.offset);
|
|
} else {
|
|
tsdbDataFileName(pFS->pTsdb, pFrom, TSDB_HEAD_FILE, fname);
|
|
taosRemoveFile(fname);
|
|
}
|
|
|
|
// data
|
|
if (tsdbFileIsSame(pFrom, pTo, TSDB_DATA_FILE)) {
|
|
if (pFrom->fData.size > pTo->fData.size) {
|
|
code = tsdbDFileRollback(pFS->pTsdb, pTo, TSDB_DATA_FILE);
|
|
if (code) goto _err;
|
|
}
|
|
} else {
|
|
tsdbDataFileName(pFS->pTsdb, pFrom, TSDB_DATA_FILE, fname);
|
|
taosRemoveFile(fname);
|
|
}
|
|
|
|
// last
|
|
if (tsdbFileIsSame(pFrom, pTo, TSDB_LAST_FILE)) {
|
|
if (pFrom->fLast.size > pTo->fLast.size) {
|
|
code = tsdbDFileRollback(pFS->pTsdb, pTo, TSDB_LAST_FILE);
|
|
if (code) goto _err;
|
|
}
|
|
} else {
|
|
tsdbDataFileName(pFS->pTsdb, pFrom, TSDB_LAST_FILE, fname);
|
|
taosRemoveFile(fname);
|
|
}
|
|
|
|
// sma
|
|
if (tsdbFileIsSame(pFrom, pTo, TSDB_SMA_FILE)) {
|
|
if (pFrom->fSma.size > pTo->fSma.size) {
|
|
code = tsdbDFileRollback(pFS->pTsdb, pTo, TSDB_SMA_FILE);
|
|
if (code) goto _err;
|
|
}
|
|
} else {
|
|
tsdbDataFileName(pFS->pTsdb, pFrom, TSDB_SMA_FILE, fname);
|
|
taosRemoveFile(fname);
|
|
}
|
|
} else if (pFrom) {
|
|
// head
|
|
tsdbDataFileName(pFS->pTsdb, pFrom, TSDB_HEAD_FILE, fname);
|
|
taosRemoveFile(fname);
|
|
|
|
// data
|
|
tsdbDataFileName(pFS->pTsdb, pFrom, TSDB_DATA_FILE, fname);
|
|
taosRemoveFile(fname);
|
|
|
|
// last
|
|
tsdbDataFileName(pFS->pTsdb, pFrom, TSDB_LAST_FILE, fname);
|
|
taosRemoveFile(fname);
|
|
|
|
// fsm
|
|
tsdbDataFileName(pFS->pTsdb, pFrom, TSDB_SMA_FILE, fname);
|
|
taosRemoveFile(fname);
|
|
}
|
|
|
|
return code;
|
|
|
|
_err:
|
|
tsdbError("vgId:%d tsdb apply disk file set change failed since %s", TD_VID(pFS->pTsdb->pVnode), tstrerror(code));
|
|
return code;
|
|
}
|
|
|
|
static int32_t tsdbApplyDelFileChange(STsdbFS *pFS, SDelFile *pFrom, SDelFile *pTo) {
|
|
int32_t code = 0;
|
|
char fname[TSDB_FILENAME_LEN];
|
|
|
|
if (pFrom && pTo) {
|
|
if (!tsdbDelFileIsSame(pFrom, pTo)) {
|
|
tsdbDelFileName(pFS->pTsdb, pFrom, fname);
|
|
if (taosRemoveFile(fname) < 0) {
|
|
code = TAOS_SYSTEM_ERROR(errno);
|
|
goto _err;
|
|
}
|
|
}
|
|
} else if (pFrom) {
|
|
tsdbDelFileName(pFS->pTsdb, pFrom, fname);
|
|
if (taosRemoveFile(fname) < 0) {
|
|
code = TAOS_SYSTEM_ERROR(errno);
|
|
goto _err;
|
|
}
|
|
} else {
|
|
// do nothing
|
|
}
|
|
|
|
return code;
|
|
|
|
_err:
|
|
tsdbError("vgId:%d tsdb apply del file change failed since %s", TD_VID(pFS->pTsdb->pVnode), tstrerror(code));
|
|
return code;
|
|
}
|
|
|
|
static int32_t tsdbFSApplyDiskChange(STsdbFS *pFS, STsdbFSState *pFrom, STsdbFSState *pTo) {
|
|
int32_t code = 0;
|
|
int32_t iFrom = 0;
|
|
int32_t nFrom = taosArrayGetSize(pFrom->aDFileSet);
|
|
int32_t iTo = 0;
|
|
int32_t nTo = taosArrayGetSize(pTo->aDFileSet);
|
|
SDFileSet *pDFileSetFrom;
|
|
SDFileSet *pDFileSetTo;
|
|
|
|
// SDelFile
|
|
code = tsdbApplyDelFileChange(pFS, pFrom->pDelFile, pTo->pDelFile);
|
|
if (code) goto _err;
|
|
|
|
// SDFileSet
|
|
while (iFrom < nFrom && iTo < nTo) {
|
|
pDFileSetFrom = (SDFileSet *)taosArrayGet(pFrom->aDFileSet, iFrom);
|
|
pDFileSetTo = (SDFileSet *)taosArrayGet(pTo->aDFileSet, iTo);
|
|
|
|
if (pDFileSetFrom->fid == pDFileSetTo->fid) {
|
|
code = tsdbApplyDFileSetChange(pFS, pDFileSetFrom, pDFileSetTo);
|
|
if (code) goto _err;
|
|
|
|
iFrom++;
|
|
iTo++;
|
|
} else if (pDFileSetFrom->fid < pDFileSetTo->fid) {
|
|
code = tsdbApplyDFileSetChange(pFS, pDFileSetFrom, NULL);
|
|
if (code) goto _err;
|
|
|
|
iFrom++;
|
|
} else {
|
|
iTo++;
|
|
}
|
|
}
|
|
|
|
while (iFrom < nFrom) {
|
|
pDFileSetFrom = (SDFileSet *)taosArrayGet(pFrom->aDFileSet, iFrom);
|
|
code = tsdbApplyDFileSetChange(pFS, pDFileSetFrom, NULL);
|
|
if (code) goto _err;
|
|
|
|
iFrom++;
|
|
}
|
|
|
|
#if 0
|
|
// do noting
|
|
while (iTo < nTo) {
|
|
pDFileSetTo = (SDFileSet *)taosArrayGetP(pTo->aDFileSet, iTo);
|
|
code = tsdbApplyDFileSetChange(pFS, NULL, pDFileSetTo);
|
|
if (code) goto _err;
|
|
|
|
iTo++;
|
|
}
|
|
#endif
|
|
|
|
return code;
|
|
|
|
_err:
|
|
tsdbError("vgId:%d tsdb fs apply disk change failed sicne %s", TD_VID(pFS->pTsdb->pVnode), tstrerror(code));
|
|
return code;
|
|
}
|
|
|
|
static void tsdbFSDestroy(STsdbFS *pFS) {
|
|
if (pFS) {
|
|
if (pFS->nState) {
|
|
taosArrayDestroy(pFS->nState->aDFileSet);
|
|
taosMemoryFree(pFS->nState);
|
|
}
|
|
|
|
if (pFS->cState) {
|
|
taosArrayDestroy(pFS->cState->aDFileSet);
|
|
taosMemoryFree(pFS->cState);
|
|
}
|
|
|
|
taosThreadRwlockDestroy(&pFS->lock);
|
|
taosMemoryFree(pFS);
|
|
}
|
|
// TODO
|
|
}
|
|
|
|
static int32_t tsdbFSCreate(STsdb *pTsdb, STsdbFS **ppFS) {
|
|
int32_t code = 0;
|
|
STsdbFS *pFS = NULL;
|
|
|
|
pFS = (STsdbFS *)taosMemoryCalloc(1, sizeof(*pFS));
|
|
if (pFS == NULL) {
|
|
code = TSDB_CODE_OUT_OF_MEMORY;
|
|
goto _err;
|
|
}
|
|
pFS->pTsdb = pTsdb;
|
|
|
|
code = taosThreadRwlockInit(&pFS->lock, NULL);
|
|
if (code) {
|
|
taosMemoryFree(pFS);
|
|
code = TAOS_SYSTEM_ERROR(code);
|
|
goto _err;
|
|
}
|
|
|
|
pFS->inTxn = 0;
|
|
|
|
pFS->cState = (STsdbFSState *)taosMemoryCalloc(1, sizeof(STsdbFSState));
|
|
if (pFS->cState == NULL) {
|
|
code = TSDB_CODE_OUT_OF_MEMORY;
|
|
goto _err;
|
|
}
|
|
pFS->cState->aDFileSet = taosArrayInit(0, sizeof(SDFileSet));
|
|
if (pFS->cState->aDFileSet == NULL) {
|
|
code = TSDB_CODE_OUT_OF_MEMORY;
|
|
goto _err;
|
|
}
|
|
|
|
pFS->nState = (STsdbFSState *)taosMemoryCalloc(1, sizeof(STsdbFSState));
|
|
if (pFS->nState == NULL) {
|
|
code = TSDB_CODE_OUT_OF_MEMORY;
|
|
goto _err;
|
|
}
|
|
pFS->nState->aDFileSet = taosArrayInit(0, sizeof(SDFileSet));
|
|
if (pFS->nState->aDFileSet == NULL) {
|
|
code = TSDB_CODE_OUT_OF_MEMORY;
|
|
goto _err;
|
|
}
|
|
|
|
*ppFS = pFS;
|
|
return code;
|
|
|
|
_err:
|
|
tsdbError("vgId:%d tsdb fs create failed since %s", TD_VID(pTsdb->pVnode), tstrerror(code));
|
|
tsdbFSDestroy(pFS);
|
|
*ppFS = NULL;
|
|
return code;
|
|
}
|
|
|
|
static int32_t tsdbScanAndTryFixFS(STsdbFS *pFS, int8_t deepScan) {
|
|
int32_t code = 0;
|
|
STsdb *pTsdb = pFS->pTsdb;
|
|
STfs *pTfs = pTsdb->pVnode->pTfs;
|
|
int64_t size;
|
|
char fname[TSDB_FILENAME_LEN];
|
|
char pHdr[TSDB_FHDR_SIZE];
|
|
TdFilePtr pFD;
|
|
|
|
// SDelFile
|
|
if (pFS->cState->pDelFile) {
|
|
tsdbDelFileName(pTsdb, pFS->cState->pDelFile, fname);
|
|
if (taosStatFile(fname, &size, NULL)) {
|
|
code = TAOS_SYSTEM_ERROR(errno);
|
|
goto _err;
|
|
}
|
|
|
|
if (size != pFS->cState->pDelFile->size) {
|
|
code = TSDB_CODE_FILE_CORRUPTED;
|
|
goto _err;
|
|
}
|
|
|
|
if (deepScan) {
|
|
// TODO
|
|
}
|
|
}
|
|
|
|
// SArray<SDFileSet>
|
|
for (int32_t iSet = 0; iSet < taosArrayGetSize(pFS->cState->aDFileSet); iSet++) {
|
|
SDFileSet *pDFileSet = (SDFileSet *)taosArrayGet(pFS->cState->aDFileSet, iSet);
|
|
|
|
// head =========
|
|
tsdbDataFileName(pTsdb, pDFileSet, TSDB_HEAD_FILE, fname);
|
|
if (taosStatFile(fname, &size, NULL)) {
|
|
code = TAOS_SYSTEM_ERROR(errno);
|
|
goto _err;
|
|
}
|
|
|
|
if (deepScan) {
|
|
// TODO
|
|
}
|
|
|
|
// data =========
|
|
tsdbDataFileName(pTsdb, pDFileSet, TSDB_DATA_FILE, fname);
|
|
if (taosStatFile(fname, &size, NULL)) {
|
|
code = TAOS_SYSTEM_ERROR(errno);
|
|
goto _err;
|
|
}
|
|
|
|
if (size < pDFileSet->fData.size) {
|
|
code = TSDB_CODE_FILE_CORRUPTED;
|
|
goto _err;
|
|
} else if (size > pDFileSet->fData.size) {
|
|
ASSERT(0);
|
|
// need to rollback the file
|
|
}
|
|
|
|
if (deepScan) {
|
|
// TODO
|
|
}
|
|
|
|
// last ===========
|
|
tsdbDataFileName(pTsdb, pDFileSet, TSDB_LAST_FILE, fname);
|
|
if (taosStatFile(fname, &size, NULL)) {
|
|
code = TAOS_SYSTEM_ERROR(errno);
|
|
goto _err;
|
|
}
|
|
|
|
if (size < pDFileSet->fLast.size) {
|
|
code = TSDB_CODE_FILE_CORRUPTED;
|
|
goto _err;
|
|
} else if (size > pDFileSet->fLast.size) {
|
|
ASSERT(0);
|
|
// need to rollback the file
|
|
}
|
|
|
|
if (deepScan) {
|
|
// TODO
|
|
}
|
|
|
|
// sma =============
|
|
tsdbDataFileName(pTsdb, pDFileSet, TSDB_SMA_FILE, fname);
|
|
if (taosStatFile(fname, &size, NULL)) {
|
|
code = TAOS_SYSTEM_ERROR(errno);
|
|
goto _err;
|
|
}
|
|
|
|
if (size < pDFileSet->fSma.size) {
|
|
code = TSDB_CODE_FILE_CORRUPTED;
|
|
goto _err;
|
|
} else if (size > pDFileSet->fSma.size) {
|
|
ASSERT(0);
|
|
// need to rollback the file
|
|
}
|
|
|
|
if (deepScan) {
|
|
// TODO
|
|
}
|
|
}
|
|
|
|
// remove those invalid files (todo)
|
|
#if 0
|
|
STfsDir *tdir;
|
|
const STfsFile *pf;
|
|
|
|
tdir = tfsOpendir(pTfs, pTsdb->path);
|
|
if (tdir == NULL) {
|
|
code = TAOS_SYSTEM_ERROR(errno);
|
|
goto _err;
|
|
}
|
|
|
|
while ((pf = tfsReaddir(tdir))) {
|
|
tfsBasename(pf, fname);
|
|
}
|
|
|
|
tfsClosedir(tdir);
|
|
#endif
|
|
|
|
return code;
|
|
|
|
_err:
|
|
tsdbError("vgId:%d tsdb scan and try fix fs failed since %s", TD_VID(pTsdb->pVnode), tstrerror(code));
|
|
return code;
|
|
}
|
|
|
|
static int32_t tDFileSetCmprFn(const void *p1, const void *p2) {
|
|
if (((SDFileSet *)p1)->fid < ((SDFileSet *)p2)->fid) {
|
|
return -1;
|
|
} else if (((SDFileSet *)p1)->fid > ((SDFileSet *)p2)->fid) {
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
// EXPOSED APIS ====================================================================================
|
|
int32_t tsdbFSOpen(STsdb *pTsdb, STsdbFS **ppFS) {
|
|
int32_t code = 0;
|
|
|
|
// create handle
|
|
code = tsdbFSCreate(pTsdb, ppFS);
|
|
if (code) goto _err;
|
|
|
|
// load current state
|
|
code = tsdbLoadCurrentState(*ppFS, (*ppFS)->cState);
|
|
if (code) {
|
|
tsdbFSDestroy(*ppFS);
|
|
goto _err;
|
|
}
|
|
|
|
// scan and fix FS
|
|
code = tsdbScanAndTryFixFS(*ppFS, 0);
|
|
if (code) {
|
|
tsdbFSDestroy(*ppFS);
|
|
goto _err;
|
|
}
|
|
|
|
return code;
|
|
|
|
_err:
|
|
*ppFS = NULL;
|
|
tsdbError("vgId:%d tsdb fs open failed since %s", TD_VID(pTsdb->pVnode), tstrerror(code));
|
|
return code;
|
|
}
|
|
|
|
int32_t tsdbFSClose(STsdbFS *pFS) {
|
|
int32_t code = 0;
|
|
tsdbFSDestroy(pFS);
|
|
return code;
|
|
}
|
|
|
|
int32_t tsdbFSBegin(STsdbFS *pFS) {
|
|
int32_t code = 0;
|
|
|
|
ASSERT(!pFS->inTxn);
|
|
|
|
// SDelFile
|
|
pFS->nState->pDelFile = NULL;
|
|
if (pFS->cState->pDelFile) {
|
|
pFS->nState->delFile = pFS->cState->delFile;
|
|
pFS->nState->pDelFile = &pFS->nState->delFile;
|
|
}
|
|
|
|
// SArray<aDFileSet>
|
|
taosArrayClear(pFS->nState->aDFileSet);
|
|
for (int32_t iSet = 0; iSet < taosArrayGetSize(pFS->cState->aDFileSet); iSet++) {
|
|
SDFileSet *pDFileSet = (SDFileSet *)taosArrayGet(pFS->cState->aDFileSet, iSet);
|
|
|
|
if (taosArrayPush(pFS->nState->aDFileSet, pDFileSet) == NULL) {
|
|
code = TSDB_CODE_OUT_OF_MEMORY;
|
|
goto _err;
|
|
}
|
|
}
|
|
|
|
pFS->inTxn = 1;
|
|
return code;
|
|
|
|
_err:
|
|
tsdbError("vgId:%d tsdb fs begin failed since %s", TD_VID(pFS->pTsdb->pVnode), tstrerror(code));
|
|
return code;
|
|
}
|
|
|
|
int32_t tsdbFSCommit(STsdbFS *pFS) {
|
|
int32_t code = 0;
|
|
STsdbFSState *pState = pFS->nState;
|
|
char tfname[TSDB_FILENAME_LEN];
|
|
char fname[TSDB_FILENAME_LEN];
|
|
|
|
// need lock (todo)
|
|
pFS->nState = pFS->cState;
|
|
pFS->cState = pState;
|
|
|
|
snprintf(tfname, TSDB_FILENAME_LEN - 1, "%s%s%s%sCURRENT.t", tfsGetPrimaryPath(pFS->pTsdb->pVnode->pTfs), TD_DIRSEP,
|
|
pFS->pTsdb->path, TD_DIRSEP);
|
|
snprintf(fname, TSDB_FILENAME_LEN - 1, "%s%s%s%sCURRENT", tfsGetPrimaryPath(pFS->pTsdb->pVnode->pTfs), TD_DIRSEP,
|
|
pFS->pTsdb->path, TD_DIRSEP);
|
|
|
|
// gnrt CURRENT.t
|
|
code = tsdbGnrtCurrent(tfname, pFS->cState);
|
|
if (code) goto _err;
|
|
|
|
// rename
|
|
code = taosRenameFile(tfname, fname);
|
|
if (code) {
|
|
code = TAOS_SYSTEM_ERROR(code);
|
|
goto _err;
|
|
}
|
|
|
|
// apply commit on disk
|
|
code = tsdbFSApplyDiskChange(pFS, pFS->nState, pFS->cState);
|
|
if (code) goto _err;
|
|
|
|
pFS->inTxn = 0;
|
|
|
|
return code;
|
|
|
|
_err:
|
|
tsdbError("vgId:%d tsdb fs commit failed since %s", TD_VID(pFS->pTsdb->pVnode), tstrerror(code));
|
|
return code;
|
|
}
|
|
|
|
int32_t tsdbFSRollback(STsdbFS *pFS) {
|
|
int32_t code = 0;
|
|
|
|
code = tsdbFSApplyDiskChange(pFS, pFS->nState, pFS->cState);
|
|
if (code) goto _err;
|
|
|
|
pFS->inTxn = 0;
|
|
|
|
return code;
|
|
|
|
_err:
|
|
tsdbError("vgId:%d tsdb fs rollback failed since %s", TD_VID(pFS->pTsdb->pVnode), tstrerror(code));
|
|
return code;
|
|
}
|
|
|
|
int32_t tsdbFSStateUpsertDelFile(STsdbFSState *pState, SDelFile *pDelFile) {
|
|
int32_t code = 0;
|
|
pState->delFile = *pDelFile;
|
|
pState->pDelFile = &pState->delFile;
|
|
return code;
|
|
}
|
|
|
|
int32_t tsdbFSStateUpsertDFileSet(STsdbFSState *pState, SDFileSet *pSet) {
|
|
int32_t code = 0;
|
|
int32_t idx = taosArraySearchIdx(pState->aDFileSet, pSet, tDFileSetCmprFn, TD_GE);
|
|
|
|
if (idx < 0) {
|
|
if (taosArrayPush(pState->aDFileSet, pSet) == NULL) {
|
|
code = TSDB_CODE_OUT_OF_MEMORY;
|
|
goto _exit;
|
|
}
|
|
} else {
|
|
SDFileSet *tDFileSet = (SDFileSet *)taosArrayGet(pState->aDFileSet, idx);
|
|
int32_t c = tDFileSetCmprFn(pSet, tDFileSet);
|
|
if (c == 0) {
|
|
taosArraySet(pState->aDFileSet, idx, pSet);
|
|
} else {
|
|
if (taosArrayInsert(pState->aDFileSet, idx, pSet) == NULL) {
|
|
code = TSDB_CODE_OUT_OF_MEMORY;
|
|
goto _exit;
|
|
}
|
|
}
|
|
}
|
|
|
|
_exit:
|
|
return code;
|
|
}
|
|
|
|
void tsdbFSStateDeleteDFileSet(STsdbFSState *pState, int32_t fid) {
|
|
int32_t idx;
|
|
|
|
idx = taosArraySearchIdx(pState->aDFileSet, &(SDFileSet){.fid = fid}, tDFileSetCmprFn, TD_EQ);
|
|
ASSERT(idx >= 0);
|
|
taosArrayRemove(pState->aDFileSet, idx);
|
|
}
|
|
|
|
SDelFile *tsdbFSStateGetDelFile(STsdbFSState *pState) { return pState->pDelFile; }
|
|
|
|
SDFileSet *tsdbFSStateGetDFileSet(STsdbFSState *pState, int32_t fid, int32_t flag) {
|
|
return (SDFileSet *)taosArraySearch(pState->aDFileSet, &(SDFileSet){.fid = fid}, tDFileSetCmprFn, flag);
|
|
}
|