refact
This commit is contained in:
parent
80394112c0
commit
4c1e95b57d
|
@ -39,6 +39,18 @@ static FORCE_INLINE int TSDB_KEY_FID(TSKEY key, int32_t days, int8_t precision)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static FORCE_INLINE int tsdbGetFidLevel(int fid, SRtn *pRtn) {
|
||||||
|
if (fid >= pRtn->maxFid) {
|
||||||
|
return 0;
|
||||||
|
} else if (fid >= pRtn->midFid) {
|
||||||
|
return 1;
|
||||||
|
} else if (fid >= pRtn->minFid) {
|
||||||
|
return 2;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
#define TSDB_DEFAULT_BLOCK_ROWS(maxRows) ((maxRows)*4 / 5)
|
#define TSDB_DEFAULT_BLOCK_ROWS(maxRows) ((maxRows)*4 / 5)
|
||||||
|
|
||||||
|
@ -52,17 +64,6 @@ int tsdbWriteBlockImpl(STsdbRepo *pRepo, STable *pTable, SDFile *pDFile, SDataCo
|
||||||
bool isLast, bool isSuper, void **ppBuf, void **ppCBuf);
|
bool isLast, bool isSuper, void **ppBuf, void **ppCBuf);
|
||||||
int tsdbApplyRtn(STsdbRepo *pRepo);
|
int tsdbApplyRtn(STsdbRepo *pRepo);
|
||||||
|
|
||||||
static FORCE_INLINE int tsdbGetFidLevel(int fid, SRtn *pRtn) {
|
|
||||||
if (fid >= pRtn->maxFid) {
|
|
||||||
return 0;
|
|
||||||
} else if (fid >= pRtn->midFid) {
|
|
||||||
return 1;
|
|
||||||
} else if (fid >= pRtn->minFid) {
|
|
||||||
return 2;
|
|
||||||
} else {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* _TD_TSDB_COMMIT_H_ */
|
#endif /* _TD_TSDB_COMMIT_H_ */
|
|
@ -41,78 +41,6 @@ typedef struct {
|
||||||
SDataCols * pDataCols;
|
SDataCols * pDataCols;
|
||||||
} SCommitH;
|
} SCommitH;
|
||||||
|
|
||||||
static void tsdbStartCommit(STsdb *pRepo);
|
|
||||||
static void tsdbEndCommit(STsdb *pTsdb, int eno);
|
|
||||||
|
|
||||||
int tsdbPrepareCommit(STsdb *pTsdb) {
|
|
||||||
if (pTsdb->mem == NULL) return 0;
|
|
||||||
|
|
||||||
ASSERT(pTsdb->imem == NULL);
|
|
||||||
|
|
||||||
pTsdb->imem = pTsdb->mem;
|
|
||||||
pTsdb->mem = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int tsdbCommit(STsdb *pTsdb) {
|
|
||||||
if (pTsdb->imem == NULL) return 0;
|
|
||||||
|
|
||||||
tsdbStartCommit(pTsdb);
|
|
||||||
|
|
||||||
tsdbEndCommit(pTsdb, TSDB_CODE_SUCCESS);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void tsdbGetRtnSnap(STsdb *pRepo, SRtn *pRtn) {
|
|
||||||
STsdbCfg *pCfg = REPO_CFG(pRepo);
|
|
||||||
TSKEY minKey, midKey, maxKey, now;
|
|
||||||
|
|
||||||
now = taosGetTimestamp(pCfg->precision);
|
|
||||||
minKey = now - pCfg->keep * tsTickPerDay[pCfg->precision];
|
|
||||||
midKey = now - pCfg->keep2 * tsTickPerDay[pCfg->precision];
|
|
||||||
maxKey = now - pCfg->keep1 * tsTickPerDay[pCfg->precision];
|
|
||||||
|
|
||||||
pRtn->minKey = minKey;
|
|
||||||
pRtn->minFid = (int)(TSDB_KEY_FID(minKey, pCfg->daysPerFile, pCfg->precision));
|
|
||||||
pRtn->midFid = (int)(TSDB_KEY_FID(midKey, pCfg->daysPerFile, pCfg->precision));
|
|
||||||
pRtn->maxFid = (int)(TSDB_KEY_FID(maxKey, pCfg->daysPerFile, pCfg->precision));
|
|
||||||
tsdbDebug("vgId:%d now:%" PRId64 " minKey:%" PRId64 " minFid:%d, midFid:%d, maxFid:%d", REPO_ID(pRepo), now, minKey,
|
|
||||||
pRtn->minFid, pRtn->midFid, pRtn->maxFid);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void tsdbStartCommit(STsdb *pRepo) {
|
|
||||||
STsdbMemTable *pMem = pRepo->imem;
|
|
||||||
|
|
||||||
tsdbInfo("vgId:%d start to commit", REPO_ID(pRepo));
|
|
||||||
|
|
||||||
tsdbStartFSTxn(pRepo, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void tsdbEndCommit(STsdb *pTsdb, int eno) {
|
|
||||||
tsdbEndFSTxn(pTsdb);
|
|
||||||
tsdbFreeMemTable(pTsdb, pTsdb->imem);
|
|
||||||
pTsdb->imem = NULL;
|
|
||||||
tsdbInfo("vgId:%d commit over, %s", REPO_ID(pTsdb), (eno == TSDB_CODE_SUCCESS) ? "succeed" : "failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
/*
|
|
||||||
* 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 "tsdbint.h"
|
|
||||||
|
|
||||||
extern int32_t tsTsdbMetaCompactRatio;
|
|
||||||
|
|
||||||
#define TSDB_COMMIT_REPO(ch) TSDB_READ_REPO(&(ch->readh))
|
#define TSDB_COMMIT_REPO(ch) TSDB_READ_REPO(&(ch->readh))
|
||||||
#define TSDB_COMMIT_REPO_ID(ch) REPO_ID(TSDB_READ_REPO(&(ch->readh)))
|
#define TSDB_COMMIT_REPO_ID(ch) REPO_ID(TSDB_READ_REPO(&(ch->readh)))
|
||||||
#define TSDB_COMMIT_WRITE_FSET(ch) (&((ch)->wSet))
|
#define TSDB_COMMIT_WRITE_FSET(ch) (&((ch)->wSet))
|
||||||
|
@ -125,69 +53,16 @@ extern int32_t tsTsdbMetaCompactRatio;
|
||||||
#define TSDB_COMMIT_DEFAULT_ROWS(ch) TSDB_DEFAULT_BLOCK_ROWS(TSDB_COMMIT_REPO(ch)->config.maxRowsPerFileBlock)
|
#define TSDB_COMMIT_DEFAULT_ROWS(ch) TSDB_DEFAULT_BLOCK_ROWS(TSDB_COMMIT_REPO(ch)->config.maxRowsPerFileBlock)
|
||||||
#define TSDB_COMMIT_TXN_VERSION(ch) FS_TXN_VERSION(REPO_FS(TSDB_COMMIT_REPO(ch)))
|
#define TSDB_COMMIT_TXN_VERSION(ch) FS_TXN_VERSION(REPO_FS(TSDB_COMMIT_REPO(ch)))
|
||||||
|
|
||||||
static int tsdbCommitMeta(STsdbRepo *pRepo);
|
static void tsdbStartCommit(STsdb *pRepo);
|
||||||
static int tsdbUpdateMetaRecord(STsdbFS *pfs, SMFile *pMFile, uint64_t uid, void *cont, int contLen, bool compact);
|
static void tsdbEndCommit(STsdb *pTsdb, int eno);
|
||||||
static int tsdbDropMetaRecord(STsdbFS *pfs, SMFile *pMFile, uint64_t uid);
|
static int tsdbInitCommitH(SCommitH *pCommith, STsdb *pRepo);
|
||||||
static int tsdbCompactMetaFile(STsdbRepo *pRepo, STsdbFS *pfs, SMFile *pMFile);
|
|
||||||
static int tsdbCommitTSData(STsdbRepo *pRepo);
|
|
||||||
static void tsdbStartCommit(STsdbRepo *pRepo);
|
|
||||||
static void tsdbEndCommit(STsdbRepo *pRepo, int eno);
|
|
||||||
static int tsdbCommitToFile(SCommitH *pCommith, SDFileSet *pSet, int fid);
|
|
||||||
static int tsdbCreateCommitIters(SCommitH *pCommith);
|
|
||||||
static void tsdbDestroyCommitIters(SCommitH *pCommith);
|
|
||||||
static void tsdbSeekCommitIter(SCommitH *pCommith, TSKEY key);
|
static void tsdbSeekCommitIter(SCommitH *pCommith, TSKEY key);
|
||||||
static int tsdbInitCommitH(SCommitH *pCommith, STsdbRepo *pRepo);
|
|
||||||
static void tsdbDestroyCommitH(SCommitH *pCommith);
|
|
||||||
static int tsdbGetFidLevel(int fid, SRtn *pRtn);
|
|
||||||
static int tsdbNextCommitFid(SCommitH *pCommith);
|
static int tsdbNextCommitFid(SCommitH *pCommith);
|
||||||
static int tsdbCommitToTable(SCommitH *pCommith, int tid);
|
static void tsdbDestroyCommitH(SCommitH *pCommith);
|
||||||
static int tsdbSetCommitTable(SCommitH *pCommith, STable *pTable);
|
static int tsdbCreateCommitIters(SCommitH *pCommith);
|
||||||
static int tsdbComparKeyBlock(const void *arg1, const void *arg2);
|
static int tsdbCommitToFile(SCommitH *pCommith, SDFileSet *pSet, int fid);
|
||||||
static int tsdbWriteBlockInfo(SCommitH *pCommih);
|
|
||||||
static int tsdbCommitMemData(SCommitH *pCommith, SCommitIter *pIter, TSKEY keyLimit, bool toData);
|
|
||||||
static int tsdbMergeMemData(SCommitH *pCommith, SCommitIter *pIter, int bidx);
|
|
||||||
static int tsdbMoveBlock(SCommitH *pCommith, int bidx);
|
|
||||||
static int tsdbCommitAddBlock(SCommitH *pCommith, const SBlock *pSupBlock, const SBlock *pSubBlocks, int nSubBlocks);
|
|
||||||
static int tsdbMergeBlockData(SCommitH *pCommith, SCommitIter *pIter, SDataCols *pDataCols, TSKEY keyLimit,
|
|
||||||
bool isLastOneBlock);
|
|
||||||
static void tsdbResetCommitFile(SCommitH *pCommith);
|
|
||||||
static void tsdbResetCommitTable(SCommitH *pCommith);
|
|
||||||
static int tsdbSetAndOpenCommitFile(SCommitH *pCommith, SDFileSet *pSet, int fid);
|
|
||||||
static void tsdbCloseCommitFile(SCommitH *pCommith, bool hasError);
|
|
||||||
static bool tsdbCanAddSubBlock(SCommitH *pCommith, SBlock *pBlock, SMergeInfo *pInfo);
|
|
||||||
static void tsdbLoadAndMergeFromCache(SDataCols *pDataCols, int *iter, SCommitIter *pCommitIter, SDataCols *pTarget,
|
|
||||||
TSKEY maxKey, int maxRows, int8_t update);
|
|
||||||
|
|
||||||
void *tsdbCommitData(STsdbRepo *pRepo) {
|
int tsdbApplyRtnOnFSet(STsdb *pRepo, SDFileSet *pSet, SRtn *pRtn) {
|
||||||
if (pRepo->imem == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
tsdbStartCommit(pRepo);
|
|
||||||
|
|
||||||
// Commit to update meta file
|
|
||||||
if (tsdbCommitMeta(pRepo) < 0) {
|
|
||||||
tsdbError("vgId:%d error occurs while committing META data since %s", REPO_ID(pRepo), tstrerror(terrno));
|
|
||||||
goto _err;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the iterator to read from cache
|
|
||||||
if (tsdbCommitTSData(pRepo) < 0) {
|
|
||||||
tsdbError("vgId:%d error occurs while committing TS data since %s", REPO_ID(pRepo), tstrerror(terrno));
|
|
||||||
goto _err;
|
|
||||||
}
|
|
||||||
|
|
||||||
tsdbEndCommit(pRepo, TSDB_CODE_SUCCESS);
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
_err:
|
|
||||||
ASSERT(terrno != TSDB_CODE_SUCCESS);
|
|
||||||
pRepo->code = terrno;
|
|
||||||
|
|
||||||
tsdbEndCommit(pRepo, terrno);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int tsdbApplyRtnOnFSet(STsdbRepo *pRepo, SDFileSet *pSet, SRtn *pRtn) {
|
|
||||||
SDiskID did;
|
SDiskID did;
|
||||||
SDFileSet nSet;
|
SDFileSet nSet;
|
||||||
STsdbFS * pfs = REPO_FS(pRepo);
|
STsdbFS * pfs = REPO_FS(pRepo);
|
||||||
|
@ -229,6 +104,364 @@ int tsdbApplyRtnOnFSet(STsdbRepo *pRepo, SDFileSet *pSet, SRtn *pRtn) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int tsdbPrepareCommit(STsdb *pTsdb) {
|
||||||
|
if (pTsdb->mem == NULL) return 0;
|
||||||
|
|
||||||
|
ASSERT(pTsdb->imem == NULL);
|
||||||
|
|
||||||
|
pTsdb->imem = pTsdb->mem;
|
||||||
|
pTsdb->mem = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tsdbCommit(STsdb *pRepo) {
|
||||||
|
STsdbMemTable *pMem = pRepo->imem;
|
||||||
|
SCommitH commith = {0};
|
||||||
|
SDFileSet * pSet = NULL;
|
||||||
|
int fid;
|
||||||
|
|
||||||
|
if (pRepo->imem == NULL) return 0;
|
||||||
|
|
||||||
|
tsdbStartCommit(pRepo);
|
||||||
|
// Resource initialization
|
||||||
|
if (tsdbInitCommitH(&commith, pRepo) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// Skip expired memory data and expired FSET
|
||||||
|
tsdbSeekCommitIter(&commith, commith.rtn.minKey);
|
||||||
|
while ((pSet = tsdbFSIterNext(&(commith.fsIter)))) {
|
||||||
|
if (pSet->fid < commith.rtn.minFid) {
|
||||||
|
tsdbInfo("vgId:%d FSET %d on level %d disk id %d expires, remove it", REPO_ID(pRepo), pSet->fid,
|
||||||
|
TSDB_FSET_LEVEL(pSet), TSDB_FSET_ID(pSet));
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loop to commit to each file
|
||||||
|
fid = tsdbNextCommitFid(&(commith));
|
||||||
|
while (true) {
|
||||||
|
// Loop over both on disk and memory
|
||||||
|
if (pSet == NULL && fid == TSDB_IVLD_FID) break;
|
||||||
|
|
||||||
|
if (pSet && (fid == TSDB_IVLD_FID || pSet->fid < fid)) {
|
||||||
|
// Only has existing FSET but no memory data to commit in this
|
||||||
|
// existing FSET, only check if file in correct retention
|
||||||
|
if (tsdbApplyRtnOnFSet(pRepo, pSet, &(commith.rtn)) < 0) {
|
||||||
|
tsdbDestroyCommitH(&commith);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pSet = tsdbFSIterNext(&(commith.fsIter));
|
||||||
|
} else {
|
||||||
|
// Has memory data to commit
|
||||||
|
SDFileSet *pCSet;
|
||||||
|
int cfid;
|
||||||
|
|
||||||
|
if (pSet == NULL || pSet->fid > fid) {
|
||||||
|
// Commit to a new FSET with fid: fid
|
||||||
|
pCSet = NULL;
|
||||||
|
cfid = fid;
|
||||||
|
} else {
|
||||||
|
// Commit to an existing FSET
|
||||||
|
pCSet = pSet;
|
||||||
|
cfid = pSet->fid;
|
||||||
|
pSet = tsdbFSIterNext(&(commith.fsIter));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tsdbCommitToFile(&commith, pCSet, cfid) < 0) {
|
||||||
|
tsdbDestroyCommitH(&commith);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fid = tsdbNextCommitFid(&commith);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
tsdbDestroyCommitH(&commith);
|
||||||
|
tsdbEndCommit(pRepo, TSDB_CODE_SUCCESS);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tsdbGetRtnSnap(STsdb *pRepo, SRtn *pRtn) {
|
||||||
|
STsdbCfg *pCfg = REPO_CFG(pRepo);
|
||||||
|
TSKEY minKey, midKey, maxKey, now;
|
||||||
|
|
||||||
|
now = taosGetTimestamp(pCfg->precision);
|
||||||
|
minKey = now - pCfg->keep * tsTickPerDay[pCfg->precision];
|
||||||
|
midKey = now - pCfg->keep2 * tsTickPerDay[pCfg->precision];
|
||||||
|
maxKey = now - pCfg->keep1 * tsTickPerDay[pCfg->precision];
|
||||||
|
|
||||||
|
pRtn->minKey = minKey;
|
||||||
|
pRtn->minFid = (int)(TSDB_KEY_FID(minKey, pCfg->daysPerFile, pCfg->precision));
|
||||||
|
pRtn->midFid = (int)(TSDB_KEY_FID(midKey, pCfg->daysPerFile, pCfg->precision));
|
||||||
|
pRtn->maxFid = (int)(TSDB_KEY_FID(maxKey, pCfg->daysPerFile, pCfg->precision));
|
||||||
|
tsdbDebug("vgId:%d now:%" PRId64 " minKey:%" PRId64 " minFid:%d, midFid:%d, maxFid:%d", REPO_ID(pRepo), now, minKey,
|
||||||
|
pRtn->minFid, pRtn->midFid, pRtn->maxFid);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tsdbStartCommit(STsdb *pRepo) {
|
||||||
|
STsdbMemTable *pMem = pRepo->imem;
|
||||||
|
|
||||||
|
tsdbInfo("vgId:%d start to commit", REPO_ID(pRepo));
|
||||||
|
|
||||||
|
tsdbStartFSTxn(pRepo, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tsdbEndCommit(STsdb *pTsdb, int eno) {
|
||||||
|
tsdbEndFSTxn(pTsdb);
|
||||||
|
tsdbFreeMemTable(pTsdb, pTsdb->imem);
|
||||||
|
pTsdb->imem = NULL;
|
||||||
|
tsdbInfo("vgId:%d commit over, %s", REPO_ID(pTsdb), (eno == TSDB_CODE_SUCCESS) ? "succeed" : "failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tsdbInitCommitH(SCommitH *pCommith, STsdb *pRepo) {
|
||||||
|
STsdbCfg *pCfg = REPO_CFG(pRepo);
|
||||||
|
|
||||||
|
memset(pCommith, 0, sizeof(*pCommith));
|
||||||
|
tsdbGetRtnSnap(pRepo, &(pCommith->rtn));
|
||||||
|
|
||||||
|
TSDB_FSET_SET_CLOSED(TSDB_COMMIT_WRITE_FSET(pCommith));
|
||||||
|
|
||||||
|
// Init read handle
|
||||||
|
if (tsdbInitReadH(&(pCommith->readh), pRepo) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init file iterator
|
||||||
|
tsdbFSIterInit(&(pCommith->fsIter), REPO_FS(pRepo), TSDB_FS_ITER_FORWARD);
|
||||||
|
|
||||||
|
if (tsdbCreateCommitIters(pCommith) < 0) {
|
||||||
|
tsdbDestroyCommitH(pCommith);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pCommith->aBlkIdx = taosArrayInit(1024, sizeof(SBlockIdx));
|
||||||
|
if (pCommith->aBlkIdx == NULL) {
|
||||||
|
terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
|
||||||
|
tsdbDestroyCommitH(pCommith);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pCommith->aSupBlk = taosArrayInit(1024, sizeof(SBlock));
|
||||||
|
if (pCommith->aSupBlk == NULL) {
|
||||||
|
terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
|
||||||
|
tsdbDestroyCommitH(pCommith);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pCommith->aSubBlk = taosArrayInit(1024, sizeof(SBlock));
|
||||||
|
if (pCommith->aSubBlk == NULL) {
|
||||||
|
terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
|
||||||
|
tsdbDestroyCommitH(pCommith);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pCommith->pDataCols = tdNewDataCols(0, pCfg->maxRowsPerFileBlock);
|
||||||
|
if (pCommith->pDataCols == NULL) {
|
||||||
|
terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
|
||||||
|
tsdbDestroyCommitH(pCommith);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip all keys until key (not included)
|
||||||
|
static void tsdbSeekCommitIter(SCommitH *pCommith, TSKEY key) {
|
||||||
|
for (int i = 0; i < pCommith->niters; i++) {
|
||||||
|
SCommitIter *pIter = pCommith->iters + i;
|
||||||
|
if (pIter->pTable == NULL || pIter->pIter == NULL) continue;
|
||||||
|
|
||||||
|
tsdbLoadDataFromCache(pIter->pTable, pIter->pIter, key - 1, INT32_MAX, NULL, NULL, 0, true, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tsdbNextCommitFid(SCommitH *pCommith) {
|
||||||
|
STsdb * pRepo = TSDB_COMMIT_REPO(pCommith);
|
||||||
|
STsdbCfg *pCfg = REPO_CFG(pRepo);
|
||||||
|
int fid = TSDB_IVLD_FID;
|
||||||
|
|
||||||
|
for (int i = 0; i < pCommith->niters; i++) {
|
||||||
|
SCommitIter *pIter = pCommith->iters + i;
|
||||||
|
if (pIter->pTable == NULL || pIter->pIter == NULL) continue;
|
||||||
|
|
||||||
|
TSKEY nextKey = tsdbNextIterKey(pIter->pIter);
|
||||||
|
if (nextKey == TSDB_DATA_TIMESTAMP_NULL) {
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
int tfid = (int)(TSDB_KEY_FID(nextKey, pCfg->daysPerFile, pCfg->precision));
|
||||||
|
if (fid == TSDB_IVLD_FID || fid > tfid) {
|
||||||
|
fid = tfid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fid;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tsdbDestroyCommitH(SCommitH *pCommith) {
|
||||||
|
pCommith->pDataCols = tdFreeDataCols(pCommith->pDataCols);
|
||||||
|
pCommith->aSubBlk = taosArrayDestroy(pCommith->aSubBlk);
|
||||||
|
pCommith->aSupBlk = taosArrayDestroy(pCommith->aSupBlk);
|
||||||
|
pCommith->aBlkIdx = taosArrayDestroy(pCommith->aBlkIdx);
|
||||||
|
tsdbDestroyCommitIters(pCommith);
|
||||||
|
tsdbDestroyReadH(&(pCommith->readh));
|
||||||
|
tsdbCloseDFileSet(TSDB_COMMIT_WRITE_FSET(pCommith));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tsdbCommitToFile(SCommitH *pCommith, SDFileSet *pSet, int fid) {
|
||||||
|
STsdb * pRepo = TSDB_COMMIT_REPO(pCommith);
|
||||||
|
STsdbCfg *pCfg = REPO_CFG(pRepo);
|
||||||
|
|
||||||
|
ASSERT(pSet == NULL || pSet->fid == fid);
|
||||||
|
|
||||||
|
tsdbResetCommitFile(pCommith);
|
||||||
|
tsdbGetFidKeyRange(pCfg->daysPerFile, pCfg->precision, fid, &(pCommith->minKey), &(pCommith->maxKey));
|
||||||
|
|
||||||
|
// Set and open files
|
||||||
|
if (tsdbSetAndOpenCommitFile(pCommith, pSet, fid) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loop to commit each table data
|
||||||
|
for (int tid = 1; tid < pCommith->niters; tid++) {
|
||||||
|
SCommitIter *pIter = pCommith->iters + tid;
|
||||||
|
|
||||||
|
if (pIter->pTable == NULL) continue;
|
||||||
|
|
||||||
|
if (tsdbCommitToTable(pCommith, tid) < 0) {
|
||||||
|
tsdbCloseCommitFile(pCommith, true);
|
||||||
|
// revert the file change
|
||||||
|
tsdbApplyDFileSetChange(TSDB_COMMIT_WRITE_FSET(pCommith), pSet);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tsdbWriteBlockIdx(TSDB_COMMIT_HEAD_FILE(pCommith), pCommith->aBlkIdx, (void **)(&(TSDB_COMMIT_BUF(pCommith)))) <
|
||||||
|
0) {
|
||||||
|
tsdbError("vgId:%d failed to write SBlockIdx part to FSET %d since %s", REPO_ID(pRepo), fid, tstrerror(terrno));
|
||||||
|
tsdbCloseCommitFile(pCommith, true);
|
||||||
|
// revert the file change
|
||||||
|
tsdbApplyDFileSetChange(TSDB_COMMIT_WRITE_FSET(pCommith), pSet);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tsdbUpdateDFileSetHeader(&(pCommith->wSet)) < 0) {
|
||||||
|
tsdbError("vgId:%d failed to update FSET %d header since %s", REPO_ID(pRepo), fid, tstrerror(terrno));
|
||||||
|
tsdbCloseCommitFile(pCommith, true);
|
||||||
|
// revert the file change
|
||||||
|
tsdbApplyDFileSetChange(TSDB_COMMIT_WRITE_FSET(pCommith), pSet);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close commit file
|
||||||
|
tsdbCloseCommitFile(pCommith, false);
|
||||||
|
|
||||||
|
if (tsdbUpdateDFileSet(REPO_FS(pRepo), &(pCommith->wSet)) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tsdbCreateCommitIters(SCommitH *pCommith) {
|
||||||
|
#if 0
|
||||||
|
STsdb *pRepo = TSDB_COMMIT_REPO(pCommith);
|
||||||
|
SMemTable *pMem = pRepo->imem;
|
||||||
|
// STsdbMeta *pMeta = pRepo->tsdbMeta;
|
||||||
|
|
||||||
|
pCommith->niters = pMem->maxTables;
|
||||||
|
pCommith->iters = (SCommitIter *)calloc(pMem->maxTables, sizeof(SCommitIter));
|
||||||
|
if (pCommith->iters == NULL) {
|
||||||
|
terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tsdbRLockRepoMeta(pRepo) < 0) return -1;
|
||||||
|
|
||||||
|
// reference all tables
|
||||||
|
for (int i = 0; i < pMem->maxTables; i++) {
|
||||||
|
if (pMeta->tables[i] != NULL) {
|
||||||
|
tsdbRefTable(pMeta->tables[i]);
|
||||||
|
pCommith->iters[i].pTable = pMeta->tables[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tsdbUnlockRepoMeta(pRepo) < 0) return -1;
|
||||||
|
|
||||||
|
for (int i = 0; i < pMem->maxTables; i++) {
|
||||||
|
if ((pCommith->iters[i].pTable != NULL) && (pMem->tData[i] != NULL) &&
|
||||||
|
(TABLE_UID(pCommith->iters[i].pTable) == pMem->tData[i]->uid)) {
|
||||||
|
if ((pCommith->iters[i].pIter = tSkipListCreateIter(pMem->tData[i]->pData)) == NULL) {
|
||||||
|
terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
tSkipListIterNext(pCommith->iters[i].pIter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/*
|
||||||
|
* 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 "tsdbint.h"
|
||||||
|
|
||||||
|
extern int32_t tsTsdbMetaCompactRatio;
|
||||||
|
|
||||||
|
|
||||||
|
static int tsdbCommitMeta(STsdbRepo *pRepo);
|
||||||
|
static int tsdbUpdateMetaRecord(STsdbFS *pfs, SMFile *pMFile, uint64_t uid, void *cont, int contLen, bool compact);
|
||||||
|
static int tsdbDropMetaRecord(STsdbFS *pfs, SMFile *pMFile, uint64_t uid);
|
||||||
|
static int tsdbCompactMetaFile(STsdbRepo *pRepo, STsdbFS *pfs, SMFile *pMFile);
|
||||||
|
static void tsdbStartCommit(STsdbRepo *pRepo);
|
||||||
|
static void tsdbEndCommit(STsdbRepo *pRepo, int eno);
|
||||||
|
static int tsdbCommitToFile(SCommitH *pCommith, SDFileSet *pSet, int fid);
|
||||||
|
static int tsdbCreateCommitIters(SCommitH *pCommith);
|
||||||
|
static void tsdbDestroyCommitIters(SCommitH *pCommith);
|
||||||
|
static void tsdbSeekCommitIter(SCommitH *pCommith, TSKEY key);
|
||||||
|
static int tsdbInitCommitH(SCommitH *pCommith, STsdbRepo *pRepo);
|
||||||
|
static void tsdbDestroyCommitH(SCommitH *pCommith);
|
||||||
|
static int tsdbGetFidLevel(int fid, SRtn *pRtn);
|
||||||
|
static int tsdbNextCommitFid(SCommitH *pCommith);
|
||||||
|
static int tsdbCommitToTable(SCommitH *pCommith, int tid);
|
||||||
|
static int tsdbSetCommitTable(SCommitH *pCommith, STable *pTable);
|
||||||
|
static int tsdbComparKeyBlock(const void *arg1, const void *arg2);
|
||||||
|
static int tsdbWriteBlockInfo(SCommitH *pCommih);
|
||||||
|
static int tsdbCommitMemData(SCommitH *pCommith, SCommitIter *pIter, TSKEY keyLimit, bool toData);
|
||||||
|
static int tsdbMergeMemData(SCommitH *pCommith, SCommitIter *pIter, int bidx);
|
||||||
|
static int tsdbMoveBlock(SCommitH *pCommith, int bidx);
|
||||||
|
static int tsdbCommitAddBlock(SCommitH *pCommith, const SBlock *pSupBlock, const SBlock *pSubBlocks, int nSubBlocks);
|
||||||
|
static int tsdbMergeBlockData(SCommitH *pCommith, SCommitIter *pIter, SDataCols *pDataCols, TSKEY keyLimit,
|
||||||
|
bool isLastOneBlock);
|
||||||
|
static void tsdbResetCommitFile(SCommitH *pCommith);
|
||||||
|
static void tsdbResetCommitTable(SCommitH *pCommith);
|
||||||
|
static int tsdbSetAndOpenCommitFile(SCommitH *pCommith, SDFileSet *pSet, int fid);
|
||||||
|
static void tsdbCloseCommitFile(SCommitH *pCommith, bool hasError);
|
||||||
|
static bool tsdbCanAddSubBlock(SCommitH *pCommith, SBlock *pBlock, SMergeInfo *pInfo);
|
||||||
|
static void tsdbLoadAndMergeFromCache(SDataCols *pDataCols, int *iter, SCommitIter *pCommitIter, SDataCols *pTarget,
|
||||||
|
TSKEY maxKey, int maxRows, int8_t update);
|
||||||
|
|
||||||
|
|
||||||
int tsdbWriteBlockInfoImpl(SDFile *pHeadf, STable *pTable, SArray *pSupA, SArray *pSubA, void **ppBuf,
|
int tsdbWriteBlockInfoImpl(SDFile *pHeadf, STable *pTable, SArray *pSupA, SArray *pSubA, void **ppBuf,
|
||||||
SBlockIdx *pIdx) {
|
SBlockIdx *pIdx) {
|
||||||
size_t nSupBlocks;
|
size_t nSupBlocks;
|
||||||
|
@ -650,82 +883,6 @@ _err:
|
||||||
}
|
}
|
||||||
|
|
||||||
// =================== Commit Time-Series Data
|
// =================== Commit Time-Series Data
|
||||||
static int tsdbCommitTSData(STsdbRepo *pRepo) {
|
|
||||||
SMemTable *pMem = pRepo->imem;
|
|
||||||
SCommitH commith;
|
|
||||||
SDFileSet *pSet = NULL;
|
|
||||||
int fid;
|
|
||||||
|
|
||||||
memset(&commith, 0, sizeof(commith));
|
|
||||||
|
|
||||||
if (pMem->numOfRows <= 0) {
|
|
||||||
// No memory data, just apply retention on each file on disk
|
|
||||||
if (tsdbApplyRtn(pRepo) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resource initialization
|
|
||||||
if (tsdbInitCommitH(&commith, pRepo) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Skip expired memory data and expired FSET
|
|
||||||
tsdbSeekCommitIter(&commith, commith.rtn.minKey);
|
|
||||||
while ((pSet = tsdbFSIterNext(&(commith.fsIter)))) {
|
|
||||||
if (pSet->fid < commith.rtn.minFid) {
|
|
||||||
tsdbInfo("vgId:%d FSET %d on level %d disk id %d expires, remove it", REPO_ID(pRepo), pSet->fid,
|
|
||||||
TSDB_FSET_LEVEL(pSet), TSDB_FSET_ID(pSet));
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Loop to commit to each file
|
|
||||||
fid = tsdbNextCommitFid(&(commith));
|
|
||||||
while (true) {
|
|
||||||
// Loop over both on disk and memory
|
|
||||||
if (pSet == NULL && fid == TSDB_IVLD_FID) break;
|
|
||||||
|
|
||||||
if (pSet && (fid == TSDB_IVLD_FID || pSet->fid < fid)) {
|
|
||||||
// Only has existing FSET but no memory data to commit in this
|
|
||||||
// existing FSET, only check if file in correct retention
|
|
||||||
if (tsdbApplyRtnOnFSet(pRepo, pSet, &(commith.rtn)) < 0) {
|
|
||||||
tsdbDestroyCommitH(&commith);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
pSet = tsdbFSIterNext(&(commith.fsIter));
|
|
||||||
} else {
|
|
||||||
// Has memory data to commit
|
|
||||||
SDFileSet *pCSet;
|
|
||||||
int cfid;
|
|
||||||
|
|
||||||
if (pSet == NULL || pSet->fid > fid) {
|
|
||||||
// Commit to a new FSET with fid: fid
|
|
||||||
pCSet = NULL;
|
|
||||||
cfid = fid;
|
|
||||||
} else {
|
|
||||||
// Commit to an existing FSET
|
|
||||||
pCSet = pSet;
|
|
||||||
cfid = pSet->fid;
|
|
||||||
pSet = tsdbFSIterNext(&(commith.fsIter));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tsdbCommitToFile(&commith, pCSet, cfid) < 0) {
|
|
||||||
tsdbDestroyCommitH(&commith);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
fid = tsdbNextCommitFid(&commith);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tsdbDestroyCommitH(&commith);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
static bool tsdbHasDataToCommit(SCommitIter *iters, int nIters, TSKEY minKey, TSKEY maxKey) {
|
static bool tsdbHasDataToCommit(SCommitIter *iters, int nIters, TSKEY minKey, TSKEY maxKey) {
|
||||||
for (int i = 0; i < nIters; i++) {
|
for (int i = 0; i < nIters; i++) {
|
||||||
|
@ -736,99 +893,7 @@ static bool tsdbHasDataToCommit(SCommitIter *iters, int nIters, TSKEY minKey, TS
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int tsdbCommitToFile(SCommitH *pCommith, SDFileSet *pSet, int fid) {
|
|
||||||
STsdbRepo *pRepo = TSDB_COMMIT_REPO(pCommith);
|
|
||||||
STsdbCfg * pCfg = REPO_CFG(pRepo);
|
|
||||||
|
|
||||||
ASSERT(pSet == NULL || pSet->fid == fid);
|
|
||||||
|
|
||||||
tsdbResetCommitFile(pCommith);
|
|
||||||
tsdbGetFidKeyRange(pCfg->daysPerFile, pCfg->precision, fid, &(pCommith->minKey), &(pCommith->maxKey));
|
|
||||||
|
|
||||||
// Set and open files
|
|
||||||
if (tsdbSetAndOpenCommitFile(pCommith, pSet, fid) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Loop to commit each table data
|
|
||||||
for (int tid = 1; tid < pCommith->niters; tid++) {
|
|
||||||
SCommitIter *pIter = pCommith->iters + tid;
|
|
||||||
|
|
||||||
if (pIter->pTable == NULL) continue;
|
|
||||||
|
|
||||||
if (tsdbCommitToTable(pCommith, tid) < 0) {
|
|
||||||
tsdbCloseCommitFile(pCommith, true);
|
|
||||||
// revert the file change
|
|
||||||
tsdbApplyDFileSetChange(TSDB_COMMIT_WRITE_FSET(pCommith), pSet);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tsdbWriteBlockIdx(TSDB_COMMIT_HEAD_FILE(pCommith), pCommith->aBlkIdx, (void **)(&(TSDB_COMMIT_BUF(pCommith)))) <
|
|
||||||
0) {
|
|
||||||
tsdbError("vgId:%d failed to write SBlockIdx part to FSET %d since %s", REPO_ID(pRepo), fid, tstrerror(terrno));
|
|
||||||
tsdbCloseCommitFile(pCommith, true);
|
|
||||||
// revert the file change
|
|
||||||
tsdbApplyDFileSetChange(TSDB_COMMIT_WRITE_FSET(pCommith), pSet);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tsdbUpdateDFileSetHeader(&(pCommith->wSet)) < 0) {
|
|
||||||
tsdbError("vgId:%d failed to update FSET %d header since %s", REPO_ID(pRepo), fid, tstrerror(terrno));
|
|
||||||
tsdbCloseCommitFile(pCommith, true);
|
|
||||||
// revert the file change
|
|
||||||
tsdbApplyDFileSetChange(TSDB_COMMIT_WRITE_FSET(pCommith), pSet);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close commit file
|
|
||||||
tsdbCloseCommitFile(pCommith, false);
|
|
||||||
|
|
||||||
if (tsdbUpdateDFileSet(REPO_FS(pRepo), &(pCommith->wSet)) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int tsdbCreateCommitIters(SCommitH *pCommith) {
|
|
||||||
STsdbRepo *pRepo = TSDB_COMMIT_REPO(pCommith);
|
|
||||||
SMemTable *pMem = pRepo->imem;
|
|
||||||
STsdbMeta *pMeta = pRepo->tsdbMeta;
|
|
||||||
|
|
||||||
pCommith->niters = pMem->maxTables;
|
|
||||||
pCommith->iters = (SCommitIter *)calloc(pMem->maxTables, sizeof(SCommitIter));
|
|
||||||
if (pCommith->iters == NULL) {
|
|
||||||
terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tsdbRLockRepoMeta(pRepo) < 0) return -1;
|
|
||||||
|
|
||||||
// reference all tables
|
|
||||||
for (int i = 0; i < pMem->maxTables; i++) {
|
|
||||||
if (pMeta->tables[i] != NULL) {
|
|
||||||
tsdbRefTable(pMeta->tables[i]);
|
|
||||||
pCommith->iters[i].pTable = pMeta->tables[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tsdbUnlockRepoMeta(pRepo) < 0) return -1;
|
|
||||||
|
|
||||||
for (int i = 0; i < pMem->maxTables; i++) {
|
|
||||||
if ((pCommith->iters[i].pTable != NULL) && (pMem->tData[i] != NULL) &&
|
|
||||||
(TABLE_UID(pCommith->iters[i].pTable) == pMem->tData[i]->uid)) {
|
|
||||||
if ((pCommith->iters[i].pIter = tSkipListCreateIter(pMem->tData[i]->pData)) == NULL) {
|
|
||||||
terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
tSkipListIterNext(pCommith->iters[i].pIter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void tsdbDestroyCommitIters(SCommitH *pCommith) {
|
static void tsdbDestroyCommitIters(SCommitH *pCommith) {
|
||||||
if (pCommith->iters == NULL) return;
|
if (pCommith->iters == NULL) return;
|
||||||
|
@ -845,100 +910,7 @@ static void tsdbDestroyCommitIters(SCommitH *pCommith) {
|
||||||
pCommith->niters = 0;
|
pCommith->niters = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip all keys until key (not included)
|
|
||||||
static void tsdbSeekCommitIter(SCommitH *pCommith, TSKEY key) {
|
|
||||||
for (int i = 0; i < pCommith->niters; i++) {
|
|
||||||
SCommitIter *pIter = pCommith->iters + i;
|
|
||||||
if (pIter->pTable == NULL || pIter->pIter == NULL) continue;
|
|
||||||
|
|
||||||
tsdbLoadDataFromCache(pIter->pTable, pIter->pIter, key - 1, INT32_MAX, NULL, NULL, 0, true, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int tsdbInitCommitH(SCommitH *pCommith, STsdbRepo *pRepo) {
|
|
||||||
STsdbCfg *pCfg = REPO_CFG(pRepo);
|
|
||||||
|
|
||||||
memset(pCommith, 0, sizeof(*pCommith));
|
|
||||||
tsdbGetRtnSnap(pRepo, &(pCommith->rtn));
|
|
||||||
|
|
||||||
TSDB_FSET_SET_CLOSED(TSDB_COMMIT_WRITE_FSET(pCommith));
|
|
||||||
|
|
||||||
// Init read handle
|
|
||||||
if (tsdbInitReadH(&(pCommith->readh), pRepo) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Init file iterator
|
|
||||||
tsdbFSIterInit(&(pCommith->fsIter), REPO_FS(pRepo), TSDB_FS_ITER_FORWARD);
|
|
||||||
|
|
||||||
if (tsdbCreateCommitIters(pCommith) < 0) {
|
|
||||||
tsdbDestroyCommitH(pCommith);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
pCommith->aBlkIdx = taosArrayInit(1024, sizeof(SBlockIdx));
|
|
||||||
if (pCommith->aBlkIdx == NULL) {
|
|
||||||
terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
|
|
||||||
tsdbDestroyCommitH(pCommith);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
pCommith->aSupBlk = taosArrayInit(1024, sizeof(SBlock));
|
|
||||||
if (pCommith->aSupBlk == NULL) {
|
|
||||||
terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
|
|
||||||
tsdbDestroyCommitH(pCommith);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
pCommith->aSubBlk = taosArrayInit(1024, sizeof(SBlock));
|
|
||||||
if (pCommith->aSubBlk == NULL) {
|
|
||||||
terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
|
|
||||||
tsdbDestroyCommitH(pCommith);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
pCommith->pDataCols = tdNewDataCols(0, pCfg->maxRowsPerFileBlock);
|
|
||||||
if (pCommith->pDataCols == NULL) {
|
|
||||||
terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
|
|
||||||
tsdbDestroyCommitH(pCommith);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void tsdbDestroyCommitH(SCommitH *pCommith) {
|
|
||||||
pCommith->pDataCols = tdFreeDataCols(pCommith->pDataCols);
|
|
||||||
pCommith->aSubBlk = taosArrayDestroy(pCommith->aSubBlk);
|
|
||||||
pCommith->aSupBlk = taosArrayDestroy(pCommith->aSupBlk);
|
|
||||||
pCommith->aBlkIdx = taosArrayDestroy(pCommith->aBlkIdx);
|
|
||||||
tsdbDestroyCommitIters(pCommith);
|
|
||||||
tsdbDestroyReadH(&(pCommith->readh));
|
|
||||||
tsdbCloseDFileSet(TSDB_COMMIT_WRITE_FSET(pCommith));
|
|
||||||
}
|
|
||||||
|
|
||||||
static int tsdbNextCommitFid(SCommitH *pCommith) {
|
|
||||||
STsdbRepo *pRepo = TSDB_COMMIT_REPO(pCommith);
|
|
||||||
STsdbCfg * pCfg = REPO_CFG(pRepo);
|
|
||||||
int fid = TSDB_IVLD_FID;
|
|
||||||
|
|
||||||
for (int i = 0; i < pCommith->niters; i++) {
|
|
||||||
SCommitIter *pIter = pCommith->iters + i;
|
|
||||||
if (pIter->pTable == NULL || pIter->pIter == NULL) continue;
|
|
||||||
|
|
||||||
TSKEY nextKey = tsdbNextIterKey(pIter->pIter);
|
|
||||||
if (nextKey == TSDB_DATA_TIMESTAMP_NULL) {
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
int tfid = (int)(TSDB_KEY_FID(nextKey, pCfg->daysPerFile, pCfg->precision));
|
|
||||||
if (fid == TSDB_IVLD_FID || fid > tfid) {
|
|
||||||
fid = tfid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return fid;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int tsdbCommitToTable(SCommitH *pCommith, int tid) {
|
static int tsdbCommitToTable(SCommitH *pCommith, int tid) {
|
||||||
SCommitIter *pIter = pCommith->iters + tid;
|
SCommitIter *pIter = pCommith->iters + tid;
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
aux_source_directory(src TSDB_SRC)
|
|
||||||
add_library(tsdb STATIC ${TSDB_SRC})
|
|
||||||
|
|
||||||
target_include_directories(
|
|
||||||
tsdb
|
|
||||||
PUBLIC "${CMAKE_SOURCE_DIR}/include/dnode/vnode/tsdb2"
|
|
||||||
PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/inc"
|
|
||||||
)
|
|
||||||
target_link_libraries(tsdb os util common tfs)
|
|
|
@ -1,51 +0,0 @@
|
||||||
/*
|
|
||||||
* 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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// #ifndef _TD_TSDB_BUFFER_H_
|
|
||||||
// #define _TD_TSDB_BUFFER_H_
|
|
||||||
|
|
||||||
// typedef struct {
|
|
||||||
// int64_t blockId;
|
|
||||||
// int offset;
|
|
||||||
// int remain;
|
|
||||||
// char data[];
|
|
||||||
// } STsdbBufBlock;
|
|
||||||
|
|
||||||
// typedef struct {
|
|
||||||
// pthread_cond_t poolNotEmpty;
|
|
||||||
// int bufBlockSize;
|
|
||||||
// int tBufBlocks;
|
|
||||||
// int nBufBlocks;
|
|
||||||
// int nRecycleBlocks;
|
|
||||||
// int nElasticBlocks;
|
|
||||||
// int64_t index;
|
|
||||||
// SList* bufBlockList;
|
|
||||||
// } STsdbBufPool;
|
|
||||||
|
|
||||||
// #define TSDB_BUFFER_RESERVE 1024 // Reseve 1K as commit threshold
|
|
||||||
|
|
||||||
// STsdbBufPool* tsdbNewBufPool();
|
|
||||||
// void tsdbFreeBufPool(STsdbBufPool* pBufPool);
|
|
||||||
// int tsdbOpenBufPool(STsdb* pRepo);
|
|
||||||
// void tsdbCloseBufPool(STsdb* pRepo);
|
|
||||||
// SListNode* tsdbAllocBufBlockFromPool(STsdb* pRepo);
|
|
||||||
// int tsdbExpandPool(STsdb* pRepo, int32_t oldTotalBlocks);
|
|
||||||
// void tsdbRecycleBufferBlock(STsdbBufPool* pPool, SListNode *pNode, bool bELastic);
|
|
||||||
|
|
||||||
// // health cite
|
|
||||||
// STsdbBufBlock *tsdbNewBufBlock(int bufBlockSize);
|
|
||||||
// void tsdbFreeBufBlock(STsdbBufBlock *pBufBlock);
|
|
||||||
|
|
||||||
// #endif /* _TD_TSDB_BUFFER_H_ */
|
|
|
@ -1,57 +0,0 @@
|
||||||
/*
|
|
||||||
* 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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _TD_TSDB_COMMIT_H_
|
|
||||||
#define _TD_TSDB_COMMIT_H_
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int minFid;
|
|
||||||
int midFid;
|
|
||||||
int maxFid;
|
|
||||||
TSKEY minKey;
|
|
||||||
} SRtn;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint64_t uid;
|
|
||||||
int64_t offset;
|
|
||||||
int64_t size;
|
|
||||||
} SKVRecord;
|
|
||||||
|
|
||||||
#define TSDB_DEFAULT_BLOCK_ROWS(maxRows) ((maxRows)*4 / 5)
|
|
||||||
|
|
||||||
void tsdbGetRtnSnap(STsdb *pRepo, SRtn *pRtn);
|
|
||||||
int tsdbEncodeKVRecord(void **buf, SKVRecord *pRecord);
|
|
||||||
void *tsdbDecodeKVRecord(void *buf, SKVRecord *pRecord);
|
|
||||||
void *tsdbCommitData(STsdb *pRepo);
|
|
||||||
int tsdbApplyRtnOnFSet(STsdb *pRepo, SDFileSet *pSet, SRtn *pRtn);
|
|
||||||
int tsdbWriteBlockInfoImpl(SDFile *pHeadf, STable *pTable, SArray *pSupA, SArray *pSubA, void **ppBuf, SBlockIdx *pIdx);
|
|
||||||
int tsdbWriteBlockIdx(SDFile *pHeadf, SArray *pIdxA, void **ppBuf);
|
|
||||||
int tsdbWriteBlockImpl(STsdb *pRepo, STable *pTable, SDFile *pDFile, SDFile *pDFileAggr, SDataCols *pDataCols,
|
|
||||||
SBlock *pBlock, bool isLast, bool isSuper, void **ppBuf, void **ppCBuf, void **ppExBuf);
|
|
||||||
int tsdbApplyRtn(STsdb *pRepo);
|
|
||||||
|
|
||||||
static FORCE_INLINE int tsdbGetFidLevel(int fid, SRtn *pRtn) {
|
|
||||||
if (fid >= pRtn->maxFid) {
|
|
||||||
return 0;
|
|
||||||
} else if (fid >= pRtn->midFid) {
|
|
||||||
return 1;
|
|
||||||
} else if (fid >= pRtn->minFid) {
|
|
||||||
return 2;
|
|
||||||
} else {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* _TD_TSDB_COMMIT_H_ */
|
|
|
@ -1,28 +0,0 @@
|
||||||
/*
|
|
||||||
* 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/>.
|
|
||||||
*/
|
|
||||||
// #ifndef _TD_TSDB_COMPACT_H_
|
|
||||||
// #define _TD_TSDB_COMPACT_H_
|
|
||||||
|
|
||||||
// #ifdef __cplusplus
|
|
||||||
// extern "C" {
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
// void *tsdbCompactImpl(STsdb *pRepo);
|
|
||||||
|
|
||||||
// #ifdef __cplusplus
|
|
||||||
// }
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
// #endif /* _TD_TSDB_COMPACT_H_ */
|
|
|
@ -1,138 +0,0 @@
|
||||||
/*
|
|
||||||
* 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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _TD_TSDB_FS_H_
|
|
||||||
#define _TD_TSDB_FS_H_
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 1. The fileset .head/.data/.last use the same fver 0 before 2021.10.10.
|
|
||||||
* 2. .head fver is 1 when extract aggregate block data from .data/.last file and save to separate .smad/.smal file
|
|
||||||
* since 2021.10.10
|
|
||||||
* // TODO update date and add release version.
|
|
||||||
*/
|
|
||||||
typedef enum {
|
|
||||||
TSDB_FS_VER_0 = 0,
|
|
||||||
TSDB_FS_VER_1,
|
|
||||||
} ETsdbFsVer;
|
|
||||||
|
|
||||||
#define TSDB_FVER_TYPE uint32_t
|
|
||||||
#define TSDB_LATEST_FVER TSDB_FS_VER_1 // latest version for DFile
|
|
||||||
#define TSDB_LATEST_SFS_VER TSDB_FS_VER_1 // latest version for 'current' file
|
|
||||||
|
|
||||||
static FORCE_INLINE uint32_t tsdbGetDFSVersion(TSDB_FILE_T fType) { // latest version for DFile
|
|
||||||
switch (fType) {
|
|
||||||
case TSDB_FILE_HEAD:
|
|
||||||
return TSDB_FS_VER_1;
|
|
||||||
default:
|
|
||||||
return TSDB_FS_VER_0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ================== TSDB global config
|
|
||||||
extern bool tsdbForceKeepFile;
|
|
||||||
|
|
||||||
// ================== CURRENT file header info
|
|
||||||
typedef struct {
|
|
||||||
uint32_t version; // Current file system version (relating to code)
|
|
||||||
uint32_t len; // Encode content length (including checksum)
|
|
||||||
} SFSHeader;
|
|
||||||
|
|
||||||
// ================== TSDB File System Meta
|
|
||||||
typedef struct {
|
|
||||||
uint32_t version; // Commit version from 0 to increase
|
|
||||||
int64_t totalPoints; // total points
|
|
||||||
int64_t totalStorage; // Uncompressed total storage
|
|
||||||
} STsdbFSMeta;
|
|
||||||
|
|
||||||
// ==================
|
|
||||||
typedef struct {
|
|
||||||
STsdbFSMeta meta; // FS meta
|
|
||||||
SMFile* pmf; // meta file pointer
|
|
||||||
SMFile mf; // meta file
|
|
||||||
SArray* df; // data file array
|
|
||||||
} SFSStatus;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
pthread_rwlock_t lock;
|
|
||||||
|
|
||||||
SFSStatus* cstatus; // current status
|
|
||||||
SHashObj* metaCache; // meta cache
|
|
||||||
SHashObj* metaCacheComp; // meta cache for compact
|
|
||||||
bool intxn;
|
|
||||||
SFSStatus* nstatus; // new status
|
|
||||||
} STsdbFS;
|
|
||||||
|
|
||||||
#define FS_CURRENT_STATUS(pfs) ((pfs)->cstatus)
|
|
||||||
#define FS_NEW_STATUS(pfs) ((pfs)->nstatus)
|
|
||||||
#define FS_IN_TXN(pfs) (pfs)->intxn
|
|
||||||
#define FS_VERSION(pfs) ((pfs)->cstatus->meta.version)
|
|
||||||
#define FS_TXN_VERSION(pfs) ((pfs)->nstatus->meta.version)
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int direction;
|
|
||||||
uint64_t version; // current FS version
|
|
||||||
STsdbFS* pfs;
|
|
||||||
int index; // used to position next fset when version the same
|
|
||||||
int fid; // used to seek when version is changed
|
|
||||||
SDFileSet* pSet;
|
|
||||||
} SFSIter;
|
|
||||||
|
|
||||||
#define TSDB_FS_ITER_FORWARD TSDB_ORDER_ASC
|
|
||||||
#define TSDB_FS_ITER_BACKWARD TSDB_ORDER_DESC
|
|
||||||
|
|
||||||
STsdbFS *tsdbNewFS(STsdbCfg *pCfg);
|
|
||||||
void * tsdbFreeFS(STsdbFS *pfs);
|
|
||||||
int tsdbOpenFS(STsdb *pRepo);
|
|
||||||
void tsdbCloseFS(STsdb *pRepo);
|
|
||||||
void tsdbStartFSTxn(STsdb *pRepo, int64_t pointsAdd, int64_t storageAdd);
|
|
||||||
int tsdbEndFSTxn(STsdb *pRepo);
|
|
||||||
int tsdbEndFSTxnWithError(STsdbFS *pfs);
|
|
||||||
void tsdbUpdateFSTxnMeta(STsdbFS *pfs, STsdbFSMeta *pMeta);
|
|
||||||
void tsdbUpdateMFile(STsdbFS *pfs, const SMFile *pMFile);
|
|
||||||
int tsdbUpdateDFileSet(STsdbFS *pfs, const SDFileSet *pSet);
|
|
||||||
|
|
||||||
void tsdbFSIterInit(SFSIter *pIter, STsdbFS *pfs, int direction);
|
|
||||||
void tsdbFSIterSeek(SFSIter *pIter, int fid);
|
|
||||||
SDFileSet *tsdbFSIterNext(SFSIter *pIter);
|
|
||||||
int tsdbLoadMetaCache(STsdb *pRepo, bool recoverMeta);
|
|
||||||
|
|
||||||
static FORCE_INLINE int tsdbRLockFS(STsdbFS* pFs) {
|
|
||||||
int code = pthread_rwlock_rdlock(&(pFs->lock));
|
|
||||||
if (code != 0) {
|
|
||||||
terrno = TAOS_SYSTEM_ERROR(code);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static FORCE_INLINE int tsdbWLockFS(STsdbFS* pFs) {
|
|
||||||
int code = pthread_rwlock_wrlock(&(pFs->lock));
|
|
||||||
if (code != 0) {
|
|
||||||
terrno = TAOS_SYSTEM_ERROR(code);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static FORCE_INLINE int tsdbUnLockFS(STsdbFS* pFs) {
|
|
||||||
int code = pthread_rwlock_unlock(&(pFs->lock));
|
|
||||||
if (code != 0) {
|
|
||||||
terrno = TAOS_SYSTEM_ERROR(code);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* _TD_TSDB_FS_H_ */
|
|
|
@ -1,406 +0,0 @@
|
||||||
/*
|
|
||||||
* 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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _TS_TSDB_FILE_H_
|
|
||||||
#define _TS_TSDB_FILE_H_
|
|
||||||
|
|
||||||
#include "os.h"
|
|
||||||
|
|
||||||
#define TSDB_FILE_HEAD_SIZE 512
|
|
||||||
#define TSDB_FILE_DELIMITER 0xF00AFA0F
|
|
||||||
#define TSDB_FILE_INIT_MAGIC 0xFFFFFFFF
|
|
||||||
#define TSDB_IVLD_FID INT_MIN
|
|
||||||
#define TSDB_FILE_STATE_OK 0
|
|
||||||
#define TSDB_FILE_STATE_BAD 1
|
|
||||||
|
|
||||||
#define TSDB_FILE_INFO(tf) (&((tf)->info))
|
|
||||||
#define TSDB_FILE_F(tf) (&((tf)->f))
|
|
||||||
#define TSDB_FILE_FD(tf) ((tf)->fd)
|
|
||||||
#define TSDB_FILE_FULL_NAME(tf) TFILE_NAME(TSDB_FILE_F(tf))
|
|
||||||
#define TSDB_FILE_OPENED(tf) (TSDB_FILE_FD(tf) >= 0)
|
|
||||||
#define TSDB_FILE_CLOSED(tf) (!TSDB_FILE_OPENED(tf))
|
|
||||||
#define TSDB_FILE_SET_CLOSED(f) (TSDB_FILE_FD(f) = -1)
|
|
||||||
#define TSDB_FILE_LEVEL(tf) TFILE_LEVEL(TSDB_FILE_F(tf))
|
|
||||||
#define TSDB_FILE_ID(tf) TFILE_ID(TSDB_FILE_F(tf))
|
|
||||||
#define TSDB_FILE_FSYNC(tf) taosFsyncFile(TSDB_FILE_FD(tf))
|
|
||||||
#define TSDB_FILE_STATE(tf) ((tf)->state)
|
|
||||||
#define TSDB_FILE_SET_STATE(tf, s) ((tf)->state = (s))
|
|
||||||
#define TSDB_FILE_IS_OK(tf) (TSDB_FILE_STATE(tf) == TSDB_FILE_STATE_OK)
|
|
||||||
#define TSDB_FILE_IS_BAD(tf) (TSDB_FILE_STATE(tf) == TSDB_FILE_STATE_BAD)
|
|
||||||
#define ASSERT_TSDB_FSET_NFILES_VALID(s) \
|
|
||||||
do { \
|
|
||||||
uint8_t nDFiles = tsdbGetNFiles(s); \
|
|
||||||
ASSERT((nDFiles >= TSDB_FILE_MIN) && (nDFiles <= TSDB_FILE_MAX)); \
|
|
||||||
} while (0)
|
|
||||||
typedef enum {
|
|
||||||
TSDB_FILE_HEAD = 0,
|
|
||||||
TSDB_FILE_DATA,
|
|
||||||
TSDB_FILE_LAST,
|
|
||||||
TSDB_FILE_SMAD, // sma for .data
|
|
||||||
TSDB_FILE_SMAL, // sma for .last
|
|
||||||
TSDB_FILE_MAX,
|
|
||||||
TSDB_FILE_META
|
|
||||||
} TSDB_FILE_T;
|
|
||||||
|
|
||||||
#define TSDB_FILE_MIN 3U // min valid number of files in one DFileSet(.head/.data/.last)
|
|
||||||
|
|
||||||
// =============== SMFile
|
|
||||||
typedef struct {
|
|
||||||
int64_t size;
|
|
||||||
int64_t tombSize;
|
|
||||||
int64_t nRecords;
|
|
||||||
int64_t nDels;
|
|
||||||
uint32_t magic;
|
|
||||||
} SMFInfo;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
SMFInfo info;
|
|
||||||
TFILE f;
|
|
||||||
int fd;
|
|
||||||
uint8_t state;
|
|
||||||
} SMFile;
|
|
||||||
|
|
||||||
void tsdbInitMFile(SMFile* pMFile, SDiskID did, int vid, uint32_t ver);
|
|
||||||
void tsdbInitMFileEx(SMFile* pMFile, const SMFile* pOMFile);
|
|
||||||
int tsdbEncodeSMFile(void** buf, SMFile* pMFile);
|
|
||||||
void* tsdbDecodeSMFile(void* buf, SMFile* pMFile);
|
|
||||||
int tsdbEncodeSMFileEx(void** buf, SMFile* pMFile);
|
|
||||||
void* tsdbDecodeSMFileEx(void* buf, SMFile* pMFile);
|
|
||||||
int tsdbApplyMFileChange(SMFile* from, SMFile* to);
|
|
||||||
int tsdbCreateMFile(SMFile* pMFile, bool updateHeader);
|
|
||||||
int tsdbUpdateMFileHeader(SMFile* pMFile);
|
|
||||||
int tsdbLoadMFileHeader(SMFile* pMFile, SMFInfo* pInfo);
|
|
||||||
int tsdbScanAndTryFixMFile(STsdb* pRepo);
|
|
||||||
int tsdbEncodeMFInfo(void** buf, SMFInfo* pInfo);
|
|
||||||
void* tsdbDecodeMFInfo(void* buf, SMFInfo* pInfo);
|
|
||||||
|
|
||||||
static FORCE_INLINE void tsdbSetMFileInfo(SMFile* pMFile, SMFInfo* pInfo) { pMFile->info = *pInfo; }
|
|
||||||
|
|
||||||
static FORCE_INLINE int tsdbOpenMFile(SMFile* pMFile, int flags) {
|
|
||||||
ASSERT(TSDB_FILE_CLOSED(pMFile));
|
|
||||||
|
|
||||||
pMFile->fd = open(TSDB_FILE_FULL_NAME(pMFile), flags | O_BINARY);
|
|
||||||
if (pMFile->fd < 0) {
|
|
||||||
terrno = TAOS_SYSTEM_ERROR(errno);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static FORCE_INLINE void tsdbCloseMFile(SMFile* pMFile) {
|
|
||||||
if (TSDB_FILE_OPENED(pMFile)) {
|
|
||||||
close(pMFile->fd);
|
|
||||||
TSDB_FILE_SET_CLOSED(pMFile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static FORCE_INLINE int64_t tsdbSeekMFile(SMFile* pMFile, int64_t offset, int whence) {
|
|
||||||
ASSERT(TSDB_FILE_OPENED(pMFile));
|
|
||||||
|
|
||||||
int64_t loffset = taosLSeekFile(TSDB_FILE_FD(pMFile), offset, whence);
|
|
||||||
if (loffset < 0) {
|
|
||||||
terrno = TAOS_SYSTEM_ERROR(errno);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return loffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
static FORCE_INLINE int64_t tsdbWriteMFile(SMFile* pMFile, void* buf, int64_t nbyte) {
|
|
||||||
ASSERT(TSDB_FILE_OPENED(pMFile));
|
|
||||||
|
|
||||||
int64_t nwrite = taosWriteFile(pMFile->fd, buf, nbyte);
|
|
||||||
if (nwrite < nbyte) {
|
|
||||||
terrno = TAOS_SYSTEM_ERROR(errno);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return nwrite;
|
|
||||||
}
|
|
||||||
|
|
||||||
static FORCE_INLINE void tsdbUpdateMFileMagic(SMFile* pMFile, void* pCksum) {
|
|
||||||
pMFile->info.magic = taosCalcChecksum(pMFile->info.magic, (uint8_t*)(pCksum), sizeof(TSCKSUM));
|
|
||||||
}
|
|
||||||
|
|
||||||
static FORCE_INLINE int tsdbAppendMFile(SMFile* pMFile, void* buf, int64_t nbyte, int64_t* offset) {
|
|
||||||
ASSERT(TSDB_FILE_OPENED(pMFile));
|
|
||||||
|
|
||||||
int64_t toffset;
|
|
||||||
|
|
||||||
if ((toffset = tsdbSeekMFile(pMFile, 0, SEEK_END)) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT(pMFile->info.size == toffset);
|
|
||||||
|
|
||||||
if (offset) {
|
|
||||||
*offset = toffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tsdbWriteMFile(pMFile, buf, nbyte) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
pMFile->info.size += nbyte;
|
|
||||||
|
|
||||||
return (int)nbyte;
|
|
||||||
}
|
|
||||||
|
|
||||||
static FORCE_INLINE int tsdbRemoveMFile(SMFile* pMFile) { return tfsremove(TSDB_FILE_F(pMFile)); }
|
|
||||||
|
|
||||||
static FORCE_INLINE int64_t tsdbReadMFile(SMFile* pMFile, void* buf, int64_t nbyte) {
|
|
||||||
ASSERT(TSDB_FILE_OPENED(pMFile));
|
|
||||||
|
|
||||||
int64_t nread = taosReadFile(pMFile->fd, buf, nbyte);
|
|
||||||
if (nread < 0) {
|
|
||||||
terrno = TAOS_SYSTEM_ERROR(errno);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return nread;
|
|
||||||
}
|
|
||||||
|
|
||||||
// =============== SDFile
|
|
||||||
typedef struct {
|
|
||||||
uint32_t magic;
|
|
||||||
uint32_t len;
|
|
||||||
uint32_t totalBlocks;
|
|
||||||
uint32_t totalSubBlocks;
|
|
||||||
uint32_t offset;
|
|
||||||
uint64_t size;
|
|
||||||
uint64_t tombSize;
|
|
||||||
uint32_t fver;
|
|
||||||
} SDFInfo;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
SDFInfo info;
|
|
||||||
TFILE f;
|
|
||||||
int fd;
|
|
||||||
uint8_t state;
|
|
||||||
} SDFile;
|
|
||||||
|
|
||||||
void tsdbInitDFile(SDFile* pDFile, SDiskID did, int vid, int fid, uint32_t ver, TSDB_FILE_T ftype);
|
|
||||||
void tsdbInitDFileEx(SDFile* pDFile, SDFile* pODFile);
|
|
||||||
int tsdbEncodeSDFile(void** buf, SDFile* pDFile);
|
|
||||||
void* tsdbDecodeSDFile(void* buf, SDFile* pDFile, uint32_t sfver);
|
|
||||||
int tsdbCreateDFile(SDFile* pDFile, bool updateHeader, TSDB_FILE_T ftype);
|
|
||||||
int tsdbUpdateDFileHeader(SDFile* pDFile);
|
|
||||||
int tsdbLoadDFileHeader(SDFile* pDFile, SDFInfo* pInfo);
|
|
||||||
int tsdbParseDFilename(const char* fname, int* vid, int* fid, TSDB_FILE_T* ftype, uint32_t* version);
|
|
||||||
|
|
||||||
static FORCE_INLINE void tsdbSetDFileInfo(SDFile* pDFile, SDFInfo* pInfo) { pDFile->info = *pInfo; }
|
|
||||||
|
|
||||||
static FORCE_INLINE int tsdbOpenDFile(SDFile* pDFile, int flags) {
|
|
||||||
ASSERT(!TSDB_FILE_OPENED(pDFile));
|
|
||||||
|
|
||||||
pDFile->fd = open(TSDB_FILE_FULL_NAME(pDFile), flags | O_BINARY);
|
|
||||||
if (pDFile->fd < 0) {
|
|
||||||
terrno = TAOS_SYSTEM_ERROR(errno);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static FORCE_INLINE void tsdbCloseDFile(SDFile* pDFile) {
|
|
||||||
if (TSDB_FILE_OPENED(pDFile)) {
|
|
||||||
close(pDFile->fd);
|
|
||||||
TSDB_FILE_SET_CLOSED(pDFile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static FORCE_INLINE int64_t tsdbSeekDFile(SDFile* pDFile, int64_t offset, int whence) {
|
|
||||||
ASSERT(TSDB_FILE_OPENED(pDFile));
|
|
||||||
|
|
||||||
int64_t loffset = taosLSeekFile(TSDB_FILE_FD(pDFile), offset, whence);
|
|
||||||
if (loffset < 0) {
|
|
||||||
terrno = TAOS_SYSTEM_ERROR(errno);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return loffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
static FORCE_INLINE int64_t tsdbWriteDFile(SDFile* pDFile, void* buf, int64_t nbyte) {
|
|
||||||
ASSERT(TSDB_FILE_OPENED(pDFile));
|
|
||||||
|
|
||||||
int64_t nwrite = taosWriteFile(pDFile->fd, buf, nbyte);
|
|
||||||
if (nwrite < nbyte) {
|
|
||||||
terrno = TAOS_SYSTEM_ERROR(errno);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return nwrite;
|
|
||||||
}
|
|
||||||
|
|
||||||
static FORCE_INLINE void tsdbUpdateDFileMagic(SDFile* pDFile, void* pCksm) {
|
|
||||||
pDFile->info.magic = taosCalcChecksum(pDFile->info.magic, (uint8_t*)(pCksm), sizeof(TSCKSUM));
|
|
||||||
}
|
|
||||||
|
|
||||||
static FORCE_INLINE int tsdbAppendDFile(SDFile* pDFile, void* buf, int64_t nbyte, int64_t* offset) {
|
|
||||||
ASSERT(TSDB_FILE_OPENED(pDFile));
|
|
||||||
|
|
||||||
int64_t toffset;
|
|
||||||
|
|
||||||
if ((toffset = tsdbSeekDFile(pDFile, 0, SEEK_END)) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT(pDFile->info.size == toffset);
|
|
||||||
|
|
||||||
if (offset) {
|
|
||||||
*offset = toffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tsdbWriteDFile(pDFile, buf, nbyte) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
pDFile->info.size += nbyte;
|
|
||||||
|
|
||||||
return (int)nbyte;
|
|
||||||
}
|
|
||||||
|
|
||||||
static FORCE_INLINE int tsdbRemoveDFile(SDFile* pDFile) { return tfsremove(TSDB_FILE_F(pDFile)); }
|
|
||||||
|
|
||||||
static FORCE_INLINE int64_t tsdbReadDFile(SDFile* pDFile, void* buf, int64_t nbyte) {
|
|
||||||
ASSERT(TSDB_FILE_OPENED(pDFile));
|
|
||||||
|
|
||||||
int64_t nread = taosReadFile(pDFile->fd, buf, nbyte);
|
|
||||||
if (nread < 0) {
|
|
||||||
terrno = TAOS_SYSTEM_ERROR(errno);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return nread;
|
|
||||||
}
|
|
||||||
|
|
||||||
static FORCE_INLINE int tsdbCopyDFile(SDFile* pSrc, SDFile* pDest) {
|
|
||||||
if (tfscopy(TSDB_FILE_F(pSrc), TSDB_FILE_F(pDest)) < 0) {
|
|
||||||
terrno = TAOS_SYSTEM_ERROR(errno);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
tsdbSetDFileInfo(pDest, TSDB_FILE_INFO(pSrc));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// =============== SDFileSet
|
|
||||||
typedef struct {
|
|
||||||
int fid;
|
|
||||||
int state;
|
|
||||||
uint16_t ver; // fset version
|
|
||||||
SDFile files[TSDB_FILE_MAX];
|
|
||||||
} SDFileSet;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
TSDB_FSET_VER_0 = 0, // .head/.data/.last
|
|
||||||
TSDB_FSET_VER_1, // .head/.data/.last/.smad/.smal
|
|
||||||
} ETsdbFSetVer;
|
|
||||||
|
|
||||||
#define TSDB_LATEST_FSET_VER TSDB_FSET_VER_1
|
|
||||||
|
|
||||||
// get nDFiles in SDFileSet
|
|
||||||
static FORCE_INLINE uint8_t tsdbGetNFiles(SDFileSet* pSet) {
|
|
||||||
switch (pSet->ver) {
|
|
||||||
case TSDB_FSET_VER_0:
|
|
||||||
return TSDB_FILE_MIN;
|
|
||||||
case TSDB_FSET_VER_1:
|
|
||||||
default:
|
|
||||||
return TSDB_FILE_MAX;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#define TSDB_FSET_FID(s) ((s)->fid)
|
|
||||||
#define TSDB_DFILE_IN_SET(s, t) ((s)->files + (t))
|
|
||||||
#define TSDB_FSET_LEVEL(s) TSDB_FILE_LEVEL(TSDB_DFILE_IN_SET(s, 0))
|
|
||||||
#define TSDB_FSET_ID(s) TSDB_FILE_ID(TSDB_DFILE_IN_SET(s, 0))
|
|
||||||
#define TSDB_FSET_SET_CLOSED(s) \
|
|
||||||
do { \
|
|
||||||
for (TSDB_FILE_T ftype = TSDB_FILE_HEAD; ftype < TSDB_FILE_MAX; ftype++) { \
|
|
||||||
TSDB_FILE_SET_CLOSED(TSDB_DFILE_IN_SET(s, ftype)); \
|
|
||||||
} \
|
|
||||||
} while (0);
|
|
||||||
#define TSDB_FSET_FSYNC(s) \
|
|
||||||
do { \
|
|
||||||
for (TSDB_FILE_T ftype = TSDB_FILE_HEAD; ftype < tsdbGetNFiles(s); ftype++) { \
|
|
||||||
TSDB_FILE_FSYNC(TSDB_DFILE_IN_SET(s, ftype)); \
|
|
||||||
} \
|
|
||||||
} while (0);
|
|
||||||
|
|
||||||
void tsdbInitDFileSet(SDFileSet* pSet, SDiskID did, int vid, int fid, uint32_t ver, uint16_t fsetVer);
|
|
||||||
void tsdbInitDFileSetEx(SDFileSet* pSet, SDFileSet* pOSet);
|
|
||||||
int tsdbEncodeDFileSet(void** buf, SDFileSet* pSet);
|
|
||||||
void* tsdbDecodeDFileSet(void* buf, SDFileSet* pSet, uint32_t sfver);
|
|
||||||
int tsdbEncodeDFileSetEx(void** buf, SDFileSet* pSet);
|
|
||||||
void* tsdbDecodeDFileSetEx(void* buf, SDFileSet* pSet);
|
|
||||||
int tsdbApplyDFileSetChange(SDFileSet* from, SDFileSet* to);
|
|
||||||
int tsdbCreateDFileSet(SDFileSet* pSet, bool updateHeader);
|
|
||||||
int tsdbUpdateDFileSetHeader(SDFileSet* pSet);
|
|
||||||
int tsdbScanAndTryFixDFileSet(STsdb* pRepo, SDFileSet* pSet);
|
|
||||||
|
|
||||||
static FORCE_INLINE void tsdbCloseDFileSet(SDFileSet* pSet) {
|
|
||||||
ASSERT_TSDB_FSET_NFILES_VALID(pSet);
|
|
||||||
for (TSDB_FILE_T ftype = 0; ftype < tsdbGetNFiles(pSet); ftype++) {
|
|
||||||
tsdbCloseDFile(TSDB_DFILE_IN_SET(pSet, ftype));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static FORCE_INLINE int tsdbOpenDFileSet(SDFileSet* pSet, int flags) {
|
|
||||||
ASSERT_TSDB_FSET_NFILES_VALID(pSet);
|
|
||||||
for (TSDB_FILE_T ftype = 0; ftype < tsdbGetNFiles(pSet); ftype++) {
|
|
||||||
if (tsdbOpenDFile(TSDB_DFILE_IN_SET(pSet, ftype), flags) < 0) {
|
|
||||||
tsdbCloseDFileSet(pSet);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static FORCE_INLINE void tsdbRemoveDFileSet(SDFileSet* pSet) {
|
|
||||||
ASSERT_TSDB_FSET_NFILES_VALID(pSet);
|
|
||||||
for (TSDB_FILE_T ftype = 0; ftype < tsdbGetNFiles(pSet); ftype++) {
|
|
||||||
(void)tsdbRemoveDFile(TSDB_DFILE_IN_SET(pSet, ftype));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static FORCE_INLINE int tsdbCopyDFileSet(SDFileSet* pSrc, SDFileSet* pDest) {
|
|
||||||
ASSERT_TSDB_FSET_NFILES_VALID(pSrc);
|
|
||||||
for (TSDB_FILE_T ftype = 0; ftype < tsdbGetNFiles(pSrc); ftype++) {
|
|
||||||
if (tsdbCopyDFile(TSDB_DFILE_IN_SET(pSrc, ftype), TSDB_DFILE_IN_SET(pDest, ftype)) < 0) {
|
|
||||||
tsdbRemoveDFileSet(pDest);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static FORCE_INLINE void tsdbGetFidKeyRange(int days, int8_t precision, int fid, TSKEY* minKey, TSKEY* maxKey) {
|
|
||||||
*minKey = fid * days * tsTickPerDay[precision];
|
|
||||||
*maxKey = *minKey + days * tsTickPerDay[precision] - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static FORCE_INLINE bool tsdbFSetIsOk(SDFileSet* pSet) {
|
|
||||||
for (TSDB_FILE_T ftype = 0; ftype < TSDB_FILE_MAX; ftype++) {
|
|
||||||
if (TSDB_FILE_IS_BAD(TSDB_DFILE_IN_SET(pSet, ftype))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* _TS_TSDB_FILE_H_ */
|
|
|
@ -1,28 +0,0 @@
|
||||||
/*
|
|
||||||
* 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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _TD_TSDB_LOG_H_
|
|
||||||
#define _TD_TSDB_LOG_H_
|
|
||||||
|
|
||||||
extern int32_t tsdbDebugFlag;
|
|
||||||
|
|
||||||
#define tsdbFatal(...) do { if (tsdbDebugFlag & DEBUG_FATAL) { taosPrintLog("TDB FATAL ", 255, __VA_ARGS__); }} while(0)
|
|
||||||
#define tsdbError(...) do { if (tsdbDebugFlag & DEBUG_ERROR) { taosPrintLog("TDB ERROR ", 255, __VA_ARGS__); }} while(0)
|
|
||||||
#define tsdbWarn(...) do { if (tsdbDebugFlag & DEBUG_WARN) { taosPrintLog("TDB WARN ", 255, __VA_ARGS__); }} while(0)
|
|
||||||
#define tsdbInfo(...) do { if (tsdbDebugFlag & DEBUG_INFO) { taosPrintLog("TDB ", 255, __VA_ARGS__); }} while(0)
|
|
||||||
#define tsdbDebug(...) do { if (tsdbDebugFlag & DEBUG_DEBUG) { taosPrintLog("TDB ", tsdbDebugFlag, __VA_ARGS__); }} while(0)
|
|
||||||
#define tsdbTrace(...) do { if (tsdbDebugFlag & DEBUG_TRACE) { taosPrintLog("TDB ", tsdbDebugFlag, __VA_ARGS__); }} while(0)
|
|
||||||
|
|
||||||
#endif /* _TD_TSDB_LOG_H_ */
|
|
|
@ -1,97 +0,0 @@
|
||||||
/*
|
|
||||||
* 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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _TD_TSDB_MEMTABLE_H_
|
|
||||||
#define _TD_TSDB_MEMTABLE_H_
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int rowsInserted;
|
|
||||||
int rowsUpdated;
|
|
||||||
int rowsDeleteSucceed;
|
|
||||||
int rowsDeleteFailed;
|
|
||||||
int nOperations;
|
|
||||||
TSKEY keyFirst;
|
|
||||||
TSKEY keyLast;
|
|
||||||
} SMergeInfo;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
STable * pTable;
|
|
||||||
SSkipListIterator *pIter;
|
|
||||||
} SCommitIter;
|
|
||||||
|
|
||||||
struct STableData {
|
|
||||||
uint64_t uid;
|
|
||||||
TSKEY keyFirst;
|
|
||||||
TSKEY keyLast;
|
|
||||||
int64_t numOfRows;
|
|
||||||
SSkipList* pData;
|
|
||||||
T_REF_DECLARE()
|
|
||||||
};
|
|
||||||
|
|
||||||
enum { TSDB_UPDATE_META, TSDB_DROP_META };
|
|
||||||
|
|
||||||
#ifdef WINDOWS
|
|
||||||
#pragma pack(push ,1)
|
|
||||||
typedef struct {
|
|
||||||
#else
|
|
||||||
typedef struct __attribute__((packed)){
|
|
||||||
#endif
|
|
||||||
char act;
|
|
||||||
uint64_t uid;
|
|
||||||
} SActObj;
|
|
||||||
#ifdef WINDOWS
|
|
||||||
#pragma pack(pop)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int len;
|
|
||||||
char cont[];
|
|
||||||
} SActCont;
|
|
||||||
|
|
||||||
int tsdbRefMemTable(STsdb* pRepo, SMemTable* pMemTable);
|
|
||||||
int tsdbUnRefMemTable(STsdb* pRepo, SMemTable* pMemTable);
|
|
||||||
int tsdbTakeMemSnapshot(STsdb* pRepo, SMemSnapshot* pSnapshot, SArray* pATable);
|
|
||||||
void tsdbUnTakeMemSnapShot(STsdb* pRepo, SMemSnapshot* pSnapshot);
|
|
||||||
void* tsdbAllocBytes(STsdb* pRepo, int bytes);
|
|
||||||
int tsdbAsyncCommit(STsdb* pRepo);
|
|
||||||
int tsdbSyncCommitConfig(STsdb* pRepo);
|
|
||||||
int tsdbLoadDataFromCache(STable* pTable, SSkipListIterator* pIter, TSKEY maxKey, int maxRowsToRead, SDataCols* pCols,
|
|
||||||
TKEY* filterKeys, int nFilterKeys, bool keepDup, SMergeInfo* pMergeInfo);
|
|
||||||
void* tsdbCommitData(STsdb* pRepo);
|
|
||||||
|
|
||||||
static FORCE_INLINE SMemRow tsdbNextIterRow(SSkipListIterator* pIter) {
|
|
||||||
if (pIter == NULL) return NULL;
|
|
||||||
|
|
||||||
SSkipListNode* node = tSkipListIterGet(pIter);
|
|
||||||
if (node == NULL) return NULL;
|
|
||||||
|
|
||||||
return (SMemRow)SL_GET_NODE_DATA(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
static FORCE_INLINE TSKEY tsdbNextIterKey(SSkipListIterator* pIter) {
|
|
||||||
SMemRow row = tsdbNextIterRow(pIter);
|
|
||||||
if (row == NULL) return TSDB_DATA_TIMESTAMP_NULL;
|
|
||||||
|
|
||||||
return memRowKey(row);
|
|
||||||
}
|
|
||||||
|
|
||||||
static FORCE_INLINE TKEY tsdbNextIterTKey(SSkipListIterator* pIter) {
|
|
||||||
SMemRow row = tsdbNextIterRow(pIter);
|
|
||||||
if (row == NULL) return TKEY_NULL;
|
|
||||||
|
|
||||||
return memRowTKey(row);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* _TD_TSDB_MEMTABLE_H_ */
|
|
|
@ -1,74 +0,0 @@
|
||||||
/*
|
|
||||||
* 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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _TD_TSDB_MEMORY_H_
|
|
||||||
#define _TD_TSDB_MEMORY_H_
|
|
||||||
|
|
||||||
static void * taosTMalloc(size_t size);
|
|
||||||
static void * taosTCalloc(size_t nmemb, size_t size);
|
|
||||||
static void * taosTRealloc(void *ptr, size_t size);
|
|
||||||
static void * taosTZfree(void *ptr);
|
|
||||||
static size_t taosTSizeof(void *ptr);
|
|
||||||
static void taosTMemset(void *ptr, int c);
|
|
||||||
|
|
||||||
static FORCE_INLINE void *taosTMalloc(size_t size) {
|
|
||||||
if (size <= 0) return NULL;
|
|
||||||
|
|
||||||
void *ret = malloc(size + sizeof(size_t));
|
|
||||||
if (ret == NULL) return NULL;
|
|
||||||
|
|
||||||
*(size_t *)ret = size;
|
|
||||||
|
|
||||||
return (void *)((char *)ret + sizeof(size_t));
|
|
||||||
}
|
|
||||||
|
|
||||||
static FORCE_INLINE void *taosTCalloc(size_t nmemb, size_t size) {
|
|
||||||
size_t tsize = nmemb * size;
|
|
||||||
void * ret = taosTMalloc(tsize);
|
|
||||||
if (ret == NULL) return NULL;
|
|
||||||
|
|
||||||
taosTMemset(ret, 0);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static FORCE_INLINE size_t taosTSizeof(void *ptr) { return (ptr) ? (*(size_t *)((char *)ptr - sizeof(size_t))) : 0; }
|
|
||||||
|
|
||||||
static FORCE_INLINE void taosTMemset(void *ptr, int c) { memset(ptr, c, taosTSizeof(ptr)); }
|
|
||||||
|
|
||||||
static FORCE_INLINE void * taosTRealloc(void *ptr, size_t size) {
|
|
||||||
if (ptr == NULL) return taosTMalloc(size);
|
|
||||||
|
|
||||||
if (size <= taosTSizeof(ptr)) return ptr;
|
|
||||||
|
|
||||||
void * tptr = (void *)((char *)ptr - sizeof(size_t));
|
|
||||||
size_t tsize = size + sizeof(size_t);
|
|
||||||
void* tptr1 = realloc(tptr, tsize);
|
|
||||||
if (tptr1 == NULL) return NULL;
|
|
||||||
tptr = tptr1;
|
|
||||||
|
|
||||||
*(size_t *)tptr = size;
|
|
||||||
|
|
||||||
return (void *)((char *)tptr + sizeof(size_t));
|
|
||||||
}
|
|
||||||
|
|
||||||
static FORCE_INLINE void* taosTZfree(void* ptr) {
|
|
||||||
if (ptr) {
|
|
||||||
free((void*)((char*)ptr - sizeof(size_t)));
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* _TD_TSDB_MEMORY_H_ */
|
|
|
@ -1,171 +0,0 @@
|
||||||
/*
|
|
||||||
* 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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _TD_TSDB_META_H_
|
|
||||||
#define _TD_TSDB_META_H_
|
|
||||||
|
|
||||||
#include "tskiplist.h"
|
|
||||||
|
|
||||||
#define TSDB_MAX_TABLE_SCHEMAS 16
|
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
|
||||||
typedef struct jsonMapValue {
|
|
||||||
void* table; // STable *
|
|
||||||
int16_t colId; // the json col ID.
|
|
||||||
} JsonMapValue;
|
|
||||||
|
|
||||||
#pragma pack(pop)
|
|
||||||
|
|
||||||
typedef struct STable {
|
|
||||||
STableId tableId;
|
|
||||||
ETableType type;
|
|
||||||
tstr* name; // NOTE: there a flexible string here
|
|
||||||
uint64_t suid;
|
|
||||||
struct STable* pSuper; // super table pointer
|
|
||||||
SArray* schema;
|
|
||||||
STSchema* tagSchema;
|
|
||||||
SKVRow tagVal;
|
|
||||||
SSkipList* pIndex; // For TSDB_SUPER_TABLE, it is the skiplist index
|
|
||||||
SHashObj* jsonKeyMap; // For json tag key {"key":[t1, t2, t3]}
|
|
||||||
void* eventHandler; // TODO
|
|
||||||
void* streamHandler; // TODO
|
|
||||||
TSKEY lastKey;
|
|
||||||
SMemRow lastRow;
|
|
||||||
char* sql;
|
|
||||||
void* cqhandle;
|
|
||||||
SRWLatch latch; // TODO: implementa latch functions
|
|
||||||
SDataCol* lastCols;
|
|
||||||
int16_t maxColNum;
|
|
||||||
int16_t restoreColumnNum;
|
|
||||||
bool hasRestoreLastColumn;
|
|
||||||
int lastColSVersion;
|
|
||||||
int16_t cacheLastConfigVersion;
|
|
||||||
T_REF_DECLARE()
|
|
||||||
} STable;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
pthread_rwlock_t rwLock;
|
|
||||||
|
|
||||||
int32_t nTables;
|
|
||||||
int32_t maxTables;
|
|
||||||
STable** tables;
|
|
||||||
SList* superList;
|
|
||||||
SHashObj* uidMap;
|
|
||||||
int maxRowBytes;
|
|
||||||
int maxCols;
|
|
||||||
} STsdbMeta;
|
|
||||||
|
|
||||||
#define TSDB_INIT_NTABLES 1024
|
|
||||||
#define TABLE_TYPE(t) (t)->type
|
|
||||||
#define TABLE_NAME(t) (t)->name
|
|
||||||
#define TABLE_CHAR_NAME(t) TABLE_NAME(t)->data
|
|
||||||
#define TABLE_UID(t) (t)->tableId.uid
|
|
||||||
#define TABLE_TID(t) (t)->tableId.tid
|
|
||||||
#define TABLE_SUID(t) (t)->suid
|
|
||||||
// #define TSDB_META_FILE_MAGIC(m) KVSTORE_MAGIC((m)->pStore)
|
|
||||||
#define TSDB_RLOCK_TABLE(t) taosRLockLatch(&((t)->latch))
|
|
||||||
#define TSDB_RUNLOCK_TABLE(t) taosRUnLockLatch(&((t)->latch))
|
|
||||||
#define TSDB_WLOCK_TABLE(t) taosWLockLatch(&((t)->latch))
|
|
||||||
#define TSDB_WUNLOCK_TABLE(t) taosWUnLockLatch(&((t)->latch))
|
|
||||||
|
|
||||||
STsdbMeta* tsdbNewMeta(STsdbCfg* pCfg);
|
|
||||||
void tsdbFreeMeta(STsdbMeta* pMeta);
|
|
||||||
int tsdbOpenMeta(STsdb* pRepo);
|
|
||||||
int tsdbCloseMeta(STsdb* pRepo);
|
|
||||||
STable* tsdbGetTableByUid(STsdbMeta* pMeta, uint64_t uid);
|
|
||||||
STSchema* tsdbGetTableSchemaByVersion(STable* pTable, int16_t _version, int8_t rowType);
|
|
||||||
int tsdbWLockRepoMeta(STsdb* pRepo);
|
|
||||||
int tsdbRLockRepoMeta(STsdb* pRepo);
|
|
||||||
int tsdbUnlockRepoMeta(STsdb* pRepo);
|
|
||||||
void tsdbRefTable(STable* pTable);
|
|
||||||
void tsdbUnRefTable(STable* pTable);
|
|
||||||
void tsdbUpdateTableSchema(STsdb* pRepo, STable* pTable, STSchema* pSchema, bool insertAct);
|
|
||||||
int tsdbRestoreTable(STsdb* pRepo, void* cont, int contLen);
|
|
||||||
void tsdbOrgMeta(STsdb* pRepo);
|
|
||||||
int tsdbInitColIdCacheWithSchema(STable* pTable, STSchema* pSchema);
|
|
||||||
int16_t tsdbGetLastColumnsIndexByColId(STable* pTable, int16_t colId);
|
|
||||||
int tsdbUpdateLastColSchema(STable* pTable, STSchema* pNewSchema);
|
|
||||||
STSchema* tsdbGetTableLatestSchema(STable* pTable);
|
|
||||||
void tsdbFreeLastColumns(STable* pTable);
|
|
||||||
int tsdbCompareJsonMapValue(const void* a, const void* b);
|
|
||||||
void* tsdbGetJsonTagValue(STable* pTable, char* key, int32_t keyLen, int16_t* colId);
|
|
||||||
|
|
||||||
static FORCE_INLINE int tsdbCompareSchemaVersion(const void* key1, const void* key2) {
|
|
||||||
if (*(int16_t*)key1 < schemaVersion(*(STSchema**)key2)) {
|
|
||||||
return -1;
|
|
||||||
} else if (*(int16_t*)key1 > schemaVersion(*(STSchema**)key2)) {
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static FORCE_INLINE STSchema* tsdbGetTableSchemaImpl(STable* pTable, bool lock, bool copy, int16_t _version,
|
|
||||||
int8_t rowType) {
|
|
||||||
STable* pDTable = (pTable->pSuper != NULL) ? pTable->pSuper : pTable; // for performance purpose
|
|
||||||
STSchema* pSchema = NULL;
|
|
||||||
STSchema* pTSchema = NULL;
|
|
||||||
|
|
||||||
if (lock) TSDB_RLOCK_TABLE(pDTable);
|
|
||||||
if (_version < 0) { // get the latest version of schema
|
|
||||||
pTSchema = *(STSchema**)taosArrayGetLast(pDTable->schema);
|
|
||||||
} else { // get the schema with version
|
|
||||||
void* ptr = taosArraySearch(pDTable->schema, &_version, tsdbCompareSchemaVersion, TD_EQ);
|
|
||||||
if (ptr == NULL) {
|
|
||||||
if (rowType == SMEM_ROW_KV) {
|
|
||||||
ptr = taosArrayGetLast(pDTable->schema);
|
|
||||||
} else {
|
|
||||||
terrno = TSDB_CODE_TDB_IVD_TB_SCHEMA_VERSION;
|
|
||||||
goto _exit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pTSchema = *(STSchema**)ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT(pTSchema != NULL);
|
|
||||||
|
|
||||||
if (copy) {
|
|
||||||
if ((pSchema = tdDupSchema(pTSchema)) == NULL) terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
|
|
||||||
} else {
|
|
||||||
pSchema = pTSchema;
|
|
||||||
}
|
|
||||||
|
|
||||||
_exit:
|
|
||||||
if (lock) TSDB_RUNLOCK_TABLE(pDTable);
|
|
||||||
return pSchema;
|
|
||||||
}
|
|
||||||
|
|
||||||
static FORCE_INLINE STSchema* tsdbGetTableSchema(STable* pTable) {
|
|
||||||
return tsdbGetTableSchemaImpl(pTable, false, false, -1, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static FORCE_INLINE STSchema* tsdbGetTableTagSchema(STable* pTable) {
|
|
||||||
if (pTable->type == TSDB_CHILD_TABLE) { // check child table first
|
|
||||||
STable* pSuper = pTable->pSuper;
|
|
||||||
if (pSuper == NULL) return NULL;
|
|
||||||
return pSuper->tagSchema;
|
|
||||||
} else if (pTable->type == TSDB_SUPER_TABLE) {
|
|
||||||
return pTable->tagSchema;
|
|
||||||
} else {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static FORCE_INLINE TSKEY tsdbGetTableLastKeyImpl(STable* pTable) {
|
|
||||||
ASSERT((pTable->lastRow == NULL) || (pTable->lastKey == memRowKey(pTable->lastRow)));
|
|
||||||
return pTable->lastKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* _TD_TSDB_META_H_ */
|
|
|
@ -1,273 +0,0 @@
|
||||||
/*
|
|
||||||
* 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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _TD_TSDB_READ_IMPL_H_
|
|
||||||
#define _TD_TSDB_READ_IMPL_H_
|
|
||||||
|
|
||||||
#include "os.h"
|
|
||||||
#include "tfs.h"
|
|
||||||
#include "tsdb.h"
|
|
||||||
#include "tsdbFile.h"
|
|
||||||
#include "tsdbMemory.h"
|
|
||||||
#include "tsdbMeta.h"
|
|
||||||
#include "tskiplist.h"
|
|
||||||
|
|
||||||
typedef struct SReadH SReadH;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int32_t tid;
|
|
||||||
uint32_t len;
|
|
||||||
uint32_t offset;
|
|
||||||
uint32_t hasLast : 2;
|
|
||||||
uint32_t numOfBlocks : 30;
|
|
||||||
uint64_t uid;
|
|
||||||
TSKEY maxKey;
|
|
||||||
} SBlockIdx;
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
typedef struct {
|
|
||||||
int64_t last : 1;
|
|
||||||
int64_t offset : 63;
|
|
||||||
int32_t algorithm : 8;
|
|
||||||
int32_t numOfRows : 24;
|
|
||||||
int32_t len;
|
|
||||||
int32_t keyLen; // key column length, keyOffset = offset+sizeof(SBlockData)+sizeof(SBlockCol)*numOfCols
|
|
||||||
int16_t numOfSubBlocks;
|
|
||||||
int16_t numOfCols; // not including timestamp column
|
|
||||||
TSKEY keyFirst;
|
|
||||||
TSKEY keyLast;
|
|
||||||
} SBlock;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* keyLen; // key column length, keyOffset = offset+sizeof(SBlockData)+sizeof(SBlockCol)*numOfCols
|
|
||||||
* numOfCols; // not including timestamp column
|
|
||||||
*/
|
|
||||||
#define SBlockFieldsP0 \
|
|
||||||
int64_t last : 1; \
|
|
||||||
int64_t offset : 63; \
|
|
||||||
int32_t algorithm : 8; \
|
|
||||||
int32_t numOfRows : 24; \
|
|
||||||
int32_t len; \
|
|
||||||
int32_t keyLen; \
|
|
||||||
int16_t numOfSubBlocks; \
|
|
||||||
int16_t numOfCols; \
|
|
||||||
TSKEY keyFirst; \
|
|
||||||
TSKEY keyLast
|
|
||||||
|
|
||||||
/**
|
|
||||||
* aggrStat; // only valid when blkVer > 0. 0 - no aggr part in .data/.last/.smad/.smal, 1 - has aggr in .smad/.smal
|
|
||||||
* blkVer; // 0 - original block, 1 - block since importing .smad/.smal
|
|
||||||
* aggrOffset; // only valid when blkVer > 0 and aggrStat > 0
|
|
||||||
*/
|
|
||||||
#define SBlockFieldsP1 \
|
|
||||||
uint64_t aggrStat : 1; \
|
|
||||||
uint64_t blkVer : 7; \
|
|
||||||
uint64_t aggrOffset : 56
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
SBlockFieldsP0;
|
|
||||||
} SBlockV0;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
SBlockFieldsP0;
|
|
||||||
SBlockFieldsP1;
|
|
||||||
} SBlockV1;
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
TSDB_SBLK_VER_0 = 0,
|
|
||||||
TSDB_SBLK_VER_1,
|
|
||||||
} ESBlockVer;
|
|
||||||
|
|
||||||
#define SBlockVerLatest TSDB_SBLK_VER_1
|
|
||||||
|
|
||||||
#define SBlock SBlockV1 // latest SBlock definition
|
|
||||||
|
|
||||||
// lastest SBlockInfo definition
|
|
||||||
typedef struct {
|
|
||||||
int32_t delimiter; // For recovery usage
|
|
||||||
int32_t tid;
|
|
||||||
uint64_t uid;
|
|
||||||
SBlock blocks[];
|
|
||||||
} SBlockInfo;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int16_t colId;
|
|
||||||
int32_t len;
|
|
||||||
uint32_t type : 8;
|
|
||||||
uint32_t offset : 24;
|
|
||||||
int64_t sum;
|
|
||||||
int64_t max;
|
|
||||||
int64_t min;
|
|
||||||
int16_t maxIndex;
|
|
||||||
int16_t minIndex;
|
|
||||||
int16_t numOfNull;
|
|
||||||
uint8_t offsetH;
|
|
||||||
char padding[1];
|
|
||||||
} SBlockColV0;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int16_t colId;
|
|
||||||
uint8_t offsetH;
|
|
||||||
uint8_t reserved; // reserved field, not used
|
|
||||||
int32_t len;
|
|
||||||
uint32_t type : 8;
|
|
||||||
uint32_t offset : 24;
|
|
||||||
} SBlockColV1;
|
|
||||||
|
|
||||||
#define SBlockCol SBlockColV1 // latest SBlockCol definition
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int16_t colId;
|
|
||||||
int16_t maxIndex;
|
|
||||||
int16_t minIndex;
|
|
||||||
int16_t numOfNull;
|
|
||||||
int64_t sum;
|
|
||||||
int64_t max;
|
|
||||||
int64_t min;
|
|
||||||
} SAggrBlkColV1;
|
|
||||||
|
|
||||||
#define SAggrBlkCol SAggrBlkColV1 // latest SAggrBlkCol definition
|
|
||||||
|
|
||||||
// Code here just for back-ward compatibility
|
|
||||||
static FORCE_INLINE void tsdbSetBlockColOffset(SBlockCol *pBlockCol, uint32_t offset) {
|
|
||||||
pBlockCol->offset = offset & ((((uint32_t)1) << 24) - 1);
|
|
||||||
pBlockCol->offsetH = (uint8_t)(offset >> 24);
|
|
||||||
}
|
|
||||||
|
|
||||||
static FORCE_INLINE uint32_t tsdbGetBlockColOffset(SBlockCol *pBlockCol) {
|
|
||||||
uint32_t offset1 = pBlockCol->offset;
|
|
||||||
uint32_t offset2 = pBlockCol->offsetH;
|
|
||||||
return (offset1 | (offset2 << 24));
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int32_t delimiter; // For recovery usage
|
|
||||||
int32_t numOfCols; // For recovery usage
|
|
||||||
uint64_t uid; // For recovery usage
|
|
||||||
SBlockCol cols[];
|
|
||||||
} SBlockData;
|
|
||||||
|
|
||||||
typedef void SAggrBlkData; // SBlockCol cols[];
|
|
||||||
|
|
||||||
struct SReadH {
|
|
||||||
STsdb * pRepo;
|
|
||||||
SDFileSet rSet; // FSET to read
|
|
||||||
SArray * aBlkIdx; // SBlockIdx array
|
|
||||||
STable * pTable; // table to read
|
|
||||||
SBlockIdx * pBlkIdx; // current reading table SBlockIdx
|
|
||||||
int cidx;
|
|
||||||
SBlockInfo * pBlkInfo; // SBlockInfoV#
|
|
||||||
SBlockData * pBlkData; // Block info
|
|
||||||
SAggrBlkData *pAggrBlkData; // Aggregate Block info
|
|
||||||
SDataCols * pDCols[2];
|
|
||||||
void * pBuf; // buffer
|
|
||||||
void * pCBuf; // compression buffer
|
|
||||||
void * pExBuf; // extra buffer
|
|
||||||
};
|
|
||||||
|
|
||||||
#define TSDB_READ_REPO(rh) ((rh)->pRepo)
|
|
||||||
#define TSDB_READ_REPO_ID(rh) REPO_ID(TSDB_READ_REPO(rh))
|
|
||||||
#define TSDB_READ_FSET(rh) (&((rh)->rSet))
|
|
||||||
#define TSDB_READ_TABLE(rh) ((rh)->pTable)
|
|
||||||
#define TSDB_READ_HEAD_FILE(rh) TSDB_DFILE_IN_SET(TSDB_READ_FSET(rh), TSDB_FILE_HEAD)
|
|
||||||
#define TSDB_READ_DATA_FILE(rh) TSDB_DFILE_IN_SET(TSDB_READ_FSET(rh), TSDB_FILE_DATA)
|
|
||||||
#define TSDB_READ_LAST_FILE(rh) TSDB_DFILE_IN_SET(TSDB_READ_FSET(rh), TSDB_FILE_LAST)
|
|
||||||
#define TSDB_READ_SMAD_FILE(rh) TSDB_DFILE_IN_SET(TSDB_READ_FSET(rh), TSDB_FILE_SMAD)
|
|
||||||
#define TSDB_READ_SMAL_FILE(rh) TSDB_DFILE_IN_SET(TSDB_READ_FSET(rh), TSDB_FILE_SMAL)
|
|
||||||
#define TSDB_READ_BUF(rh) ((rh)->pBuf)
|
|
||||||
#define TSDB_READ_COMP_BUF(rh) ((rh)->pCBuf)
|
|
||||||
#define TSDB_READ_EXBUF(rh) ((rh)->pExBuf)
|
|
||||||
|
|
||||||
#define TSDB_BLOCK_STATIS_SIZE(ncols, blkVer) \
|
|
||||||
(sizeof(SBlockData) + sizeof(SBlockColV##blkVer) * (ncols) + sizeof(TSCKSUM))
|
|
||||||
|
|
||||||
static FORCE_INLINE size_t tsdbBlockStatisSize(int nCols, uint32_t blkVer) {
|
|
||||||
switch (blkVer) {
|
|
||||||
case TSDB_SBLK_VER_0:
|
|
||||||
return TSDB_BLOCK_STATIS_SIZE(nCols, 0);
|
|
||||||
case TSDB_SBLK_VER_1:
|
|
||||||
default:
|
|
||||||
return TSDB_BLOCK_STATIS_SIZE(nCols, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#define TSDB_BLOCK_AGGR_SIZE(ncols, blkVer) (sizeof(SAggrBlkColV##blkVer) * (ncols) + sizeof(TSCKSUM))
|
|
||||||
|
|
||||||
static FORCE_INLINE size_t tsdbBlockAggrSize(int nCols, uint32_t blkVer) {
|
|
||||||
switch (blkVer) {
|
|
||||||
case TSDB_SBLK_VER_0:
|
|
||||||
ASSERT(false);
|
|
||||||
return 0;
|
|
||||||
case TSDB_SBLK_VER_1:
|
|
||||||
default:
|
|
||||||
return TSDB_BLOCK_AGGR_SIZE(nCols, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int tsdbInitReadH(SReadH *pReadh, STsdb *pRepo);
|
|
||||||
void tsdbDestroyReadH(SReadH *pReadh);
|
|
||||||
int tsdbSetAndOpenReadFSet(SReadH *pReadh, SDFileSet *pSet);
|
|
||||||
void tsdbCloseAndUnsetFSet(SReadH *pReadh);
|
|
||||||
int tsdbLoadBlockIdx(SReadH *pReadh);
|
|
||||||
int tsdbSetReadTable(SReadH *pReadh, STable *pTable);
|
|
||||||
int tsdbLoadBlockInfo(SReadH *pReadh, void **pTarget, uint32_t *extendedLen);
|
|
||||||
int tsdbLoadBlockData(SReadH *pReadh, SBlock *pBlock, SBlockInfo *pBlockInfo);
|
|
||||||
int tsdbLoadBlockDataCols(SReadH *pReadh, SBlock *pBlock, SBlockInfo *pBlkInfo, int16_t *colIds, int numOfColsIds);
|
|
||||||
int tsdbLoadBlockStatis(SReadH *pReadh, SBlock *pBlock);
|
|
||||||
int tsdbLoadBlockOffset(SReadH *pReadh, SBlock *pBlock);
|
|
||||||
int tsdbEncodeSBlockIdx(void **buf, SBlockIdx *pIdx);
|
|
||||||
void *tsdbDecodeSBlockIdx(void *buf, SBlockIdx *pIdx);
|
|
||||||
void tsdbGetBlockStatis(SReadH *pReadh, SDataStatis *pStatis, int numOfCols, SBlock *pBlock);
|
|
||||||
|
|
||||||
static FORCE_INLINE int tsdbMakeRoom(void **ppBuf, size_t size) {
|
|
||||||
void * pBuf = *ppBuf;
|
|
||||||
size_t tsize = taosTSizeof(pBuf);
|
|
||||||
|
|
||||||
if (tsize < size) {
|
|
||||||
if (tsize == 0) tsize = 1024;
|
|
||||||
|
|
||||||
while (tsize < size) {
|
|
||||||
tsize *= 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
*ppBuf = taosTRealloc(pBuf, tsize);
|
|
||||||
if (*ppBuf == NULL) {
|
|
||||||
terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static FORCE_INLINE SBlockCol *tsdbGetSBlockCol(SBlock *pBlock, SBlockCol **pDestBlkCol, SBlockCol *pBlkCols,
|
|
||||||
int colIdx) {
|
|
||||||
if (pBlock->blkVer == SBlockVerLatest) {
|
|
||||||
*pDestBlkCol = pBlkCols + colIdx;
|
|
||||||
return *pDestBlkCol;
|
|
||||||
}
|
|
||||||
if (pBlock->blkVer == TSDB_SBLK_VER_0) {
|
|
||||||
SBlockColV0 *pBlkCol = (SBlockColV0 *)pBlkCols + colIdx;
|
|
||||||
(*pDestBlkCol)->colId = pBlkCol->colId;
|
|
||||||
(*pDestBlkCol)->len = pBlkCol->len;
|
|
||||||
(*pDestBlkCol)->type = pBlkCol->type;
|
|
||||||
(*pDestBlkCol)->offset = pBlkCol->offset;
|
|
||||||
(*pDestBlkCol)->offsetH = pBlkCol->offsetH;
|
|
||||||
}
|
|
||||||
return *pDestBlkCol;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /*_TD_TSDB_READ_IMPL_H_*/
|
|
|
@ -1,45 +0,0 @@
|
||||||
/*
|
|
||||||
* 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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef TSDB_ROW_MERGE_BUF_H
|
|
||||||
#define TSDB_ROW_MERGE_BUF_H
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "tsdb.h"
|
|
||||||
#include "tchecksum.h"
|
|
||||||
#include "tsdbReadImpl.h"
|
|
||||||
|
|
||||||
typedef void* SMergeBuf;
|
|
||||||
|
|
||||||
SDataRow tsdbMergeTwoRows(SMergeBuf *pBuf, SMemRow row1, SMemRow row2, STSchema *pSchema1, STSchema *pSchema2);
|
|
||||||
|
|
||||||
static FORCE_INLINE int tsdbMergeBufMakeSureRoom(SMergeBuf *pBuf, STSchema* pSchema1, STSchema* pSchema2) {
|
|
||||||
size_t len1 = dataRowMaxBytesFromSchema(pSchema1);
|
|
||||||
size_t len2 = dataRowMaxBytesFromSchema(pSchema2);
|
|
||||||
return tsdbMakeRoom(pBuf, MAX(len1, len2));
|
|
||||||
}
|
|
||||||
|
|
||||||
static FORCE_INLINE void tsdbFreeMergeBuf(SMergeBuf buf) {
|
|
||||||
taosTZfree(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* ifndef TSDB_ROW_MERGE_BUF_H */
|
|
|
@ -1,94 +0,0 @@
|
||||||
/*
|
|
||||||
* 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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _TD_TSDB_INT_H_
|
|
||||||
#define _TD_TSDB_INT_H_
|
|
||||||
|
|
||||||
#include "os.h"
|
|
||||||
#include "taosdef.h"
|
|
||||||
#include "taoserror.h"
|
|
||||||
#include "tarray.h"
|
|
||||||
#include "tchecksum.h"
|
|
||||||
#include "tcoding.h"
|
|
||||||
#include "tcompression.h"
|
|
||||||
#include "tdataformat.h"
|
|
||||||
#include "tfs.h"
|
|
||||||
#include "thash.h"
|
|
||||||
#include "tlist.h"
|
|
||||||
#include "tlockfree.h"
|
|
||||||
#include "tlog.h"
|
|
||||||
#include "tsdbMemory.h"
|
|
||||||
#include "tskiplist.h"
|
|
||||||
|
|
||||||
#include "tsdb.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Log
|
|
||||||
#include "tsdbLog.h"
|
|
||||||
// Meta
|
|
||||||
#include "tsdbMeta.h"
|
|
||||||
// // Buffer
|
|
||||||
// #include "tsdbBuffer.h"
|
|
||||||
// MemTable
|
|
||||||
#include "tsdbMemTable.h"
|
|
||||||
// File
|
|
||||||
#include "tsdbFile.h"
|
|
||||||
// FS
|
|
||||||
#include "tsdbFS.h"
|
|
||||||
// ReadImpl
|
|
||||||
#include "tsdbReadImpl.h"
|
|
||||||
// Commit
|
|
||||||
#include "tsdbCommit.h"
|
|
||||||
// Compact
|
|
||||||
#include "tsdbCompact.h"
|
|
||||||
|
|
||||||
#include "tsdbRowMergeBuf.h"
|
|
||||||
// Main definitions
|
|
||||||
struct STsdb {
|
|
||||||
uint8_t state;
|
|
||||||
STsdbCfg config;
|
|
||||||
STsdbStat stat;
|
|
||||||
STsdbMeta* tsdbMeta;
|
|
||||||
SMemTable* mem;
|
|
||||||
SMemTable* imem;
|
|
||||||
STsdbFS* fs;
|
|
||||||
SRtn rtn;
|
|
||||||
SMergeBuf mergeBuf; // used when update=2
|
|
||||||
};
|
|
||||||
|
|
||||||
#define REPO_ID(r) (r)->config.tsdbId
|
|
||||||
#define REPO_CFG(r) (&((r)->config))
|
|
||||||
#define REPO_FS(r) ((r)->fs)
|
|
||||||
#define IS_REPO_LOCKED(r) (r)->repoLocked
|
|
||||||
#define TSDB_SUBMIT_MSG_HEAD_SIZE sizeof(SSubmitMsg)
|
|
||||||
|
|
||||||
int tsdbLockRepo(STsdb* pRepo);
|
|
||||||
int tsdbUnlockRepo(STsdb* pRepo);
|
|
||||||
STsdbMeta* tsdbGetMeta(STsdb* pRepo);
|
|
||||||
int tsdbCheckCommit(STsdb* pRepo);
|
|
||||||
int tsdbRestoreInfo(STsdb* pRepo);
|
|
||||||
UNUSED_FUNC int tsdbCacheLastData(STsdb* pRepo, STsdbCfg* oldCfg);
|
|
||||||
int32_t tsdbLoadLastCache(STsdb* pRepo, STable* pTable);
|
|
||||||
void tsdbGetRootDir(int repoid, char dirName[]);
|
|
||||||
void tsdbGetDataDir(int repoid, char dirName[]);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* _TD_TSDB_INT_H_ */
|
|
|
@ -1,217 +0,0 @@
|
||||||
/*
|
|
||||||
* 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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
|
|
||||||
#include "tsdbHealth.h"
|
|
||||||
#include "tsdbint.h"
|
|
||||||
|
|
||||||
#define POOL_IS_EMPTY(b) (listNEles((b)->bufBlockList) == 0)
|
|
||||||
|
|
||||||
// ---------------- INTERNAL FUNCTIONS ----------------
|
|
||||||
STsdbBufPool *tsdbNewBufPool() {
|
|
||||||
STsdbBufPool *pBufPool = (STsdbBufPool *)calloc(1, sizeof(*pBufPool));
|
|
||||||
if (pBufPool == NULL) {
|
|
||||||
terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
|
|
||||||
goto _err;
|
|
||||||
}
|
|
||||||
|
|
||||||
int code = pthread_cond_init(&(pBufPool->poolNotEmpty), NULL);
|
|
||||||
if (code != 0) {
|
|
||||||
terrno = TAOS_SYSTEM_ERROR(code);
|
|
||||||
goto _err;
|
|
||||||
}
|
|
||||||
|
|
||||||
pBufPool->bufBlockList = tdListNew(sizeof(STsdbBufBlock *));
|
|
||||||
if (pBufPool->bufBlockList == NULL) {
|
|
||||||
terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
|
|
||||||
goto _err;
|
|
||||||
}
|
|
||||||
|
|
||||||
return pBufPool;
|
|
||||||
|
|
||||||
_err:
|
|
||||||
tsdbFreeBufPool(pBufPool);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void tsdbFreeBufPool(STsdbBufPool *pBufPool) {
|
|
||||||
if (pBufPool) {
|
|
||||||
if (pBufPool->bufBlockList) {
|
|
||||||
ASSERT(listNEles(pBufPool->bufBlockList) == 0);
|
|
||||||
tdListFree(pBufPool->bufBlockList);
|
|
||||||
}
|
|
||||||
|
|
||||||
pthread_cond_destroy(&pBufPool->poolNotEmpty);
|
|
||||||
|
|
||||||
free(pBufPool);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int tsdbOpenBufPool(STsdb *pRepo) {
|
|
||||||
STsdbCfg * pCfg = &(pRepo->config);
|
|
||||||
STsdbBufPool *pPool = pRepo->pPool;
|
|
||||||
|
|
||||||
ASSERT(pPool != NULL);
|
|
||||||
pPool->bufBlockSize = pCfg->cacheBlockSize * 1024 * 1024; // MB
|
|
||||||
pPool->tBufBlocks = pCfg->totalBlocks;
|
|
||||||
pPool->nBufBlocks = 0;
|
|
||||||
pPool->nElasticBlocks = 0;
|
|
||||||
pPool->index = 0;
|
|
||||||
pPool->nRecycleBlocks = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < pCfg->totalBlocks; i++) {
|
|
||||||
STsdbBufBlock *pBufBlock = tsdbNewBufBlock(pPool->bufBlockSize);
|
|
||||||
if (pBufBlock == NULL) goto _err;
|
|
||||||
|
|
||||||
if (tdListAppend(pPool->bufBlockList, (void *)(&pBufBlock)) < 0) {
|
|
||||||
tsdbFreeBufBlock(pBufBlock);
|
|
||||||
terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
|
|
||||||
goto _err;
|
|
||||||
}
|
|
||||||
|
|
||||||
pPool->nBufBlocks++;
|
|
||||||
}
|
|
||||||
|
|
||||||
tsdbDebug("vgId:%d buffer pool is opened! bufBlockSize:%d tBufBlocks:%d nBufBlocks:%d", REPO_ID(pRepo),
|
|
||||||
pPool->bufBlockSize, pPool->tBufBlocks, pPool->nBufBlocks);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
_err:
|
|
||||||
tsdbCloseBufPool(pRepo);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void tsdbCloseBufPool(STsdb *pRepo) {
|
|
||||||
if (pRepo == NULL) return;
|
|
||||||
|
|
||||||
STsdbBufPool * pBufPool = pRepo->pPool;
|
|
||||||
STsdbBufBlock *pBufBlock = NULL;
|
|
||||||
|
|
||||||
if (pBufPool) {
|
|
||||||
SListNode *pNode = NULL;
|
|
||||||
while ((pNode = tdListPopHead(pBufPool->bufBlockList)) != NULL) {
|
|
||||||
tdListNodeGetData(pBufPool->bufBlockList, pNode, (void *)(&pBufBlock));
|
|
||||||
tsdbFreeBufBlock(pBufBlock);
|
|
||||||
free(pNode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tsdbDebug("vgId:%d, buffer pool is closed", REPO_ID(pRepo));
|
|
||||||
}
|
|
||||||
|
|
||||||
SListNode *tsdbAllocBufBlockFromPool(STsdb *pRepo) {
|
|
||||||
ASSERT(pRepo != NULL && pRepo->pPool != NULL);
|
|
||||||
ASSERT(IS_REPO_LOCKED(pRepo));
|
|
||||||
|
|
||||||
STsdbBufPool *pBufPool = pRepo->pPool;
|
|
||||||
|
|
||||||
while (POOL_IS_EMPTY(pBufPool)) {
|
|
||||||
if (tsDeadLockKillQuery) {
|
|
||||||
// supply new Block
|
|
||||||
if (tsdbInsertNewBlock(pRepo) > 0) {
|
|
||||||
tsdbWarn("vgId:%d add new elastic block . elasticBlocks=%d cur free Blocks=%d", REPO_ID(pRepo),
|
|
||||||
pBufPool->nElasticBlocks, TD_DLIST_NELES(pBufPool->bufBlockList));
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
// no newBlock, kill query free
|
|
||||||
if (!tsdbUrgeQueryFree(pRepo)) tsdbWarn("vgId:%d Urge query free thread start failed.", REPO_ID(pRepo));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pRepo->repoLocked = false;
|
|
||||||
pthread_cond_wait(&(pBufPool->poolNotEmpty), &(pRepo->mutex));
|
|
||||||
pRepo->repoLocked = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
SListNode *pNode = tdListPopHead(pBufPool->bufBlockList);
|
|
||||||
ASSERT(pNode != NULL);
|
|
||||||
STsdbBufBlock *pBufBlock = NULL;
|
|
||||||
tdListNodeGetData(pBufPool->bufBlockList, pNode, (void *)(&pBufBlock));
|
|
||||||
|
|
||||||
pBufBlock->blockId = pBufPool->index++;
|
|
||||||
pBufBlock->offset = 0;
|
|
||||||
pBufBlock->remain = pBufPool->bufBlockSize;
|
|
||||||
|
|
||||||
tsdbDebug("vgId:%d, buffer block is allocated, blockId:%" PRId64, REPO_ID(pRepo), pBufBlock->blockId);
|
|
||||||
return pNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------- LOCAL FUNCTIONS ----------------
|
|
||||||
STsdbBufBlock *tsdbNewBufBlock(int bufBlockSize) {
|
|
||||||
STsdbBufBlock *pBufBlock = (STsdbBufBlock *)malloc(sizeof(*pBufBlock) + bufBlockSize);
|
|
||||||
if (pBufBlock == NULL) {
|
|
||||||
terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
pBufBlock->blockId = 0;
|
|
||||||
pBufBlock->offset = 0;
|
|
||||||
pBufBlock->remain = bufBlockSize;
|
|
||||||
|
|
||||||
return pBufBlock;
|
|
||||||
}
|
|
||||||
|
|
||||||
void tsdbFreeBufBlock(STsdbBufBlock *pBufBlock) { tfree(pBufBlock); }
|
|
||||||
|
|
||||||
int tsdbExpandPool(STsdb *pRepo, int32_t oldTotalBlocks) {
|
|
||||||
if (oldTotalBlocks == pRepo->config.totalBlocks) {
|
|
||||||
return TSDB_CODE_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
int err = TSDB_CODE_SUCCESS;
|
|
||||||
|
|
||||||
if (tsdbLockRepo(pRepo) < 0) return terrno;
|
|
||||||
STsdbBufPool *pPool = pRepo->pPool;
|
|
||||||
|
|
||||||
if (pRepo->config.totalBlocks > oldTotalBlocks) {
|
|
||||||
for (int i = 0; i < pRepo->config.totalBlocks - oldTotalBlocks; i++) {
|
|
||||||
STsdbBufBlock *pBufBlock = tsdbNewBufBlock(pPool->bufBlockSize);
|
|
||||||
if (pBufBlock == NULL) goto err;
|
|
||||||
|
|
||||||
if (tdListAppend(pPool->bufBlockList, (void *)(&pBufBlock)) < 0) {
|
|
||||||
tsdbFreeBufBlock(pBufBlock);
|
|
||||||
terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
|
|
||||||
err = TSDB_CODE_TDB_OUT_OF_MEMORY;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
pPool->nBufBlocks++;
|
|
||||||
}
|
|
||||||
pthread_cond_signal(&pPool->poolNotEmpty);
|
|
||||||
} else {
|
|
||||||
pPool->nRecycleBlocks = oldTotalBlocks - pRepo->config.totalBlocks;
|
|
||||||
}
|
|
||||||
|
|
||||||
err:
|
|
||||||
tsdbUnlockRepo(pRepo);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
void tsdbRecycleBufferBlock(STsdbBufPool *pPool, SListNode *pNode, bool bELastic) {
|
|
||||||
STsdbBufBlock *pBufBlock = NULL;
|
|
||||||
tdListNodeGetData(pPool->bufBlockList, pNode, (void *)(&pBufBlock));
|
|
||||||
tsdbFreeBufBlock(pBufBlock);
|
|
||||||
free(pNode);
|
|
||||||
if (bELastic) {
|
|
||||||
pPool->nElasticBlocks--;
|
|
||||||
tsdbWarn("pPool=%p elastic block reduce one . nElasticBlocks=%d cur free Blocks=%d", pPool, pPool->nElasticBlocks,
|
|
||||||
TD_DLIST_NELES(pPool->bufBlockList));
|
|
||||||
} else
|
|
||||||
pPool->nBufBlocks--;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,543 +0,0 @@
|
||||||
/*
|
|
||||||
* 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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
#include "tsdbint.h"
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
STable * pTable;
|
|
||||||
SBlockIdx * pBlkIdx;
|
|
||||||
SBlockIdx bindex;
|
|
||||||
SBlockInfo *pInfo;
|
|
||||||
} STableCompactH;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
SRtn rtn;
|
|
||||||
SFSIter fsIter;
|
|
||||||
SArray * tbArray; // table array to cache table obj and block indexes
|
|
||||||
SReadH readh;
|
|
||||||
SDFileSet wSet;
|
|
||||||
SArray * aBlkIdx;
|
|
||||||
SArray * aSupBlk;
|
|
||||||
SDataCols *pDataCols;
|
|
||||||
} SCompactH;
|
|
||||||
|
|
||||||
#define TSDB_COMPACT_WSET(pComph) (&((pComph)->wSet))
|
|
||||||
#define TSDB_COMPACT_REPO(pComph) TSDB_READ_REPO(&((pComph)->readh))
|
|
||||||
#define TSDB_COMPACT_HEAD_FILE(pComph) TSDB_DFILE_IN_SET(TSDB_COMPACT_WSET(pComph), TSDB_FILE_HEAD)
|
|
||||||
#define TSDB_COMPACT_DATA_FILE(pComph) TSDB_DFILE_IN_SET(TSDB_COMPACT_WSET(pComph), TSDB_FILE_DATA)
|
|
||||||
#define TSDB_COMPACT_LAST_FILE(pComph) TSDB_DFILE_IN_SET(TSDB_COMPACT_WSET(pComph), TSDB_FILE_LAST)
|
|
||||||
#define TSDB_COMPACT_SMAD_FILE(pComph) TSDB_DFILE_IN_SET(TSDB_COMPACT_WSET(pComph), TSDB_FILE_SMAD)
|
|
||||||
#define TSDB_COMPACT_SMAL_FILE(pComph) TSDB_DFILE_IN_SET(TSDB_COMPACT_WSET(pComph), TSDB_FILE_SMAL)
|
|
||||||
#define TSDB_COMPACT_BUF(pComph) TSDB_READ_BUF(&((pComph)->readh))
|
|
||||||
#define TSDB_COMPACT_COMP_BUF(pComph) TSDB_READ_COMP_BUF(&((pComph)->readh))
|
|
||||||
#define TSDB_COMPACT_EXBUF(pComph) TSDB_READ_EXBUF(&((pComph)->readh))
|
|
||||||
|
|
||||||
// static int tsdbAsyncCompact(STsdb *pRepo);
|
|
||||||
static void tsdbStartCompact(STsdb *pRepo);
|
|
||||||
static void tsdbEndCompact(STsdb *pRepo, int eno);
|
|
||||||
static int tsdbCompactMeta(STsdb *pRepo);
|
|
||||||
static int tsdbCompactTSData(STsdb *pRepo);
|
|
||||||
static int tsdbCompactFSet(SCompactH *pComph, SDFileSet *pSet);
|
|
||||||
static bool tsdbShouldCompact(SCompactH *pComph);
|
|
||||||
static int tsdbInitCompactH(SCompactH *pComph, STsdb *pRepo);
|
|
||||||
static void tsdbDestroyCompactH(SCompactH *pComph);
|
|
||||||
static int tsdbInitCompTbArray(SCompactH *pComph);
|
|
||||||
static void tsdbDestroyCompTbArray(SCompactH *pComph);
|
|
||||||
static int tsdbCacheFSetIndex(SCompactH *pComph);
|
|
||||||
static int tsdbCompactFSetInit(SCompactH *pComph, SDFileSet *pSet);
|
|
||||||
static void tsdbCompactFSetEnd(SCompactH *pComph);
|
|
||||||
static int tsdbCompactFSetImpl(SCompactH *pComph);
|
|
||||||
static int tsdbWriteBlockToRightFile(SCompactH *pComph, STable *pTable, SDataCols *pDataCols, void **ppBuf,
|
|
||||||
void **ppCBuf, void **ppExBuf);
|
|
||||||
|
|
||||||
enum { TSDB_NO_COMPACT, TSDB_IN_COMPACT, TSDB_WAITING_COMPACT};
|
|
||||||
// int tsdbCompact(STsdb *pRepo) { return tsdbAsyncCompact(pRepo); }
|
|
||||||
|
|
||||||
void *tsdbCompactImpl(STsdb *pRepo) {
|
|
||||||
// Check if there are files in TSDB FS to compact
|
|
||||||
if (REPO_FS(pRepo)->cstatus->pmf == NULL) {
|
|
||||||
pRepo->compactState = TSDB_NO_COMPACT;
|
|
||||||
tsem_post(&(pRepo->readyToCommit));
|
|
||||||
tsdbInfo("vgId:%d compact over, no file to compact in FS", REPO_ID(pRepo));
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
tsdbStartCompact(pRepo);
|
|
||||||
|
|
||||||
if (tsdbCompactMeta(pRepo) < 0) {
|
|
||||||
tsdbError("vgId:%d failed to compact META data since %s", REPO_ID(pRepo), tstrerror(terrno));
|
|
||||||
goto _err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tsdbCompactTSData(pRepo) < 0) {
|
|
||||||
tsdbError("vgId:%d failed to compact TS data since %s", REPO_ID(pRepo), tstrerror(terrno));
|
|
||||||
goto _err;
|
|
||||||
}
|
|
||||||
|
|
||||||
tsdbEndCompact(pRepo, TSDB_CODE_SUCCESS);
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
_err:
|
|
||||||
pRepo->code = terrno;
|
|
||||||
tsdbEndCompact(pRepo, terrno);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// static int tsdbAsyncCompact(STsdb *pRepo) {
|
|
||||||
// if (pRepo->compactState != TSDB_NO_COMPACT) {
|
|
||||||
// tsdbInfo("vgId:%d not compact tsdb again ", REPO_ID(pRepo));
|
|
||||||
// return 0;
|
|
||||||
// }
|
|
||||||
// pRepo->compactState = TSDB_WAITING_COMPACT;
|
|
||||||
// tsem_wait(&(pRepo->readyToCommit));
|
|
||||||
// return tsdbScheduleCommit(pRepo, COMPACT_REQ);
|
|
||||||
// }
|
|
||||||
|
|
||||||
static void tsdbStartCompact(STsdb *pRepo) {
|
|
||||||
assert(pRepo->compactState != TSDB_IN_COMPACT);
|
|
||||||
tsdbInfo("vgId:%d start to compact!", REPO_ID(pRepo));
|
|
||||||
tsdbStartFSTxn(pRepo, 0, 0);
|
|
||||||
pRepo->code = TSDB_CODE_SUCCESS;
|
|
||||||
pRepo->compactState = TSDB_IN_COMPACT;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void tsdbEndCompact(STsdb *pRepo, int eno) {
|
|
||||||
if (eno != TSDB_CODE_SUCCESS) {
|
|
||||||
tsdbEndFSTxnWithError(REPO_FS(pRepo));
|
|
||||||
} else {
|
|
||||||
tsdbEndFSTxn(pRepo);
|
|
||||||
}
|
|
||||||
pRepo->compactState = TSDB_NO_COMPACT;
|
|
||||||
tsdbInfo("vgId:%d compact over, %s", REPO_ID(pRepo), (eno == TSDB_CODE_SUCCESS) ? "succeed" : "failed");
|
|
||||||
tsem_post(&(pRepo->readyToCommit));
|
|
||||||
}
|
|
||||||
|
|
||||||
static int tsdbCompactMeta(STsdb *pRepo) {
|
|
||||||
STsdbFS *pfs = REPO_FS(pRepo);
|
|
||||||
tsdbUpdateMFile(pfs, pfs->cstatus->pmf);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int tsdbCompactTSData(STsdb *pRepo) {
|
|
||||||
SCompactH compactH;
|
|
||||||
SDFileSet *pSet = NULL;
|
|
||||||
|
|
||||||
tsdbDebug("vgId:%d start to compact TS data", REPO_ID(pRepo));
|
|
||||||
|
|
||||||
// If no file, just return 0;
|
|
||||||
if (taosArrayGetSize(REPO_FS(pRepo)->cstatus->df) <= 0) {
|
|
||||||
tsdbDebug("vgId:%d no TS data file to compact, compact over", REPO_ID(pRepo));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tsdbInitCompactH(&compactH, pRepo) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((pSet = tsdbFSIterNext(&(compactH.fsIter)))) {
|
|
||||||
// Remove those expired files
|
|
||||||
if (pSet->fid < compactH.rtn.minFid) {
|
|
||||||
tsdbInfo("vgId:%d FSET %d on level %d disk id %d expires, remove it", REPO_ID(pRepo), pSet->fid,
|
|
||||||
TSDB_FSET_LEVEL(pSet), TSDB_FSET_ID(pSet));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TSDB_FSET_LEVEL(pSet) == TFS_MAX_LEVEL) {
|
|
||||||
tsdbDebug("vgId:%d FSET %d on level %d, should not compact", REPO_ID(pRepo), pSet->fid, TFS_MAX_LEVEL);
|
|
||||||
tsdbUpdateDFileSet(REPO_FS(pRepo), pSet);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tsdbCompactFSet(&compactH, pSet) < 0) {
|
|
||||||
tsdbDestroyCompactH(&compactH);
|
|
||||||
tsdbError("vgId:%d failed to compact FSET %d since %s", REPO_ID(pRepo), pSet->fid, tstrerror(terrno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tsdbDestroyCompactH(&compactH);
|
|
||||||
tsdbDebug("vgId:%d compact TS data over", REPO_ID(pRepo));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int tsdbCompactFSet(SCompactH *pComph, SDFileSet *pSet) {
|
|
||||||
STsdb *pRepo = TSDB_COMPACT_REPO(pComph);
|
|
||||||
SDiskID did;
|
|
||||||
|
|
||||||
tsdbDebug("vgId:%d start to compact FSET %d on level %d id %d", REPO_ID(pRepo), pSet->fid, TSDB_FSET_LEVEL(pSet),
|
|
||||||
TSDB_FSET_ID(pSet));
|
|
||||||
|
|
||||||
if (tsdbCompactFSetInit(pComph, pSet) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!tsdbShouldCompact(pComph)) {
|
|
||||||
tsdbDebug("vgId:%d no need to compact FSET %d", REPO_ID(pRepo), pSet->fid);
|
|
||||||
if (tsdbApplyRtnOnFSet(TSDB_COMPACT_REPO(pComph), pSet, &(pComph->rtn)) < 0) {
|
|
||||||
tsdbCompactFSetEnd(pComph);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Create new fset as compacted fset
|
|
||||||
tfsAllocDisk(tsdbGetFidLevel(pSet->fid, &(pComph->rtn)), &(did.level), &(did.id));
|
|
||||||
if (did.level == TFS_UNDECIDED_LEVEL) {
|
|
||||||
terrno = TSDB_CODE_TDB_NO_AVAIL_DISK;
|
|
||||||
tsdbError("vgId:%d failed to compact FSET %d since %s", REPO_ID(pRepo), pSet->fid, tstrerror(terrno));
|
|
||||||
tsdbCompactFSetEnd(pComph);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
tsdbInitDFileSet(TSDB_COMPACT_WSET(pComph), did, REPO_ID(pRepo), TSDB_FSET_FID(pSet),
|
|
||||||
FS_TXN_VERSION(REPO_FS(pRepo)), TSDB_LATEST_FSET_VER);
|
|
||||||
if (tsdbCreateDFileSet(TSDB_COMPACT_WSET(pComph), true) < 0) {
|
|
||||||
tsdbError("vgId:%d failed to compact FSET %d since %s", REPO_ID(pRepo), pSet->fid, tstrerror(terrno));
|
|
||||||
tsdbCompactFSetEnd(pComph);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tsdbCompactFSetImpl(pComph) < 0) {
|
|
||||||
tsdbCloseDFileSet(TSDB_COMPACT_WSET(pComph));
|
|
||||||
tsdbRemoveDFileSet(TSDB_COMPACT_WSET(pComph));
|
|
||||||
tsdbCompactFSetEnd(pComph);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
tsdbCloseDFileSet(TSDB_COMPACT_WSET(pComph));
|
|
||||||
tsdbUpdateDFileSet(REPO_FS(pRepo), TSDB_COMPACT_WSET(pComph));
|
|
||||||
tsdbDebug("vgId:%d FSET %d compact over", REPO_ID(pRepo), pSet->fid);
|
|
||||||
}
|
|
||||||
|
|
||||||
tsdbCompactFSetEnd(pComph);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool tsdbShouldCompact(SCompactH *pComph) {
|
|
||||||
// if (tsdbForceCompactFile) {
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
STsdb * pRepo = TSDB_COMPACT_REPO(pComph);
|
|
||||||
STsdbCfg * pCfg = REPO_CFG(pRepo);
|
|
||||||
SReadH * pReadh = &(pComph->readh);
|
|
||||||
STableCompactH *pTh;
|
|
||||||
SBlock * pBlock;
|
|
||||||
int defaultRows = TSDB_DEFAULT_BLOCK_ROWS(pCfg->maxRowsPerFileBlock);
|
|
||||||
SDFile * pDataF = TSDB_READ_DATA_FILE(pReadh);
|
|
||||||
SDFile * pLastF = TSDB_READ_LAST_FILE(pReadh);
|
|
||||||
|
|
||||||
int tblocks = 0; // total blocks
|
|
||||||
int nSubBlocks = 0; // # of blocks with sub-blocks
|
|
||||||
int nSmallBlocks = 0; // # of blocks with rows < defaultRows
|
|
||||||
int64_t tsize = 0;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < taosArrayGetSize(pComph->tbArray); i++) {
|
|
||||||
pTh = (STableCompactH *)taosArrayGet(pComph->tbArray, i);
|
|
||||||
|
|
||||||
if (pTh->pTable == NULL || pTh->pBlkIdx == NULL) continue;
|
|
||||||
|
|
||||||
for (size_t bidx = 0; bidx < pTh->pBlkIdx->numOfBlocks; bidx++) {
|
|
||||||
tblocks++;
|
|
||||||
pBlock = pTh->pInfo->blocks + bidx;
|
|
||||||
|
|
||||||
if (pBlock->numOfRows < defaultRows) {
|
|
||||||
nSmallBlocks++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pBlock->numOfSubBlocks > 1) {
|
|
||||||
nSubBlocks++;
|
|
||||||
for (int k = 0; k < pBlock->numOfSubBlocks; k++) {
|
|
||||||
SBlock *iBlock = ((SBlock *)POINTER_SHIFT(pTh->pInfo, pBlock->offset)) + k;
|
|
||||||
tsize = tsize + iBlock->len;
|
|
||||||
}
|
|
||||||
} else if (pBlock->numOfSubBlocks == 1) {
|
|
||||||
tsize += pBlock->len;
|
|
||||||
} else {
|
|
||||||
ASSERT(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (((nSubBlocks * 1.0 / tblocks) > 0.33) || ((nSmallBlocks * 1.0 / tblocks) > 0.33) ||
|
|
||||||
(tsize * 1.0 / (pDataF->info.size + pLastF->info.size - 2 * TSDB_FILE_HEAD_SIZE) < 0.85));
|
|
||||||
}
|
|
||||||
|
|
||||||
static int tsdbInitCompactH(SCompactH *pComph, STsdb *pRepo) {
|
|
||||||
STsdbCfg *pCfg = REPO_CFG(pRepo);
|
|
||||||
|
|
||||||
memset(pComph, 0, sizeof(*pComph));
|
|
||||||
|
|
||||||
TSDB_FSET_SET_CLOSED(TSDB_COMPACT_WSET(pComph));
|
|
||||||
|
|
||||||
tsdbGetRtnSnap(pRepo, &(pComph->rtn));
|
|
||||||
tsdbFSIterInit(&(pComph->fsIter), REPO_FS(pRepo), TSDB_FS_ITER_FORWARD);
|
|
||||||
|
|
||||||
if (tsdbInitReadH(&(pComph->readh), pRepo) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tsdbInitCompTbArray(pComph) < 0) {
|
|
||||||
tsdbDestroyCompactH(pComph);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
pComph->aBlkIdx = taosArrayInit(1024, sizeof(SBlockIdx));
|
|
||||||
if (pComph->aBlkIdx == NULL) {
|
|
||||||
terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
|
|
||||||
tsdbDestroyCompactH(pComph);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
pComph->aSupBlk = taosArrayInit(1024, sizeof(SBlock));
|
|
||||||
if (pComph->aSupBlk == NULL) {
|
|
||||||
terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
|
|
||||||
tsdbDestroyCompactH(pComph);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
pComph->pDataCols = tdNewDataCols(0, pCfg->maxRowsPerFileBlock);
|
|
||||||
if (pComph->pDataCols == NULL) {
|
|
||||||
terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
|
|
||||||
tsdbDestroyCompactH(pComph);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void tsdbDestroyCompactH(SCompactH *pComph) {
|
|
||||||
pComph->pDataCols = tdFreeDataCols(pComph->pDataCols);
|
|
||||||
pComph->aSupBlk = taosArrayDestroy(pComph->aSupBlk);
|
|
||||||
pComph->aBlkIdx = taosArrayDestroy(pComph->aBlkIdx);
|
|
||||||
tsdbDestroyCompTbArray(pComph);
|
|
||||||
tsdbDestroyReadH(&(pComph->readh));
|
|
||||||
tsdbCloseDFileSet(TSDB_COMPACT_WSET(pComph));
|
|
||||||
}
|
|
||||||
|
|
||||||
static int tsdbInitCompTbArray(SCompactH *pComph) { // Init pComp->tbArray
|
|
||||||
STsdb *pRepo = TSDB_COMPACT_REPO(pComph);
|
|
||||||
STsdbMeta *pMeta = pRepo->tsdbMeta;
|
|
||||||
|
|
||||||
if (tsdbRLockRepoMeta(pRepo) < 0) return -1;
|
|
||||||
|
|
||||||
pComph->tbArray = taosArrayInit(pMeta->maxTables, sizeof(STableCompactH));
|
|
||||||
if (pComph->tbArray == NULL) {
|
|
||||||
terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
|
|
||||||
tsdbUnlockRepoMeta(pRepo);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note here must start from 0
|
|
||||||
for (int i = 0; i < pMeta->maxTables; i++) {
|
|
||||||
STableCompactH ch = {0};
|
|
||||||
if (pMeta->tables[i] != NULL) {
|
|
||||||
tsdbRefTable(pMeta->tables[i]);
|
|
||||||
ch.pTable = pMeta->tables[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (taosArrayPush(pComph->tbArray, &ch) == NULL) {
|
|
||||||
terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
|
|
||||||
tsdbUnlockRepoMeta(pRepo);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tsdbUnlockRepoMeta(pRepo) < 0) return -1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void tsdbDestroyCompTbArray(SCompactH *pComph) {
|
|
||||||
STableCompactH *pTh;
|
|
||||||
|
|
||||||
if (pComph->tbArray == NULL) return;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < taosArrayGetSize(pComph->tbArray); i++) {
|
|
||||||
pTh = (STableCompactH *)taosArrayGet(pComph->tbArray, i);
|
|
||||||
if (pTh->pTable) {
|
|
||||||
tsdbUnRefTable(pTh->pTable);
|
|
||||||
}
|
|
||||||
|
|
||||||
// pTh->pInfo = taosTZfree(pTh->pInfo);
|
|
||||||
tfree(pTh->pInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
pComph->tbArray = taosArrayDestroy(pComph->tbArray);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int tsdbCacheFSetIndex(SCompactH *pComph) {
|
|
||||||
SReadH *pReadH = &(pComph->readh);
|
|
||||||
|
|
||||||
if (tsdbLoadBlockIdx(pReadH) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int tid = 1; tid < taosArrayGetSize(pComph->tbArray); tid++) {
|
|
||||||
STableCompactH *pTh = (STableCompactH *)taosArrayGet(pComph->tbArray, tid);
|
|
||||||
pTh->pBlkIdx = NULL;
|
|
||||||
|
|
||||||
if (pTh->pTable == NULL) continue;
|
|
||||||
if (tsdbSetReadTable(pReadH, pTh->pTable) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pReadH->pBlkIdx == NULL) continue;
|
|
||||||
pTh->bindex = *(pReadH->pBlkIdx);
|
|
||||||
pTh->pBlkIdx = &(pTh->bindex);
|
|
||||||
|
|
||||||
uint32_t originLen = 0;
|
|
||||||
if (tsdbLoadBlockInfo(pReadH, (void **)(&(pTh->pInfo)), &originLen) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int tsdbCompactFSetInit(SCompactH *pComph, SDFileSet *pSet) {
|
|
||||||
taosArrayClear(pComph->aBlkIdx);
|
|
||||||
taosArrayClear(pComph->aSupBlk);
|
|
||||||
|
|
||||||
if (tsdbSetAndOpenReadFSet(&(pComph->readh), pSet) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tsdbCacheFSetIndex(pComph) < 0) {
|
|
||||||
tsdbCloseAndUnsetFSet(&(pComph->readh));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void tsdbCompactFSetEnd(SCompactH *pComph) { tsdbCloseAndUnsetFSet(&(pComph->readh)); }
|
|
||||||
|
|
||||||
static int tsdbCompactFSetImpl(SCompactH *pComph) {
|
|
||||||
STsdb *pRepo = TSDB_COMPACT_REPO(pComph);
|
|
||||||
STsdbCfg * pCfg = REPO_CFG(pRepo);
|
|
||||||
SReadH * pReadh = &(pComph->readh);
|
|
||||||
SBlockIdx blkIdx;
|
|
||||||
void ** ppBuf = &(TSDB_COMPACT_BUF(pComph));
|
|
||||||
void ** ppCBuf = &(TSDB_COMPACT_COMP_BUF(pComph));
|
|
||||||
void ** ppExBuf = &(TSDB_COMPACT_EXBUF(pComph));
|
|
||||||
int defaultRows = TSDB_DEFAULT_BLOCK_ROWS(pCfg->maxRowsPerFileBlock);
|
|
||||||
|
|
||||||
taosArrayClear(pComph->aBlkIdx);
|
|
||||||
|
|
||||||
for (int tid = 1; tid < taosArrayGetSize(pComph->tbArray); tid++) {
|
|
||||||
STableCompactH *pTh = (STableCompactH *)taosArrayGet(pComph->tbArray, tid);
|
|
||||||
STSchema * pSchema;
|
|
||||||
|
|
||||||
if (pTh->pTable == NULL || pTh->pBlkIdx == NULL) continue;
|
|
||||||
|
|
||||||
pSchema = tsdbGetTableSchemaImpl(pTh->pTable, true, true, -1, -1);
|
|
||||||
taosArrayClear(pComph->aSupBlk);
|
|
||||||
if ((tdInitDataCols(pComph->pDataCols, pSchema) < 0) || (tdInitDataCols(pReadh->pDCols[0], pSchema) < 0) ||
|
|
||||||
(tdInitDataCols(pReadh->pDCols[1], pSchema) < 0)) {
|
|
||||||
terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
|
|
||||||
tdFreeSchema(pSchema);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
tdFreeSchema(pSchema);
|
|
||||||
|
|
||||||
// Loop to compact each block data
|
|
||||||
for (int i = 0; i < pTh->pBlkIdx->numOfBlocks; i++) {
|
|
||||||
SBlock *pBlock = pTh->pInfo->blocks + i;
|
|
||||||
|
|
||||||
// Load the block data
|
|
||||||
if (tsdbLoadBlockData(pReadh, pBlock, pTh->pInfo) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Merge pComph->pDataCols and pReadh->pDCols[0] and write data to file
|
|
||||||
if (pComph->pDataCols->numOfRows == 0 && pBlock->numOfRows >= defaultRows) {
|
|
||||||
if (tsdbWriteBlockToRightFile(pComph, pTh->pTable, pReadh->pDCols[0], ppBuf, ppCBuf, ppExBuf) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
int ridx = 0;
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
if (pReadh->pDCols[0]->numOfRows - ridx == 0) break;
|
|
||||||
int rowsToMerge = MIN(pReadh->pDCols[0]->numOfRows - ridx, defaultRows - pComph->pDataCols->numOfRows);
|
|
||||||
|
|
||||||
tdMergeDataCols(pComph->pDataCols, pReadh->pDCols[0], rowsToMerge, &ridx, pCfg->update != TD_ROW_PARTIAL_UPDATE);
|
|
||||||
|
|
||||||
if (pComph->pDataCols->numOfRows < defaultRows) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tsdbWriteBlockToRightFile(pComph, pTh->pTable, pComph->pDataCols, ppBuf, ppCBuf, ppExBuf) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
tdResetDataCols(pComph->pDataCols);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pComph->pDataCols->numOfRows > 0 &&
|
|
||||||
tsdbWriteBlockToRightFile(pComph, pTh->pTable, pComph->pDataCols, ppBuf, ppCBuf, ppExBuf) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tsdbWriteBlockInfoImpl(TSDB_COMPACT_HEAD_FILE(pComph), pTh->pTable, pComph->aSupBlk, NULL, ppBuf, &blkIdx) <
|
|
||||||
0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((blkIdx.numOfBlocks > 0) && (taosArrayPush(pComph->aBlkIdx, (void *)(&blkIdx)) == NULL)) {
|
|
||||||
terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tsdbWriteBlockIdx(TSDB_COMPACT_HEAD_FILE(pComph), pComph->aBlkIdx, ppBuf) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int tsdbWriteBlockToRightFile(SCompactH *pComph, STable *pTable, SDataCols *pDataCols, void **ppBuf,
|
|
||||||
void **ppCBuf, void **ppExBuf) {
|
|
||||||
STsdb *pRepo = TSDB_COMPACT_REPO(pComph);
|
|
||||||
STsdbCfg * pCfg = REPO_CFG(pRepo);
|
|
||||||
SDFile * pDFile;
|
|
||||||
bool isLast;
|
|
||||||
SBlock block;
|
|
||||||
|
|
||||||
ASSERT(pDataCols->numOfRows > 0);
|
|
||||||
|
|
||||||
if (pDataCols->numOfRows < pCfg->minRowsPerFileBlock) {
|
|
||||||
pDFile = TSDB_COMPACT_LAST_FILE(pComph);
|
|
||||||
isLast = true;
|
|
||||||
} else {
|
|
||||||
pDFile = TSDB_COMPACT_DATA_FILE(pComph);
|
|
||||||
isLast = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tsdbWriteBlockImpl(pRepo, pTable, pDFile,
|
|
||||||
isLast ? TSDB_COMPACT_SMAL_FILE(pComph) : TSDB_COMPACT_SMAD_FILE(pComph), pDataCols, &block,
|
|
||||||
isLast, true, ppBuf, ppCBuf, ppExBuf) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (taosArrayPush(pComph->aSupBlk, (void *)(&block)) == NULL) {
|
|
||||||
terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,719 +0,0 @@
|
||||||
/*
|
|
||||||
* 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 "tsdbint.h"
|
|
||||||
|
|
||||||
static const char *TSDB_FNAME_SUFFIX[] = {
|
|
||||||
"head", // TSDB_FILE_HEAD
|
|
||||||
"data", // TSDB_FILE_DATA
|
|
||||||
"last", // TSDB_FILE_LAST
|
|
||||||
"smad", // TSDB_FILE_SMA_DATA(Small Materialized Aggregate for .data File)
|
|
||||||
"smal", // TSDB_FILE_SMA_LAST(Small Materialized Aggregate for .last File)
|
|
||||||
"", // TSDB_FILE_MAX
|
|
||||||
"meta", // TSDB_FILE_META
|
|
||||||
};
|
|
||||||
|
|
||||||
static void tsdbGetFilename(int vid, int fid, uint32_t ver, TSDB_FILE_T ftype, char *fname);
|
|
||||||
static int tsdbRollBackMFile(SMFile *pMFile);
|
|
||||||
static int tsdbEncodeDFInfo(void **buf, SDFInfo *pInfo);
|
|
||||||
static void *tsdbDecodeDFInfo(void *buf, SDFInfo *pInfo, TSDB_FVER_TYPE sfver);
|
|
||||||
static int tsdbRollBackDFile(SDFile *pDFile);
|
|
||||||
|
|
||||||
// ============== SMFile
|
|
||||||
void tsdbInitMFile(SMFile *pMFile, SDiskID did, int vid, uint32_t ver) {
|
|
||||||
char fname[TSDB_FILENAME_LEN];
|
|
||||||
|
|
||||||
TSDB_FILE_SET_STATE(pMFile, TSDB_FILE_STATE_OK);
|
|
||||||
|
|
||||||
memset(&(pMFile->info), 0, sizeof(pMFile->info));
|
|
||||||
pMFile->info.magic = TSDB_FILE_INIT_MAGIC;
|
|
||||||
|
|
||||||
tsdbGetFilename(vid, 0, ver, TSDB_FILE_META, fname);
|
|
||||||
tfsInitFile(TSDB_FILE_F(pMFile), did.level, did.id, fname);
|
|
||||||
}
|
|
||||||
|
|
||||||
void tsdbInitMFileEx(SMFile *pMFile, const SMFile *pOMFile) {
|
|
||||||
*pMFile = *pOMFile;
|
|
||||||
TSDB_FILE_SET_CLOSED(pMFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
int tsdbEncodeSMFile(void **buf, SMFile *pMFile) {
|
|
||||||
int tlen = 0;
|
|
||||||
|
|
||||||
tlen += tsdbEncodeMFInfo(buf, &(pMFile->info));
|
|
||||||
tlen += tfsEncodeFile(buf, &(pMFile->f));
|
|
||||||
|
|
||||||
return tlen;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *tsdbDecodeSMFile(void *buf, SMFile *pMFile) {
|
|
||||||
buf = tsdbDecodeMFInfo(buf, &(pMFile->info));
|
|
||||||
buf = tfsDecodeFile(buf, &(pMFile->f));
|
|
||||||
TSDB_FILE_SET_CLOSED(pMFile);
|
|
||||||
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
int tsdbEncodeSMFileEx(void **buf, SMFile *pMFile) {
|
|
||||||
int tlen = 0;
|
|
||||||
|
|
||||||
tlen += tsdbEncodeMFInfo(buf, &(pMFile->info));
|
|
||||||
tlen += taosEncodeString(buf, TSDB_FILE_FULL_NAME(pMFile));
|
|
||||||
|
|
||||||
return tlen;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *tsdbDecodeSMFileEx(void *buf, SMFile *pMFile) {
|
|
||||||
char *aname;
|
|
||||||
buf = tsdbDecodeMFInfo(buf, &(pMFile->info));
|
|
||||||
buf = taosDecodeString(buf, &aname);
|
|
||||||
tstrncpy(TSDB_FILE_FULL_NAME(pMFile), aname, TSDB_FILENAME_LEN);
|
|
||||||
TSDB_FILE_SET_CLOSED(pMFile);
|
|
||||||
|
|
||||||
tfree(aname);
|
|
||||||
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
int tsdbApplyMFileChange(SMFile *from, SMFile *to) {
|
|
||||||
if (from == NULL && to == NULL) return 0;
|
|
||||||
|
|
||||||
if (from != NULL) {
|
|
||||||
if (to == NULL) {
|
|
||||||
return tsdbRemoveMFile(from);
|
|
||||||
} else {
|
|
||||||
if (tfsIsSameFile(TSDB_FILE_F(from), TSDB_FILE_F(to))) {
|
|
||||||
if (from->info.size > to->info.size) {
|
|
||||||
tsdbRollBackMFile(to);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return tsdbRemoveMFile(from);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int tsdbCreateMFile(SMFile *pMFile, bool updateHeader) {
|
|
||||||
ASSERT(pMFile->info.size == 0 && pMFile->info.magic == TSDB_FILE_INIT_MAGIC);
|
|
||||||
|
|
||||||
pMFile->fd = open(TSDB_FILE_FULL_NAME(pMFile), O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0755);
|
|
||||||
if (pMFile->fd < 0) {
|
|
||||||
if (errno == ENOENT) {
|
|
||||||
// Try to create directory recursively
|
|
||||||
char *s = strdup(TFILE_REL_NAME(&(pMFile->f)));
|
|
||||||
if (tfsMkdirRecurAt(dirname(s), TSDB_FILE_LEVEL(pMFile), TSDB_FILE_ID(pMFile)) < 0) {
|
|
||||||
tfree(s);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
tfree(s);
|
|
||||||
|
|
||||||
pMFile->fd = open(TSDB_FILE_FULL_NAME(pMFile), O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0755);
|
|
||||||
if (pMFile->fd < 0) {
|
|
||||||
terrno = TAOS_SYSTEM_ERROR(errno);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
terrno = TAOS_SYSTEM_ERROR(errno);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!updateHeader) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
pMFile->info.size += TSDB_FILE_HEAD_SIZE;
|
|
||||||
|
|
||||||
if (tsdbUpdateMFileHeader(pMFile) < 0) {
|
|
||||||
tsdbCloseMFile(pMFile);
|
|
||||||
tsdbRemoveMFile(pMFile);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int tsdbUpdateMFileHeader(SMFile *pMFile) {
|
|
||||||
char buf[TSDB_FILE_HEAD_SIZE] = "\0";
|
|
||||||
|
|
||||||
if (tsdbSeekMFile(pMFile, 0, SEEK_SET) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *ptr = buf;
|
|
||||||
tsdbEncodeMFInfo(&ptr, TSDB_FILE_INFO(pMFile));
|
|
||||||
|
|
||||||
taosCalcChecksumAppend(0, (uint8_t *)buf, TSDB_FILE_HEAD_SIZE);
|
|
||||||
if (tsdbWriteMFile(pMFile, buf, TSDB_FILE_HEAD_SIZE) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int tsdbLoadMFileHeader(SMFile *pMFile, SMFInfo *pInfo) {
|
|
||||||
char buf[TSDB_FILE_HEAD_SIZE] = "\0";
|
|
||||||
|
|
||||||
ASSERT(TSDB_FILE_OPENED(pMFile));
|
|
||||||
|
|
||||||
if (tsdbSeekMFile(pMFile, 0, SEEK_SET) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tsdbReadMFile(pMFile, buf, TSDB_FILE_HEAD_SIZE) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!taosCheckChecksumWhole((uint8_t *)buf, TSDB_FILE_HEAD_SIZE)) {
|
|
||||||
terrno = TSDB_CODE_TDB_FILE_CORRUPTED;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
tsdbDecodeMFInfo(buf, pInfo);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int tsdbScanAndTryFixMFile(STsdb *pRepo) {
|
|
||||||
SMFile * pMFile = pRepo->fs->cstatus->pmf;
|
|
||||||
struct stat mfstat;
|
|
||||||
SMFile mf;
|
|
||||||
|
|
||||||
if (pMFile == NULL) {
|
|
||||||
// No meta file, no need to scan
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
tsdbInitMFileEx(&mf, pMFile);
|
|
||||||
|
|
||||||
if (access(TSDB_FILE_FULL_NAME(pMFile), F_OK) != 0) {
|
|
||||||
tsdbError("vgId:%d meta file %s not exist, report to upper layer to fix it", REPO_ID(pRepo),
|
|
||||||
TSDB_FILE_FULL_NAME(pMFile));
|
|
||||||
pRepo->state |= TSDB_STATE_BAD_META;
|
|
||||||
TSDB_FILE_SET_STATE(pMFile, TSDB_FILE_STATE_BAD);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stat(TSDB_FILE_FULL_NAME(&mf), &mfstat) < 0) {
|
|
||||||
terrno = TAOS_SYSTEM_ERROR(errno);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pMFile->info.size < mfstat.st_size) {
|
|
||||||
if (tsdbOpenMFile(&mf, O_WRONLY) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (taosFtruncateFile(mf.fd, mf.info.size) < 0) {
|
|
||||||
terrno = TAOS_SYSTEM_ERROR(errno);
|
|
||||||
tsdbCloseMFile(&mf);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tsdbUpdateMFileHeader(&mf) < 0) {
|
|
||||||
tsdbCloseMFile(&mf);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
tsdbCloseMFile(&mf);
|
|
||||||
tsdbInfo("vgId:%d file %s is truncated from %" PRId64 " to %" PRId64, REPO_ID(pRepo), TSDB_FILE_FULL_NAME(pMFile),
|
|
||||||
mfstat.st_size, pMFile->info.size);
|
|
||||||
} else if (pMFile->info.size > mfstat.st_size) {
|
|
||||||
tsdbError("vgId:%d meta file %s has wrong size %" PRId64 " expected %" PRId64 ", report to upper layer to fix it",
|
|
||||||
REPO_ID(pRepo), TSDB_FILE_FULL_NAME(pMFile), mfstat.st_size, pMFile->info.size);
|
|
||||||
pRepo->state |= TSDB_STATE_BAD_META;
|
|
||||||
TSDB_FILE_SET_STATE(pMFile, TSDB_FILE_STATE_BAD);
|
|
||||||
terrno = TSDB_CODE_TDB_FILE_CORRUPTED;
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
tsdbDebug("vgId:%d meta file %s passes the scan", REPO_ID(pRepo), TSDB_FILE_FULL_NAME(pMFile));
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int tsdbEncodeMFInfo(void **buf, SMFInfo *pInfo) {
|
|
||||||
int tlen = 0;
|
|
||||||
|
|
||||||
tlen += taosEncodeVariantI64(buf, pInfo->size);
|
|
||||||
tlen += taosEncodeVariantI64(buf, pInfo->tombSize);
|
|
||||||
tlen += taosEncodeVariantI64(buf, pInfo->nRecords);
|
|
||||||
tlen += taosEncodeVariantI64(buf, pInfo->nDels);
|
|
||||||
tlen += taosEncodeFixedU32(buf, pInfo->magic);
|
|
||||||
|
|
||||||
return tlen;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *tsdbDecodeMFInfo(void *buf, SMFInfo *pInfo) {
|
|
||||||
buf = taosDecodeVariantI64(buf, &(pInfo->size));
|
|
||||||
buf = taosDecodeVariantI64(buf, &(pInfo->tombSize));
|
|
||||||
buf = taosDecodeVariantI64(buf, &(pInfo->nRecords));
|
|
||||||
buf = taosDecodeVariantI64(buf, &(pInfo->nDels));
|
|
||||||
buf = taosDecodeFixedU32(buf, &(pInfo->magic));
|
|
||||||
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int tsdbRollBackMFile(SMFile *pMFile) {
|
|
||||||
SMFile mf;
|
|
||||||
|
|
||||||
tsdbInitMFileEx(&mf, pMFile);
|
|
||||||
|
|
||||||
if (tsdbOpenMFile(&mf, O_WRONLY) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (taosFtruncateFile(TSDB_FILE_FD(&mf), pMFile->info.size) < 0) {
|
|
||||||
terrno = TAOS_SYSTEM_ERROR(errno);
|
|
||||||
tsdbCloseMFile(&mf);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tsdbUpdateMFileHeader(&mf) < 0) {
|
|
||||||
tsdbCloseMFile(&mf);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
TSDB_FILE_FSYNC(&mf);
|
|
||||||
|
|
||||||
tsdbCloseMFile(&mf);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ============== Operations on SDFile
|
|
||||||
void tsdbInitDFile(SDFile *pDFile, SDiskID did, int vid, int fid, uint32_t ver, TSDB_FILE_T ftype) {
|
|
||||||
char fname[TSDB_FILENAME_LEN];
|
|
||||||
|
|
||||||
TSDB_FILE_SET_STATE(pDFile, TSDB_FILE_STATE_OK);
|
|
||||||
|
|
||||||
TSDB_FILE_SET_CLOSED(pDFile);
|
|
||||||
|
|
||||||
memset(&(pDFile->info), 0, sizeof(pDFile->info));
|
|
||||||
pDFile->info.magic = TSDB_FILE_INIT_MAGIC;
|
|
||||||
pDFile->info.fver = tsdbGetDFSVersion(ftype);
|
|
||||||
|
|
||||||
tsdbGetFilename(vid, fid, ver, ftype, fname);
|
|
||||||
tfsInitFile(&(pDFile->f), did.level, did.id, fname);
|
|
||||||
}
|
|
||||||
|
|
||||||
void tsdbInitDFileEx(SDFile *pDFile, SDFile *pODFile) {
|
|
||||||
*pDFile = *pODFile;
|
|
||||||
TSDB_FILE_SET_CLOSED(pDFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
int tsdbEncodeSDFile(void **buf, SDFile *pDFile) {
|
|
||||||
int tlen = 0;
|
|
||||||
|
|
||||||
tlen += tsdbEncodeDFInfo(buf, &(pDFile->info));
|
|
||||||
tlen += tfsEncodeFile(buf, &(pDFile->f));
|
|
||||||
|
|
||||||
return tlen;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *tsdbDecodeSDFile(void *buf, SDFile *pDFile, uint32_t sfver) {
|
|
||||||
buf = tsdbDecodeDFInfo(buf, &(pDFile->info), sfver);
|
|
||||||
buf = tfsDecodeFile(buf, &(pDFile->f));
|
|
||||||
TSDB_FILE_SET_CLOSED(pDFile);
|
|
||||||
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int tsdbEncodeSDFileEx(void **buf, SDFile *pDFile) {
|
|
||||||
int tlen = 0;
|
|
||||||
|
|
||||||
tlen += tsdbEncodeDFInfo(buf, &(pDFile->info));
|
|
||||||
tlen += taosEncodeString(buf, TSDB_FILE_FULL_NAME(pDFile));
|
|
||||||
|
|
||||||
return tlen;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void *tsdbDecodeSDFileEx(void *buf, SDFile *pDFile) {
|
|
||||||
char *aname;
|
|
||||||
// The sync module would send DFileSet with latest verion.
|
|
||||||
buf = tsdbDecodeDFInfo(buf, &(pDFile->info), TSDB_LATEST_SFS_VER);
|
|
||||||
buf = taosDecodeString(buf, &aname);
|
|
||||||
tstrncpy(TSDB_FILE_FULL_NAME(pDFile), aname, TSDB_FILENAME_LEN);
|
|
||||||
TSDB_FILE_SET_CLOSED(pDFile);
|
|
||||||
tfree(aname);
|
|
||||||
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
int tsdbCreateDFile(SDFile *pDFile, bool updateHeader, TSDB_FILE_T fType) {
|
|
||||||
ASSERT(pDFile->info.size == 0 && pDFile->info.magic == TSDB_FILE_INIT_MAGIC);
|
|
||||||
|
|
||||||
pDFile->fd = open(TSDB_FILE_FULL_NAME(pDFile), O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0755);
|
|
||||||
if (pDFile->fd < 0) {
|
|
||||||
if (errno == ENOENT) {
|
|
||||||
// Try to create directory recursively
|
|
||||||
char *s = strdup(TFILE_REL_NAME(&(pDFile->f)));
|
|
||||||
if (tfsMkdirRecurAt(dirname(s), TSDB_FILE_LEVEL(pDFile), TSDB_FILE_ID(pDFile)) < 0) {
|
|
||||||
tfree(s);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
tfree(s);
|
|
||||||
|
|
||||||
pDFile->fd = open(TSDB_FILE_FULL_NAME(pDFile), O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0755);
|
|
||||||
if (pDFile->fd < 0) {
|
|
||||||
terrno = TAOS_SYSTEM_ERROR(errno);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
terrno = TAOS_SYSTEM_ERROR(errno);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!updateHeader) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
pDFile->info.size += TSDB_FILE_HEAD_SIZE;
|
|
||||||
pDFile->info.fver = tsdbGetDFSVersion(fType);
|
|
||||||
|
|
||||||
if (tsdbUpdateDFileHeader(pDFile) < 0) {
|
|
||||||
tsdbCloseDFile(pDFile);
|
|
||||||
tsdbRemoveDFile(pDFile);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int tsdbUpdateDFileHeader(SDFile *pDFile) {
|
|
||||||
char buf[TSDB_FILE_HEAD_SIZE] = "\0";
|
|
||||||
|
|
||||||
if (tsdbSeekDFile(pDFile, 0, SEEK_SET) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *ptr = buf;
|
|
||||||
tsdbEncodeDFInfo(&ptr, &(pDFile->info));
|
|
||||||
|
|
||||||
taosCalcChecksumAppend(0, (uint8_t *)buf, TSDB_FILE_HEAD_SIZE);
|
|
||||||
if (tsdbWriteDFile(pDFile, buf, TSDB_FILE_HEAD_SIZE) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int tsdbLoadDFileHeader(SDFile *pDFile, SDFInfo *pInfo) {
|
|
||||||
char buf[TSDB_FILE_HEAD_SIZE] = "\0";
|
|
||||||
// uint32_t _version;
|
|
||||||
|
|
||||||
ASSERT(TSDB_FILE_OPENED(pDFile));
|
|
||||||
|
|
||||||
if (tsdbSeekDFile(pDFile, 0, SEEK_SET) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tsdbReadDFile(pDFile, buf, TSDB_FILE_HEAD_SIZE) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!taosCheckChecksumWhole((uint8_t *)buf, TSDB_FILE_HEAD_SIZE)) {
|
|
||||||
terrno = TSDB_CODE_TDB_FILE_CORRUPTED;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *pBuf = buf;
|
|
||||||
pBuf = tsdbDecodeDFInfo(pBuf, pInfo, TSDB_LATEST_FVER); // only make sure the parameter sfver > 0
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int tsdbScanAndTryFixDFile(STsdb *pRepo, SDFile *pDFile) {
|
|
||||||
struct stat dfstat;
|
|
||||||
SDFile df;
|
|
||||||
|
|
||||||
tsdbInitDFileEx(&df, pDFile);
|
|
||||||
|
|
||||||
if (access(TSDB_FILE_FULL_NAME(pDFile), F_OK) != 0) {
|
|
||||||
tsdbError("vgId:%d data file %s not exist, report to upper layer to fix it", REPO_ID(pRepo),
|
|
||||||
TSDB_FILE_FULL_NAME(pDFile));
|
|
||||||
pRepo->state |= TSDB_STATE_BAD_DATA;
|
|
||||||
TSDB_FILE_SET_STATE(pDFile, TSDB_FILE_STATE_BAD);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stat(TSDB_FILE_FULL_NAME(&df), &dfstat) < 0) {
|
|
||||||
terrno = TAOS_SYSTEM_ERROR(errno);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pDFile->info.size < dfstat.st_size) {
|
|
||||||
if (tsdbOpenDFile(&df, O_WRONLY) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (taosFtruncateFile(df.fd, df.info.size) < 0) {
|
|
||||||
terrno = TAOS_SYSTEM_ERROR(errno);
|
|
||||||
tsdbCloseDFile(&df);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tsdbUpdateDFileHeader(&df) < 0) {
|
|
||||||
tsdbCloseDFile(&df);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
tsdbCloseDFile(&df);
|
|
||||||
tsdbInfo("vgId:%d file %s is truncated from %" PRId64 " to %" PRId64, REPO_ID(pRepo), TSDB_FILE_FULL_NAME(pDFile),
|
|
||||||
dfstat.st_size, pDFile->info.size);
|
|
||||||
} else if (pDFile->info.size > dfstat.st_size) {
|
|
||||||
tsdbError("vgId:%d data file %s has wrong size %" PRId64 " expected %" PRId64 ", report to upper layer to fix it",
|
|
||||||
REPO_ID(pRepo), TSDB_FILE_FULL_NAME(pDFile), dfstat.st_size, pDFile->info.size);
|
|
||||||
pRepo->state |= TSDB_STATE_BAD_DATA;
|
|
||||||
TSDB_FILE_SET_STATE(pDFile, TSDB_FILE_STATE_BAD);
|
|
||||||
terrno = TSDB_CODE_TDB_FILE_CORRUPTED;
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
tsdbDebug("vgId:%d file %s passes the scan", REPO_ID(pRepo), TSDB_FILE_FULL_NAME(pDFile));
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int tsdbEncodeDFInfo(void **buf, SDFInfo *pInfo) {
|
|
||||||
int tlen = 0;
|
|
||||||
tlen += taosEncodeFixedU32(buf, pInfo->fver);
|
|
||||||
tlen += taosEncodeFixedU32(buf, pInfo->magic);
|
|
||||||
tlen += taosEncodeFixedU32(buf, pInfo->len);
|
|
||||||
tlen += taosEncodeFixedU32(buf, pInfo->totalBlocks);
|
|
||||||
tlen += taosEncodeFixedU32(buf, pInfo->totalSubBlocks);
|
|
||||||
tlen += taosEncodeFixedU32(buf, pInfo->offset);
|
|
||||||
tlen += taosEncodeFixedU64(buf, pInfo->size);
|
|
||||||
tlen += taosEncodeFixedU64(buf, pInfo->tombSize);
|
|
||||||
|
|
||||||
return tlen;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void *tsdbDecodeDFInfo(void *buf, SDFInfo *pInfo, TSDB_FVER_TYPE sfver) {
|
|
||||||
if (sfver > TSDB_FS_VER_0) {
|
|
||||||
buf = taosDecodeFixedU32(buf, &(pInfo->fver));
|
|
||||||
} else {
|
|
||||||
pInfo->fver = TSDB_FS_VER_0; // default value
|
|
||||||
}
|
|
||||||
buf = taosDecodeFixedU32(buf, &(pInfo->magic));
|
|
||||||
buf = taosDecodeFixedU32(buf, &(pInfo->len));
|
|
||||||
buf = taosDecodeFixedU32(buf, &(pInfo->totalBlocks));
|
|
||||||
buf = taosDecodeFixedU32(buf, &(pInfo->totalSubBlocks));
|
|
||||||
buf = taosDecodeFixedU32(buf, &(pInfo->offset));
|
|
||||||
buf = taosDecodeFixedU64(buf, &(pInfo->size));
|
|
||||||
buf = taosDecodeFixedU64(buf, &(pInfo->tombSize));
|
|
||||||
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int tsdbApplyDFileChange(SDFile *from, SDFile *to) {
|
|
||||||
ASSERT(from != NULL || to != NULL);
|
|
||||||
|
|
||||||
if (from != NULL) {
|
|
||||||
if (to == NULL) {
|
|
||||||
tsdbRemoveDFile(from);
|
|
||||||
} else {
|
|
||||||
if (tfsIsSameFile(TSDB_FILE_F(from), TSDB_FILE_F(to))) {
|
|
||||||
if (from->info.size > to->info.size) {
|
|
||||||
tsdbRollBackDFile(to);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
(void)tsdbRemoveDFile(from);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int tsdbRollBackDFile(SDFile *pDFile) {
|
|
||||||
SDFile df = *pDFile;
|
|
||||||
|
|
||||||
if (tsdbOpenDFile(&df, O_WRONLY) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (taosFtruncateFile(TSDB_FILE_FD(&df), pDFile->info.size) < 0) {
|
|
||||||
terrno = TAOS_SYSTEM_ERROR(errno);
|
|
||||||
tsdbCloseDFile(&df);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tsdbUpdateDFileHeader(&df) < 0) {
|
|
||||||
tsdbCloseDFile(&df);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
TSDB_FILE_FSYNC(&df);
|
|
||||||
|
|
||||||
tsdbCloseDFile(&df);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ============== Operations on SDFileSet
|
|
||||||
void tsdbInitDFileSet(SDFileSet *pSet, SDiskID did, int vid, int fid, uint32_t ver, uint16_t fsetVer) {
|
|
||||||
pSet->fid = fid;
|
|
||||||
pSet->state = 0;
|
|
||||||
pSet->ver = fsetVer;
|
|
||||||
|
|
||||||
for (TSDB_FILE_T ftype = 0; ftype < tsdbGetNFiles(pSet); ftype++) {
|
|
||||||
SDFile *pDFile = TSDB_DFILE_IN_SET(pSet, ftype);
|
|
||||||
tsdbInitDFile(pDFile, did, vid, fid, ver, ftype);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void tsdbInitDFileSetEx(SDFileSet *pSet, SDFileSet *pOSet) {
|
|
||||||
ASSERT_TSDB_FSET_NFILES_VALID(pOSet);
|
|
||||||
pSet->fid = pOSet->fid;
|
|
||||||
pSet->ver = pOSet->ver;
|
|
||||||
for (TSDB_FILE_T ftype = 0; ftype < tsdbGetNFiles(pSet); ftype++) {
|
|
||||||
tsdbInitDFileEx(TSDB_DFILE_IN_SET(pSet, ftype), TSDB_DFILE_IN_SET(pOSet, ftype));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int tsdbEncodeDFileSet(void **buf, SDFileSet *pSet) {
|
|
||||||
int tlen = 0;
|
|
||||||
|
|
||||||
tlen += taosEncodeFixedI32(buf, pSet->fid);
|
|
||||||
tlen += taosEncodeFixedU16(buf, pSet->ver);
|
|
||||||
for (TSDB_FILE_T ftype = 0; ftype < tsdbGetNFiles(pSet); ftype++) {
|
|
||||||
tlen += tsdbEncodeSDFile(buf, TSDB_DFILE_IN_SET(pSet, ftype));
|
|
||||||
}
|
|
||||||
|
|
||||||
return tlen;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *tsdbDecodeDFileSet(void *buf, SDFileSet *pSet, uint32_t sfver) {
|
|
||||||
int32_t fid;
|
|
||||||
|
|
||||||
buf = taosDecodeFixedI32(buf, &(fid));
|
|
||||||
pSet->state = 0;
|
|
||||||
pSet->fid = fid;
|
|
||||||
|
|
||||||
if (sfver > TSDB_FS_VER_0) {
|
|
||||||
buf = taosDecodeFixedU16(buf, &(pSet->ver));
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT_TSDB_FSET_NFILES_VALID(pSet);
|
|
||||||
for (TSDB_FILE_T ftype = 0; ftype < tsdbGetNFiles(pSet); ftype++) {
|
|
||||||
buf = tsdbDecodeSDFile(buf, TSDB_DFILE_IN_SET(pSet, ftype), sfver);
|
|
||||||
}
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
int tsdbEncodeDFileSetEx(void **buf, SDFileSet *pSet) {
|
|
||||||
int tlen = 0;
|
|
||||||
|
|
||||||
tlen += taosEncodeFixedI32(buf, pSet->fid);
|
|
||||||
tlen += taosEncodeFixedU16(buf, pSet->ver);
|
|
||||||
for (TSDB_FILE_T ftype = 0; ftype < tsdbGetNFiles(pSet); ftype++) {
|
|
||||||
tlen += tsdbEncodeSDFileEx(buf, TSDB_DFILE_IN_SET(pSet, ftype));
|
|
||||||
}
|
|
||||||
|
|
||||||
return tlen;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *tsdbDecodeDFileSetEx(void *buf, SDFileSet *pSet) {
|
|
||||||
int32_t fid;
|
|
||||||
|
|
||||||
buf = taosDecodeFixedI32(buf, &(fid));
|
|
||||||
buf = taosDecodeFixedU16(buf, &(pSet->ver));
|
|
||||||
pSet->fid = fid;
|
|
||||||
for (TSDB_FILE_T ftype = 0; ftype < tsdbGetNFiles(pSet); ftype++) {
|
|
||||||
buf = tsdbDecodeSDFileEx(buf, TSDB_DFILE_IN_SET(pSet, ftype));
|
|
||||||
}
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
int tsdbApplyDFileSetChange(SDFileSet *from, SDFileSet *to) {
|
|
||||||
uint8_t nFilesFrom = from ? tsdbGetNFiles(from) : 0;
|
|
||||||
uint8_t nFilesTo = to ? tsdbGetNFiles(to) : 0;
|
|
||||||
for (TSDB_FILE_T ftype = 0; ftype < MAX(nFilesFrom, nFilesTo); ftype++) {
|
|
||||||
SDFile *pDFileFrom = ftype < nFilesFrom ? TSDB_DFILE_IN_SET(from, ftype) : NULL;
|
|
||||||
SDFile *pDFileTo = ftype < nFilesTo ? TSDB_DFILE_IN_SET(to, ftype) : NULL;
|
|
||||||
if (tsdbApplyDFileChange(pDFileFrom, pDFileTo) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int tsdbCreateDFileSet(SDFileSet *pSet, bool updateHeader) {
|
|
||||||
for (TSDB_FILE_T ftype = 0; ftype < tsdbGetNFiles(pSet); ftype++) {
|
|
||||||
if (tsdbCreateDFile(TSDB_DFILE_IN_SET(pSet, ftype), updateHeader, ftype) < 0) {
|
|
||||||
tsdbCloseDFileSet(pSet);
|
|
||||||
tsdbRemoveDFileSet(pSet);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int tsdbUpdateDFileSetHeader(SDFileSet *pSet) {
|
|
||||||
for (TSDB_FILE_T ftype = 0; ftype < tsdbGetNFiles(pSet); ftype++) {
|
|
||||||
if (tsdbUpdateDFileHeader(TSDB_DFILE_IN_SET(pSet, ftype)) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int tsdbScanAndTryFixDFileSet(STsdb *pRepo, SDFileSet *pSet) {
|
|
||||||
ASSERT_TSDB_FSET_NFILES_VALID(pSet);
|
|
||||||
for (TSDB_FILE_T ftype = 0; ftype < tsdbGetNFiles(pSet); ftype++) {
|
|
||||||
if (tsdbScanAndTryFixDFile(pRepo, TSDB_DFILE_IN_SET(pSet, ftype)) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int tsdbParseDFilename(const char *fname, int *vid, int *fid, TSDB_FILE_T *ftype, uint32_t *_version) {
|
|
||||||
char *p = NULL;
|
|
||||||
*_version = 0;
|
|
||||||
*ftype = TSDB_FILE_MAX;
|
|
||||||
|
|
||||||
sscanf(fname, "v%df%d.%m[a-z]-ver%" PRIu32, vid, fid, &p, _version);
|
|
||||||
for (TSDB_FILE_T i = 0; i < TSDB_FILE_MAX; i++) {
|
|
||||||
if (strcmp(p, TSDB_FNAME_SUFFIX[i]) == 0) {
|
|
||||||
*ftype = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tfree(p);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void tsdbGetFilename(int vid, int fid, uint32_t ver, TSDB_FILE_T ftype, char *fname) {
|
|
||||||
ASSERT(ftype != TSDB_FILE_MAX);
|
|
||||||
|
|
||||||
if (ftype < TSDB_FILE_MAX) {
|
|
||||||
if (ver == 0) {
|
|
||||||
snprintf(fname, TSDB_FILENAME_LEN, "vnode/vnode%d/tsdb/data/v%df%d.%s", vid, vid, fid, TSDB_FNAME_SUFFIX[ftype]);
|
|
||||||
} else {
|
|
||||||
snprintf(fname, TSDB_FILENAME_LEN, "vnode/vnode%d/tsdb/data/v%df%d.%s-ver%" PRIu32, vid, vid, fid,
|
|
||||||
TSDB_FNAME_SUFFIX[ftype], ver);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (ver == 0) {
|
|
||||||
snprintf(fname, TSDB_FILENAME_LEN, "vnode/vnode%d/tsdb/%s", vid, TSDB_FNAME_SUFFIX[ftype]);
|
|
||||||
} else {
|
|
||||||
snprintf(fname, TSDB_FILENAME_LEN, "vnode/vnode%d/tsdb/%s-ver%" PRIu32, vid, TSDB_FNAME_SUFFIX[ftype], ver);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,878 +0,0 @@
|
||||||
/*
|
|
||||||
* 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 "tsdbint.h"
|
|
||||||
|
|
||||||
#define TSDB_KEY_COL_OFFSET 0
|
|
||||||
|
|
||||||
static void tsdbResetReadTable(SReadH *pReadh);
|
|
||||||
static void tsdbResetReadFile(SReadH *pReadh);
|
|
||||||
static int tsdbLoadBlockDataImpl(SReadH *pReadh, SBlock *pBlock, SDataCols *pDataCols);
|
|
||||||
static int tsdbCheckAndDecodeColumnData(SDataCol *pDataCol, void *content, int32_t len, int8_t comp, int numOfRows,
|
|
||||||
int maxPoints, char *buffer, int bufferSize);
|
|
||||||
static int tsdbLoadBlockDataColsImpl(SReadH *pReadh, SBlock *pBlock, SDataCols *pDataCols, int16_t *colIds,
|
|
||||||
int numOfColIds);
|
|
||||||
static int tsdbLoadColData(SReadH *pReadh, SDFile *pDFile, SBlock *pBlock, SBlockCol *pBlockCol, SDataCol *pDataCol);
|
|
||||||
static int tsdbLoadBlockStatisFromDFile(SReadH *pReadh, SBlock *pBlock);
|
|
||||||
static int tsdbLoadBlockStatisFromAggr(SReadH *pReadh, SBlock *pBlock);
|
|
||||||
|
|
||||||
int tsdbInitReadH(SReadH *pReadh, STsdb *pRepo) {
|
|
||||||
ASSERT(pReadh != NULL && pRepo != NULL);
|
|
||||||
|
|
||||||
STsdbCfg *pCfg = REPO_CFG(pRepo);
|
|
||||||
|
|
||||||
memset((void *)pReadh, 0, sizeof(*pReadh));
|
|
||||||
pReadh->pRepo = pRepo;
|
|
||||||
|
|
||||||
TSDB_FSET_SET_CLOSED(TSDB_READ_FSET(pReadh));
|
|
||||||
|
|
||||||
pReadh->aBlkIdx = taosArrayInit(1024, sizeof(SBlockIdx));
|
|
||||||
if (pReadh->aBlkIdx == NULL) {
|
|
||||||
terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
pReadh->pDCols[0] = tdNewDataCols(0, pCfg->maxRowsPerFileBlock);
|
|
||||||
if (pReadh->pDCols[0] == NULL) {
|
|
||||||
terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
|
|
||||||
tsdbDestroyReadH(pReadh);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
pReadh->pDCols[1] = tdNewDataCols(0, pCfg->maxRowsPerFileBlock);
|
|
||||||
if (pReadh->pDCols[1] == NULL) {
|
|
||||||
terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
|
|
||||||
tsdbDestroyReadH(pReadh);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void tsdbDestroyReadH(SReadH *pReadh) {
|
|
||||||
if (pReadh == NULL) return;
|
|
||||||
pReadh->pExBuf = taosTZfree(pReadh->pExBuf);
|
|
||||||
pReadh->pCBuf = taosTZfree(pReadh->pCBuf);
|
|
||||||
pReadh->pBuf = taosTZfree(pReadh->pBuf);
|
|
||||||
pReadh->pDCols[0] = tdFreeDataCols(pReadh->pDCols[0]);
|
|
||||||
pReadh->pDCols[1] = tdFreeDataCols(pReadh->pDCols[1]);
|
|
||||||
pReadh->pAggrBlkData = taosTZfree(pReadh->pAggrBlkData);
|
|
||||||
pReadh->pBlkData = taosTZfree(pReadh->pBlkData);
|
|
||||||
pReadh->pBlkInfo = taosTZfree(pReadh->pBlkInfo);
|
|
||||||
pReadh->cidx = 0;
|
|
||||||
pReadh->pBlkIdx = NULL;
|
|
||||||
pReadh->pTable = NULL;
|
|
||||||
pReadh->aBlkIdx = taosArrayDestroy(pReadh->aBlkIdx);
|
|
||||||
tsdbCloseDFileSet(TSDB_READ_FSET(pReadh));
|
|
||||||
pReadh->pRepo = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int tsdbSetAndOpenReadFSet(SReadH *pReadh, SDFileSet *pSet) {
|
|
||||||
ASSERT(pSet != NULL);
|
|
||||||
tsdbResetReadFile(pReadh);
|
|
||||||
|
|
||||||
pReadh->rSet = *pSet;
|
|
||||||
TSDB_FSET_SET_CLOSED(TSDB_READ_FSET(pReadh));
|
|
||||||
if (tsdbOpenDFileSet(TSDB_READ_FSET(pReadh), O_RDONLY) < 0) {
|
|
||||||
tsdbError("vgId:%d failed to open file set %d since %s", TSDB_READ_REPO_ID(pReadh), TSDB_FSET_FID(pSet),
|
|
||||||
tstrerror(terrno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void tsdbCloseAndUnsetFSet(SReadH *pReadh) { tsdbResetReadFile(pReadh); }
|
|
||||||
|
|
||||||
int tsdbLoadBlockIdx(SReadH *pReadh) {
|
|
||||||
SDFile * pHeadf = TSDB_READ_HEAD_FILE(pReadh);
|
|
||||||
SBlockIdx blkIdx;
|
|
||||||
|
|
||||||
ASSERT(taosArrayGetSize(pReadh->aBlkIdx) == 0);
|
|
||||||
|
|
||||||
// No data at all, just return
|
|
||||||
if (pHeadf->info.offset <= 0) return 0;
|
|
||||||
|
|
||||||
if (tsdbSeekDFile(pHeadf, pHeadf->info.offset, SEEK_SET) < 0) {
|
|
||||||
tsdbError("vgId:%d failed to load SBlockIdx part while seek file %s since %s, offset:%u len :%u",
|
|
||||||
TSDB_READ_REPO_ID(pReadh), TSDB_FILE_FULL_NAME(pHeadf), tstrerror(terrno), pHeadf->info.offset,
|
|
||||||
pHeadf->info.len);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tsdbMakeRoom((void **)(&TSDB_READ_BUF(pReadh)), pHeadf->info.len) < 0) return -1;
|
|
||||||
|
|
||||||
int64_t nread = tsdbReadDFile(pHeadf, TSDB_READ_BUF(pReadh), pHeadf->info.len);
|
|
||||||
if (nread < 0) {
|
|
||||||
tsdbError("vgId:%d failed to load SBlockIdx part while read file %s since %s, offset:%u len :%u",
|
|
||||||
TSDB_READ_REPO_ID(pReadh), TSDB_FILE_FULL_NAME(pHeadf), tstrerror(terrno), pHeadf->info.offset,
|
|
||||||
pHeadf->info.len);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nread < pHeadf->info.len) {
|
|
||||||
terrno = TSDB_CODE_TDB_FILE_CORRUPTED;
|
|
||||||
tsdbError("vgId:%d SBlockIdx part in file %s is corrupted, offset:%u expected bytes:%u read bytes: %" PRId64,
|
|
||||||
TSDB_READ_REPO_ID(pReadh), TSDB_FILE_FULL_NAME(pHeadf), pHeadf->info.offset, pHeadf->info.len, nread);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!taosCheckChecksumWhole((uint8_t *)TSDB_READ_BUF(pReadh), pHeadf->info.len)) {
|
|
||||||
terrno = TSDB_CODE_TDB_FILE_CORRUPTED;
|
|
||||||
tsdbError("vgId:%d SBlockIdx part in file %s is corrupted since wrong checksum, offset:%u len :%u",
|
|
||||||
TSDB_READ_REPO_ID(pReadh), TSDB_FILE_FULL_NAME(pHeadf), pHeadf->info.offset, pHeadf->info.len);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *ptr = TSDB_READ_BUF(pReadh);
|
|
||||||
int tsize = 0;
|
|
||||||
while (POINTER_DISTANCE(ptr, TSDB_READ_BUF(pReadh)) < (pHeadf->info.len - sizeof(TSCKSUM))) {
|
|
||||||
ptr = tsdbDecodeSBlockIdx(ptr, &blkIdx);
|
|
||||||
ASSERT(ptr != NULL);
|
|
||||||
|
|
||||||
if (taosArrayPush(pReadh->aBlkIdx, (void *)(&blkIdx)) == NULL) {
|
|
||||||
terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
tsize++;
|
|
||||||
ASSERT(tsize == 1 || ((SBlockIdx *)taosArrayGet(pReadh->aBlkIdx, tsize - 2))->tid <
|
|
||||||
((SBlockIdx *)taosArrayGet(pReadh->aBlkIdx, tsize - 1))->tid);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int tsdbSetReadTable(SReadH *pReadh, STable *pTable) {
|
|
||||||
STSchema *pSchema = tsdbGetTableSchemaImpl(pTable, false, false, -1, -1);
|
|
||||||
|
|
||||||
pReadh->pTable = pTable;
|
|
||||||
|
|
||||||
if (tdInitDataCols(pReadh->pDCols[0], pSchema) < 0) {
|
|
||||||
terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tdInitDataCols(pReadh->pDCols[1], pSchema) < 0) {
|
|
||||||
terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t size = taosArrayGetSize(pReadh->aBlkIdx);
|
|
||||||
if (size > 0) {
|
|
||||||
while (true) {
|
|
||||||
if (pReadh->cidx >= size) {
|
|
||||||
pReadh->pBlkIdx = NULL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
SBlockIdx *pBlkIdx = taosArrayGet(pReadh->aBlkIdx, pReadh->cidx);
|
|
||||||
if (pBlkIdx->tid == TABLE_TID(pTable)) {
|
|
||||||
if (pBlkIdx->uid == TABLE_UID(pTable)) {
|
|
||||||
pReadh->pBlkIdx = pBlkIdx;
|
|
||||||
} else {
|
|
||||||
pReadh->pBlkIdx = NULL;
|
|
||||||
}
|
|
||||||
pReadh->cidx++;
|
|
||||||
break;
|
|
||||||
} else if (pBlkIdx->tid > TABLE_TID(pTable)) {
|
|
||||||
pReadh->pBlkIdx = NULL;
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
pReadh->cidx++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
pReadh->pBlkIdx = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
int tsdbLoadBlockInfo(SReadH *pReadh, void *pTarget) {
|
|
||||||
ASSERT(pReadh->pBlkIdx != NULL);
|
|
||||||
|
|
||||||
SDFile * pHeadf = TSDB_READ_HEAD_FILE(pReadh);
|
|
||||||
SBlockIdx *pBlkIdx = pReadh->pBlkIdx;
|
|
||||||
|
|
||||||
if (tsdbSeekDFile(pHeadf, pBlkIdx->offset, SEEK_SET) < 0) {
|
|
||||||
tsdbError("vgId:%d failed to load SBlockInfo part while seek file %s since %s, offset:%u len:%u",
|
|
||||||
TSDB_READ_REPO_ID(pReadh), TSDB_FILE_FULL_NAME(pHeadf), tstrerror(terrno), pBlkIdx->offset, pBlkIdx->len);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tsdbMakeRoom((void **)(&(pReadh->pBlkInfo)), pBlkIdx->len) < 0) return -1;
|
|
||||||
|
|
||||||
int64_t nread = tsdbReadDFile(pHeadf, (void *)(pReadh->pBlkInfo), pBlkIdx->len);
|
|
||||||
if (nread < 0) {
|
|
||||||
tsdbError("vgId:%d failed to load SBlockInfo part while read file %s since %s, offset:%u len :%u",
|
|
||||||
TSDB_READ_REPO_ID(pReadh), TSDB_FILE_FULL_NAME(pHeadf), tstrerror(terrno), pBlkIdx->offset, pBlkIdx->len);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nread < pBlkIdx->len) {
|
|
||||||
terrno = TSDB_CODE_TDB_FILE_CORRUPTED;
|
|
||||||
tsdbError("vgId:%d SBlockInfo part in file %s is corrupted, offset:%u expected bytes:%u read bytes:%" PRId64,
|
|
||||||
TSDB_READ_REPO_ID(pReadh), TSDB_FILE_FULL_NAME(pHeadf), pBlkIdx->offset, pBlkIdx->len, nread);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!taosCheckChecksumWhole((uint8_t *)(pReadh->pBlkInfo), pBlkIdx->len)) {
|
|
||||||
terrno = TSDB_CODE_TDB_FILE_CORRUPTED;
|
|
||||||
tsdbError("vgId:%d SBlockInfo part in file %s is corrupted since wrong checksum, offset:%u len :%u",
|
|
||||||
TSDB_READ_REPO_ID(pReadh), TSDB_FILE_FULL_NAME(pHeadf), pBlkIdx->offset, pBlkIdx->len);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT(pBlkIdx->tid == pReadh->pBlkInfo->tid && pBlkIdx->uid == pReadh->pBlkInfo->uid);
|
|
||||||
|
|
||||||
if (pTarget) {
|
|
||||||
memcpy(pTarget, (void *)(pReadh->pBlkInfo), pBlkIdx->len);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static FORCE_INLINE int32_t tsdbGetSBlockVer(int32_t fver) {
|
|
||||||
switch (fver) {
|
|
||||||
case TSDB_FS_VER_0:
|
|
||||||
return TSDB_SBLK_VER_0;
|
|
||||||
case TSDB_FS_VER_1:
|
|
||||||
return TSDB_SBLK_VER_1;
|
|
||||||
default:
|
|
||||||
return SBlockVerLatest;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static FORCE_INLINE size_t tsdbSizeOfSBlock(int32_t sBlkVer) {
|
|
||||||
switch (sBlkVer) {
|
|
||||||
case TSDB_SBLK_VER_0:
|
|
||||||
return sizeof(SBlockV0);
|
|
||||||
case TSDB_SBLK_VER_1:
|
|
||||||
return sizeof(SBlockV1);
|
|
||||||
default:
|
|
||||||
return sizeof(SBlock);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int tsdbSBlkInfoRefactor(SDFile *pHeadf, SBlockInfo **pDstBlkInfo, SBlockIdx *pBlkIdx, uint32_t *dstBlkInfoLen) {
|
|
||||||
int sBlkVer = tsdbGetSBlockVer(pHeadf->info.fver);
|
|
||||||
if (sBlkVer > TSDB_SBLK_VER_0) {
|
|
||||||
*dstBlkInfoLen = pBlkIdx->len;
|
|
||||||
return TSDB_CODE_SUCCESS;
|
|
||||||
}
|
|
||||||
size_t originBlkSize = tsdbSizeOfSBlock(sBlkVer);
|
|
||||||
size_t nBlks = (pBlkIdx->len - sizeof(SBlockInfo)) / originBlkSize;
|
|
||||||
|
|
||||||
*dstBlkInfoLen = (uint32_t)(sizeof(SBlockInfo) + nBlks * sizeof(SBlock));
|
|
||||||
|
|
||||||
if (pBlkIdx->len == *dstBlkInfoLen) {
|
|
||||||
return TSDB_CODE_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT(*dstBlkInfoLen >= pBlkIdx->len);
|
|
||||||
|
|
||||||
SBlockInfo *tmpBlkInfo = NULL;
|
|
||||||
if (tsdbMakeRoom((void **)(&tmpBlkInfo), *dstBlkInfoLen) < 0) return -1;
|
|
||||||
memset(tmpBlkInfo, 0, *dstBlkInfoLen); // the blkVer is set to 0
|
|
||||||
memcpy(tmpBlkInfo, *pDstBlkInfo, sizeof(SBlockInfo)); // copy header
|
|
||||||
uint32_t nSubBlks = 0;
|
|
||||||
for (int i = 0; i < nBlks; ++i) {
|
|
||||||
SBlock *tmpBlk = tmpBlkInfo->blocks + i;
|
|
||||||
memcpy(tmpBlk, POINTER_SHIFT((*pDstBlkInfo)->blocks, i * originBlkSize), originBlkSize);
|
|
||||||
if (i < pBlkIdx->numOfBlocks) { // super blocks
|
|
||||||
if (tmpBlk->numOfSubBlocks > 1) { // has sub blocks
|
|
||||||
tmpBlk->offset = sizeof(SBlockInfo) + (pBlkIdx->numOfBlocks + nSubBlks) * sizeof(SBlock);
|
|
||||||
nSubBlks += tmpBlk->numOfSubBlocks;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// TODO: update the fields if the SBlock definition change later
|
|
||||||
}
|
|
||||||
|
|
||||||
taosTZfree(*pDstBlkInfo);
|
|
||||||
*pDstBlkInfo = tmpBlkInfo;
|
|
||||||
|
|
||||||
return TSDB_CODE_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
int tsdbLoadBlockInfo(SReadH *pReadh, void **pTarget, uint32_t *extendedLen) {
|
|
||||||
ASSERT(pReadh->pBlkIdx != NULL);
|
|
||||||
|
|
||||||
SDFile * pHeadf = TSDB_READ_HEAD_FILE(pReadh);
|
|
||||||
SBlockIdx * pBlkIdx = pReadh->pBlkIdx;
|
|
||||||
|
|
||||||
if (tsdbSeekDFile(pHeadf, pBlkIdx->offset, SEEK_SET) < 0) {
|
|
||||||
tsdbError("vgId:%d failed to load SBlockInfo part while seek file %s since %s, offset:%u len:%u",
|
|
||||||
TSDB_READ_REPO_ID(pReadh), TSDB_FILE_FULL_NAME(pHeadf), tstrerror(terrno), pBlkIdx->offset, pBlkIdx->len);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tsdbMakeRoom((void **)(&pReadh->pBlkInfo), pBlkIdx->len) < 0) return -1;
|
|
||||||
|
|
||||||
int64_t nread = tsdbReadDFile(pHeadf, (void *)(pReadh->pBlkInfo), pBlkIdx->len);
|
|
||||||
if (nread < 0) {
|
|
||||||
tsdbError("vgId:%d failed to load SBlockInfo part while read file %s since %s, offset:%u len :%u",
|
|
||||||
TSDB_READ_REPO_ID(pReadh), TSDB_FILE_FULL_NAME(pHeadf), tstrerror(terrno), pBlkIdx->offset, pBlkIdx->len);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nread < pBlkIdx->len) {
|
|
||||||
terrno = TSDB_CODE_TDB_FILE_CORRUPTED;
|
|
||||||
tsdbError("vgId:%d SBlockInfo part in file %s is corrupted, offset:%u expected bytes:%u read bytes:%" PRId64,
|
|
||||||
TSDB_READ_REPO_ID(pReadh), TSDB_FILE_FULL_NAME(pHeadf), pBlkIdx->offset, pBlkIdx->len, nread);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!taosCheckChecksumWhole((uint8_t *)(pReadh->pBlkInfo), pBlkIdx->len)) {
|
|
||||||
terrno = TSDB_CODE_TDB_FILE_CORRUPTED;
|
|
||||||
tsdbError("vgId:%d SBlockInfo part in file %s is corrupted since wrong checksum, offset:%u len :%u",
|
|
||||||
TSDB_READ_REPO_ID(pReadh), TSDB_FILE_FULL_NAME(pHeadf), pBlkIdx->offset, pBlkIdx->len);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT(pBlkIdx->tid == pReadh->pBlkInfo->tid && pBlkIdx->uid == pReadh->pBlkInfo->uid);
|
|
||||||
|
|
||||||
uint32_t dstBlkInfoLen = 0;
|
|
||||||
if (tsdbSBlkInfoRefactor(pHeadf, &(pReadh->pBlkInfo), pBlkIdx, &dstBlkInfoLen) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (extendedLen != NULL) {
|
|
||||||
if (pTarget != NULL) {
|
|
||||||
if (*extendedLen < dstBlkInfoLen) {
|
|
||||||
char *t = realloc(*pTarget, dstBlkInfoLen);
|
|
||||||
if (t == NULL) {
|
|
||||||
terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
*pTarget = t;
|
|
||||||
}
|
|
||||||
memcpy(*pTarget, (void *)(pReadh->pBlkInfo), dstBlkInfoLen);
|
|
||||||
}
|
|
||||||
*extendedLen = dstBlkInfoLen;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TSDB_CODE_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
int tsdbLoadBlockData(SReadH *pReadh, SBlock *pBlock, SBlockInfo *pBlkInfo) {
|
|
||||||
ASSERT(pBlock->numOfSubBlocks > 0);
|
|
||||||
int8_t update = pReadh->pRepo->config.update;
|
|
||||||
|
|
||||||
SBlock *iBlock = pBlock;
|
|
||||||
if (pBlock->numOfSubBlocks > 1) {
|
|
||||||
if (pBlkInfo) {
|
|
||||||
iBlock = (SBlock *)POINTER_SHIFT(pBlkInfo, pBlock->offset);
|
|
||||||
} else {
|
|
||||||
iBlock = (SBlock *)POINTER_SHIFT(pReadh->pBlkInfo, pBlock->offset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tsdbLoadBlockDataImpl(pReadh, iBlock, pReadh->pDCols[0]) < 0) return -1;
|
|
||||||
for (int i = 1; i < pBlock->numOfSubBlocks; i++) {
|
|
||||||
iBlock++;
|
|
||||||
if (tsdbLoadBlockDataImpl(pReadh, iBlock, pReadh->pDCols[1]) < 0) return -1;
|
|
||||||
if (tdMergeDataCols(pReadh->pDCols[0], pReadh->pDCols[1], pReadh->pDCols[1]->numOfRows, NULL, update != TD_ROW_PARTIAL_UPDATE) < 0) return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT(pReadh->pDCols[0]->numOfRows == pBlock->numOfRows);
|
|
||||||
ASSERT(dataColsKeyFirst(pReadh->pDCols[0]) == pBlock->keyFirst);
|
|
||||||
ASSERT(dataColsKeyLast(pReadh->pDCols[0]) == pBlock->keyLast);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int tsdbLoadBlockDataCols(SReadH *pReadh, SBlock *pBlock, SBlockInfo *pBlkInfo, int16_t *colIds, int numOfColsIds) {
|
|
||||||
ASSERT(pBlock->numOfSubBlocks > 0);
|
|
||||||
int8_t update = pReadh->pRepo->config.update;
|
|
||||||
|
|
||||||
SBlock *iBlock = pBlock;
|
|
||||||
if (pBlock->numOfSubBlocks > 1) {
|
|
||||||
if (pBlkInfo) {
|
|
||||||
iBlock = POINTER_SHIFT(pBlkInfo, pBlock->offset);
|
|
||||||
} else {
|
|
||||||
iBlock = POINTER_SHIFT(pReadh->pBlkInfo, pBlock->offset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tsdbLoadBlockDataColsImpl(pReadh, iBlock, pReadh->pDCols[0], colIds, numOfColsIds) < 0) return -1;
|
|
||||||
for (int i = 1; i < pBlock->numOfSubBlocks; i++) {
|
|
||||||
iBlock++;
|
|
||||||
if (tsdbLoadBlockDataColsImpl(pReadh, iBlock, pReadh->pDCols[1], colIds, numOfColsIds) < 0) return -1;
|
|
||||||
if (tdMergeDataCols(pReadh->pDCols[0], pReadh->pDCols[1], pReadh->pDCols[1]->numOfRows, NULL, update != TD_ROW_PARTIAL_UPDATE) < 0) return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT(pReadh->pDCols[0]->numOfRows == pBlock->numOfRows);
|
|
||||||
ASSERT(dataColsKeyFirst(pReadh->pDCols[0]) == pBlock->keyFirst);
|
|
||||||
ASSERT(dataColsKeyLast(pReadh->pDCols[0]) == pBlock->keyLast);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int tsdbLoadBlockStatisFromDFile(SReadH *pReadh, SBlock *pBlock) {
|
|
||||||
SDFile *pDFile = (pBlock->last) ? TSDB_READ_LAST_FILE(pReadh) : TSDB_READ_DATA_FILE(pReadh);
|
|
||||||
if (tsdbSeekDFile(pDFile, pBlock->offset, SEEK_SET) < 0) {
|
|
||||||
tsdbError("vgId:%d failed to load block statis part while seek file %s to offset %" PRId64 " since %s",
|
|
||||||
TSDB_READ_REPO_ID(pReadh), TSDB_FILE_FULL_NAME(pDFile), (int64_t)pBlock->offset, tstrerror(terrno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t size = tsdbBlockStatisSize(pBlock->numOfCols, (uint32_t)pBlock->blkVer);
|
|
||||||
if (tsdbMakeRoom((void **)(&(pReadh->pBlkData)), size) < 0) return -1;
|
|
||||||
|
|
||||||
int64_t nread = tsdbReadDFile(pDFile, (void *)(pReadh->pBlkData), size);
|
|
||||||
if (nread < 0) {
|
|
||||||
tsdbError("vgId:%d failed to load block statis part while read file %s since %s, offset:%" PRId64 " len :%" PRIzu,
|
|
||||||
TSDB_READ_REPO_ID(pReadh), TSDB_FILE_FULL_NAME(pDFile), tstrerror(terrno), (int64_t)pBlock->offset, size);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nread < size) {
|
|
||||||
terrno = TSDB_CODE_TDB_FILE_CORRUPTED;
|
|
||||||
tsdbError("vgId:%d block statis part in file %s is corrupted, offset:%" PRId64 " expected bytes:%" PRIzu
|
|
||||||
" read bytes: %" PRId64,
|
|
||||||
TSDB_READ_REPO_ID(pReadh), TSDB_FILE_FULL_NAME(pDFile), (int64_t)pBlock->offset, size, nread);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!taosCheckChecksumWhole((uint8_t *)(pReadh->pBlkData), (uint32_t)size)) {
|
|
||||||
terrno = TSDB_CODE_TDB_FILE_CORRUPTED;
|
|
||||||
tsdbError("vgId:%d block statis part in file %s is corrupted since wrong checksum, offset:%" PRId64 " len :%" PRIzu,
|
|
||||||
TSDB_READ_REPO_ID(pReadh), TSDB_FILE_FULL_NAME(pDFile), (int64_t)pBlock->offset, size);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int tsdbLoadBlockStatisFromAggr(SReadH *pReadh, SBlock *pBlock) {
|
|
||||||
ASSERT((pBlock->blkVer > TSDB_SBLK_VER_0) && (pBlock->aggrStat)); // TODO: remove after pass all the test
|
|
||||||
SDFile *pDFileAggr = pBlock->last ? TSDB_READ_SMAL_FILE(pReadh) : TSDB_READ_SMAD_FILE(pReadh);
|
|
||||||
|
|
||||||
if (tsdbSeekDFile(pDFileAggr, pBlock->aggrOffset, SEEK_SET) < 0) {
|
|
||||||
tsdbError("vgId:%d failed to load block aggr part while seek file %s to offset %" PRIu64 " since %s",
|
|
||||||
TSDB_READ_REPO_ID(pReadh), TSDB_FILE_FULL_NAME(pDFileAggr), (uint64_t)pBlock->aggrOffset,
|
|
||||||
tstrerror(terrno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t sizeAggr = tsdbBlockAggrSize(pBlock->numOfCols, (uint32_t)pBlock->blkVer);
|
|
||||||
if (tsdbMakeRoom((void **)(&(pReadh->pAggrBlkData)), sizeAggr) < 0) return -1;
|
|
||||||
|
|
||||||
int64_t nreadAggr = tsdbReadDFile(pDFileAggr, (void *)(pReadh->pAggrBlkData), sizeAggr);
|
|
||||||
if (nreadAggr < 0) {
|
|
||||||
tsdbError("vgId:%d failed to load block aggr part while read file %s since %s, offset:%" PRIu64 " len :%" PRIzu,
|
|
||||||
TSDB_READ_REPO_ID(pReadh), TSDB_FILE_FULL_NAME(pDFileAggr), tstrerror(terrno),
|
|
||||||
(uint64_t)pBlock->aggrOffset, sizeAggr);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nreadAggr < sizeAggr) {
|
|
||||||
terrno = TSDB_CODE_TDB_FILE_CORRUPTED;
|
|
||||||
tsdbError("vgId:%d block aggr part in file %s is corrupted, offset:%" PRIu64 " expected bytes:%" PRIzu
|
|
||||||
" read bytes: %" PRId64,
|
|
||||||
TSDB_READ_REPO_ID(pReadh), TSDB_FILE_FULL_NAME(pDFileAggr), (uint64_t)pBlock->aggrOffset, sizeAggr,
|
|
||||||
nreadAggr);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!taosCheckChecksumWhole((uint8_t *)(pReadh->pAggrBlkData), (uint32_t)sizeAggr)) {
|
|
||||||
terrno = TSDB_CODE_TDB_FILE_CORRUPTED;
|
|
||||||
tsdbError("vgId:%d block aggr part in file %s is corrupted since wrong checksum, offset:%" PRIu64 " len :%" PRIzu,
|
|
||||||
TSDB_READ_REPO_ID(pReadh), TSDB_FILE_FULL_NAME(pDFileAggr), (uint64_t)pBlock->aggrOffset, sizeAggr);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int tsdbLoadBlockStatis(SReadH *pReadh, SBlock *pBlock) {
|
|
||||||
ASSERT(pBlock->numOfSubBlocks <= 1);
|
|
||||||
|
|
||||||
if (pBlock->blkVer > TSDB_SBLK_VER_0) {
|
|
||||||
if (pBlock->aggrStat) {
|
|
||||||
return tsdbLoadBlockStatisFromAggr(pReadh, pBlock);
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return tsdbLoadBlockStatisFromDFile(pReadh, pBlock);
|
|
||||||
}
|
|
||||||
|
|
||||||
int tsdbLoadBlockOffset(SReadH *pReadh, SBlock *pBlock) {
|
|
||||||
ASSERT(pBlock->numOfSubBlocks <= 1);
|
|
||||||
return tsdbLoadBlockStatisFromDFile(pReadh, pBlock);
|
|
||||||
}
|
|
||||||
|
|
||||||
int tsdbEncodeSBlockIdx(void **buf, SBlockIdx *pIdx) {
|
|
||||||
int tlen = 0;
|
|
||||||
|
|
||||||
tlen += taosEncodeVariantI32(buf, pIdx->tid);
|
|
||||||
tlen += taosEncodeVariantU32(buf, pIdx->len);
|
|
||||||
tlen += taosEncodeVariantU32(buf, pIdx->offset);
|
|
||||||
tlen += taosEncodeFixedU8(buf, pIdx->hasLast);
|
|
||||||
tlen += taosEncodeVariantU32(buf, pIdx->numOfBlocks);
|
|
||||||
tlen += taosEncodeFixedU64(buf, pIdx->uid);
|
|
||||||
tlen += taosEncodeFixedU64(buf, pIdx->maxKey);
|
|
||||||
|
|
||||||
return tlen;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *tsdbDecodeSBlockIdx(void *buf, SBlockIdx *pIdx) {
|
|
||||||
uint8_t hasLast = 0;
|
|
||||||
uint32_t numOfBlocks = 0;
|
|
||||||
uint64_t value = 0;
|
|
||||||
|
|
||||||
if ((buf = taosDecodeVariantI32(buf, &(pIdx->tid))) == NULL) return NULL;
|
|
||||||
if ((buf = taosDecodeVariantU32(buf, &(pIdx->len))) == NULL) return NULL;
|
|
||||||
if ((buf = taosDecodeVariantU32(buf, &(pIdx->offset))) == NULL) return NULL;
|
|
||||||
if ((buf = taosDecodeFixedU8(buf, &(hasLast))) == NULL) return NULL;
|
|
||||||
pIdx->hasLast = hasLast;
|
|
||||||
if ((buf = taosDecodeVariantU32(buf, &(numOfBlocks))) == NULL) return NULL;
|
|
||||||
pIdx->numOfBlocks = numOfBlocks;
|
|
||||||
if ((buf = taosDecodeFixedU64(buf, &value)) == NULL) return NULL;
|
|
||||||
pIdx->uid = (int64_t)value;
|
|
||||||
if ((buf = taosDecodeFixedU64(buf, &value)) == NULL) return NULL;
|
|
||||||
pIdx->maxKey = (TSKEY)value;
|
|
||||||
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
void tsdbGetBlockStatis(SReadH *pReadh, SDataStatis *pStatis, int numOfCols, SBlock *pBlock) {
|
|
||||||
if (pBlock->blkVer == TSDB_SBLK_VER_0) {
|
|
||||||
SBlockData *pBlockData = pReadh->pBlkData;
|
|
||||||
|
|
||||||
for (int i = 0, j = 0; i < numOfCols;) {
|
|
||||||
if (j >= pBlockData->numOfCols) {
|
|
||||||
pStatis[i].numOfNull = -1;
|
|
||||||
i++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
SBlockColV0 *pSBlkCol = ((SBlockColV0 *)(pBlockData->cols)) + j;
|
|
||||||
if (pStatis[i].colId == pSBlkCol->colId) {
|
|
||||||
pStatis[i].sum = pSBlkCol->sum;
|
|
||||||
pStatis[i].max = pSBlkCol->max;
|
|
||||||
pStatis[i].min = pSBlkCol->min;
|
|
||||||
pStatis[i].maxIndex = pSBlkCol->maxIndex;
|
|
||||||
pStatis[i].minIndex = pSBlkCol->minIndex;
|
|
||||||
pStatis[i].numOfNull = pSBlkCol->numOfNull;
|
|
||||||
i++;
|
|
||||||
j++;
|
|
||||||
} else if (pStatis[i].colId < pSBlkCol->colId) {
|
|
||||||
pStatis[i].numOfNull = -1;
|
|
||||||
i++;
|
|
||||||
} else {
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (pBlock->aggrStat) {
|
|
||||||
SAggrBlkData *pAggrBlkData = pReadh->pAggrBlkData;
|
|
||||||
|
|
||||||
for (int i = 0, j = 0; i < numOfCols;) {
|
|
||||||
if (j >= pBlock->numOfCols) {
|
|
||||||
pStatis[i].numOfNull = -1;
|
|
||||||
i++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
SAggrBlkCol *pAggrBlkCol = ((SAggrBlkCol *)(pAggrBlkData)) + j;
|
|
||||||
if (pStatis[i].colId == pAggrBlkCol->colId) {
|
|
||||||
pStatis[i].sum = pAggrBlkCol->sum;
|
|
||||||
pStatis[i].max = pAggrBlkCol->max;
|
|
||||||
pStatis[i].min = pAggrBlkCol->min;
|
|
||||||
pStatis[i].maxIndex = pAggrBlkCol->maxIndex;
|
|
||||||
pStatis[i].minIndex = pAggrBlkCol->minIndex;
|
|
||||||
pStatis[i].numOfNull = pAggrBlkCol->numOfNull;
|
|
||||||
i++;
|
|
||||||
j++;
|
|
||||||
} else if (pStatis[i].colId < pAggrBlkCol->colId) {
|
|
||||||
pStatis[i].numOfNull = -1;
|
|
||||||
i++;
|
|
||||||
} else {
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void tsdbResetReadTable(SReadH *pReadh) {
|
|
||||||
tdResetDataCols(pReadh->pDCols[0]);
|
|
||||||
tdResetDataCols(pReadh->pDCols[1]);
|
|
||||||
pReadh->cidx = 0;
|
|
||||||
pReadh->pBlkIdx = NULL;
|
|
||||||
pReadh->pTable = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void tsdbResetReadFile(SReadH *pReadh) {
|
|
||||||
tsdbResetReadTable(pReadh);
|
|
||||||
taosArrayClear(pReadh->aBlkIdx);
|
|
||||||
tsdbCloseDFileSet(TSDB_READ_FSET(pReadh));
|
|
||||||
}
|
|
||||||
|
|
||||||
static int tsdbLoadBlockDataImpl(SReadH *pReadh, SBlock *pBlock, SDataCols *pDataCols) {
|
|
||||||
ASSERT(pBlock->numOfSubBlocks == 0 || pBlock->numOfSubBlocks == 1);
|
|
||||||
|
|
||||||
SDFile *pDFile = (pBlock->last) ? TSDB_READ_LAST_FILE(pReadh) : TSDB_READ_DATA_FILE(pReadh);
|
|
||||||
|
|
||||||
tdResetDataCols(pDataCols);
|
|
||||||
if (tsdbMakeRoom((void **)(&TSDB_READ_BUF(pReadh)), pBlock->len) < 0) return -1;
|
|
||||||
|
|
||||||
SBlockData *pBlockData = (SBlockData *)TSDB_READ_BUF(pReadh);
|
|
||||||
|
|
||||||
if (tsdbSeekDFile(pDFile, pBlock->offset, SEEK_SET) < 0) {
|
|
||||||
tsdbError("vgId:%d failed to load block data part while seek file %s to offset %" PRId64 " since %s",
|
|
||||||
TSDB_READ_REPO_ID(pReadh), TSDB_FILE_FULL_NAME(pDFile), (int64_t)pBlock->offset, tstrerror(terrno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t nread = tsdbReadDFile(pDFile, TSDB_READ_BUF(pReadh), pBlock->len);
|
|
||||||
if (nread < 0) {
|
|
||||||
tsdbError("vgId:%d failed to load block data part while read file %s since %s, offset:%" PRId64 " len :%d",
|
|
||||||
TSDB_READ_REPO_ID(pReadh), TSDB_FILE_FULL_NAME(pDFile), tstrerror(terrno), (int64_t)pBlock->offset,
|
|
||||||
pBlock->len);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nread < pBlock->len) {
|
|
||||||
terrno = TSDB_CODE_TDB_FILE_CORRUPTED;
|
|
||||||
tsdbError("vgId:%d block data part in file %s is corrupted, offset:%" PRId64
|
|
||||||
" expected bytes:%d read bytes: %" PRId64,
|
|
||||||
TSDB_READ_REPO_ID(pReadh), TSDB_FILE_FULL_NAME(pDFile), (int64_t)pBlock->offset, pBlock->len, nread);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t tsize = (int32_t)tsdbBlockStatisSize(pBlock->numOfCols, (uint32_t)pBlock->blkVer);
|
|
||||||
if (!taosCheckChecksumWhole((uint8_t *)TSDB_READ_BUF(pReadh), tsize)) {
|
|
||||||
terrno = TSDB_CODE_TDB_FILE_CORRUPTED;
|
|
||||||
tsdbError("vgId:%d block statis part in file %s is corrupted since wrong checksum, offset:%" PRId64 " len :%d",
|
|
||||||
TSDB_READ_REPO_ID(pReadh), TSDB_FILE_FULL_NAME(pDFile), (int64_t)pBlock->offset, tsize);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT(tsize < pBlock->len);
|
|
||||||
ASSERT(pBlockData->numOfCols == pBlock->numOfCols);
|
|
||||||
|
|
||||||
pDataCols->numOfRows = pBlock->numOfRows;
|
|
||||||
|
|
||||||
// Recover the data
|
|
||||||
int ccol = 0; // loop iter for SBlockCol object
|
|
||||||
int dcol = 0; // loop iter for SDataCols object
|
|
||||||
SBlockCol blockCol = {0};
|
|
||||||
SBlockCol *pBlockCol = &blockCol;
|
|
||||||
while (dcol < pDataCols->numOfCols) {
|
|
||||||
SDataCol *pDataCol = &(pDataCols->cols[dcol]);
|
|
||||||
if (dcol != 0 && ccol >= pBlockData->numOfCols) {
|
|
||||||
// Set current column as NULL and forward
|
|
||||||
dataColReset(pDataCol);
|
|
||||||
dcol++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
int16_t tcolId = 0;
|
|
||||||
uint32_t toffset = TSDB_KEY_COL_OFFSET;
|
|
||||||
int32_t tlen = pBlock->keyLen;
|
|
||||||
|
|
||||||
|
|
||||||
if (dcol != 0) {
|
|
||||||
tsdbGetSBlockCol(pBlock, &pBlockCol, pBlockData->cols, ccol);
|
|
||||||
tcolId = pBlockCol->colId;
|
|
||||||
toffset = tsdbGetBlockColOffset(pBlockCol);
|
|
||||||
tlen = pBlockCol->len;
|
|
||||||
} else {
|
|
||||||
ASSERT(pDataCol->colId == tcolId);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tcolId == pDataCol->colId) {
|
|
||||||
if (pBlock->algorithm == TWO_STAGE_COMP) {
|
|
||||||
int zsize = pDataCol->bytes * pBlock->numOfRows + COMP_OVERFLOW_BYTES;
|
|
||||||
if (tsdbMakeRoom((void **)(&TSDB_READ_COMP_BUF(pReadh)), zsize) < 0) return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tsdbCheckAndDecodeColumnData(pDataCol, POINTER_SHIFT(pBlockData, tsize + toffset), tlen, pBlock->algorithm,
|
|
||||||
pBlock->numOfRows, pDataCols->maxPoints, TSDB_READ_COMP_BUF(pReadh),
|
|
||||||
(int)taosTSizeof(TSDB_READ_COMP_BUF(pReadh))) < 0) {
|
|
||||||
tsdbError("vgId:%d file %s is broken at column %d block offset %" PRId64 " column offset %u",
|
|
||||||
TSDB_READ_REPO_ID(pReadh), TSDB_FILE_FULL_NAME(pDFile), tcolId, (int64_t)pBlock->offset, toffset);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dcol != 0) {
|
|
||||||
ccol++;
|
|
||||||
}
|
|
||||||
dcol++;
|
|
||||||
} else if (tcolId < pDataCol->colId) {
|
|
||||||
ccol++;
|
|
||||||
} else {
|
|
||||||
// Set current column as NULL and forward
|
|
||||||
dataColReset(pDataCol);
|
|
||||||
dcol++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int tsdbCheckAndDecodeColumnData(SDataCol *pDataCol, void *content, int32_t len, int8_t comp, int numOfRows,
|
|
||||||
int maxPoints, char *buffer, int bufferSize) {
|
|
||||||
if (!taosCheckChecksumWhole((uint8_t *)content, len)) {
|
|
||||||
terrno = TSDB_CODE_TDB_FILE_CORRUPTED;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
tdAllocMemForCol(pDataCol, maxPoints);
|
|
||||||
|
|
||||||
// Decode the data
|
|
||||||
if (comp) {
|
|
||||||
// Need to decompress
|
|
||||||
int tlen = (*(tDataTypes[pDataCol->type].decompFunc))(content, len - sizeof(TSCKSUM), numOfRows, pDataCol->pData,
|
|
||||||
pDataCol->spaceSize, comp, buffer, bufferSize);
|
|
||||||
if (tlen <= 0) {
|
|
||||||
tsdbError("Failed to decompress column, file corrupted, len:%d comp:%d numOfRows:%d maxPoints:%d bufferSize:%d",
|
|
||||||
len, comp, numOfRows, maxPoints, bufferSize);
|
|
||||||
terrno = TSDB_CODE_TDB_FILE_CORRUPTED;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
pDataCol->len = tlen;
|
|
||||||
} else {
|
|
||||||
// No need to decompress, just memcpy it
|
|
||||||
pDataCol->len = len - sizeof(TSCKSUM);
|
|
||||||
memcpy(pDataCol->pData, content, pDataCol->len);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IS_VAR_DATA_TYPE(pDataCol->type)) {
|
|
||||||
dataColSetOffset(pDataCol, numOfRows);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int tsdbLoadBlockDataColsImpl(SReadH *pReadh, SBlock *pBlock, SDataCols *pDataCols, int16_t *colIds,
|
|
||||||
int numOfColIds) {
|
|
||||||
ASSERT(pBlock->numOfSubBlocks == 0 || pBlock->numOfSubBlocks == 1);
|
|
||||||
ASSERT(colIds[0] == 0);
|
|
||||||
|
|
||||||
SDFile * pDFile = (pBlock->last) ? TSDB_READ_LAST_FILE(pReadh) : TSDB_READ_DATA_FILE(pReadh);
|
|
||||||
SBlockCol blockCol = {0};
|
|
||||||
|
|
||||||
tdResetDataCols(pDataCols);
|
|
||||||
|
|
||||||
// If only load timestamp column, no need to load SBlockData part
|
|
||||||
if (numOfColIds > 1 && tsdbLoadBlockOffset(pReadh, pBlock) < 0) return -1;
|
|
||||||
|
|
||||||
pDataCols->numOfRows = pBlock->numOfRows;
|
|
||||||
|
|
||||||
int dcol = 0;
|
|
||||||
int ccol = 0;
|
|
||||||
for (int i = 0; i < numOfColIds; i++) {
|
|
||||||
int16_t colId = colIds[i];
|
|
||||||
SDataCol * pDataCol = NULL;
|
|
||||||
SBlockCol *pBlockCol = NULL;
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
if (dcol >= pDataCols->numOfCols) {
|
|
||||||
pDataCol = NULL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
pDataCol = &pDataCols->cols[dcol];
|
|
||||||
if (pDataCol->colId > colId) {
|
|
||||||
pDataCol = NULL;
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
dcol++;
|
|
||||||
if (pDataCol->colId == colId) break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pDataCol == NULL) continue;
|
|
||||||
ASSERT(pDataCol->colId == colId);
|
|
||||||
|
|
||||||
if (colId == 0) { // load the key row
|
|
||||||
blockCol.colId = colId;
|
|
||||||
blockCol.len = pBlock->keyLen;
|
|
||||||
blockCol.type = pDataCol->type;
|
|
||||||
blockCol.offset = TSDB_KEY_COL_OFFSET;
|
|
||||||
pBlockCol = &blockCol;
|
|
||||||
} else { // load non-key rows
|
|
||||||
while (true) {
|
|
||||||
if (ccol >= pBlock->numOfCols) {
|
|
||||||
pBlockCol = NULL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
pBlockCol = &blockCol;
|
|
||||||
tsdbGetSBlockCol(pBlock, &pBlockCol, pReadh->pBlkData->cols, ccol);
|
|
||||||
|
|
||||||
if (pBlockCol->colId > colId) {
|
|
||||||
pBlockCol = NULL;
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
ccol++;
|
|
||||||
if (pBlockCol->colId == colId) break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pBlockCol == NULL) {
|
|
||||||
dataColReset(pDataCol);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT(pBlockCol->colId == pDataCol->colId);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tsdbLoadColData(pReadh, pDFile, pBlock, pBlockCol, pDataCol) < 0) return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int tsdbLoadColData(SReadH *pReadh, SDFile *pDFile, SBlock *pBlock, SBlockCol *pBlockCol, SDataCol *pDataCol) {
|
|
||||||
ASSERT(pDataCol->colId == pBlockCol->colId);
|
|
||||||
|
|
||||||
STsdb *pRepo = TSDB_READ_REPO(pReadh);
|
|
||||||
STsdbCfg * pCfg = REPO_CFG(pRepo);
|
|
||||||
int tsize = pDataCol->bytes * pBlock->numOfRows + COMP_OVERFLOW_BYTES;
|
|
||||||
|
|
||||||
if (tsdbMakeRoom((void **)(&TSDB_READ_BUF(pReadh)), pBlockCol->len) < 0) return -1;
|
|
||||||
if (tsdbMakeRoom((void **)(&TSDB_READ_COMP_BUF(pReadh)), tsize) < 0) return -1;
|
|
||||||
|
|
||||||
int64_t offset = pBlock->offset + tsdbBlockStatisSize(pBlock->numOfCols, (uint32_t)pBlock->blkVer) +
|
|
||||||
tsdbGetBlockColOffset(pBlockCol);
|
|
||||||
if (tsdbSeekDFile(pDFile, offset, SEEK_SET) < 0) {
|
|
||||||
tsdbError("vgId:%d failed to load block column data while seek file %s to offset %" PRId64 " since %s",
|
|
||||||
TSDB_READ_REPO_ID(pReadh), TSDB_FILE_FULL_NAME(pDFile), offset, tstrerror(terrno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t nread = tsdbReadDFile(pDFile, TSDB_READ_BUF(pReadh), pBlockCol->len);
|
|
||||||
if (nread < 0) {
|
|
||||||
tsdbError("vgId:%d failed to load block column data while read file %s since %s, offset:%" PRId64 " len :%d",
|
|
||||||
TSDB_READ_REPO_ID(pReadh), TSDB_FILE_FULL_NAME(pDFile), tstrerror(terrno), offset, pBlockCol->len);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nread < pBlockCol->len) {
|
|
||||||
terrno = TSDB_CODE_TDB_FILE_CORRUPTED;
|
|
||||||
tsdbError("vgId:%d block column data in file %s is corrupted, offset:%" PRId64 " expected bytes:%d" PRIzu
|
|
||||||
" read bytes: %" PRId64,
|
|
||||||
TSDB_READ_REPO_ID(pReadh), TSDB_FILE_FULL_NAME(pDFile), offset, pBlockCol->len, nread);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tsdbCheckAndDecodeColumnData(pDataCol, pReadh->pBuf, pBlockCol->len, pBlock->algorithm, pBlock->numOfRows,
|
|
||||||
pCfg->maxRowsPerFileBlock, pReadh->pCBuf, (int32_t)taosTSizeof(pReadh->pCBuf)) < 0) {
|
|
||||||
tsdbError("vgId:%d file %s is broken at column %d offset %" PRId64, REPO_ID(pRepo), TSDB_FILE_FULL_NAME(pDFile),
|
|
||||||
pBlockCol->colId, offset);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
/*
|
|
||||||
* 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/>.
|
|
||||||
*/
|
|
|
@ -1,30 +0,0 @@
|
||||||
/*
|
|
||||||
* 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 "tsdbRowMergeBuf.h"
|
|
||||||
#include "tdataformat.h"
|
|
||||||
|
|
||||||
// row1 has higher priority
|
|
||||||
SMemRow tsdbMergeTwoRows(SMergeBuf *pBuf, SMemRow row1, SMemRow row2, STSchema *pSchema1, STSchema *pSchema2) {
|
|
||||||
if(row2 == NULL) return row1;
|
|
||||||
if(row1 == NULL) return row2;
|
|
||||||
ASSERT(pSchema1->version == memRowVersion(row1));
|
|
||||||
ASSERT(pSchema2->version == memRowVersion(row2));
|
|
||||||
|
|
||||||
if(tsdbMergeBufMakeSureRoom(pBuf, pSchema1, pSchema2) < 0) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return mergeTwoMemRows(*pBuf, row1, row2, pSchema1, pSchema2);
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR} SOURCE_LIST)
|
|
||||||
|
|
||||||
add_executable(tsdbTests ${SOURCE_LIST})
|
|
||||||
target_link_libraries(tsdbTests gtest gtest_main pthread common tsdb tutil trpc)
|
|
||||||
|
|
||||||
add_test(NAME unit COMMAND ${CMAKE_CURRENT_BINARY_DIR}/tsdbTests)
|
|
|
@ -1,163 +0,0 @@
|
||||||
#include <gtest/gtest.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
|
|
||||||
#include "tsdb.h"
|
|
||||||
#include "tsdbMain.h"
|
|
||||||
|
|
||||||
static double getCurTime() {
|
|
||||||
struct timeval tv;
|
|
||||||
gettimeofday(&tv, NULL);
|
|
||||||
return tv.tv_sec + tv.tv_usec * 1E-6;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
STsdbRepo *pRepo;
|
|
||||||
bool isAscend;
|
|
||||||
int tid;
|
|
||||||
uint64_t uid;
|
|
||||||
int sversion;
|
|
||||||
TSKEY startTime;
|
|
||||||
TSKEY interval;
|
|
||||||
int totalRows;
|
|
||||||
int rowsPerSubmit;
|
|
||||||
STSchema * pSchema;
|
|
||||||
} SInsertInfo;
|
|
||||||
|
|
||||||
static int insertData(SInsertInfo *pInfo) {
|
|
||||||
SSubmitMsg *pMsg =
|
|
||||||
(SSubmitMsg *)malloc(sizeof(SSubmitMsg) + sizeof(SSubmitBlk) + dataRowMaxBytesFromSchema(pInfo->pSchema) * pInfo->rowsPerSubmit);
|
|
||||||
if (pMsg == NULL) return -1;
|
|
||||||
TSKEY start_time = pInfo->startTime;
|
|
||||||
|
|
||||||
// Loop to write data
|
|
||||||
double stime = getCurTime();
|
|
||||||
|
|
||||||
for (int k = 0; k < pInfo->totalRows/pInfo->rowsPerSubmit; k++) {
|
|
||||||
memset((void *)pMsg, 0, sizeof(SSubmitMsg));
|
|
||||||
SSubmitBlk *pBlock = (SSubmitBlk *)pMsg->blocks;
|
|
||||||
pBlock->uid = pInfo->uid;
|
|
||||||
pBlock->tid = pInfo->tid;
|
|
||||||
pBlock->sversion = pInfo->sversion;
|
|
||||||
pBlock->dataLen = 0;
|
|
||||||
pBlock->schemaLen = 0;
|
|
||||||
pBlock->numOfRows = 0;
|
|
||||||
for (int i = 0; i < pInfo->rowsPerSubmit; i++) {
|
|
||||||
// start_time += 1000;
|
|
||||||
if (pInfo->isAscend) {
|
|
||||||
start_time += pInfo->interval;
|
|
||||||
} else {
|
|
||||||
start_time -= pInfo->interval;
|
|
||||||
}
|
|
||||||
SDataRow row = (SDataRow)(pBlock->data + pBlock->dataLen);
|
|
||||||
tdInitDataRow(row, pInfo->pSchema);
|
|
||||||
|
|
||||||
for (int j = 0; j < schemaNCols(pInfo->pSchema); j++) {
|
|
||||||
STColumn *pTCol = schemaColAt(pInfo->pSchema, j);
|
|
||||||
if (j == 0) { // Just for timestamp
|
|
||||||
tdAppendColVal(row, (void *)(&start_time), pTCol->type, pTCol->offset);
|
|
||||||
} else { // For int
|
|
||||||
int val = 10;
|
|
||||||
tdAppendColVal(row, (void *)(&val), pTCol->type, pTCol->offset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pBlock->dataLen += dataRowLen(row);
|
|
||||||
pBlock->numOfRows++;
|
|
||||||
}
|
|
||||||
pMsg->length = sizeof(SSubmitMsg) + sizeof(SSubmitBlk) + pBlock->dataLen;
|
|
||||||
pMsg->numOfBlocks = 1;
|
|
||||||
|
|
||||||
pBlock->dataLen = htonl(pBlock->dataLen);
|
|
||||||
pBlock->numOfRows = htonl(pBlock->numOfRows);
|
|
||||||
pBlock->schemaLen = htonl(pBlock->schemaLen);
|
|
||||||
pBlock->uid = htobe64(pBlock->uid);
|
|
||||||
pBlock->tid = htonl(pBlock->tid);
|
|
||||||
|
|
||||||
pBlock->sversion = htonl(pBlock->sversion);
|
|
||||||
pBlock->padding = htonl(pBlock->padding);
|
|
||||||
|
|
||||||
pMsg->length = htonl(pMsg->length);
|
|
||||||
pMsg->numOfBlocks = htonl(pMsg->numOfBlocks);
|
|
||||||
|
|
||||||
if (tsdbInsertData(pInfo->pRepo, pMsg, NULL) < 0) {
|
|
||||||
tfree(pMsg);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
double etime = getCurTime();
|
|
||||||
|
|
||||||
printf("Spent %f seconds to write %d records\n", etime - stime, pInfo->totalRows);
|
|
||||||
tfree(pMsg);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void tsdbSetCfg(STsdbCfg *pCfg, int32_t tsdbId, int32_t cacheBlockSize, int32_t totalBlocks, int32_t maxTables,
|
|
||||||
int32_t daysPerFile, int32_t keep, int32_t minRows, int32_t maxRows, int8_t precision,
|
|
||||||
int8_t compression) {
|
|
||||||
pCfg->tsdbId = tsdbId;
|
|
||||||
pCfg->cacheBlockSize = cacheBlockSize;
|
|
||||||
pCfg->totalBlocks = totalBlocks;
|
|
||||||
// pCfg->maxTables = maxTables;
|
|
||||||
pCfg->daysPerFile = daysPerFile;
|
|
||||||
pCfg->keep = keep;
|
|
||||||
pCfg->minRowsPerFileBlock = minRows;
|
|
||||||
pCfg->maxRowsPerFileBlock = maxRows;
|
|
||||||
pCfg->precision = precision;
|
|
||||||
pCfg->compression = compression;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void tsdbSetTableCfg(STableCfg *pCfg) {
|
|
||||||
STSchemaBuilder schemaBuilder = {0};
|
|
||||||
|
|
||||||
pCfg->type = TSDB_NORMAL_TABLE;
|
|
||||||
pCfg->superUid = TSDB_INVALID_SUPER_TABLE_ID;
|
|
||||||
pCfg->tableId.tid = 1;
|
|
||||||
pCfg->tableId.uid = 5849583783847394;
|
|
||||||
tdInitTSchemaBuilder(&schemaBuilder, 0);
|
|
||||||
|
|
||||||
int colId = 0;
|
|
||||||
for (int i = 0; i < 5; i++) {
|
|
||||||
tdAddColToSchema(&schemaBuilder, (colId == 0) ? TSDB_DATA_TYPE_TIMESTAMP : TSDB_DATA_TYPE_INT, colId, 0);
|
|
||||||
colId++;
|
|
||||||
}
|
|
||||||
|
|
||||||
pCfg->schema = tdGetSchemaFromBuilder(&schemaBuilder);
|
|
||||||
pCfg->name = strdup("t1");
|
|
||||||
|
|
||||||
tdDestroyTSchemaBuilder(&schemaBuilder);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(TsdbTest, testInsertSpeed) {
|
|
||||||
int vnode = 1;
|
|
||||||
int ret = 0;
|
|
||||||
STsdbCfg tsdbCfg;
|
|
||||||
STableCfg tableCfg;
|
|
||||||
std::string testDir = "./test";
|
|
||||||
char * rootDir = strdup((testDir + "/vnode" + std::to_string(vnode)).c_str());
|
|
||||||
|
|
||||||
tsdbDebugFlag = 131; //NOTE: you must set the flag
|
|
||||||
|
|
||||||
taosRemoveDir(rootDir);
|
|
||||||
|
|
||||||
// Create and open repository
|
|
||||||
tsdbSetCfg(&tsdbCfg, 1, 16, 4, -1, -1, -1, -1, -1, -1, -1);
|
|
||||||
tsdbCreateRepo(rootDir, &tsdbCfg);
|
|
||||||
STsdbRepo *repo = tsdbOpenRepo(rootDir, NULL);
|
|
||||||
ASSERT_NE(repo, nullptr);
|
|
||||||
|
|
||||||
// Create table
|
|
||||||
tsdbSetTableCfg(&tableCfg);
|
|
||||||
tsdbCreateTable(repo, &tableCfg);
|
|
||||||
|
|
||||||
// Insert data
|
|
||||||
SInsertInfo iInfo = {repo, true, 1, 5849583783847394, 0, 1590000000000, 10, 10000000, 100, tableCfg.schema};
|
|
||||||
|
|
||||||
insertData(&iInfo);
|
|
||||||
|
|
||||||
tsdbCloseRepo(repo, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *getTKey(const void *data) {
|
|
||||||
return (char *)data;
|
|
||||||
}
|
|
Loading…
Reference in New Issue