commit
99ea015b47
|
@ -13,15 +13,23 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _TD_TVK_ROCKSDB_H_
|
||||
#define _TD_TVK_ROCKSDB_H_
|
||||
#ifndef _TD_COMMON_CFG_H_
|
||||
#define _TD_COMMON_CFG_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "tdef.h"
|
||||
|
||||
typedef struct {
|
||||
char dir[TSDB_FILENAME_LEN];
|
||||
int level;
|
||||
int primary;
|
||||
} SDiskCfg;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*_TD_TVK_ROCKSDB_H_*/
|
||||
#endif /*_TD_COMMON_CFG_H_*/
|
|
@ -21,6 +21,7 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
#include "tdef.h"
|
||||
#include "tcfg.h"
|
||||
|
||||
// cluster
|
||||
extern char tsFirst[];
|
||||
|
@ -105,11 +106,6 @@ extern uint32_t tsMaxRange;
|
|||
extern uint32_t tsCurRange;
|
||||
extern char tsCompressor[];
|
||||
|
||||
typedef struct {
|
||||
char dir[TSDB_FILENAME_LEN];
|
||||
int level;
|
||||
int primary;
|
||||
} SDiskCfg;
|
||||
extern int32_t tsDiskCfgNum;
|
||||
extern SDiskCfg tsDiskCfg[];
|
||||
|
||||
|
|
|
@ -58,6 +58,7 @@ int metaCommit(SMeta *pMeta);
|
|||
STbCfg * metaGetTbInfoByUid(SMeta *pMeta, tb_uid_t uid);
|
||||
STbCfg * metaGetTbInfoByName(SMeta *pMeta, char *tbname, tb_uid_t *uid);
|
||||
SSchemaWrapper *metaGetTableSchema(SMeta *pMeta, tb_uid_t uid, int32_t sver, bool isinline);
|
||||
STSchema * metaGetTbTSchema(SMeta *pMeta, tb_uid_t uid, int32_t sver);
|
||||
|
||||
SMTbCursor *metaOpenTbCursor(SMeta *pMeta);
|
||||
void metaCloseTbCursor(SMTbCursor *pTbCur);
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#define _TD_TSDB_H_
|
||||
|
||||
#include "mallocator.h"
|
||||
#include "meta.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -33,7 +34,7 @@ typedef struct SDataStatis {
|
|||
} SDataStatis;
|
||||
|
||||
typedef struct STable {
|
||||
int32_t tid;
|
||||
uint64_t tid;
|
||||
uint64_t uid;
|
||||
STSchema *pSchema;
|
||||
} STable;
|
||||
|
@ -54,10 +55,11 @@ typedef struct STsdbCfg {
|
|||
int32_t keep1;
|
||||
int32_t keep2;
|
||||
int8_t update;
|
||||
int8_t compression;
|
||||
} STsdbCfg;
|
||||
|
||||
// STsdb
|
||||
STsdb *tsdbOpen(const char *path, const STsdbCfg *pTsdbCfg, SMemAllocatorFactory *pMAF);
|
||||
STsdb *tsdbOpen(const char *path, int32_t vgId, const STsdbCfg *pTsdbCfg, SMemAllocatorFactory *pMAF, SMeta *pMeta);
|
||||
void tsdbClose(STsdb *);
|
||||
void tsdbRemove(const char *path);
|
||||
int tsdbInsertData(STsdb *pTsdb, SSubmitMsg *pMsg, SSubmitRsp *pRsp);
|
||||
|
|
|
@ -1,433 +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_H_
|
||||
#define _TD_TSDB_H_
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "taosdef.h"
|
||||
#include "tarray.h"
|
||||
#include "tdataformat.h"
|
||||
#include "thash.h"
|
||||
#include "tlist.h"
|
||||
#include "tlockfree.h"
|
||||
#include "tmsg.h"
|
||||
#include "tname.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define TSDB_VERSION_MAJOR 1
|
||||
#define TSDB_VERSION_MINOR 0
|
||||
|
||||
#define TSDB_INVALID_SUPER_TABLE_ID -1
|
||||
|
||||
#define TSDB_STATUS_COMMIT_START 1
|
||||
#define TSDB_STATUS_COMMIT_OVER 2
|
||||
#define TSDB_STATUS_COMMIT_NOBLOCK 3 // commit no block, need to be solved
|
||||
|
||||
// TSDB STATE DEFINITION
|
||||
#define TSDB_STATE_OK 0x0
|
||||
#define TSDB_STATE_BAD_META 0x1
|
||||
#define TSDB_STATE_BAD_DATA 0x2
|
||||
|
||||
typedef struct SDataStatis {
|
||||
int16_t colId;
|
||||
int64_t sum;
|
||||
int64_t max;
|
||||
int64_t min;
|
||||
int16_t maxIndex;
|
||||
int16_t minIndex;
|
||||
int16_t numOfNull;
|
||||
} SDataStatis;
|
||||
|
||||
// --------- TSDB APPLICATION HANDLE DEFINITION
|
||||
|
||||
// --------- TSDB REPOSITORY CONFIGURATION DEFINITION
|
||||
typedef struct {
|
||||
int32_t tsdbId;
|
||||
int32_t cacheBlockSize;
|
||||
int32_t totalBlocks;
|
||||
int32_t daysPerFile; // day per file sharding policy
|
||||
int32_t keep; // day of data to keep
|
||||
int32_t keep1;
|
||||
int32_t keep2;
|
||||
int32_t lruCacheSize;
|
||||
int32_t minRowsPerFileBlock; // minimum rows per file block
|
||||
int32_t maxRowsPerFileBlock; // maximum rows per file block
|
||||
int8_t precision;
|
||||
int8_t compression;
|
||||
int8_t update;
|
||||
int8_t cacheLastRow; // 0:no cache, 1: cache last row, 2: cache last NULL column 3: 1&2
|
||||
} STsdbCfg;
|
||||
|
||||
#define CACHE_NO_LAST(c) ((c)->cacheLastRow == 0)
|
||||
#define CACHE_LAST_ROW(c) (((c)->cacheLastRow & 1) > 0)
|
||||
#define CACHE_LAST_NULL_COLUMN(c) (((c)->cacheLastRow & 2) > 0)
|
||||
|
||||
// --------- TSDB REPOSITORY USAGE STATISTICS
|
||||
typedef struct {
|
||||
int64_t totalStorage; // total bytes occupie
|
||||
int64_t compStorage;
|
||||
int64_t pointsWritten; // total data points written
|
||||
} STsdbStat;
|
||||
|
||||
typedef struct STsdb STsdb;
|
||||
|
||||
STsdbCfg *tsdbGetCfg(const STsdb *repo);
|
||||
|
||||
// --------- TSDB REPOSITORY DEFINITION
|
||||
// int32_t tsdbCreateRepo(int repoid);
|
||||
// int32_t tsdbDropRepo(int repoid);
|
||||
STsdb * tsdbOpen(STsdbCfg *pCfg, STsdbAppH *pAppH);
|
||||
int tsdbClose(STsdb *repo, int toCommit);
|
||||
int32_t tsdbConfigRepo(STsdb *repo, STsdbCfg *pCfg);
|
||||
int tsdbGetState(STsdb *repo);
|
||||
int8_t tsdbGetCompactState(STsdb *repo);
|
||||
// --------- TSDB TABLE DEFINITION
|
||||
typedef struct {
|
||||
uint64_t uid; // the unique table ID
|
||||
int32_t tid; // the table ID in the repository.
|
||||
} STableId;
|
||||
|
||||
// --------- TSDB TABLE configuration
|
||||
typedef struct {
|
||||
ETableType type;
|
||||
char * name;
|
||||
STableId tableId;
|
||||
int32_t sversion;
|
||||
char * sname; // super table name
|
||||
uint64_t superUid;
|
||||
STSchema * schema;
|
||||
STSchema * tagSchema;
|
||||
SKVRow tagValues;
|
||||
char * sql;
|
||||
} STableCfg;
|
||||
|
||||
void tsdbClearTableCfg(STableCfg *config);
|
||||
|
||||
void *tsdbGetTableTagVal(const void *pTable, int32_t colId, int16_t type);
|
||||
char *tsdbGetTableName(void *pTable);
|
||||
|
||||
#define TSDB_TABLEID(_table) ((STableId *)(_table))
|
||||
#define TSDB_PREV_ROW 0x1
|
||||
#define TSDB_NEXT_ROW 0x2
|
||||
|
||||
STableCfg *tsdbCreateTableCfgFromMsg(SMDCreateTableMsg *pMsg);
|
||||
|
||||
int tsdbCreateTable(STsdb *repo, STableCfg *pCfg);
|
||||
int tsdbDropTable(STsdb *pRepo, STableId tableId);
|
||||
int tsdbUpdateTableTagValue(STsdb *repo, SUpdateTableTagValMsg *pMsg);
|
||||
|
||||
uint32_t tsdbGetFileInfo(STsdb *repo, char *name, uint32_t *index, uint32_t eindex, int64_t *size);
|
||||
|
||||
// the TSDB repository info
|
||||
typedef struct STsdbRepoInfo {
|
||||
STsdbCfg tsdbCfg;
|
||||
uint64_t version; // version of the repository
|
||||
int64_t tsdbTotalDataSize; // the original inserted data size
|
||||
int64_t tsdbTotalDiskSize; // the total disk size taken by this TSDB repository
|
||||
// TODO: Other informations to add
|
||||
} STsdbRepoInfo;
|
||||
STsdbRepoInfo *tsdbGetStatus(STsdb *pRepo);
|
||||
|
||||
// the meter information report structure
|
||||
typedef struct {
|
||||
STableCfg tableCfg;
|
||||
uint64_t version;
|
||||
int64_t tableTotalDataSize; // In bytes
|
||||
int64_t tableTotalDiskSize; // In bytes
|
||||
} STableInfo;
|
||||
|
||||
// -- FOR INSERT DATA
|
||||
/**
|
||||
* Insert data to a table in a repository
|
||||
* @param pRepo the TSDB repository handle
|
||||
* @param pData the data to insert (will give a more specific description)
|
||||
*
|
||||
* @return the number of points inserted, -1 for failure and the error number is set
|
||||
*/
|
||||
int32_t tsdbInsertData(STsdb *repo, SSubmitMsg *pMsg, SShellSubmitRspMsg *pRsp);
|
||||
|
||||
// -- FOR QUERY TIME SERIES DATA
|
||||
|
||||
typedef void *TsdbQueryHandleT; // Use void to hide implementation details
|
||||
|
||||
#define BLOCK_LOAD_OFFSET_SEQ_ORDER 1
|
||||
#define BLOCK_LOAD_TABLE_SEQ_ORDER 2
|
||||
#define BLOCK_LOAD_TABLE_RR_ORDER 3
|
||||
|
||||
// query condition to build multi-table data block iterator
|
||||
typedef struct STsdbQueryCond {
|
||||
STimeWindow twindow;
|
||||
int32_t order; // desc|asc order to iterate the data block
|
||||
int64_t offset; // skip offset put down to tsdb
|
||||
int32_t numOfCols;
|
||||
SColumnInfo *colList;
|
||||
bool loadExternalRows; // load external rows or not
|
||||
int32_t type; // data block load type:
|
||||
} STsdbQueryCond;
|
||||
|
||||
typedef struct STableData STableData;
|
||||
typedef struct {
|
||||
T_REF_DECLARE()
|
||||
SRWLatch latch;
|
||||
TSKEY keyFirst;
|
||||
TSKEY keyLast;
|
||||
int64_t numOfRows;
|
||||
int32_t maxTables;
|
||||
STableData **tData;
|
||||
SList * actList;
|
||||
SList * extraBuffList;
|
||||
SList * bufBlockList;
|
||||
int64_t pointsAdd; // TODO
|
||||
int64_t storageAdd; // TODO
|
||||
} SMemTable;
|
||||
|
||||
typedef struct {
|
||||
SMemTable *mem;
|
||||
SMemTable *imem;
|
||||
SMemTable mtable;
|
||||
SMemTable *omem;
|
||||
} SMemSnapshot;
|
||||
|
||||
typedef struct SMemRef {
|
||||
int32_t ref;
|
||||
SMemSnapshot snapshot;
|
||||
} SMemRef;
|
||||
|
||||
#if 0
|
||||
typedef struct SFileBlockInfo {
|
||||
int32_t numBlocksOfStep;
|
||||
} SFileBlockInfo;
|
||||
|
||||
typedef struct {
|
||||
void *pTable;
|
||||
TSKEY lastKey;
|
||||
} STableKeyInfo;
|
||||
|
||||
typedef struct {
|
||||
uint32_t numOfTables;
|
||||
SArray * pGroupList;
|
||||
SHashObj *map; // speedup acquire the tableQueryInfo by table uid
|
||||
} STableGroupInfo;
|
||||
|
||||
#define TSDB_BLOCK_DIST_STEP_ROWS 16
|
||||
typedef struct {
|
||||
uint16_t rowSize;
|
||||
uint16_t numOfFiles;
|
||||
uint32_t numOfTables;
|
||||
uint64_t totalSize;
|
||||
uint64_t totalRows;
|
||||
int32_t maxRows;
|
||||
int32_t minRows;
|
||||
int32_t firstSeekTimeUs;
|
||||
uint32_t numOfRowsInMemTable;
|
||||
uint32_t numOfSmallBlocks;
|
||||
SArray * dataBlockInfos;
|
||||
} STableBlockDist;
|
||||
|
||||
/**
|
||||
* Get the data block iterator, starting from position according to the query condition
|
||||
*
|
||||
* @param tsdb tsdb handle
|
||||
* @param pCond query condition, including time window, result set order, and basic required columns for each block
|
||||
* @param tableInfoGroup table object list in the form of set, grouped into different sets according to the
|
||||
* group by condition
|
||||
* @param qinfo query info handle from query processor
|
||||
* @return
|
||||
*/
|
||||
TsdbQueryHandleT *tsdbQueryTables(STsdb *tsdb, STsdbQueryCond *pCond, STableGroupInfo *tableInfoGroup, uint64_t qId,
|
||||
SMemRef *pRef);
|
||||
|
||||
/**
|
||||
* Get the last row of the given query time window for all the tables in STableGroupInfo object.
|
||||
* Note that only one data block with only row will be returned while invoking retrieve data block function for
|
||||
* all tables in this group.
|
||||
*
|
||||
* @param tsdb tsdb handle
|
||||
* @param pCond query condition, including time window, result set order, and basic required columns for each block
|
||||
* @param tableInfo table list.
|
||||
* @return
|
||||
*/
|
||||
TsdbQueryHandleT tsdbQueryLastRow(STsdb *tsdb, STsdbQueryCond *pCond, STableGroupInfo *tableInfo, uint64_t qId,
|
||||
SMemRef *pRef);
|
||||
|
||||
TsdbQueryHandleT tsdbQueryCacheLast(STsdb *tsdb, STsdbQueryCond *pCond, STableGroupInfo *groupList, uint64_t qId,
|
||||
SMemRef *pMemRef);
|
||||
|
||||
bool isTsdbCacheLastRow(TsdbQueryHandleT *pQueryHandle);
|
||||
|
||||
/**
|
||||
* get the queried table object list
|
||||
* @param pHandle
|
||||
* @return
|
||||
*/
|
||||
SArray *tsdbGetQueriedTableList(TsdbQueryHandleT *pHandle);
|
||||
|
||||
/**
|
||||
* get the group list according to table id from client
|
||||
* @param tsdb
|
||||
* @param pCond
|
||||
* @param groupList
|
||||
* @param qinfo
|
||||
* @return
|
||||
*/
|
||||
TsdbQueryHandleT tsdbQueryRowsInExternalWindow(STsdb *tsdb, STsdbQueryCond *pCond, STableGroupInfo *groupList,
|
||||
uint64_t qId, SMemRef *pRef);
|
||||
|
||||
/**
|
||||
* get num of rows in mem table
|
||||
*
|
||||
* @param pHandle
|
||||
* @return row size
|
||||
*/
|
||||
|
||||
int64_t tsdbGetNumOfRowsInMemTable(TsdbQueryHandleT *pHandle);
|
||||
|
||||
/**
|
||||
* move to next block if exists
|
||||
*
|
||||
* @param pQueryHandle
|
||||
* @return
|
||||
*/
|
||||
bool tsdbNextDataBlock(TsdbQueryHandleT pQueryHandle);
|
||||
|
||||
/**
|
||||
* Get current data block information
|
||||
*
|
||||
* @param pQueryHandle
|
||||
* @param pBlockInfo
|
||||
* @return
|
||||
*/
|
||||
void tsdbRetrieveDataBlockInfo(TsdbQueryHandleT *pQueryHandle, SDataBlockInfo *pBlockInfo);
|
||||
|
||||
/**
|
||||
*
|
||||
* Get the pre-calculated information w.r.t. current data block.
|
||||
*
|
||||
* In case of data block in cache, the pBlockStatis will always be NULL.
|
||||
* If a block is not completed loaded from disk, the pBlockStatis will be NULL.
|
||||
|
||||
* @pBlockStatis the pre-calculated value for current data blocks. if the block is a cache block, always return 0
|
||||
* @return
|
||||
*/
|
||||
int32_t tsdbRetrieveDataBlockStatisInfo(TsdbQueryHandleT *pQueryHandle, SDataStatis **pBlockStatis);
|
||||
|
||||
/**
|
||||
*
|
||||
* The query condition with primary timestamp is passed to iterator during its constructor function,
|
||||
* the returned data block must be satisfied with the time window condition in any cases,
|
||||
* which means the SData data block is not actually the completed disk data blocks.
|
||||
*
|
||||
* @param pQueryHandle query handle
|
||||
* @param pColumnIdList required data columns id list
|
||||
* @return
|
||||
*/
|
||||
SArray *tsdbRetrieveDataBlock(TsdbQueryHandleT *pQueryHandle, SArray *pColumnIdList);
|
||||
|
||||
/**
|
||||
* Get the qualified table id for a super table according to the tag query expression.
|
||||
* @param stableid. super table sid
|
||||
* @param pTagCond. tag query condition
|
||||
*/
|
||||
int32_t tsdbQuerySTableByTagCond(STsdb *tsdb, uint64_t uid, TSKEY key, const char *pTagCond, size_t len,
|
||||
STableGroupInfo *pGroupList, SColIndex *pColIndex, int32_t numOfCols);
|
||||
|
||||
/**
|
||||
* destroy the created table group list, which is generated by tag query
|
||||
* @param pGroupList
|
||||
*/
|
||||
void tsdbDestroyTableGroup(STableGroupInfo *pGroupList);
|
||||
|
||||
/**
|
||||
* create the table group result including only one table, used to handle the normal table query
|
||||
*
|
||||
* @param tsdb tsdbHandle
|
||||
* @param uid table uid
|
||||
* @param pGroupInfo the generated result
|
||||
* @return
|
||||
*/
|
||||
int32_t tsdbGetOneTableGroup(STsdb *tsdb, uint64_t uid, TSKEY startKey, STableGroupInfo *pGroupInfo);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param tsdb
|
||||
* @param pTableIdList
|
||||
* @param pGroupInfo
|
||||
* @return
|
||||
*/
|
||||
int32_t tsdbGetTableGroupFromIdList(STsdb *tsdb, SArray *pTableIdList, STableGroupInfo *pGroupInfo);
|
||||
|
||||
/**
|
||||
* clean up the query handle
|
||||
* @param queryHandle
|
||||
*/
|
||||
void tsdbCleanupQueryHandle(TsdbQueryHandleT queryHandle);
|
||||
|
||||
void tsdbResetQueryHandle(TsdbQueryHandleT queryHandle, STsdbQueryCond *pCond);
|
||||
|
||||
void tsdbResetQueryHandleForNewTable(TsdbQueryHandleT queryHandle, STsdbQueryCond *pCond, STableGroupInfo *groupList);
|
||||
|
||||
int32_t tsdbGetFileBlocksDistInfo(TsdbQueryHandleT *queryHandle, STableBlockDist *pTableBlockInfo);
|
||||
|
||||
// obtain queryHandle attribute
|
||||
int64_t tsdbSkipOffset(TsdbQueryHandleT queryHandle);
|
||||
|
||||
/**
|
||||
* get the statistics of repo usage
|
||||
* @param repo. point to the tsdbrepo
|
||||
* @param totalPoints. total data point written
|
||||
* @param totalStorage. total bytes took by the tsdb
|
||||
* @param compStorage. total bytes took by the tsdb after compressed
|
||||
*/
|
||||
void tsdbReportStat(void *repo, int64_t *totalPoints, int64_t *totalStorage, int64_t *compStorage);
|
||||
|
||||
int tsdbInitCommitQueue();
|
||||
void tsdbDestroyCommitQueue();
|
||||
int tsdbSyncCommit(STsdb *repo);
|
||||
void tsdbIncCommitRef(int vgId);
|
||||
void tsdbDecCommitRef(int vgId);
|
||||
void tsdbSwitchTable(TsdbQueryHandleT pQueryHandle);
|
||||
|
||||
// For TSDB file sync
|
||||
int tsdbSyncSend(void *pRepo, SOCKET socketFd);
|
||||
int tsdbSyncRecv(void *pRepo, SOCKET socketFd);
|
||||
|
||||
// // For TSDB Compact
|
||||
// int tsdbCompact(STsdb *pRepo);
|
||||
|
||||
// For TSDB Health Monitor
|
||||
|
||||
// // no problem return true
|
||||
// bool tsdbNoProblem(STsdb *pRepo);
|
||||
// // unit of walSize: MB
|
||||
// int tsdbCheckWal(STsdb *pRepo, uint32_t walSize);
|
||||
|
||||
// // for json tag
|
||||
// void *getJsonTagValueElment(void *data, char *key, int32_t keyLen, char *out, int16_t bytes);
|
||||
// void getJsonTagValueAll(void *data, void *dst, int16_t bytes);
|
||||
// char *parseTagDatatoJson(void *p);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _TD_TSDB_H_
|
|
@ -89,7 +89,7 @@ void vnodeClear();
|
|||
* @param pVnodeCfg options of the vnode
|
||||
* @return SVnode* The vnode object
|
||||
*/
|
||||
SVnode *vnodeOpen(const char *path, const SVnodeCfg *pVnodeCfg);
|
||||
SVnode *vnodeOpen(const char *path, const SVnodeCfg *pVnodeCfg, int32_t vid);
|
||||
|
||||
/**
|
||||
* @brief Close a VNODE
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#ifndef _TD_TKV_H_
|
||||
#define _TD_TKV_H_
|
||||
|
||||
#if 0
|
||||
#include "os.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -59,4 +60,5 @@ void tkvWriteOptsDestroy(STkvWriteOpts *);
|
|||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif /*_TD_TKV_H_*/
|
|
@ -54,7 +54,7 @@ int32_t taosFtruncateFile(FileFd fd, int64_t length);
|
|||
int32_t taosFsyncFile(FileFd fd);
|
||||
|
||||
int64_t taosReadFile(FileFd fd, void *buf, int64_t count);
|
||||
int64_t taosWriteFile(FileFd fd, void *buf, int64_t count);
|
||||
int64_t taosWriteFile(FileFd fd, const void *buf, int64_t count);
|
||||
|
||||
void taosCloseFile(FileFd fd);
|
||||
|
||||
|
|
|
@ -26,14 +26,10 @@ extern "C" {
|
|||
#define TD_MOD_UNINITIALIZED 0
|
||||
#define TD_MOD_INITIALIZED 1
|
||||
|
||||
#define TD_MOD_UNCLEARD 0
|
||||
#define TD_MOD_CLEARD 1
|
||||
|
||||
typedef int8_t td_mode_flag_t;
|
||||
|
||||
#define TD_CHECK_AND_SET_MODE_INIT(FLAG) atomic_val_compare_exchange_8((FLAG), TD_MOD_UNINITIALIZED, TD_MOD_INITIALIZED)
|
||||
|
||||
#define TD_CHECK_AND_SET_MOD_CLEAR(FLAG) atomic_val_compare_exchange_8((FLAG), TD_MOD_UNCLEARD, TD_MOD_CLEARD)
|
||||
#define TD_CHECK_AND_SET_MOD_CLEAR(FLAG) atomic_val_compare_exchange_8((FLAG), TD_MOD_INITIALIZED, TD_MOD_UNINITIALIZED)
|
||||
|
||||
#define TD_IS_NULL(PTR) ((PTR) == NULL)
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ target_link_libraries(
|
|||
PUBLIC wal
|
||||
PUBLIC sync
|
||||
PUBLIC taos
|
||||
PUBLIC tfs
|
||||
)
|
||||
target_include_directories(
|
||||
dnode
|
||||
|
|
|
@ -21,8 +21,9 @@ extern "C" {
|
|||
#endif
|
||||
#include "dndInt.h"
|
||||
|
||||
int32_t dndInitDnode(SDnode *pDnode);
|
||||
void dndCleanupDnode(SDnode *pDnode);
|
||||
int32_t dndInitMgmt(SDnode *pDnode);
|
||||
void dndStopMgmt(SDnode *pDnode);
|
||||
void dndCleanupMgmt(SDnode *pDnode);
|
||||
|
||||
int32_t dndGetDnodeId(SDnode *pDnode);
|
||||
int64_t dndGetClusterId(SDnode *pDnode);
|
||||
|
|
|
@ -497,7 +497,7 @@ static void *dnodeThreadRoutine(void *param) {
|
|||
}
|
||||
}
|
||||
|
||||
int32_t dndInitDnode(SDnode *pDnode) {
|
||||
int32_t dndInitMgmt(SDnode *pDnode) {
|
||||
SDnodeMgmt *pMgmt = &pDnode->dmgmt;
|
||||
|
||||
pMgmt->dnodeId = 0;
|
||||
|
@ -547,16 +547,18 @@ int32_t dndInitDnode(SDnode *pDnode) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
void dndCleanupDnode(SDnode *pDnode) {
|
||||
void dndStopMgmt(SDnode *pDnode) {
|
||||
SDnodeMgmt *pMgmt = &pDnode->dmgmt;
|
||||
|
||||
dndCleanupWorker(&pMgmt->mgmtWorker);
|
||||
|
||||
if (pMgmt->threadId != NULL) {
|
||||
taosDestoryThread(pMgmt->threadId);
|
||||
pMgmt->threadId = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void dndCleanupMgmt(SDnode *pDnode) {
|
||||
SDnodeMgmt *pMgmt = &pDnode->dmgmt;
|
||||
taosWLockLatch(&pMgmt->latch);
|
||||
|
||||
if (pMgmt->dnodeEps != NULL) {
|
||||
|
|
|
@ -33,9 +33,9 @@ typedef struct {
|
|||
int8_t dropped;
|
||||
int8_t accessState;
|
||||
uint64_t dbUid;
|
||||
char *db;
|
||||
char *path;
|
||||
SVnode *pImpl;
|
||||
char * db;
|
||||
char * path;
|
||||
SVnode * pImpl;
|
||||
STaosQueue *pWriteQ;
|
||||
STaosQueue *pSyncQ;
|
||||
STaosQueue *pApplyQ;
|
||||
|
@ -49,7 +49,7 @@ typedef struct {
|
|||
int32_t failed;
|
||||
int32_t threadIndex;
|
||||
pthread_t thread;
|
||||
SDnode *pDnode;
|
||||
SDnode * pDnode;
|
||||
SWrapperCfg *pCfgs;
|
||||
} SVnodeThread;
|
||||
|
||||
|
@ -67,7 +67,7 @@ void dndProcessVnodeWriteMsg(SDnode *pDnode, SRpcMsg *pMsg, SEpSet *pE
|
|||
void dndProcessVnodeSyncMsg(SDnode *pDnode, SRpcMsg *pMsg, SEpSet *pEpSet);
|
||||
static int32_t dndPutMsgIntoVnodeApplyQueue(SDnode *pDnode, int32_t vgId, SRpcMsg *pMsg);
|
||||
|
||||
static SVnodeObj *dndAcquireVnode(SDnode *pDnode, int32_t vgId);
|
||||
static SVnodeObj * dndAcquireVnode(SDnode *pDnode, int32_t vgId);
|
||||
static void dndReleaseVnode(SDnode *pDnode, SVnodeObj *pVnode);
|
||||
static int32_t dndOpenVnode(SDnode *pDnode, SWrapperCfg *pCfg, SVnode *pImpl);
|
||||
static void dndCloseVnode(SDnode *pDnode, SVnodeObj *pVnode);
|
||||
|
@ -80,7 +80,7 @@ static void dndCloseVnodes(SDnode *pDnode);
|
|||
|
||||
static SVnodeObj *dndAcquireVnode(SDnode *pDnode, int32_t vgId) {
|
||||
SVnodesMgmt *pMgmt = &pDnode->vmgmt;
|
||||
SVnodeObj *pVnode = NULL;
|
||||
SVnodeObj * pVnode = NULL;
|
||||
int32_t refCount = 0;
|
||||
|
||||
taosRLockLatch(&pMgmt->latch);
|
||||
|
@ -111,7 +111,7 @@ static void dndReleaseVnode(SDnode *pDnode, SVnodeObj *pVnode) {
|
|||
|
||||
static int32_t dndOpenVnode(SDnode *pDnode, SWrapperCfg *pCfg, SVnode *pImpl) {
|
||||
SVnodesMgmt *pMgmt = &pDnode->vmgmt;
|
||||
SVnodeObj *pVnode = calloc(1, sizeof(SVnodeObj));
|
||||
SVnodeObj * pVnode = calloc(1, sizeof(SVnodeObj));
|
||||
if (pVnode == NULL) {
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
return -1;
|
||||
|
@ -167,6 +167,11 @@ static void dndCloseVnode(SDnode *pDnode, SVnodeObj *pVnode) {
|
|||
|
||||
dDebug("vgId:%d, vnode is closed", pVnode->vgId);
|
||||
|
||||
if (pVnode->dropped) {
|
||||
dDebug("vgId:%d, vnode is destroyed for dropped:%d", pVnode->vgId, pVnode->dropped);
|
||||
vnodeDestroy(pVnode->path);
|
||||
}
|
||||
|
||||
free(pVnode->path);
|
||||
free(pVnode->db);
|
||||
free(pVnode);
|
||||
|
@ -183,7 +188,7 @@ static SVnodeObj **dndGetVnodesFromHash(SDnode *pDnode, int32_t *numOfVnodes) {
|
|||
void *pIter = taosHashIterate(pMgmt->hash, NULL);
|
||||
while (pIter) {
|
||||
SVnodeObj **ppVnode = pIter;
|
||||
SVnodeObj *pVnode = *ppVnode;
|
||||
SVnodeObj * pVnode = *ppVnode;
|
||||
if (pVnode && num < size) {
|
||||
int32_t refCount = atomic_add_fetch_32(&pVnode->refCount, 1);
|
||||
dTrace("vgId:%d, acquire vnode, refCount:%d", pVnode->vgId, refCount);
|
||||
|
@ -205,9 +210,9 @@ static int32_t dndGetVnodesFromFile(SDnode *pDnode, SWrapperCfg **ppCfgs, int32_
|
|||
int32_t code = TSDB_CODE_DND_VNODE_READ_FILE_ERROR;
|
||||
int32_t len = 0;
|
||||
int32_t maxLen = 30000;
|
||||
char *content = calloc(1, maxLen + 1);
|
||||
cJSON *root = NULL;
|
||||
FILE *fp = NULL;
|
||||
char * content = calloc(1, maxLen + 1);
|
||||
cJSON * root = NULL;
|
||||
FILE * fp = NULL;
|
||||
char file[PATH_MAX + 20] = {0};
|
||||
SWrapperCfg *pCfgs = NULL;
|
||||
|
||||
|
@ -320,7 +325,7 @@ static int32_t dndWriteVnodesToFile(SDnode *pDnode) {
|
|||
|
||||
int32_t len = 0;
|
||||
int32_t maxLen = 65536;
|
||||
char *content = calloc(1, maxLen + 1);
|
||||
char * content = calloc(1, maxLen + 1);
|
||||
|
||||
len += snprintf(content + len, maxLen - len, "{\n");
|
||||
len += snprintf(content + len, maxLen - len, " \"vnodes\": [\n");
|
||||
|
@ -362,8 +367,8 @@ static int32_t dndWriteVnodesToFile(SDnode *pDnode) {
|
|||
|
||||
static void *dnodeOpenVnodeFunc(void *param) {
|
||||
SVnodeThread *pThread = param;
|
||||
SDnode *pDnode = pThread->pDnode;
|
||||
SVnodesMgmt *pMgmt = &pDnode->vmgmt;
|
||||
SDnode * pDnode = pThread->pDnode;
|
||||
SVnodesMgmt * pMgmt = &pDnode->vmgmt;
|
||||
|
||||
dDebug("thread:%d, start to open %d vnodes", pThread->threadIndex, pThread->vnodeNum);
|
||||
setThreadName("open-vnodes");
|
||||
|
@ -376,10 +381,7 @@ static void *dnodeOpenVnodeFunc(void *param) {
|
|||
pMgmt->openVnodes, pMgmt->totalVnodes);
|
||||
dndReportStartup(pDnode, "open-vnodes", stepDesc);
|
||||
|
||||
SVnodeCfg vnodeCfg = {0};
|
||||
vnodeCfg.vgId = pCfg->vgId;
|
||||
|
||||
SVnode *pImpl = vnodeOpen(pCfg->path, &vnodeCfg);
|
||||
SVnode *pImpl = vnodeOpen(pCfg->path, NULL, pCfg->vgId);
|
||||
if (pImpl == NULL) {
|
||||
dError("vgId:%d, failed to open vnode by thread:%d", pCfg->vgId, pThread->threadIndex);
|
||||
pThread->failed++;
|
||||
|
@ -469,6 +471,7 @@ static int32_t dndOpenVnodes(SDnode *pDnode) {
|
|||
}
|
||||
|
||||
static void dndCloseVnodes(SDnode *pDnode) {
|
||||
dInfo("start to close all vnodes");
|
||||
SVnodesMgmt *pMgmt = &pDnode->vmgmt;
|
||||
|
||||
int32_t numOfVnodes = 0;
|
||||
|
@ -578,7 +581,7 @@ int32_t dndProcessCreateVnodeReq(SDnode *pDnode, SRpcMsg *pReq) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
SVnode *pImpl = vnodeOpen(wrapperCfg.path, &vnodeCfg);
|
||||
SVnode *pImpl = vnodeOpen(wrapperCfg.path, NULL /*pCfg*/, pCreate->vgId);
|
||||
if (pImpl == NULL) {
|
||||
dError("vgId:%d, failed to create vnode since %s", pCreate->vgId, terrstr());
|
||||
return -1;
|
||||
|
@ -661,8 +664,6 @@ int32_t dndProcessDropVnodeReq(SDnode *pDnode, SRpcMsg *pReq) {
|
|||
}
|
||||
|
||||
dndCloseVnode(pDnode, pVnode);
|
||||
vnodeClose(pVnode->pImpl);
|
||||
vnodeDestroy(pVnode->path);
|
||||
dndWriteVnodesToFile(pDnode);
|
||||
|
||||
return 0;
|
||||
|
@ -992,12 +993,12 @@ void dndGetVnodeLoads(SDnode *pDnode, SVnodeLoads *pLoads) {
|
|||
pLoads->num = taosHashGetSize(pMgmt->hash);
|
||||
|
||||
int32_t v = 0;
|
||||
void *pIter = taosHashIterate(pMgmt->hash, NULL);
|
||||
void * pIter = taosHashIterate(pMgmt->hash, NULL);
|
||||
while (pIter) {
|
||||
SVnodeObj **ppVnode = pIter;
|
||||
if (ppVnode == NULL || *ppVnode == NULL) continue;
|
||||
|
||||
SVnodeObj *pVnode = *ppVnode;
|
||||
SVnodeObj * pVnode = *ppVnode;
|
||||
SVnodeLoad *pLoad = &pLoads->data[v++];
|
||||
|
||||
vnodeGetLoad(pVnode->pImpl, pLoad);
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "dndVnodes.h"
|
||||
#include "sync.h"
|
||||
#include "wal.h"
|
||||
#include "tfs.h"
|
||||
|
||||
EStat dndGetStat(SDnode *pDnode) { return pDnode->stat; }
|
||||
|
||||
|
@ -185,13 +186,23 @@ SDnode *dndInit(SDnodeOpt *pOption) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
SDiskCfg dCfg;
|
||||
strcpy(dCfg.dir, pDnode->opt.dataDir);
|
||||
dCfg.level = 0;
|
||||
dCfg.primary = 1;
|
||||
if (tfsInit(&dCfg, 1) != 0) {
|
||||
dError("failed to init tfs env");
|
||||
dndCleanup(pDnode);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (vnodeInit(pDnode->opt.numOfCommitThreads) != 0) {
|
||||
dError("failed to init vnode env");
|
||||
dndCleanup(pDnode);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (dndInitDnode(pDnode) != 0) {
|
||||
if (dndInitMgmt(pDnode) != 0) {
|
||||
dError("failed to init dnode");
|
||||
dndCleanup(pDnode);
|
||||
return NULL;
|
||||
|
@ -252,13 +263,15 @@ void dndCleanup(SDnode *pDnode) {
|
|||
dInfo("start to cleanup TDengine");
|
||||
dndSetStat(pDnode, DND_STAT_STOPPED);
|
||||
dndCleanupTrans(pDnode);
|
||||
dndStopMgmt(pDnode);
|
||||
dndCleanupMnode(pDnode);
|
||||
dndCleanupBnode(pDnode);
|
||||
dndCleanupSnode(pDnode);
|
||||
dndCleanupQnode(pDnode);
|
||||
dndCleanupVnodes(pDnode);
|
||||
dndCleanupDnode(pDnode);
|
||||
dndCleanupMgmt(pDnode);
|
||||
vnodeClear();
|
||||
tfsDestroy();
|
||||
walCleanUp();
|
||||
rpcCleanup();
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "tlockfree.h"
|
||||
#include "tmacro.h"
|
||||
#include "wal.h"
|
||||
#include "tfs.h"
|
||||
|
||||
#include "vnode.h"
|
||||
|
||||
|
@ -48,7 +49,6 @@ typedef struct SVnodeTask {
|
|||
|
||||
typedef struct SVnodeMgr {
|
||||
td_mode_flag_t vnodeInitFlag;
|
||||
td_mode_flag_t vnodeClearFlag;
|
||||
// For commit
|
||||
bool stop;
|
||||
uint16_t nthreads;
|
||||
|
|
|
@ -97,14 +97,17 @@ int vnodeBufPoolSwitch(SVnode *pVnode) {
|
|||
|
||||
pVnode->pBufPool->inuse = NULL;
|
||||
|
||||
TD_DLIST_APPEND(&(pVnode->pBufPool->incycle), pvma);
|
||||
if (pvma) {
|
||||
TD_DLIST_APPEND(&(pVnode->pBufPool->incycle), pvma);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vnodeBufPoolRecycle(SVnode *pVnode) {
|
||||
SVBufPool * pBufPool = pVnode->pBufPool;
|
||||
SVMemAllocator *pvma = TD_DLIST_HEAD(&(pBufPool->incycle));
|
||||
ASSERT(pvma != NULL);
|
||||
if (pvma == NULL) return 0;
|
||||
// ASSERT(pvma != NULL);
|
||||
|
||||
TD_DLIST_POP(&(pBufPool->incycle), pvma);
|
||||
vmaReset(pvma);
|
||||
|
|
|
@ -40,6 +40,7 @@ int vnodeAsyncCommit(SVnode *pVnode) {
|
|||
int vnodeSyncCommit(SVnode *pVnode) {
|
||||
vnodeAsyncCommit(pVnode);
|
||||
vnodeWaitCommit(pVnode);
|
||||
tsem_post(&(pVnode->canCommit));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,12 +15,12 @@
|
|||
|
||||
#include "vnodeDef.h"
|
||||
|
||||
static SVnode *vnodeNew(const char *path, const SVnodeCfg *pVnodeCfg);
|
||||
static SVnode *vnodeNew(const char *path, const SVnodeCfg *pVnodeCfg, int32_t vid);
|
||||
static void vnodeFree(SVnode *pVnode);
|
||||
static int vnodeOpenImpl(SVnode *pVnode);
|
||||
static void vnodeCloseImpl(SVnode *pVnode);
|
||||
|
||||
SVnode *vnodeOpen(const char *path, const SVnodeCfg *pVnodeCfg) {
|
||||
SVnode *vnodeOpen(const char *path, const SVnodeCfg *pVnodeCfg, int32_t vid) {
|
||||
SVnode *pVnode = NULL;
|
||||
|
||||
// Set default options
|
||||
|
@ -35,7 +35,7 @@ SVnode *vnodeOpen(const char *path, const SVnodeCfg *pVnodeCfg) {
|
|||
}
|
||||
|
||||
// Create the handle
|
||||
pVnode = vnodeNew(path, pVnodeCfg);
|
||||
pVnode = vnodeNew(path, pVnodeCfg, vid);
|
||||
if (pVnode == NULL) {
|
||||
// TODO: handle error
|
||||
return NULL;
|
||||
|
@ -62,7 +62,7 @@ void vnodeClose(SVnode *pVnode) {
|
|||
void vnodeDestroy(const char *path) { taosRemoveDir(path); }
|
||||
|
||||
/* ------------------------ STATIC METHODS ------------------------ */
|
||||
static SVnode *vnodeNew(const char *path, const SVnodeCfg *pVnodeCfg) {
|
||||
static SVnode *vnodeNew(const char *path, const SVnodeCfg *pVnodeCfg, int32_t vid) {
|
||||
SVnode *pVnode = NULL;
|
||||
|
||||
pVnode = (SVnode *)calloc(1, sizeof(*pVnode));
|
||||
|
@ -71,6 +71,7 @@ static SVnode *vnodeNew(const char *path, const SVnodeCfg *pVnodeCfg) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
pVnode->vgId = vid;
|
||||
pVnode->path = strdup(path);
|
||||
vnodeOptionsCopy(&(pVnode->config), pVnodeCfg);
|
||||
|
||||
|
@ -105,7 +106,7 @@ static int vnodeOpenImpl(SVnode *pVnode) {
|
|||
|
||||
// Open tsdb
|
||||
sprintf(dir, "%s/tsdb", pVnode->path);
|
||||
pVnode->pTsdb = tsdbOpen(dir, &(pVnode->config.tsdbCfg), vBufPoolGetMAF(pVnode));
|
||||
pVnode->pTsdb = tsdbOpen(dir, pVnode->vgId, &(pVnode->config.tsdbCfg), vBufPoolGetMAF(pVnode), pVnode->pMeta);
|
||||
if (pVnode->pTsdb == NULL) {
|
||||
// TODO: handle error
|
||||
return -1;
|
||||
|
@ -137,7 +138,7 @@ static int vnodeOpenImpl(SVnode *pVnode) {
|
|||
}
|
||||
|
||||
static void vnodeCloseImpl(SVnode *pVnode) {
|
||||
// vnodeSyncCommit(pVnode);
|
||||
vnodeSyncCommit(pVnode);
|
||||
if (pVnode) {
|
||||
vnodeCloseBufPool(pVnode);
|
||||
metaClose(pVnode->pMeta);
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
#include "vnodeDef.h"
|
||||
|
||||
SVnodeMgr vnodeMgr = {.vnodeInitFlag = TD_MOD_UNINITIALIZED, .vnodeClearFlag = TD_MOD_UNCLEARD, .stop = false};
|
||||
SVnodeMgr vnodeMgr = {.vnodeInitFlag = TD_MOD_UNINITIALIZED};
|
||||
|
||||
static void* loop(void* arg);
|
||||
|
||||
|
@ -24,6 +24,8 @@ int vnodeInit(uint16_t nthreads) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
vnodeMgr.stop = false;
|
||||
|
||||
// Start commit handers
|
||||
if (nthreads > 0) {
|
||||
vnodeMgr.nthreads = nthreads;
|
||||
|
@ -38,6 +40,7 @@ int vnodeInit(uint16_t nthreads) {
|
|||
|
||||
for (uint16_t i = 0; i < nthreads; i++) {
|
||||
pthread_create(&(vnodeMgr.threads[i]), NULL, loop, NULL);
|
||||
pthread_setname_np(vnodeMgr.threads[i], "VND Commit Thread");
|
||||
}
|
||||
} else {
|
||||
// TODO: if no commit thread is set, then another mechanism should be
|
||||
|
@ -53,7 +56,7 @@ int vnodeInit(uint16_t nthreads) {
|
|||
}
|
||||
|
||||
void vnodeClear() {
|
||||
if (TD_CHECK_AND_SET_MOD_CLEAR(&(vnodeMgr.vnodeClearFlag)) == TD_MOD_CLEARD) {
|
||||
if (TD_CHECK_AND_SET_MOD_CLEAR(&(vnodeMgr.vnodeInitFlag)) == TD_MOD_UNINITIALIZED) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -589,4 +589,36 @@ char *metaTbCursorNext(SMTbCursor *pTbCur) {
|
|||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
STSchema *metaGetTbTSchema(SMeta *pMeta, tb_uid_t uid, int32_t sver) {
|
||||
STSchemaBuilder sb;
|
||||
STSchema * pTSchema = NULL;
|
||||
SSchema * pSchema;
|
||||
SSchemaWrapper *pSW;
|
||||
STbCfg * pTbCfg;
|
||||
tb_uid_t quid;
|
||||
|
||||
pTbCfg = metaGetTbInfoByUid(pMeta, uid);
|
||||
if (pTbCfg->type == META_CHILD_TABLE) {
|
||||
quid = pTbCfg->ctbCfg.suid;
|
||||
} else {
|
||||
quid = uid;
|
||||
}
|
||||
|
||||
pSW = metaGetTableSchema(pMeta, quid, sver, true);
|
||||
if (pSW == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Rebuild a schema
|
||||
tdInitTSchemaBuilder(&sb, 0);
|
||||
for (int32_t i = 0; i < pSW->nCols; i++) {
|
||||
pSchema = pSW->pSchema + i;
|
||||
tdAddColToSchema(&sb, pSchema->type, pSchema->colId, pSchema->bytes);
|
||||
}
|
||||
pTSchema = tdGetSchemaFromBuilder(&sb);
|
||||
tdDestroyTSchemaBuilder(&sb);
|
||||
|
||||
return pTSchema;
|
||||
}
|
|
@ -2,7 +2,7 @@ aux_source_directory(src TSDB_SRC)
|
|||
if(0)
|
||||
add_library(tsdb ${TSDB_SRC})
|
||||
else(0)
|
||||
add_library(tsdb "")
|
||||
add_library(tsdb STATIC "")
|
||||
target_sources(tsdb
|
||||
PRIVATE
|
||||
"src/tsdbCommit.c"
|
||||
|
@ -29,4 +29,5 @@ target_link_libraries(
|
|||
PUBLIC common
|
||||
PUBLIC tkv
|
||||
PUBLIC tfs
|
||||
PUBLIC meta
|
||||
)
|
|
@ -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
|
||||
#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);
|
||||
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 /* _TD_TSDB_COMMIT_H_ */
|
|
@ -12,6 +12,8 @@
|
|||
* 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
|
||||
|
||||
#ifndef _TD_TSDB_COMPACT_H_
|
||||
#define _TD_TSDB_COMPACT_H_
|
||||
|
||||
|
@ -19,14 +21,12 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
|
||||
void *tsdbCompactImpl(STsdbRepo *pRepo);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _TD_TSDB_COMPACT_H_ */
|
||||
#endif /* _TD_TSDB_COMPACT_H_ */
|
||||
|
||||
#endif
|
|
@ -17,6 +17,7 @@
|
|||
#define _TD_TSDB_DEF_H_
|
||||
|
||||
#include "mallocator.h"
|
||||
#include "meta.h"
|
||||
#include "tcompression.h"
|
||||
#include "tglobal.h"
|
||||
#include "thash.h"
|
||||
|
@ -47,12 +48,17 @@ struct STsdb {
|
|||
STsdbMemTable * imem;
|
||||
SRtn rtn;
|
||||
SMemAllocatorFactory *pmaf;
|
||||
STsdbFS fs;
|
||||
STsdbFS * fs;
|
||||
SMeta * pMeta;
|
||||
};
|
||||
|
||||
#define REPO_ID(r) 0
|
||||
#define REPO_ID(r) ((r)->vgId)
|
||||
#define REPO_CFG(r) (&(r)->config)
|
||||
#define REPO_FS(r) (&(r)->fs)
|
||||
#define REPO_FS(r) (r)->fs
|
||||
|
||||
static FORCE_INLINE STSchema *tsdbGetTableSchemaImpl(STable *pTable, bool lock, bool copy, int32_t version) {
|
||||
return pTable->pSchema;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -70,7 +70,7 @@ typedef struct {
|
|||
#define TSDB_FS_ITER_FORWARD TSDB_ORDER_ASC
|
||||
#define TSDB_FS_ITER_BACKWARD TSDB_ORDER_DESC
|
||||
|
||||
STsdbFS *tsdbNewFS(STsdbCfg *pCfg);
|
||||
STsdbFS *tsdbNewFS(const STsdbCfg *pCfg);
|
||||
void * tsdbFreeFS(STsdbFS *pfs);
|
||||
int tsdbOpenFS(STsdb *pRepo);
|
||||
void tsdbCloseFS(STsdb *pRepo);
|
||||
|
@ -79,7 +79,7 @@ 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);
|
||||
int tsdbUpdateDFileSet(STsdbFS *pfs, const SDFileSet *pSet);
|
||||
|
||||
void tsdbFSIterInit(SFSIter *pIter, STsdbFS *pfs, int direction);
|
||||
void tsdbFSIterSeek(SFSIter *pIter, int fid);
|
||||
|
|
|
@ -22,11 +22,57 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct STsdbMemTable STsdbMemTable;
|
||||
typedef struct {
|
||||
int rowsInserted;
|
||||
int rowsUpdated;
|
||||
int rowsDeleteSucceed;
|
||||
int rowsDeleteFailed;
|
||||
int nOperations;
|
||||
TSKEY keyFirst;
|
||||
TSKEY keyLast;
|
||||
} SMergeInfo;
|
||||
|
||||
typedef struct STbData {
|
||||
tb_uid_t uid;
|
||||
TSKEY keyMin;
|
||||
TSKEY keyMax;
|
||||
int64_t nrows;
|
||||
SSkipList *pData;
|
||||
} STbData;
|
||||
|
||||
typedef struct STsdbMemTable {
|
||||
T_REF_DECLARE()
|
||||
SRWLatch latch;
|
||||
TSKEY keyMin;
|
||||
TSKEY keyMax;
|
||||
uint64_t nRow;
|
||||
SMemAllocator *pMA;
|
||||
// Container
|
||||
SSkipList *pSlIdx; // SSkiplist<STbData>
|
||||
SHashObj * pHashIdx;
|
||||
} STsdbMemTable;
|
||||
|
||||
STsdbMemTable *tsdbNewMemTable(STsdb *pTsdb);
|
||||
void tsdbFreeMemTable(STsdb *pTsdb, STsdbMemTable *pMemTable);
|
||||
int tsdbMemTableInsert(STsdb *pTsdb, STsdbMemTable *pMemTable, SSubmitMsg *pMsg, SShellSubmitRspMsg *pRsp);
|
||||
int tsdbLoadDataFromCache(STable *pTable, SSkipListIterator *pIter, TSKEY maxKey, int maxRowsToRead, SDataCols *pCols,
|
||||
TKEY *filterKeys, int nFilterKeys, bool keepDup, SMergeInfo *pMergeInfo);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -12,6 +12,7 @@
|
|||
* 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 {
|
||||
|
@ -528,3 +529,5 @@ static int tsdbCompactMeta(STsdbRepo *pRepo) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -191,7 +191,7 @@ static int tsdbAddDFileSetToStatus(SFSStatus *pStatus, const SDFileSet *pSet) {
|
|||
}
|
||||
|
||||
// ================== STsdbFS
|
||||
STsdbFS *tsdbNewFS(STsdbCfg *pCfg) {
|
||||
STsdbFS *tsdbNewFS(const STsdbCfg *pCfg) {
|
||||
int keep = pCfg->keep;
|
||||
int days = pCfg->daysPerFile;
|
||||
int maxFSet = TSDB_MAX_FSETS(keep, days);
|
||||
|
@ -1287,7 +1287,7 @@ static int tsdbRestoreCurrent(STsdb *pRepo) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (tsdbSaveFSStatus(pRepo->fs.cstatus, REPO_ID(pRepo)) < 0) {
|
||||
if (tsdbSaveFSStatus(pRepo->fs->cstatus, REPO_ID(pRepo)) < 0) {
|
||||
tsdbError("vgId:%d failed to restore corrent since %s", REPO_ID(pRepo), tstrerror(terrno));
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -15,18 +15,19 @@
|
|||
|
||||
#include "tsdbDef.h"
|
||||
|
||||
static STsdb *tsdbNew(const char *path, const STsdbCfg *pTsdbCfg, SMemAllocatorFactory *pMAF);
|
||||
static STsdb *tsdbNew(const char *path, int32_t vgId, const STsdbCfg *pTsdbCfg, SMemAllocatorFactory *pMAF,
|
||||
SMeta *pMeta);
|
||||
static void tsdbFree(STsdb *pTsdb);
|
||||
static int tsdbOpenImpl(STsdb *pTsdb);
|
||||
static void tsdbCloseImpl(STsdb *pTsdb);
|
||||
|
||||
STsdb *tsdbOpen(const char *path, const STsdbCfg *pTsdbCfg, SMemAllocatorFactory *pMAF) {
|
||||
STsdb *tsdbOpen(const char *path, int32_t vgId, const STsdbCfg *pTsdbCfg, SMemAllocatorFactory *pMAF, SMeta *pMeta) {
|
||||
STsdb *pTsdb = NULL;
|
||||
|
||||
// Set default TSDB Options
|
||||
if (pTsdbCfg == NULL) {
|
||||
pTsdbCfg = &defautlTsdbOptions;
|
||||
}
|
||||
// if (pTsdbCfg == NULL) {
|
||||
pTsdbCfg = &defautlTsdbOptions;
|
||||
// }
|
||||
|
||||
// Validate the options
|
||||
if (tsdbValidateOptions(pTsdbCfg) < 0) {
|
||||
|
@ -35,7 +36,7 @@ STsdb *tsdbOpen(const char *path, const STsdbCfg *pTsdbCfg, SMemAllocatorFactory
|
|||
}
|
||||
|
||||
// Create the handle
|
||||
pTsdb = tsdbNew(path, pTsdbCfg, pMAF);
|
||||
pTsdb = tsdbNew(path, vgId, pTsdbCfg, pMAF, pMeta);
|
||||
if (pTsdb == NULL) {
|
||||
// TODO: handle error
|
||||
return NULL;
|
||||
|
@ -62,7 +63,8 @@ void tsdbClose(STsdb *pTsdb) {
|
|||
void tsdbRemove(const char *path) { taosRemoveDir(path); }
|
||||
|
||||
/* ------------------------ STATIC METHODS ------------------------ */
|
||||
static STsdb *tsdbNew(const char *path, const STsdbCfg *pTsdbCfg, SMemAllocatorFactory *pMAF) {
|
||||
static STsdb *tsdbNew(const char *path, int32_t vgId, const STsdbCfg *pTsdbCfg, SMemAllocatorFactory *pMAF,
|
||||
SMeta *pMeta) {
|
||||
STsdb *pTsdb = NULL;
|
||||
|
||||
pTsdb = (STsdb *)calloc(1, sizeof(STsdb));
|
||||
|
@ -72,25 +74,32 @@ static STsdb *tsdbNew(const char *path, const STsdbCfg *pTsdbCfg, SMemAllocatorF
|
|||
}
|
||||
|
||||
pTsdb->path = strdup(path);
|
||||
pTsdb->vgId = vgId;
|
||||
tsdbOptionsCopy(&(pTsdb->config), pTsdbCfg);
|
||||
pTsdb->pmaf = pMAF;
|
||||
pTsdb->pMeta = pMeta;
|
||||
|
||||
pTsdb->fs = tsdbNewFS(pTsdbCfg);
|
||||
|
||||
return pTsdb;
|
||||
}
|
||||
|
||||
static void tsdbFree(STsdb *pTsdb) {
|
||||
if (pTsdb) {
|
||||
tsdbFreeFS(pTsdb->fs);
|
||||
tfree(pTsdb->path);
|
||||
free(pTsdb);
|
||||
}
|
||||
}
|
||||
|
||||
static int tsdbOpenImpl(STsdb *pTsdb) {
|
||||
tsdbOpenFS(pTsdb);
|
||||
// TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void tsdbCloseImpl(STsdb *pTsdb) {
|
||||
tsdbCloseFS(pTsdb);
|
||||
// TODO
|
||||
}
|
||||
#if 0
|
||||
|
@ -112,8 +121,8 @@ static void tsdbCloseImpl(STsdb *pTsdb) {
|
|||
// no test file errors here
|
||||
#include "taosdef.h"
|
||||
#include "tsdbint.h"
|
||||
#include "ttimer.h"
|
||||
#include "tthread.h"
|
||||
#include "ttimer.h"
|
||||
|
||||
#define IS_VALID_PRECISION(precision) \
|
||||
(((precision) >= TSDB_TIME_PRECISION_MILLI) && ((precision) <= TSDB_TIME_PRECISION_NANO))
|
||||
|
|
|
@ -15,30 +15,6 @@
|
|||
|
||||
#include "tsdbDef.h"
|
||||
|
||||
typedef struct STbData {
|
||||
tb_uid_t uid;
|
||||
TSKEY keyMin;
|
||||
TSKEY keyMax;
|
||||
int64_t nrows;
|
||||
SSkipList *pData;
|
||||
} STbData;
|
||||
|
||||
struct STsdbMemTable {
|
||||
T_REF_DECLARE()
|
||||
SRWLatch latch;
|
||||
TSKEY keyMin;
|
||||
TSKEY keyMax;
|
||||
uint64_t nRow;
|
||||
SMemAllocator *pMA;
|
||||
// Container
|
||||
#if 1
|
||||
SSkipList *pSlIdx; // SSkiplist<STbData>
|
||||
SHashObj * pHashIdx;
|
||||
#else
|
||||
TD_SLIST(STbData) list;
|
||||
#endif
|
||||
};
|
||||
|
||||
static int tsdbScanAndConvertSubmitMsg(STsdb *pTsdb, SSubmitMsg *pMsg);
|
||||
static int tsdbMemTableInsertTbData(STsdb *pRepo, SSubmitBlk *pBlock, int32_t *pAffectedRows);
|
||||
static STbData *tsdbNewTbData(tb_uid_t uid);
|
||||
|
@ -46,6 +22,7 @@ static void tsdbFreeTbData(STbData *pTbData);
|
|||
static char * tsdbGetTsTupleKey(const void *data);
|
||||
static int tsdbTbDataComp(const void *arg1, const void *arg2);
|
||||
static char * tsdbTbDataGetUid(const void *arg);
|
||||
static int tsdbAppendTableRowToCols(STable *pTable, SDataCols *pCols, STSchema **ppSchema, SMemRow row);
|
||||
|
||||
STsdbMemTable *tsdbNewMemTable(STsdb *pTsdb) {
|
||||
STsdbMemTable *pMemTable = (STsdbMemTable *)calloc(1, sizeof(*pMemTable));
|
||||
|
@ -127,6 +104,129 @@ int tsdbMemTableInsert(STsdb *pTsdb, STsdbMemTable *pMemTable, SSubmitMsg *pMsg,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is an important function to load data or try to load data from memory skiplist iterator.
|
||||
*
|
||||
* This function load memory data until:
|
||||
* 1. iterator ends
|
||||
* 2. data key exceeds maxKey
|
||||
* 3. rowsIncreased = rowsInserted - rowsDeleteSucceed >= maxRowsToRead
|
||||
* 4. operations in pCols not exceeds its max capacity if pCols is given
|
||||
*
|
||||
* The function tries to procceed AS MUCH AS POSSIBLE.
|
||||
*/
|
||||
int tsdbLoadDataFromCache(STable *pTable, SSkipListIterator *pIter, TSKEY maxKey, int maxRowsToRead, SDataCols *pCols,
|
||||
TKEY *filterKeys, int nFilterKeys, bool keepDup, SMergeInfo *pMergeInfo) {
|
||||
ASSERT(maxRowsToRead > 0 && nFilterKeys >= 0);
|
||||
if (pIter == NULL) return 0;
|
||||
STSchema * pSchema = NULL;
|
||||
TSKEY rowKey = 0;
|
||||
TSKEY fKey = 0;
|
||||
bool isRowDel = false;
|
||||
int filterIter = 0;
|
||||
SMemRow row = NULL;
|
||||
SMergeInfo mInfo;
|
||||
|
||||
if (pMergeInfo == NULL) pMergeInfo = &mInfo;
|
||||
|
||||
memset(pMergeInfo, 0, sizeof(*pMergeInfo));
|
||||
pMergeInfo->keyFirst = INT64_MAX;
|
||||
pMergeInfo->keyLast = INT64_MIN;
|
||||
if (pCols) tdResetDataCols(pCols);
|
||||
|
||||
row = tsdbNextIterRow(pIter);
|
||||
if (row == NULL || memRowKey(row) > maxKey) {
|
||||
rowKey = INT64_MAX;
|
||||
isRowDel = false;
|
||||
} else {
|
||||
rowKey = memRowKey(row);
|
||||
isRowDel = memRowDeleted(row);
|
||||
}
|
||||
|
||||
if (filterIter >= nFilterKeys) {
|
||||
fKey = INT64_MAX;
|
||||
} else {
|
||||
fKey = tdGetKey(filterKeys[filterIter]);
|
||||
}
|
||||
|
||||
while (true) {
|
||||
if (fKey == INT64_MAX && rowKey == INT64_MAX) break;
|
||||
|
||||
if (fKey < rowKey) {
|
||||
pMergeInfo->keyFirst = MIN(pMergeInfo->keyFirst, fKey);
|
||||
pMergeInfo->keyLast = MAX(pMergeInfo->keyLast, fKey);
|
||||
|
||||
filterIter++;
|
||||
if (filterIter >= nFilterKeys) {
|
||||
fKey = INT64_MAX;
|
||||
} else {
|
||||
fKey = tdGetKey(filterKeys[filterIter]);
|
||||
}
|
||||
} else if (fKey > rowKey) {
|
||||
if (isRowDel) {
|
||||
pMergeInfo->rowsDeleteFailed++;
|
||||
} else {
|
||||
if (pMergeInfo->rowsInserted - pMergeInfo->rowsDeleteSucceed >= maxRowsToRead) break;
|
||||
if (pCols && pMergeInfo->nOperations >= pCols->maxPoints) break;
|
||||
pMergeInfo->rowsInserted++;
|
||||
pMergeInfo->nOperations++;
|
||||
pMergeInfo->keyFirst = MIN(pMergeInfo->keyFirst, rowKey);
|
||||
pMergeInfo->keyLast = MAX(pMergeInfo->keyLast, rowKey);
|
||||
tsdbAppendTableRowToCols(pTable, pCols, &pSchema, row);
|
||||
}
|
||||
|
||||
tSkipListIterNext(pIter);
|
||||
row = tsdbNextIterRow(pIter);
|
||||
if (row == NULL || memRowKey(row) > maxKey) {
|
||||
rowKey = INT64_MAX;
|
||||
isRowDel = false;
|
||||
} else {
|
||||
rowKey = memRowKey(row);
|
||||
isRowDel = memRowDeleted(row);
|
||||
}
|
||||
} else {
|
||||
if (isRowDel) {
|
||||
ASSERT(!keepDup);
|
||||
if (pCols && pMergeInfo->nOperations >= pCols->maxPoints) break;
|
||||
pMergeInfo->rowsDeleteSucceed++;
|
||||
pMergeInfo->nOperations++;
|
||||
tsdbAppendTableRowToCols(pTable, pCols, &pSchema, row);
|
||||
} else {
|
||||
if (keepDup) {
|
||||
if (pCols && pMergeInfo->nOperations >= pCols->maxPoints) break;
|
||||
pMergeInfo->rowsUpdated++;
|
||||
pMergeInfo->nOperations++;
|
||||
pMergeInfo->keyFirst = MIN(pMergeInfo->keyFirst, rowKey);
|
||||
pMergeInfo->keyLast = MAX(pMergeInfo->keyLast, rowKey);
|
||||
tsdbAppendTableRowToCols(pTable, pCols, &pSchema, row);
|
||||
} else {
|
||||
pMergeInfo->keyFirst = MIN(pMergeInfo->keyFirst, fKey);
|
||||
pMergeInfo->keyLast = MAX(pMergeInfo->keyLast, fKey);
|
||||
}
|
||||
}
|
||||
|
||||
tSkipListIterNext(pIter);
|
||||
row = tsdbNextIterRow(pIter);
|
||||
if (row == NULL || memRowKey(row) > maxKey) {
|
||||
rowKey = INT64_MAX;
|
||||
isRowDel = false;
|
||||
} else {
|
||||
rowKey = memRowKey(row);
|
||||
isRowDel = memRowDeleted(row);
|
||||
}
|
||||
|
||||
filterIter++;
|
||||
if (filterIter >= nFilterKeys) {
|
||||
fKey = INT64_MAX;
|
||||
} else {
|
||||
fKey = tdGetKey(filterKeys[filterIter]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tsdbScanAndConvertSubmitMsg(STsdb *pTsdb, SSubmitMsg *pMsg) {
|
||||
ASSERT(pMsg != NULL);
|
||||
// STsdbMeta * pMeta = pTsdb->tsdbMeta;
|
||||
|
@ -337,6 +437,21 @@ static char *tsdbTbDataGetUid(const void *arg) {
|
|||
STbData *pTbData = (STbData *)arg;
|
||||
return (char *)(&(pTbData->uid));
|
||||
}
|
||||
static int tsdbAppendTableRowToCols(STable *pTable, SDataCols *pCols, STSchema **ppSchema, SMemRow row) {
|
||||
if (pCols) {
|
||||
if (*ppSchema == NULL || schemaVersion(*ppSchema) != memRowVersion(row)) {
|
||||
*ppSchema = tsdbGetTableSchemaImpl(pTable, false, false, memRowVersion(row));
|
||||
if (*ppSchema == NULL) {
|
||||
ASSERT(false);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
tdAppendMemRowToDataCol(row, *ppSchema, pCols, true);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ------------------------ REFACTORING ------------------------ */
|
||||
#if 0
|
||||
|
@ -674,21 +789,6 @@ int tsdbLoadDataFromCache(STable *pTable, SSkipListIterator *pIter, TSKEY maxKey
|
|||
}
|
||||
|
||||
// ---------------- LOCAL FUNCTIONS ----------------
|
||||
static int tsdbAppendTableRowToCols(STable *pTable, SDataCols *pCols, STSchema **ppSchema, SMemRow row) {
|
||||
if (pCols) {
|
||||
if (*ppSchema == NULL || schemaVersion(*ppSchema) != memRowVersion(row)) {
|
||||
*ppSchema = tsdbGetTableSchemaImpl(pTable, false, false, memRowVersion(row), (int8_t)memRowType(row));
|
||||
if (*ppSchema == NULL) {
|
||||
ASSERT(false);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
tdAppendMemRowToDataCol(row, *ppSchema, pCols, true, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static FORCE_INLINE int tsdbCheckRowRange(STsdbRepo *pRepo, STable *pTable, SMemRow row, TSKEY minKey, TSKEY maxKey,
|
||||
TSKEY now) {
|
||||
|
|
|
@ -15,7 +15,16 @@
|
|||
|
||||
#include "tsdbDef.h"
|
||||
|
||||
const STsdbCfg defautlTsdbOptions = {.lruCacheSize = 0};
|
||||
const STsdbCfg defautlTsdbOptions = {.precision = 0,
|
||||
.lruCacheSize = 0,
|
||||
.daysPerFile = 10,
|
||||
.minRowsPerFileBlock = 100,
|
||||
.maxRowsPerFileBlock = 4096,
|
||||
.keep = 3650,
|
||||
.keep1 = 3650,
|
||||
.keep2 = 3650,
|
||||
.update = 0,
|
||||
.compression = TWO_STAGE_COMP};
|
||||
|
||||
int tsdbOptionsInit(STsdbCfg *pTsdbOptions) {
|
||||
// TODO
|
||||
|
|
|
@ -25,7 +25,6 @@ static int tsdbCheckAndDecodeColumnData(SDataCol *pDataCol, void *content, int3
|
|||
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 STSchema *tsdbGetTableSchemaImpl(STable *pTable, bool lock, bool copy, int32_t version) { return NULL; }
|
||||
|
||||
int tsdbInitReadH(SReadH *pReadh, STsdb *pRepo) {
|
||||
ASSERT(pReadh != NULL && pRepo != NULL);
|
||||
|
@ -667,4 +666,3 @@ static int tsdbLoadColData(SReadH *pReadh, SDFile *pDFile, SBlock *pBlock, SBloc
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -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,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,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;
|
||||
}
|
|
@ -8,10 +8,4 @@ target_include_directories(
|
|||
target_link_libraries(
|
||||
tkv
|
||||
PUBLIC os
|
||||
)
|
||||
if(${BUILD_WITH_ROCKSDB})
|
||||
target_link_libraries(
|
||||
tkv
|
||||
PUBLIC rocksdb
|
||||
)
|
||||
endif(${BUILD_WITH_ROCKSDB})
|
||||
)
|
|
@ -13,18 +13,27 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "tsdbRowMergeBuf.h"
|
||||
#include "tdataformat.h"
|
||||
#ifndef _TD_TDISK_MGR_H_
|
||||
#define _TD_TDISK_MGR_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));
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
if(tsdbMergeBufMakeSureRoom(pBuf, pSchema1, pSchema2) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
return mergeTwoMemRows(*pBuf, row1, row2, pSchema1, pSchema2);
|
||||
#include "os.h"
|
||||
|
||||
#include "tkvDef.h"
|
||||
|
||||
typedef struct SDiskMgr SDiskMgr;
|
||||
|
||||
int tdmOpen(SDiskMgr **ppDiskMgr, const char *fname, uint16_t pgsize);
|
||||
int tdmClose(SDiskMgr *pDiskMgr);
|
||||
int tdmReadPage(SDiskMgr *pDiskMgr, pgid_t pgid, void *pData);
|
||||
int tdmWritePage(SDiskMgr *pDiskMgr, pgid_t pgid, const void *pData);
|
||||
int32_t tdmAllocPage(SDiskMgr *pDiskMgr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*_TD_TDISK_MGR_H_*/
|
|
@ -12,17 +12,30 @@
|
|||
* 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
|
||||
#ifndef _TD_TKV_PAGE_H_
|
||||
#define _TD_TKV_PAGE_H_
|
||||
|
||||
// void *tsdbCompactImpl(STsdb *pRepo);
|
||||
#include "os.h"
|
||||
|
||||
// #ifdef __cplusplus
|
||||
// }
|
||||
// #endif
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// #endif /* _TD_TSDB_COMPACT_H_ */
|
||||
typedef struct {
|
||||
uint16_t dbver;
|
||||
uint16_t pgsize;
|
||||
uint32_t cksm;
|
||||
} SPgHdr;
|
||||
|
||||
typedef struct {
|
||||
SPgHdr chdr;
|
||||
uint16_t used; // number of used slots
|
||||
uint16_t loffset; // the offset of the starting location of the last slot used
|
||||
} SSlottedPgHdr;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*_TD_TKV_PAGE_H_*/
|
|
@ -16,40 +16,15 @@
|
|||
#ifndef _TD_TKV_DEF_H_
|
||||
#define _TD_TKV_DEF_H_
|
||||
|
||||
#ifdef USE_ROCKSDB
|
||||
#include <rocksdb/c.h>
|
||||
#endif
|
||||
#include "os.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
struct STkvDb {
|
||||
#ifdef USE_ROCKSDB
|
||||
rocksdb_t *db;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct STkvOpts {
|
||||
#ifdef USE_ROCKSDB
|
||||
rocksdb_options_t *opts;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct STkvCache {
|
||||
// TODO
|
||||
};
|
||||
|
||||
struct STkvReadOpts {
|
||||
#ifdef USE_ROCKSDB
|
||||
rocksdb_readoptions_t *ropts;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct STkvWriteOpts {
|
||||
#ifdef USE_ROCKSDB
|
||||
rocksdb_writeoptions_t *wopts;
|
||||
#endif
|
||||
};
|
||||
// pgid_t
|
||||
typedef int32_t pgid_t;
|
||||
#define TKV_IVLD_PGID ((pgid_t)-1)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* 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 "tDiskMgr.h"
|
||||
|
||||
struct SDiskMgr {
|
||||
const char *fname;
|
||||
uint16_t pgsize;
|
||||
FileFd fd;
|
||||
int32_t npgid;
|
||||
};
|
||||
|
||||
#define PAGE_OFFSET(PGID, PGSIZE) ((PGID) * (PGSIZE))
|
||||
|
||||
int tdmOpen(SDiskMgr **ppDiskMgr, const char *fname, uint16_t pgsize) {
|
||||
// TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tdmClose(SDiskMgr *pDiskMgr) {
|
||||
// TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tdmReadPage(SDiskMgr *pDiskMgr, pgid_t pgid, void *pData) {
|
||||
taosLSeekFile(pDiskMgr->fd, PAGE_OFFSET(pgid, pDiskMgr->pgsize), SEEK_SET);
|
||||
taosReadFile(pDiskMgr->fd, pData, pDiskMgr->pgsize);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tdmWritePage(SDiskMgr *pDiskMgr, pgid_t pgid, const void *pData) {
|
||||
taosLSeekFile(pDiskMgr->fd, PAGE_OFFSET(pgid, pDiskMgr->pgsize), SEEK_SET);
|
||||
taosWriteFile(pDiskMgr->fd, pData, pDiskMgr->pgsize);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t tdmAllocPage(SDiskMgr *pDiskMgr) { return pDiskMgr->npgid++; }
|
|
@ -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/>.
|
||||
*/
|
||||
|
||||
#include "tkv.h"
|
||||
#include "tkvDef.h"
|
||||
|
||||
static pthread_once_t isInit = PTHREAD_ONCE_INIT;
|
||||
static STkvReadOpts defaultReadOpts;
|
||||
static STkvWriteOpts defaultWriteOpts;
|
||||
|
||||
static void tkvInit();
|
||||
|
||||
STkvDb *tkvOpen(const STkvOpts *options, const char *path) {
|
||||
pthread_once(&isInit, tkvInit);
|
||||
STkvDb *pDb = NULL;
|
||||
|
||||
pDb = (STkvDb *)malloc(sizeof(*pDb));
|
||||
if (pDb == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef USE_ROCKSDB
|
||||
char *err = NULL;
|
||||
|
||||
pDb->db = rocksdb_open(options->opts, path, &err);
|
||||
// TODO: check err
|
||||
#endif
|
||||
|
||||
return pDb;
|
||||
}
|
||||
|
||||
void tkvClose(STkvDb *pDb) {
|
||||
if (pDb) {
|
||||
#ifdef USE_ROCKSDB
|
||||
rocksdb_close(pDb->db);
|
||||
#endif
|
||||
free(pDb);
|
||||
}
|
||||
}
|
||||
|
||||
void tkvPut(STkvDb *pDb, const STkvWriteOpts *pwopts, const char *key, size_t keylen, const char *val, size_t vallen) {
|
||||
#ifdef USE_ROCKSDB
|
||||
char *err = NULL;
|
||||
rocksdb_put(pDb->db, pwopts ? pwopts->wopts : defaultWriteOpts.wopts, key, keylen, val, vallen, &err);
|
||||
// TODO: check error
|
||||
#endif
|
||||
}
|
||||
|
||||
char *tkvGet(STkvDb *pDb, const STkvReadOpts *propts, const char *key, size_t keylen, size_t *vallen) {
|
||||
char *ret = NULL;
|
||||
|
||||
#ifdef USE_ROCKSDB
|
||||
char *err = NULL;
|
||||
ret = rocksdb_get(pDb->db, propts ? propts->ropts : defaultReadOpts.ropts, key, keylen, vallen, &err);
|
||||
// TODD: check error
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
STkvOpts *tkvOptsCreate() {
|
||||
STkvOpts *pOpts = NULL;
|
||||
|
||||
pOpts = (STkvOpts *)malloc(sizeof(*pOpts));
|
||||
if (pOpts == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef USE_ROCKSDB
|
||||
pOpts->opts = rocksdb_options_create();
|
||||
// TODO: check error
|
||||
#endif
|
||||
|
||||
return pOpts;
|
||||
}
|
||||
|
||||
void tkvOptsDestroy(STkvOpts *pOpts) {
|
||||
if (pOpts) {
|
||||
#ifdef USE_ROCKSDB
|
||||
rocksdb_options_destroy(pOpts->opts);
|
||||
#endif
|
||||
free(pOpts);
|
||||
}
|
||||
}
|
||||
|
||||
void tkvOptionsSetCache(STkvOpts *popts, STkvCache *pCache) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void tkvOptsSetCreateIfMissing(STkvOpts *pOpts, unsigned char c) {
|
||||
#ifdef USE_ROCKSDB
|
||||
rocksdb_options_set_create_if_missing(pOpts->opts, c);
|
||||
#endif
|
||||
}
|
||||
|
||||
STkvReadOpts *tkvReadOptsCreate() {
|
||||
STkvReadOpts *pReadOpts = NULL;
|
||||
|
||||
pReadOpts = (STkvReadOpts *)malloc(sizeof(*pReadOpts));
|
||||
if (pReadOpts == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef USE_ROCKSDB
|
||||
pReadOpts->ropts = rocksdb_readoptions_create();
|
||||
#endif
|
||||
|
||||
return pReadOpts;
|
||||
}
|
||||
|
||||
void tkvReadOptsDestroy(STkvReadOpts *pReadOpts) {
|
||||
if (pReadOpts) {
|
||||
#ifdef USE_ROCKSDB
|
||||
rocksdb_readoptions_destroy(pReadOpts->ropts);
|
||||
#endif
|
||||
free(pReadOpts);
|
||||
}
|
||||
}
|
||||
|
||||
STkvWriteOpts *tkvWriteOptsCreate() {
|
||||
STkvWriteOpts *pWriteOpts = NULL;
|
||||
|
||||
pWriteOpts = (STkvWriteOpts *)malloc(sizeof(*pWriteOpts));
|
||||
if (pWriteOpts == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef USE_ROCKSDB
|
||||
pWriteOpts->wopts = rocksdb_writeoptions_create();
|
||||
#endif
|
||||
|
||||
return pWriteOpts;
|
||||
}
|
||||
|
||||
void tkvWriteOptsDestroy(STkvWriteOpts *pWriteOpts) {
|
||||
if (pWriteOpts) {
|
||||
#ifdef USE_ROCKSDB
|
||||
rocksdb_writeoptions_destroy(pWriteOpts->wopts);
|
||||
#endif
|
||||
free(pWriteOpts);
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------ STATIC METHODS ------------------------ */
|
||||
static void tkvInit() {
|
||||
#ifdef USE_ROCKSDB
|
||||
defaultReadOpts.ropts = rocksdb_readoptions_create();
|
||||
defaultWriteOpts.wopts = rocksdb_writeoptions_create();
|
||||
rocksdb_writeoptions_disable_WAL(defaultWriteOpts.wopts, true);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
static void tkvClear() {
|
||||
#ifdef USE_ROCKSDB
|
||||
rocksdb_readoptions_destroy(defaultReadOpts.ropts);
|
||||
rocksdb_writeoptions_destroy(defaultWriteOpts.wopts);
|
||||
#endif
|
||||
}
|
|
@ -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/>.
|
||||
*/
|
|
@ -0,0 +1,10 @@
|
|||
#include "gtest/gtest.h"
|
||||
|
||||
#include "iostream"
|
||||
|
||||
#include "tDiskMgr.h"
|
||||
|
||||
TEST(tDiskMgrTest, simple_test) {
|
||||
// TODO
|
||||
std::cout << "This is in tDiskMgrTest::simple_test" << std::endl;
|
||||
}
|
|
@ -120,7 +120,7 @@ int64_t taosReadFile(FileFd fd, void *buf, int64_t count) {
|
|||
return count;
|
||||
}
|
||||
|
||||
int64_t taosWriteFile(FileFd fd, void *buf, int64_t n) {
|
||||
int64_t taosWriteFile(FileFd fd, const void *buf, int64_t n) {
|
||||
int64_t nleft = n;
|
||||
int64_t nwritten = 0;
|
||||
char * tbuf = (char *)buf;
|
||||
|
|
Loading…
Reference in New Issue