Merge branch '3.0' of https://github.com/taosdata/TDengine into 3.0
This commit is contained in:
commit
610f317e81
|
@ -11,6 +11,7 @@ CMakeSettings.json
|
|||
cmake-build-debug/
|
||||
cmake-build-release/
|
||||
cscope.out
|
||||
cscope.files
|
||||
.DS_Store
|
||||
debug/
|
||||
release/
|
||||
|
|
|
@ -181,17 +181,17 @@ ELSE ()
|
|||
ENDIF()
|
||||
MESSAGE(STATUS "SIMD instructions (FMA/AVX/AVX2) is ACTIVATED")
|
||||
|
||||
IF (COMPILER_SUPPORT_AVX512F AND COMPILER_SUPPORT_AVX512BMI)
|
||||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mavx512f -mavx512vbmi")
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mavx512f -mavx512vbmi")
|
||||
MESSAGE(STATUS "avx512f/avx512bmi supported by compiler")
|
||||
ENDIF()
|
||||
|
||||
IF (COMPILER_SUPPORT_AVX512VL)
|
||||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mavx512vl")
|
||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mavx512vl")
|
||||
MESSAGE(STATUS "avx512vl supported by compiler")
|
||||
ENDIF()
|
||||
# IF (COMPILER_SUPPORT_AVX512F AND COMPILER_SUPPORT_AVX512BMI)
|
||||
# SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mavx512f -mavx512vbmi")
|
||||
# SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mavx512f -mavx512vbmi")
|
||||
# MESSAGE(STATUS "avx512f/avx512bmi supported by compiler")
|
||||
# ENDIF()
|
||||
#
|
||||
# IF (COMPILER_SUPPORT_AVX512VL)
|
||||
# SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mavx512vl")
|
||||
# SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mavx512vl")
|
||||
# MESSAGE(STATUS "avx512vl supported by compiler")
|
||||
# ENDIF()
|
||||
ENDIF()
|
||||
|
||||
# build mode
|
||||
|
|
|
@ -253,6 +253,7 @@ typedef struct SQueryTableDataCond {
|
|||
STimeWindow twindows;
|
||||
int64_t startVersion;
|
||||
int64_t endVersion;
|
||||
bool notLoadData; // response the actual data, not only the rows in the attribute of info.row of ssdatablock
|
||||
} SQueryTableDataCond;
|
||||
|
||||
int32_t tEncodeDataBlock(void** buf, const SSDataBlock* pBlock);
|
||||
|
|
|
@ -26,10 +26,10 @@
|
|||
|
||||
#undef TD_NEW_MSG_SEG
|
||||
#undef TD_DEF_MSG_TYPE
|
||||
#undef TD_CLOSE_MSG_TYPE
|
||||
#undef TD_CLOSE_MSG_SEG
|
||||
#define TD_NEW_MSG_SEG(TYPE) "null",
|
||||
#define TD_DEF_MSG_TYPE(TYPE, MSG, REQ, RSP) MSG, MSG "-rsp",
|
||||
#define TD_CLOSE_MSG_TYPE(TYPE)
|
||||
#define TD_CLOSE_MSG_SEG(TYPE)
|
||||
|
||||
char *tMsgInfo[] = {
|
||||
|
||||
|
@ -37,20 +37,20 @@
|
|||
|
||||
#undef TD_NEW_MSG_SEG
|
||||
#undef TD_DEF_MSG_TYPE
|
||||
#undef TD_CLOSE_MSG_TYPE
|
||||
#undef TD_CLOSE_MSG_SEG
|
||||
#define TD_NEW_MSG_SEG(TYPE)
|
||||
#define TD_DEF_MSG_TYPE(TYPE, MSG, REQ, RSP)
|
||||
#define TD_CLOSE_MSG_TYPE(TYPE) TYPE,
|
||||
#define TD_CLOSE_MSG_SEG(TYPE) TYPE,
|
||||
int32_t tMsgRangeDict[] = {
|
||||
|
||||
#elif defined(TD_MSG_NUMBER_)
|
||||
|
||||
#undef TD_NEW_MSG_SEG
|
||||
#undef TD_DEF_MSG_TYPE
|
||||
#undef TD_CLOSE_MSG_TYPE
|
||||
#undef TD_CLOSE_MSG_SEG
|
||||
#define TD_NEW_MSG_SEG(TYPE) TYPE##_NUM,
|
||||
#define TD_DEF_MSG_TYPE(TYPE, MSG, REQ, RSP) TYPE##_NUM, TYPE##_RSP_NUM,
|
||||
#define TD_CLOSE_MSG_TYPE(TYPE)
|
||||
#define TD_CLOSE_MSG_SEG(TYPE)
|
||||
|
||||
enum {
|
||||
|
||||
|
@ -58,10 +58,10 @@
|
|||
|
||||
#undef TD_NEW_MSG_SEG
|
||||
#undef TD_DEF_MSG_TYPE
|
||||
#undef TD_CLOSE_MSG_TYPE
|
||||
#undef TD_CLOSE_MSG_SEG
|
||||
#define TD_NEW_MSG_SEG(TYPE) TYPE##_NUM,
|
||||
#define TD_DEF_MSG_TYPE(TYPE, MSG, REQ, RSP)
|
||||
#define TD_CLOSE_MSG_TYPE(type)
|
||||
#define TD_CLOSE_MSG_SEG(type)
|
||||
|
||||
int32_t tMsgDict[] = {
|
||||
|
||||
|
@ -70,10 +70,10 @@
|
|||
|
||||
#undef TD_NEW_MSG_SEG
|
||||
#undef TD_DEF_MSG_TYPE
|
||||
#undef TD_CLOSE_MSG_TYPE
|
||||
#undef TD_CLOSE_MSG_SEG
|
||||
#define TD_NEW_MSG_SEG(TYPE) TYPE##_SEG_CODE,
|
||||
#define TD_DEF_MSG_TYPE(TYPE, MSG, REQ, RSP)
|
||||
#define TD_CLOSE_MSG_TYPE(TYPE)
|
||||
#define TD_CLOSE_MSG_SEG(TYPE)
|
||||
|
||||
enum {
|
||||
|
||||
|
@ -82,10 +82,10 @@
|
|||
|
||||
#undef TD_NEW_MSG_SEG
|
||||
#undef TD_DEF_MSG_TYPE
|
||||
#undef TD_CLOSE_MSG_TYPE
|
||||
#undef TD_CLOSE_MSG_SEG
|
||||
#define TD_NEW_MSG_SEG(TYPE) TYPE = ((TYPE##_SEG_CODE) << 8),
|
||||
#define TD_DEF_MSG_TYPE(TYPE, MSG, REQ, RSP) TYPE, TYPE##_RSP,
|
||||
#define TD_CLOSE_MSG_TYPE(TYPE) TYPE,
|
||||
#define TD_CLOSE_MSG_SEG(TYPE) TYPE,
|
||||
|
||||
enum { // WARN: new msg should be appended to segment tail
|
||||
#endif
|
||||
|
@ -109,7 +109,7 @@
|
|||
TD_DEF_MSG_TYPE(TDMT_DND_ALTER_VNODE_TYPE, "dnode-alter-vnode-type", NULL, NULL)
|
||||
TD_DEF_MSG_TYPE(TDMT_DND_CHECK_VNODE_LEARNER_CATCHUP, "dnode-check-vnode-learner-catchup", NULL, NULL)
|
||||
TD_DEF_MSG_TYPE(TDMT_DND_MAX_MSG, "dnd-max", NULL, NULL)
|
||||
TD_CLOSE_MSG_TYPE(TDMT_END_DND_MSG)
|
||||
TD_CLOSE_MSG_SEG(TDMT_END_DND_MSG)
|
||||
|
||||
TD_NEW_MSG_SEG(TDMT_MND_MSG) // 1<<8
|
||||
TD_DEF_MSG_TYPE(TDMT_MND_CONNECT, "connect", NULL, NULL)
|
||||
|
@ -218,7 +218,7 @@
|
|||
TD_DEF_MSG_TYPE(TDMT_MND_DROP_VIEW, "drop-view", SCMDropViewReq, NULL)
|
||||
TD_DEF_MSG_TYPE(TDMT_MND_VIEW_META, "view-meta", NULL, NULL)
|
||||
TD_DEF_MSG_TYPE(TDMT_MND_MAX_MSG, "mnd-max", NULL, NULL)
|
||||
TD_CLOSE_MSG_TYPE(TDMT_END_MND_MSG)
|
||||
TD_CLOSE_MSG_SEG(TDMT_END_MND_MSG)
|
||||
|
||||
TD_NEW_MSG_SEG(TDMT_VND_MSG) // 2<<8
|
||||
TD_DEF_MSG_TYPE(TDMT_VND_SUBMIT, "submit", SSubmitReq, SSubmitRsp)
|
||||
|
@ -268,7 +268,7 @@ TD_DEF_MSG_TYPE(TDMT_VND_ALTER_CONFIG, "alter-config", NULL, NULL)
|
|||
TD_DEF_MSG_TYPE(TDMT_VND_DROP_INDEX, "vnode-drop-index", NULL, NULL)
|
||||
TD_DEF_MSG_TYPE(TDMT_VND_DISABLE_WRITE, "vnode-disable-write", NULL, NULL)
|
||||
TD_DEF_MSG_TYPE(TDMT_VND_MAX_MSG, "vnd-max", NULL, NULL)
|
||||
TD_CLOSE_MSG_TYPE(TDMT_END_VND_MSG)
|
||||
TD_CLOSE_MSG_SEG(TDMT_END_VND_MSG)
|
||||
|
||||
TD_NEW_MSG_SEG(TDMT_SCH_MSG) // 3<<8
|
||||
TD_DEF_MSG_TYPE(TDMT_SCH_QUERY, "query", NULL, NULL)
|
||||
|
@ -283,7 +283,7 @@ TD_DEF_MSG_TYPE(TDMT_VND_ALTER_CONFIG, "alter-config", NULL, NULL)
|
|||
TD_DEF_MSG_TYPE(TDMT_SCH_LINK_BROKEN, "link-broken", NULL, NULL)
|
||||
TD_DEF_MSG_TYPE(TDMT_SCH_TASK_NOTIFY, "task-notify", NULL, NULL)
|
||||
TD_DEF_MSG_TYPE(TDMT_SCH_MAX_MSG, "sch-max", NULL, NULL)
|
||||
TD_CLOSE_MSG_TYPE(TDMT_END_SCH_MSG)
|
||||
TD_CLOSE_MSG_SEG(TDMT_END_SCH_MSG)
|
||||
|
||||
|
||||
TD_NEW_MSG_SEG(TDMT_STREAM_MSG) //4 << 8
|
||||
|
@ -301,11 +301,11 @@ TD_DEF_MSG_TYPE(TDMT_VND_ALTER_CONFIG, "alter-config", NULL, NULL)
|
|||
TD_DEF_MSG_TYPE(TDMT_STREAM_TASK_STOP, "stream-task-stop", NULL, NULL)
|
||||
TD_DEF_MSG_TYPE(TDMT_STREAM_HTASK_DROP, "stream-htask-drop", NULL, NULL)
|
||||
TD_DEF_MSG_TYPE(TDMT_STREAM_MAX_MSG, "stream-max", NULL, NULL)
|
||||
TD_CLOSE_MSG_TYPE(TDMT_END_STREAM_MSG)
|
||||
TD_CLOSE_MSG_SEG(TDMT_END_STREAM_MSG)
|
||||
|
||||
TD_NEW_MSG_SEG(TDMT_MON_MSG) //5 << 8
|
||||
TD_DEF_MSG_TYPE(TDMT_MON_MAX_MSG, "monitor-max", NULL, NULL)
|
||||
TD_CLOSE_MSG_TYPE(TDMT_END_MON_MSG)
|
||||
TD_CLOSE_MSG_SEG(TDMT_END_MON_MSG)
|
||||
|
||||
TD_NEW_MSG_SEG(TDMT_SYNC_MSG) //6 << 8
|
||||
TD_DEF_MSG_TYPE(TDMT_SYNC_TIMEOUT, "sync-timer", NULL, NULL)
|
||||
|
@ -337,7 +337,7 @@ TD_DEF_MSG_TYPE(TDMT_VND_ALTER_CONFIG, "alter-config", NULL, NULL)
|
|||
TD_DEF_MSG_TYPE(TDMT_SYNC_PREP_SNAPSHOT_REPLY, "sync-prep-snapshot-reply", NULL, NULL)
|
||||
TD_DEF_MSG_TYPE(TDMT_SYNC_MAX_MSG, "sync-max", NULL, NULL)
|
||||
TD_DEF_MSG_TYPE(TDMT_SYNC_FORCE_FOLLOWER, "sync-force-become-follower", NULL, NULL)
|
||||
TD_CLOSE_MSG_TYPE(TDMT_END_SYNC_MSG)
|
||||
TD_CLOSE_MSG_SEG(TDMT_END_SYNC_MSG)
|
||||
|
||||
|
||||
TD_NEW_MSG_SEG(TDMT_VND_STREAM_MSG) //7 << 8
|
||||
|
@ -348,7 +348,7 @@ TD_DEF_MSG_TYPE(TDMT_VND_ALTER_CONFIG, "alter-config", NULL, NULL)
|
|||
TD_DEF_MSG_TYPE(TDMT_VND_STREAM_TASK_RESET, "vnode-stream-reset", NULL, NULL)
|
||||
TD_DEF_MSG_TYPE(TDMT_VND_STREAM_TASK_CHECK, "vnode-stream-task-check", NULL, NULL)
|
||||
TD_DEF_MSG_TYPE(TDMT_VND_STREAM_MAX_MSG, "vnd-stream-max", NULL, NULL)
|
||||
TD_CLOSE_MSG_TYPE(TDMT_END_VND_STREAM_MSG)
|
||||
TD_CLOSE_MSG_SEG(TDMT_END_VND_STREAM_MSG)
|
||||
|
||||
TD_NEW_MSG_SEG(TDMT_VND_TMQ_MSG) //8 << 8
|
||||
TD_DEF_MSG_TYPE(TDMT_VND_TMQ_SUBSCRIBE, "vnode-tmq-subscribe", SMqRebVgReq, SMqRebVgRsp)
|
||||
|
@ -362,10 +362,10 @@ TD_DEF_MSG_TYPE(TDMT_VND_ALTER_CONFIG, "alter-config", NULL, NULL)
|
|||
TD_DEF_MSG_TYPE(TDMT_VND_TMQ_VG_WALINFO, "vnode-tmq-vg-walinfo", SMqPollReq, SMqDataBlkRsp)
|
||||
TD_DEF_MSG_TYPE(TDMT_VND_TMQ_VG_COMMITTEDINFO, "vnode-tmq-committedinfo", NULL, NULL)
|
||||
TD_DEF_MSG_TYPE(TDMT_VND_TMQ_MAX_MSG, "vnd-tmq-max", NULL, NULL)
|
||||
TD_CLOSE_MSG_TYPE(TDMT_END_TMQ_MSG)
|
||||
TD_CLOSE_MSG_SEG(TDMT_END_TMQ_MSG)
|
||||
|
||||
TD_NEW_MSG_SEG(TDMT_MAX_MSG) // msg end mark
|
||||
|
||||
TD_CLOSE_MSG_SEG(TDMT_END_MAX_MSG)
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -275,9 +275,11 @@ typedef struct {
|
|||
#define IS_VALID_TINYINT(_t) ((_t) >= INT8_MIN && (_t) <= INT8_MAX)
|
||||
#define IS_VALID_SMALLINT(_t) ((_t) >= INT16_MIN && (_t) <= INT16_MAX)
|
||||
#define IS_VALID_INT(_t) ((_t) >= INT32_MIN && (_t) <= INT32_MAX)
|
||||
#define IS_VALID_INT64(_t) ((_t) >= INT64_MIN && (_t) <= INT64_MAX)
|
||||
#define IS_VALID_UTINYINT(_t) ((_t) >= 0 && (_t) <= UINT8_MAX)
|
||||
#define IS_VALID_USMALLINT(_t) ((_t) >= 0 && (_t) <= UINT16_MAX)
|
||||
#define IS_VALID_UINT(_t) ((_t) >= 0 && (_t) <= UINT32_MAX)
|
||||
#define IS_VALID_UINT64(_t) ((_t) >= 0 && (_t) <= UINT64_MAX)
|
||||
#define IS_VALID_FLOAT(_t) ((_t) >= -FLT_MAX && (_t) <= FLT_MAX)
|
||||
#define IS_VALID_DOUBLE(_t) ((_t) >= -DBL_MAX && (_t) <= DBL_MAX)
|
||||
|
||||
|
|
|
@ -37,6 +37,10 @@ typedef struct SVariant {
|
|||
};
|
||||
} SVariant;
|
||||
|
||||
int32_t toIntegerEx(const char *z, int32_t n, uint32_t type, int64_t *value);
|
||||
int32_t toUIntegerEx(const char *z, int32_t n, uint32_t type, uint64_t *value);
|
||||
int32_t toDoubleEx(const char *z, int32_t n, uint32_t type, double *value);
|
||||
|
||||
int32_t toInteger(const char *z, int32_t n, int32_t base, int64_t *value);
|
||||
int32_t toUInteger(const char *z, int32_t n, int32_t base, uint64_t *value);
|
||||
|
||||
|
|
|
@ -152,10 +152,21 @@ typedef struct {
|
|||
|
||||
// clang-format off
|
||||
/*-------------------------------------------------new api format---------------------------------------------------*/
|
||||
typedef enum {
|
||||
TSD_READER_NOTIFY_DURATION_START
|
||||
} ETsdReaderNotifyType;
|
||||
|
||||
typedef union {
|
||||
struct {
|
||||
int32_t filesetId;
|
||||
} duration;
|
||||
} STsdReaderNotifyInfo;
|
||||
|
||||
typedef void (*TsdReaderNotifyCbFn)(ETsdReaderNotifyType type, STsdReaderNotifyInfo* info, void* param);
|
||||
|
||||
typedef struct TsdReader {
|
||||
int32_t (*tsdReaderOpen)(void* pVnode, SQueryTableDataCond* pCond, void* pTableList, int32_t numOfTables,
|
||||
SSDataBlock* pResBlock, void** ppReader, const char* idstr, bool countOnly,
|
||||
SHashObj** pIgnoreTables);
|
||||
SSDataBlock* pResBlock, void** ppReader, const char* idstr, SHashObj** pIgnoreTables);
|
||||
void (*tsdReaderClose)();
|
||||
void (*tsdSetReaderTaskId)(void *pReader, const char *pId);
|
||||
int32_t (*tsdSetQueryTableList)();
|
||||
|
@ -170,6 +181,9 @@ typedef struct TsdReader {
|
|||
int32_t (*tsdReaderGetDataBlockDistInfo)();
|
||||
int64_t (*tsdReaderGetNumOfInMemRows)();
|
||||
void (*tsdReaderNotifyClosing)();
|
||||
|
||||
void (*tsdSetFilesetDelimited)(void* pReader);
|
||||
void (*tsdSetSetNotifyCb)(void* pReader, TsdReaderNotifyCbFn notifyFn, void* param);
|
||||
} TsdReader;
|
||||
|
||||
typedef struct SStoreCacheReader {
|
||||
|
|
|
@ -118,6 +118,7 @@ typedef struct SScanLogicNode {
|
|||
bool igLastNull;
|
||||
bool groupOrderScan;
|
||||
bool onlyMetaCtbIdx; // for tag scan with no tbname
|
||||
bool filesetDelimited; // returned blocks delimited by fileset
|
||||
} SScanLogicNode;
|
||||
|
||||
typedef struct SJoinLogicNode {
|
||||
|
@ -432,6 +433,7 @@ typedef struct STableScanPhysiNode {
|
|||
int8_t igExpired;
|
||||
bool assignBlockUid;
|
||||
int8_t igCheckUpdate;
|
||||
bool filesetDelimited;
|
||||
} STableScanPhysiNode;
|
||||
|
||||
typedef STableScanPhysiNode STableSeqScanPhysiNode;
|
||||
|
|
|
@ -289,6 +289,9 @@ const char* syncStr(ESyncState state);
|
|||
|
||||
int32_t syncNodeGetConfig(int64_t rid, SSyncCfg *cfg);
|
||||
|
||||
// util
|
||||
int32_t syncSnapInfoDataRealloc(SSnapshot* pSnap, int32_t size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -288,6 +288,7 @@ typedef enum ELogicConditionType {
|
|||
#define TSDB_CONN_ACTIVE_KEY_LEN 255
|
||||
|
||||
#define TSDB_DEFAULT_PKT_SIZE 65480 // same as RPC_MAX_UDP_SIZE
|
||||
#define TSDB_SNAP_DATA_PAYLOAD_SIZE (1 * 1024 * 1024)
|
||||
|
||||
#define TSDB_PAYLOAD_SIZE TSDB_DEFAULT_PKT_SIZE
|
||||
#define TSDB_DEFAULT_PAYLOAD_SIZE 5120 // default payload size, greater than PATH_MAX value
|
||||
|
|
|
@ -19,6 +19,278 @@
|
|||
#include "ttokendef.h"
|
||||
#include "tvariant.h"
|
||||
|
||||
int32_t parseBinaryUInteger(const char *z, int32_t n, uint64_t *value) {
|
||||
// skip head 0b
|
||||
const char *p = z + 2;
|
||||
int32_t l = n - 2;
|
||||
|
||||
while (*p == '0' && l > 0) {
|
||||
p++;
|
||||
l--;
|
||||
}
|
||||
if (l > 64) { // too big
|
||||
return TSDB_CODE_FAILED;
|
||||
}
|
||||
|
||||
uint64_t val = 0;
|
||||
for (int32_t i = 0; i < l; i++) {
|
||||
val = val << 1;
|
||||
if (p[i] == '1') {
|
||||
val |= 1;
|
||||
} else if (p[i] != '0') { // abnormal char
|
||||
return TSDB_CODE_FAILED;
|
||||
}
|
||||
}
|
||||
*value = val;
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t parseSignAndUInteger(const char *z, int32_t n, bool *is_neg, uint64_t *value) {
|
||||
// parse sign
|
||||
bool has_sign = false;
|
||||
if (z[0] == '-') {
|
||||
*is_neg = true;
|
||||
has_sign = true;
|
||||
} else if (z[0] == '+') {
|
||||
has_sign = true;
|
||||
} else if (z[0] != '.' && (z[0] < '0' || z[0] > '9')) {
|
||||
return TSDB_CODE_FAILED;
|
||||
}
|
||||
if (has_sign) {
|
||||
if (n < 2) {
|
||||
return TSDB_CODE_FAILED;
|
||||
}
|
||||
z++;
|
||||
n--;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
char *endPtr = NULL;
|
||||
bool parsed = false;
|
||||
if (z[0] == '0' && n > 2) {
|
||||
if (z[1] == 'b' || z[1] == 'B') {
|
||||
// paring as binary
|
||||
return parseBinaryUInteger(z, n, value);
|
||||
}
|
||||
|
||||
if (z[1] == 'x' || z[1] == 'X') {
|
||||
// parsing as hex
|
||||
*value = taosStr2UInt64(z, &endPtr, 16);
|
||||
parsed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!parsed) {
|
||||
// parsing as double
|
||||
double val = taosStr2Double(z, &endPtr);
|
||||
if (val > UINT64_MAX) {
|
||||
return TSDB_CODE_FAILED;
|
||||
}
|
||||
*value = round(val);
|
||||
}
|
||||
|
||||
if (errno == ERANGE || errno == EINVAL || endPtr - z != n) {
|
||||
return TSDB_CODE_FAILED;
|
||||
}
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
int32_t toDoubleEx(const char *z, int32_t n, uint32_t type, double* value) {
|
||||
if (n == 0) {
|
||||
*value = 0;
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
char* endPtr = NULL;
|
||||
*value = taosStr2Double(z, &endPtr);
|
||||
|
||||
if (errno == ERANGE || errno == EINVAL) {
|
||||
return TSDB_CODE_FAILED;
|
||||
}
|
||||
|
||||
if (endPtr - z != n) {
|
||||
return TSDB_CODE_FAILED;
|
||||
}
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t toIntegerEx(const char *z, int32_t n, uint32_t type, int64_t *value) {
|
||||
errno = 0;
|
||||
char *endPtr = NULL;
|
||||
switch (type)
|
||||
{
|
||||
case TK_NK_INTEGER: {
|
||||
*value = taosStr2Int64(z, &endPtr, 10);
|
||||
if (errno == ERANGE || errno == EINVAL || endPtr - z != n) {
|
||||
return TSDB_CODE_FAILED;
|
||||
}
|
||||
return TSDB_CODE_SUCCESS;
|
||||
} break;
|
||||
case TK_NK_FLOAT: {
|
||||
double val = round(taosStr2Double(z, &endPtr));
|
||||
if (!IS_VALID_INT64(val)) {
|
||||
return TSDB_CODE_FAILED;
|
||||
}
|
||||
if (errno == ERANGE || errno == EINVAL || endPtr - z != n) {
|
||||
return TSDB_CODE_FAILED;
|
||||
}
|
||||
*value = val;
|
||||
return TSDB_CODE_SUCCESS;
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (n == 0) {
|
||||
*value = 0;
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
// 1. try to parse as integer
|
||||
*value = taosStr2Int64(z, &endPtr, 10);
|
||||
if (endPtr - z == n) {
|
||||
if (errno == ERANGE || errno == EINVAL) {
|
||||
return TSDB_CODE_FAILED;
|
||||
}
|
||||
return TSDB_CODE_SUCCESS;
|
||||
} else if (errno == 0 && *endPtr == '.') {
|
||||
// pure decimal part
|
||||
const char *s = endPtr + 1;
|
||||
const char *end = z + n;
|
||||
bool pure = true;
|
||||
while (s < end) {
|
||||
if (*s < '0' || *s > '9') {
|
||||
pure = false;
|
||||
break;
|
||||
}
|
||||
s++;
|
||||
}
|
||||
if (pure) {
|
||||
if (endPtr+1 < end && endPtr[1] > '4') {
|
||||
const char *p = z;
|
||||
while (*p == ' ') {
|
||||
p++;
|
||||
}
|
||||
if (*p == '-') {
|
||||
if ( *value > INT64_MIN) {
|
||||
(*value)--;
|
||||
}
|
||||
} else {
|
||||
if ( *value < INT64_MAX) {
|
||||
(*value)++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. parse as other
|
||||
bool is_neg = false;
|
||||
uint64_t uv = 0;
|
||||
int32_t code = parseSignAndUInteger(z, n, &is_neg, &uv);
|
||||
if (code == TSDB_CODE_SUCCESS) {
|
||||
// truncate into int64
|
||||
if (is_neg) {
|
||||
if (uv > 1ull + INT64_MAX) {
|
||||
*value = INT64_MIN;
|
||||
return TSDB_CODE_FAILED;
|
||||
} else {
|
||||
*value = -uv;
|
||||
}
|
||||
} else {
|
||||
if (uv > INT64_MAX) {
|
||||
*value = INT64_MAX;
|
||||
return TSDB_CODE_FAILED;
|
||||
}
|
||||
*value = uv;
|
||||
}
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
int32_t toUIntegerEx(const char *z, int32_t n, uint32_t type, uint64_t *value) {
|
||||
errno = 0;
|
||||
char *endPtr = NULL;
|
||||
const char *p = z;
|
||||
while (*p == ' ') {
|
||||
p++;
|
||||
}
|
||||
switch (type) {
|
||||
case TK_NK_INTEGER: {
|
||||
*value = taosStr2UInt64(p, &endPtr, 10);
|
||||
if (*p == '-' && *value) {
|
||||
return TSDB_CODE_FAILED;
|
||||
}
|
||||
if (errno == ERANGE || errno == EINVAL || endPtr - z != n) {
|
||||
return TSDB_CODE_FAILED;
|
||||
}
|
||||
return TSDB_CODE_SUCCESS;
|
||||
} break;
|
||||
case TK_NK_FLOAT: {
|
||||
double val = round(taosStr2Double(p, &endPtr));
|
||||
if (!IS_VALID_UINT64(val)) {
|
||||
return TSDB_CODE_FAILED;
|
||||
}
|
||||
if (errno == ERANGE || errno == EINVAL || endPtr - z != n) {
|
||||
return TSDB_CODE_FAILED;
|
||||
}
|
||||
*value = val;
|
||||
return TSDB_CODE_SUCCESS;
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (n == 0) {
|
||||
*value = 0;
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
// 1. parse as integer
|
||||
*value = taosStr2UInt64(p, &endPtr, 10);
|
||||
if (*p == '-' && *value) {
|
||||
return TSDB_CODE_FAILED;
|
||||
}
|
||||
if (endPtr - z == n) {
|
||||
if (errno == ERANGE || errno == EINVAL) {
|
||||
return TSDB_CODE_FAILED;
|
||||
}
|
||||
return TSDB_CODE_SUCCESS;
|
||||
} else if (errno == 0 && *endPtr == '.') {
|
||||
const char *s = endPtr + 1;
|
||||
const char *end = z + n;
|
||||
bool pure = true;
|
||||
while (s < end) {
|
||||
if (*s < '0' || *s > '9') {
|
||||
pure = false;
|
||||
break;
|
||||
}
|
||||
s++;
|
||||
}
|
||||
if (pure) {
|
||||
if (endPtr + 1 < end && endPtr[1] > '4' && *value < UINT64_MAX) {
|
||||
(*value)++;
|
||||
}
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. parse as other
|
||||
bool is_neg = false;
|
||||
int32_t code = parseSignAndUInteger(z, n, &is_neg, value);
|
||||
if (is_neg) {
|
||||
if (TSDB_CODE_SUCCESS == code && 0 == *value) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
return TSDB_CODE_FAILED;
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
int32_t toInteger(const char *z, int32_t n, int32_t base, int64_t *value) {
|
||||
errno = 0;
|
||||
char *endPtr = NULL;
|
||||
|
@ -26,10 +298,10 @@ int32_t toInteger(const char *z, int32_t n, int32_t base, int64_t *value) {
|
|||
*value = taosStr2Int64(z, &endPtr, base);
|
||||
if (errno == ERANGE || errno == EINVAL || endPtr - z != n) {
|
||||
errno = 0;
|
||||
return -1;
|
||||
return TSDB_CODE_FAILED;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t toUInteger(const char *z, int32_t n, int32_t base, uint64_t *value) {
|
||||
|
@ -39,16 +311,15 @@ int32_t toUInteger(const char *z, int32_t n, int32_t base, uint64_t *value) {
|
|||
const char *p = z;
|
||||
while (*p == ' ') p++;
|
||||
if (*p == '-') {
|
||||
return -1;
|
||||
return TSDB_CODE_FAILED;
|
||||
}
|
||||
|
||||
*value = taosStr2UInt64(z, &endPtr, base);
|
||||
if (errno == ERANGE || errno == EINVAL || endPtr - z != n) {
|
||||
errno = 0;
|
||||
return -1;
|
||||
return TSDB_CODE_FAILED;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -147,14 +418,13 @@ void taosVariantDestroy(SVariant *pVar) {
|
|||
taosMemoryFreeClear(pVar->pz);
|
||||
pVar->nLen = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void taosVariantAssign(SVariant *pDst, const SVariant *pSrc) {
|
||||
if (pSrc == NULL || pDst == NULL) return;
|
||||
|
||||
pDst->nType = pSrc->nType;
|
||||
if (pSrc->nType == TSDB_DATA_TYPE_BINARY ||pSrc->nType == TSDB_DATA_TYPE_VARBINARY ||
|
||||
if (pSrc->nType == TSDB_DATA_TYPE_BINARY || pSrc->nType == TSDB_DATA_TYPE_VARBINARY ||
|
||||
pSrc->nType == TSDB_DATA_TYPE_NCHAR || pSrc->nType == TSDB_DATA_TYPE_JSON ||
|
||||
pSrc->nType == TSDB_DATA_TYPE_GEOMETRY) {
|
||||
int32_t len = pSrc->nLen + TSDB_NCHAR_SIZE;
|
||||
|
@ -172,7 +442,6 @@ void taosVariantAssign(SVariant *pDst, const SVariant *pSrc) {
|
|||
if (IS_NUMERIC_TYPE(pSrc->nType) || (pSrc->nType == TSDB_DATA_TYPE_BOOL)) {
|
||||
pDst->i = pSrc->i;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int32_t taosVariantCompare(const SVariant *p1, const SVariant *p2) {
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "tdef.h"
|
||||
#include "tvariant.h"
|
||||
#include "ttime.h"
|
||||
#include "ttokendef.h"
|
||||
|
||||
namespace {
|
||||
//
|
||||
|
@ -24,40 +25,177 @@ int main(int argc, char** argv) {
|
|||
return RUN_ALL_TESTS();
|
||||
}
|
||||
|
||||
TEST(testCase, toInteger_test) {
|
||||
|
||||
TEST(testCase, toUIntegerEx_test) {
|
||||
uint64_t val = 0;
|
||||
|
||||
char* s = "123";
|
||||
uint32_t type = 0;
|
||||
|
||||
int64_t val = 0;
|
||||
|
||||
int32_t ret = toInteger(s, strlen(s), 10, &val);
|
||||
int32_t ret = toUIntegerEx(s, strlen(s), TK_NK_INTEGER, &val);
|
||||
ASSERT_EQ(ret, 0);
|
||||
ASSERT_EQ(val, 123);
|
||||
|
||||
s = "1000u";
|
||||
ret = toUIntegerEx(s, strlen(s), 0, &val);
|
||||
ASSERT_EQ(ret, -1);
|
||||
|
||||
s = "0x1f";
|
||||
ret = toUIntegerEx(s, strlen(s), TK_NK_HEX, &val);
|
||||
ASSERT_EQ(ret, 0);
|
||||
ASSERT_EQ(val, 31);
|
||||
|
||||
s = "0b110";
|
||||
ret = toUIntegerEx(s, strlen(s), 0, &val);
|
||||
ASSERT_EQ(ret, 0);
|
||||
ASSERT_EQ(val, 6);
|
||||
|
||||
s = "2567.4787";
|
||||
ret = toUIntegerEx(s, strlen(s), TK_NK_FLOAT, &val);
|
||||
ASSERT_EQ(ret, 0);
|
||||
ASSERT_EQ(val, 2567);
|
||||
|
||||
s = "1.869895343e4";
|
||||
ret = toUIntegerEx(s, strlen(s), TK_NK_FLOAT, &val);
|
||||
ASSERT_EQ(ret, 0);
|
||||
ASSERT_EQ(val, 18699);
|
||||
|
||||
s = "-1";
|
||||
ret = toUIntegerEx(s, strlen(s),TK_NK_INTEGER, &val);
|
||||
ASSERT_EQ(ret, -1);
|
||||
|
||||
s = "-0b10010";
|
||||
ret = toUIntegerEx(s, strlen(s), 0, &val);
|
||||
ASSERT_EQ(ret, -1);
|
||||
|
||||
s = "-0x40";
|
||||
ret = toUIntegerEx(s, strlen(s), TK_NK_HEX, &val);
|
||||
ASSERT_EQ(ret, -1);
|
||||
|
||||
s = "-80.9999";
|
||||
ret = toUIntegerEx(s, strlen(s), TK_NK_FLOAT, &val);
|
||||
ASSERT_EQ(ret, -1);
|
||||
|
||||
s = "-5.2343544534e10";
|
||||
ret = toUIntegerEx(s, strlen(s), TK_NK_FLOAT, &val);
|
||||
ASSERT_EQ(ret, -1);
|
||||
|
||||
// INT64_MAX
|
||||
s = "9223372036854775807";
|
||||
ret = toInteger(s, strlen(s), 10, &val);
|
||||
ret = toUIntegerEx(s, strlen(s), TK_NK_INTEGER, &val);
|
||||
ASSERT_EQ(ret, 0);
|
||||
ASSERT_EQ(val, 9223372036854775807);
|
||||
|
||||
s = "9323372036854775807";
|
||||
ret = toInteger(s, strlen(s), 10, &val);
|
||||
// UINT64_MAX
|
||||
s = "18446744073709551615";
|
||||
ret = toUIntegerEx(s, strlen(s), TK_NK_INTEGER, &val);
|
||||
ASSERT_EQ(ret, 0);
|
||||
ASSERT_EQ(val, 9323372036854775807u);
|
||||
ASSERT_EQ(val, 18446744073709551615u);
|
||||
|
||||
// out of range
|
||||
s = "18446744073709551616";
|
||||
ret = toUIntegerEx(s, strlen(s), TK_NK_INTEGER, &val);
|
||||
ASSERT_EQ(ret, -1);
|
||||
|
||||
s = "5.23e25";
|
||||
ret = toUIntegerEx(s, strlen(s), TK_NK_FLOAT, &val);
|
||||
ASSERT_EQ(ret, -1);
|
||||
}
|
||||
|
||||
TEST(testCase, toIntegerEx_test) {
|
||||
int64_t val = 0;
|
||||
|
||||
char* s = "123";
|
||||
int32_t ret = toIntegerEx(s, strlen(s), TK_NK_INTEGER, &val);
|
||||
ASSERT_EQ(ret, 0);
|
||||
ASSERT_EQ(val, 123);
|
||||
|
||||
s = "-1";
|
||||
ret = toIntegerEx(s, strlen(s), TK_NK_INTEGER, &val);
|
||||
ASSERT_EQ(ret, 0);
|
||||
ASSERT_EQ(val, -1);
|
||||
|
||||
s = "1000u";
|
||||
ret = toIntegerEx(s, strlen(s), TK_NK_INTEGER, &val);
|
||||
ASSERT_EQ(ret, -1);
|
||||
|
||||
s = "0x1f";
|
||||
ret = toIntegerEx(s, strlen(s), TK_NK_HEX, &val);
|
||||
ASSERT_EQ(ret, 0);
|
||||
ASSERT_EQ(val, 31);
|
||||
|
||||
s = "-0x40";
|
||||
ret = toIntegerEx(s, strlen(s), TK_NK_HEX, &val);
|
||||
ASSERT_EQ(ret, 0);
|
||||
ASSERT_EQ(val, -64);
|
||||
|
||||
s = "0b110";
|
||||
ret = toIntegerEx(s, strlen(s), TK_NK_BIN, &val);
|
||||
ASSERT_EQ(ret, 0);
|
||||
ASSERT_EQ(val, 6);
|
||||
|
||||
s = "-0b10010";
|
||||
ret = toIntegerEx(s, strlen(s), 0, &val);
|
||||
ASSERT_EQ(ret, 0);
|
||||
ASSERT_EQ(val, -18);
|
||||
|
||||
s = "-80.9999";
|
||||
ret = toIntegerEx(s, strlen(s), TK_NK_FLOAT, &val);
|
||||
ASSERT_EQ(ret, 0);
|
||||
ASSERT_EQ(val, -81);
|
||||
|
||||
s = "2567.8787";
|
||||
ret = toIntegerEx(s, strlen(s), TK_NK_FLOAT, &val);
|
||||
ASSERT_EQ(ret, 0);
|
||||
ASSERT_EQ(val, 2568);
|
||||
|
||||
s = "-5.2343544534e10";
|
||||
ret = toIntegerEx(s, strlen(s), TK_NK_FLOAT, &val);
|
||||
ASSERT_EQ(ret, 0);
|
||||
ASSERT_EQ(val, -52343544534);
|
||||
|
||||
s = "1.869895343e4";
|
||||
ret = toIntegerEx(s, strlen(s), TK_NK_FLOAT, &val);
|
||||
ASSERT_EQ(ret, 0);
|
||||
ASSERT_EQ(val, 18699);
|
||||
|
||||
// INT64_MAX
|
||||
s = "9223372036854775807";
|
||||
ret = toIntegerEx(s, strlen(s), TK_NK_INTEGER, &val);
|
||||
ASSERT_EQ(ret, 0);
|
||||
ASSERT_EQ(val, 9223372036854775807LL);
|
||||
|
||||
s = "-9223372036854775808";
|
||||
ret = toIntegerEx(s, strlen(s), TK_NK_INTEGER, &val);
|
||||
ASSERT_EQ(ret, 0);
|
||||
ASSERT_EQ(val, -9223372036854775808);
|
||||
|
||||
// out of range
|
||||
s = "9323372036854775807";
|
||||
ret = toIntegerEx(s, strlen(s), TK_NK_INTEGER, &val);
|
||||
ASSERT_EQ(ret, -1);
|
||||
|
||||
s = "-9323372036854775807";
|
||||
ret = toInteger(s, strlen(s), 10, &val);
|
||||
ret = toIntegerEx(s, strlen(s), TK_NK_INTEGER, &val);
|
||||
ASSERT_EQ(ret, -1);
|
||||
|
||||
// UINT64_MAX
|
||||
s = "18446744073709551615";
|
||||
ret = toIntegerEx(s, strlen(s), TK_NK_INTEGER, &val);
|
||||
ASSERT_EQ(ret, -1);
|
||||
}
|
||||
|
||||
TEST(testCase, toInteger_test) {
|
||||
int64_t val = 0;
|
||||
|
||||
char* s = "123";
|
||||
int32_t ret = toInteger(s, strlen(s), 10, &val);
|
||||
ASSERT_EQ(ret, 0);
|
||||
ASSERT_EQ(val, 123);
|
||||
|
||||
s = "-1";
|
||||
ret = toInteger(s, strlen(s), 10, &val);
|
||||
ASSERT_EQ(ret, 0);
|
||||
ASSERT_EQ(val, -1);
|
||||
|
||||
s = "-9223372036854775807";
|
||||
ret = toInteger(s, strlen(s), 10, &val);
|
||||
ASSERT_EQ(ret, 0);
|
||||
ASSERT_EQ(val, -9223372036854775807);
|
||||
|
||||
s = "1000u";
|
||||
ret = toInteger(s, strlen(s), 10, &val);
|
||||
ASSERT_EQ(ret, -1);
|
||||
|
@ -77,13 +215,22 @@ TEST(testCase, toInteger_test) {
|
|||
ASSERT_EQ(ret, 0);
|
||||
ASSERT_EQ(val, 72);
|
||||
|
||||
// 18446744073709551615 UINT64_MAX
|
||||
s = "18446744073709551615";
|
||||
s = "9223372036854775807";
|
||||
ret = toInteger(s, strlen(s), 10, &val);
|
||||
ASSERT_EQ(ret, 0);
|
||||
ASSERT_EQ(val, 18446744073709551615u);
|
||||
ASSERT_EQ(val, 9223372036854775807);
|
||||
|
||||
s = "18446744073709551616";
|
||||
s = "-9223372036854775808";
|
||||
ret = toInteger(s, strlen(s), 10, &val);
|
||||
ASSERT_EQ(ret, 0);
|
||||
ASSERT_EQ(val, -9223372036854775808);
|
||||
|
||||
// out of range
|
||||
s = "9323372036854775807";
|
||||
ret = toInteger(s, strlen(s), 10, &val);
|
||||
ASSERT_EQ(ret, -1);
|
||||
|
||||
s = "-9323372036854775807";
|
||||
ret = toInteger(s, strlen(s), 10, &val);
|
||||
ASSERT_EQ(ret, -1);
|
||||
}
|
||||
|
|
|
@ -154,8 +154,7 @@ typedef struct STsdbReader STsdbReader;
|
|||
#define CACHESCAN_RETRIEVE_LAST 0x8
|
||||
|
||||
int32_t tsdbReaderOpen2(void *pVnode, SQueryTableDataCond *pCond, void *pTableList, int32_t numOfTables,
|
||||
SSDataBlock *pResBlock, void **ppReader, const char *idstr, bool countOnly,
|
||||
SHashObj **pIgnoreTables);
|
||||
SSDataBlock *pResBlock, void **ppReader, const char *idstr, SHashObj **pIgnoreTables);
|
||||
int32_t tsdbSetTableList2(STsdbReader *pReader, const void *pTableList, int32_t num);
|
||||
void tsdbReaderSetId2(STsdbReader *pReader, const char *idstr);
|
||||
void tsdbReaderClose2(STsdbReader *pReader);
|
||||
|
@ -170,7 +169,9 @@ void *tsdbGetIdx2(SMeta *pMeta);
|
|||
void *tsdbGetIvtIdx2(SMeta *pMeta);
|
||||
uint64_t tsdbGetReaderMaxVersion2(STsdbReader *pReader);
|
||||
void tsdbReaderSetCloseFlag(STsdbReader *pReader);
|
||||
//======================================================================================================================
|
||||
int64_t tsdbGetLastTimestamp2(SVnode *pVnode, void *pTableList, int32_t numOfTables, const char *pIdStr);
|
||||
void tsdbSetFilesetDelimited(STsdbReader* pReader);
|
||||
void tsdbReaderSetNotifyCb(STsdbReader* pReader, TsdReaderNotifyCbFn notifyFn, void* param);
|
||||
|
||||
int32_t tsdbReuseCacherowsReader(void *pReader, void *pTableIdList, int32_t numOfTables);
|
||||
int32_t tsdbCacherowsReaderOpen(void *pVnode, int32_t type, void *pTableIdList, int32_t numOfTables, int32_t numOfCols,
|
||||
|
|
|
@ -676,46 +676,57 @@ struct SDelFWriter {
|
|||
};
|
||||
|
||||
#include "tarray2.h"
|
||||
// #include "tsdbFS2.h"
|
||||
// struct STFileSet;
|
||||
typedef struct STFileSet STFileSet;
|
||||
typedef TARRAY2(STFileSet *) TFileSetArray;
|
||||
|
||||
typedef struct STSnapRange STSnapRange;
|
||||
typedef TARRAY2(STSnapRange *) TSnapRangeArray; // disjoint snap ranges
|
||||
// fset range
|
||||
typedef struct STFileSetRange STFileSetRange;
|
||||
typedef TARRAY2(STFileSetRange *) TFileSetRangeArray; // disjoint ranges
|
||||
|
||||
// util
|
||||
int32_t tSerializeSnapRangeArray(void *buf, int32_t bufLen, TSnapRangeArray *pSnapR);
|
||||
int32_t tDeserializeSnapRangeArray(void *buf, int32_t bufLen, TSnapRangeArray *pSnapR);
|
||||
void tsdbSnapRangeArrayDestroy(TSnapRangeArray **ppSnap);
|
||||
SHashObj *tsdbGetSnapRangeHash(TSnapRangeArray *pRanges);
|
||||
|
||||
// snap partition list
|
||||
typedef TARRAY2(SVersionRange) SVerRangeList;
|
||||
typedef struct STsdbSnapPartition STsdbSnapPartition;
|
||||
typedef TARRAY2(STsdbSnapPartition *) STsdbSnapPartList;
|
||||
// util
|
||||
STsdbSnapPartList *tsdbSnapPartListCreate();
|
||||
void tsdbSnapPartListDestroy(STsdbSnapPartList **ppList);
|
||||
int32_t tSerializeTsdbSnapPartList(void *buf, int32_t bufLen, STsdbSnapPartList *pList);
|
||||
int32_t tDeserializeTsdbSnapPartList(void *buf, int32_t bufLen, STsdbSnapPartList *pList);
|
||||
int32_t tsdbSnapPartListToRangeDiff(STsdbSnapPartList *pList, TSnapRangeArray **ppRanges);
|
||||
int32_t tsdbTFileSetRangeClear(STFileSetRange **fsr);
|
||||
int32_t tsdbTFileSetRangeArrayDestroy(TFileSetRangeArray **ppArr);
|
||||
|
||||
// fset partition
|
||||
enum {
|
||||
TSDB_SNAP_RANGE_TYP_HEAD = 0,
|
||||
TSDB_SNAP_RANGE_TYP_DATA,
|
||||
TSDB_SNAP_RANGE_TYP_SMA,
|
||||
TSDB_SNAP_RANGE_TYP_TOMB,
|
||||
TSDB_SNAP_RANGE_TYP_STT,
|
||||
TSDB_SNAP_RANGE_TYP_MAX,
|
||||
TSDB_FSET_RANGE_TYP_HEAD = 0,
|
||||
TSDB_FSET_RANGE_TYP_DATA,
|
||||
TSDB_FSET_RANGE_TYP_SMA,
|
||||
TSDB_FSET_RANGE_TYP_TOMB,
|
||||
TSDB_FSET_RANGE_TYP_STT,
|
||||
TSDB_FSET_RANGE_TYP_MAX,
|
||||
};
|
||||
|
||||
struct STsdbSnapPartition {
|
||||
typedef TARRAY2(SVersionRange) SVerRangeList;
|
||||
|
||||
struct STsdbFSetPartition {
|
||||
int64_t fid;
|
||||
int8_t stat;
|
||||
SVerRangeList verRanges[TSDB_SNAP_RANGE_TYP_MAX];
|
||||
SVerRangeList verRanges[TSDB_FSET_RANGE_TYP_MAX];
|
||||
};
|
||||
|
||||
typedef struct STsdbFSetPartition STsdbFSetPartition;
|
||||
typedef TARRAY2(STsdbFSetPartition *) STsdbFSetPartList;
|
||||
|
||||
STsdbFSetPartList *tsdbFSetPartListCreate();
|
||||
void tsdbFSetPartListDestroy(STsdbFSetPartList **ppList);
|
||||
int32_t tSerializeTsdbFSetPartList(void *buf, int32_t bufLen, STsdbFSetPartList *pList);
|
||||
int32_t tDeserializeTsdbFSetPartList(void *buf, int32_t bufLen, STsdbFSetPartList *pList);
|
||||
int32_t tsdbFSetPartListToRangeDiff(STsdbFSetPartList *pList, TFileSetRangeArray **ppRanges);
|
||||
|
||||
// snap rep format
|
||||
typedef enum ETsdbRepFmt {
|
||||
TSDB_SNAP_REP_FMT_DEFAULT = 0,
|
||||
TSDB_SNAP_REP_FMT_RAW,
|
||||
TSDB_SNAP_REP_FMT_HYBRID,
|
||||
} ETsdbRepFmt;
|
||||
|
||||
typedef struct STsdbRepOpts {
|
||||
ETsdbRepFmt format;
|
||||
} STsdbRepOpts;
|
||||
|
||||
int32_t tSerializeTsdbRepOpts(void *buf, int32_t bufLen, STsdbRepOpts *pInfo);
|
||||
int32_t tDeserializeTsdbRepOpts(void *buf, int32_t bufLen, STsdbRepOpts *pInfo);
|
||||
|
||||
// snap read
|
||||
struct STsdbReadSnap {
|
||||
SMemTable *pMem;
|
||||
|
@ -773,20 +784,25 @@ typedef struct SBlockDataInfo {
|
|||
int32_t sttBlockIndex;
|
||||
} SBlockDataInfo;
|
||||
|
||||
typedef struct SSttBlockLoadInfo {
|
||||
SBlockDataInfo blockData[2]; // buffered block data
|
||||
int32_t statisBlockIndex; // buffered statistics block index
|
||||
void *statisBlock; // buffered statistics block data
|
||||
void *pSttStatisBlkArray;
|
||||
SArray *aSttBlk;
|
||||
int32_t currentLoadBlockIndex;
|
||||
STSchema *pSchema;
|
||||
int16_t *colIds;
|
||||
int32_t numOfCols;
|
||||
bool checkRemainingRow; // todo: no assign value?
|
||||
bool isLast;
|
||||
bool sttBlockLoaded;
|
||||
// todo: move away
|
||||
typedef struct {
|
||||
SArray *pUid;
|
||||
SArray *pFirstKey;
|
||||
SArray *pLastKey;
|
||||
SArray *pCount;
|
||||
} SSttTableRowsInfo;
|
||||
|
||||
typedef struct SSttBlockLoadInfo {
|
||||
SBlockDataInfo blockData[2]; // buffered block data
|
||||
SArray *aSttBlk;
|
||||
int32_t currentLoadBlockIndex;
|
||||
STSchema *pSchema;
|
||||
int16_t *colIds;
|
||||
int32_t numOfCols;
|
||||
bool checkRemainingRow; // todo: no assign value?
|
||||
bool isLast;
|
||||
bool sttBlockLoaded;
|
||||
SSttTableRowsInfo info;
|
||||
SSttBlockLoadCostInfo cost;
|
||||
} SSttBlockLoadInfo;
|
||||
|
||||
|
@ -875,27 +891,31 @@ typedef struct {
|
|||
_load_tomb_fn loadTombFn;
|
||||
void *pReader;
|
||||
void *idstr;
|
||||
bool rspRows; // response the rows in stt-file, if possible
|
||||
} SMergeTreeConf;
|
||||
|
||||
int32_t tMergeTreeOpen2(SMergeTree *pMTree, SMergeTreeConf *pConf);
|
||||
typedef struct SSttDataInfoForTable {
|
||||
SArray* pTimeWindowList;
|
||||
int64_t numOfRows;
|
||||
} SSttDataInfoForTable;
|
||||
|
||||
void tMergeTreeAddIter(SMergeTree *pMTree, SLDataIter *pIter);
|
||||
bool tMergeTreeNext(SMergeTree *pMTree);
|
||||
void tMergeTreePinSttBlock(SMergeTree *pMTree);
|
||||
void tMergeTreeUnpinSttBlock(SMergeTree *pMTree);
|
||||
bool tMergeTreeIgnoreEarlierTs(SMergeTree *pMTree);
|
||||
void tMergeTreeClose(SMergeTree *pMTree);
|
||||
int32_t tMergeTreeOpen2(SMergeTree *pMTree, SMergeTreeConf *pConf, SSttDataInfoForTable* pTableInfo);
|
||||
void tMergeTreeAddIter(SMergeTree *pMTree, SLDataIter *pIter);
|
||||
bool tMergeTreeNext(SMergeTree *pMTree);
|
||||
void tMergeTreePinSttBlock(SMergeTree *pMTree);
|
||||
void tMergeTreeUnpinSttBlock(SMergeTree *pMTree);
|
||||
bool tMergeTreeIgnoreEarlierTs(SMergeTree *pMTree);
|
||||
void tMergeTreeClose(SMergeTree *pMTree);
|
||||
|
||||
SSttBlockLoadInfo *tCreateSttBlockLoadInfo(STSchema *pSchema, int16_t *colList, int32_t numOfCols);
|
||||
void getSttBlockLoadInfo(SSttBlockLoadInfo *pLoadInfo, SSttBlockLoadCostInfo *pLoadCost);
|
||||
void *destroySttBlockLoadInfo(SSttBlockLoadInfo *pLoadInfo);
|
||||
void *destroySttBlockReader(SArray *pLDataIterArray, SSttBlockLoadCostInfo *pLoadCost);
|
||||
|
||||
// tsdbCache ==============================================================================================
|
||||
typedef enum {
|
||||
READ_MODE_COUNT_ONLY = 0x1,
|
||||
READ_MODE_ALL,
|
||||
} EReadMode;
|
||||
READER_EXEC_DATA = 0x1,
|
||||
READER_EXEC_ROWS = 0x2,
|
||||
} EExecMode;
|
||||
|
||||
typedef struct {
|
||||
TSKEY ts;
|
||||
|
@ -1042,7 +1062,7 @@ typedef enum {
|
|||
|
||||
// utils
|
||||
ETsdbFsState tsdbSnapGetFsState(SVnode *pVnode);
|
||||
int32_t tsdbSnapGetDetails(SVnode *pVnode, SSnapshot *pSnap);
|
||||
int32_t tsdbSnapPrepDescription(SVnode *pVnode, SSnapshot *pSnap);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -65,6 +65,8 @@ typedef struct SMetaSnapReader SMetaSnapReader;
|
|||
typedef struct SMetaSnapWriter SMetaSnapWriter;
|
||||
typedef struct STsdbSnapReader STsdbSnapReader;
|
||||
typedef struct STsdbSnapWriter STsdbSnapWriter;
|
||||
typedef struct STsdbSnapRAWReader STsdbSnapRAWReader;
|
||||
typedef struct STsdbSnapRAWWriter STsdbSnapRAWWriter;
|
||||
typedef struct STqSnapReader STqSnapReader;
|
||||
typedef struct STqSnapWriter STqSnapWriter;
|
||||
typedef struct STqOffsetReader STqOffsetReader;
|
||||
|
@ -236,10 +238,8 @@ int32_t tqProcessTaskUpdateReq(STQ* pTq, SRpcMsg* pMsg);
|
|||
int32_t tqProcessTaskResetReq(STQ* pTq, SRpcMsg* pMsg);
|
||||
int32_t tqProcessTaskDropHTask(STQ* pTq, SRpcMsg* pMsg);
|
||||
|
||||
int32_t tqRestartStreamTasks(STQ* pTq);
|
||||
int32_t tqExpandTask(STQ* pTq, SStreamTask* pTask, int64_t ver);
|
||||
int32_t tqScanWal(STQ* pTq);
|
||||
int32_t tqStartStreamTasks(STQ* pTq);
|
||||
|
||||
int tqCommit(STQ*);
|
||||
int32_t tqUpdateTbUidList(STQ* pTq, const SArray* tbUidList, bool isAdd);
|
||||
|
@ -313,6 +313,15 @@ int32_t tsdbSnapWriterOpen(STsdb* pTsdb, int64_t sver, int64_t ever, void* pRang
|
|||
int32_t tsdbSnapWrite(STsdbSnapWriter* pWriter, SSnapDataHdr* pHdr);
|
||||
int32_t tsdbSnapWriterPrepareClose(STsdbSnapWriter* pWriter);
|
||||
int32_t tsdbSnapWriterClose(STsdbSnapWriter** ppWriter, int8_t rollback);
|
||||
// STsdbSnapRAWReader ========================================
|
||||
int32_t tsdbSnapRAWReaderOpen(STsdb* pTsdb, int64_t ever, int8_t type, STsdbSnapRAWReader** ppReader);
|
||||
int32_t tsdbSnapRAWReaderClose(STsdbSnapRAWReader** ppReader);
|
||||
int32_t tsdbSnapRAWRead(STsdbSnapRAWReader* pReader, uint8_t** ppData);
|
||||
// STsdbSnapRAWWriter ========================================
|
||||
int32_t tsdbSnapRAWWriterOpen(STsdb* pTsdb, int64_t ever, STsdbSnapRAWWriter** ppWriter);
|
||||
int32_t tsdbSnapRAWWrite(STsdbSnapRAWWriter* pWriter, SSnapDataHdr* pHdr);
|
||||
int32_t tsdbSnapRAWWriterPrepareClose(STsdbSnapRAWWriter* pWriter);
|
||||
int32_t tsdbSnapRAWWriterClose(STsdbSnapRAWWriter** ppWriter, int8_t rollback);
|
||||
// STqSnapshotReader ==
|
||||
int32_t tqSnapReaderOpen(STQ* pTq, int64_t sver, int64_t ever, STqSnapReader** ppReader);
|
||||
int32_t tqSnapReaderClose(STqSnapReader** ppReader);
|
||||
|
@ -531,6 +540,7 @@ enum {
|
|||
SNAP_DATA_STREAM_STATE = 11,
|
||||
SNAP_DATA_STREAM_STATE_BACKEND = 12,
|
||||
SNAP_DATA_TQ_CHECKINFO = 13,
|
||||
SNAP_DATA_RAW = 14,
|
||||
};
|
||||
|
||||
struct SSnapDataHdr {
|
||||
|
|
|
@ -1167,26 +1167,33 @@ int32_t tsdbCacheDel(STsdb *pTsdb, tb_uid_t suid, tb_uid_t uid, TSKEY sKey, TSKE
|
|||
|
||||
// taosThreadMutexLock(&pTsdb->lruMutex);
|
||||
|
||||
bool erase = false;
|
||||
LRUHandle *h = taosLRUCacheLookup(pTsdb->lruCache, keys_list[i], klen);
|
||||
if (h) {
|
||||
SLastCol *pLastCol = (SLastCol *)taosLRUCacheValue(pTsdb->lruCache, h);
|
||||
if (pLastCol->dirty) {
|
||||
if (pLastCol->dirty && (pLastCol->ts <= eKey && pLastCol->ts >= sKey)) {
|
||||
pLastCol->dirty = 0;
|
||||
erase = true;
|
||||
}
|
||||
taosLRUCacheRelease(pTsdb->lruCache, h, true);
|
||||
taosLRUCacheRelease(pTsdb->lruCache, h, erase);
|
||||
}
|
||||
if (erase) {
|
||||
taosLRUCacheErase(pTsdb->lruCache, keys_list[i], klen);
|
||||
}
|
||||
taosLRUCacheErase(pTsdb->lruCache, keys_list[i], klen);
|
||||
|
||||
erase = false;
|
||||
h = taosLRUCacheLookup(pTsdb->lruCache, keys_list[num_keys + i], klen);
|
||||
if (h) {
|
||||
SLastCol *pLastCol = (SLastCol *)taosLRUCacheValue(pTsdb->lruCache, h);
|
||||
if (pLastCol->dirty) {
|
||||
if (pLastCol->dirty && (pLastCol->ts <= eKey && pLastCol->ts >= sKey)) {
|
||||
pLastCol->dirty = 0;
|
||||
erase = true;
|
||||
}
|
||||
taosLRUCacheRelease(pTsdb->lruCache, h, true);
|
||||
taosLRUCacheRelease(pTsdb->lruCache, h, erase);
|
||||
}
|
||||
if (erase) {
|
||||
taosLRUCacheErase(pTsdb->lruCache, keys_list[num_keys + i], klen);
|
||||
}
|
||||
taosLRUCacheErase(pTsdb->lruCache, keys_list[num_keys + i], klen);
|
||||
|
||||
// taosThreadMutexUnlock(&pTsdb->lruMutex);
|
||||
}
|
||||
for (int i = 0; i < num_keys; ++i) {
|
||||
|
@ -1870,7 +1877,7 @@ static int32_t lastIterOpen(SFSLastIter *iter, STFileSet *pFileSet, STsdb *pTsdb
|
|||
.idstr = pr->idstr,
|
||||
};
|
||||
|
||||
code = tMergeTreeOpen2(&iter->mergeTree, &conf);
|
||||
code = tMergeTreeOpen2(&iter->mergeTree, &conf, NULL);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -435,7 +435,7 @@ _exit:
|
|||
tsdbDebug("vgId:%d %s done, fid:%d minKey:%" PRId64 " maxKey:%" PRId64 " expLevel:%d", TD_VID(tsdb->pVnode),
|
||||
__func__, committer->ctx->fid, committer->ctx->minKey, committer->ctx->maxKey, committer->ctx->expLevel);
|
||||
}
|
||||
return 0;
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t tsdbCommitFileSetEnd(SCommitter2 *committer) {
|
||||
|
|
|
@ -0,0 +1,222 @@
|
|||
/*
|
||||
* 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 "tsdbDataFileRAW.h"
|
||||
|
||||
// SDataFileRAWReader =============================================
|
||||
int32_t tsdbDataFileRAWReaderOpen(const char *fname, const SDataFileRAWReaderConfig *config,
|
||||
SDataFileRAWReader **reader) {
|
||||
int32_t code = 0;
|
||||
int32_t lino = 0;
|
||||
|
||||
reader[0] = taosMemoryCalloc(1, sizeof(SDataFileRAWReader));
|
||||
if (reader[0] == NULL) {
|
||||
code = TSDB_CODE_OUT_OF_MEMORY;
|
||||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
}
|
||||
|
||||
reader[0]->config[0] = config[0];
|
||||
|
||||
if (fname) {
|
||||
if (fname) {
|
||||
code = tsdbOpenFile(fname, config->tsdb, TD_FILE_READ, &reader[0]->fd);
|
||||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
}
|
||||
} else {
|
||||
char fname1[TSDB_FILENAME_LEN];
|
||||
tsdbTFileName(config->tsdb, &config->file, fname1);
|
||||
code = tsdbOpenFile(fname1, config->tsdb, TD_FILE_READ, &reader[0]->fd);
|
||||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
}
|
||||
|
||||
_exit:
|
||||
if (code) {
|
||||
TSDB_ERROR_LOG(TD_VID(config->tsdb->pVnode), lino, code);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
int32_t tsdbDataFileRAWReaderClose(SDataFileRAWReader **reader) {
|
||||
if (reader[0] == NULL) return 0;
|
||||
|
||||
if (reader[0]->fd) {
|
||||
tsdbCloseFile(&reader[0]->fd);
|
||||
}
|
||||
|
||||
taosMemoryFree(reader[0]);
|
||||
reader[0] = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t tsdbDataFileRAWReadBlockData(SDataFileRAWReader *reader, STsdbDataRAWBlockHeader *pBlock) {
|
||||
int32_t code = 0;
|
||||
int32_t lino = 0;
|
||||
|
||||
pBlock->file.type = reader->config->file.type;
|
||||
pBlock->file.fid = reader->config->file.fid;
|
||||
pBlock->file.cid = reader->config->file.cid;
|
||||
pBlock->file.size = reader->config->file.size;
|
||||
pBlock->file.minVer = reader->config->file.minVer;
|
||||
pBlock->file.maxVer = reader->config->file.maxVer;
|
||||
pBlock->file.stt->level = reader->config->file.stt->level;
|
||||
|
||||
code = tsdbReadFile(reader->fd, pBlock->offset, pBlock->data, pBlock->dataLength, 0);
|
||||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
|
||||
_exit:
|
||||
if (code) {
|
||||
TSDB_ERROR_LOG(TD_VID(reader->config->tsdb->pVnode), lino, code);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
// SDataFileRAWWriter =============================================
|
||||
int32_t tsdbDataFileRAWWriterOpen(const SDataFileRAWWriterConfig *config, SDataFileRAWWriter **ppWriter) {
|
||||
int32_t code = 0;
|
||||
int32_t lino = 0;
|
||||
|
||||
SDataFileRAWWriter *writer = taosMemoryCalloc(1, sizeof(SDataFileRAWWriter));
|
||||
if (!writer) return TSDB_CODE_OUT_OF_MEMORY;
|
||||
|
||||
writer->config[0] = config[0];
|
||||
|
||||
code = tsdbDataFileRAWWriterDoOpen(writer);
|
||||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
|
||||
_exit:
|
||||
if (code) {
|
||||
taosMemoryFree(writer);
|
||||
writer = NULL;
|
||||
TSDB_ERROR_LOG(TD_VID(writer->config->tsdb->pVnode), lino, code);
|
||||
}
|
||||
ppWriter[0] = writer;
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t tsdbDataFileRAWWriterCloseAbort(SDataFileRAWWriter *writer) {
|
||||
ASSERT(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t tsdbDataFileRAWWriterDoClose(SDataFileRAWWriter *writer) { return 0; }
|
||||
|
||||
static int32_t tsdbDataFileRAWWriterCloseCommit(SDataFileRAWWriter *writer, TFileOpArray *opArr) {
|
||||
int32_t code = 0;
|
||||
int32_t lino = 0;
|
||||
ASSERT(writer->ctx->offset == writer->file.size);
|
||||
ASSERT(writer->config->fid == writer->file.fid);
|
||||
|
||||
STFileOp op = (STFileOp){
|
||||
.optype = TSDB_FOP_CREATE,
|
||||
.fid = writer->config->fid,
|
||||
.nf = writer->file,
|
||||
};
|
||||
code = TARRAY2_APPEND(opArr, op);
|
||||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
|
||||
if (writer->fd) {
|
||||
code = tsdbFsyncFile(writer->fd);
|
||||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
tsdbCloseFile(&writer->fd);
|
||||
}
|
||||
|
||||
_exit:
|
||||
if (code) {
|
||||
TSDB_ERROR_LOG(TD_VID(writer->config->tsdb->pVnode), lino, code);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t tsdbDataFileRAWWriterOpenDataFD(SDataFileRAWWriter *writer) {
|
||||
int32_t code = 0;
|
||||
int32_t lino = 0;
|
||||
|
||||
char fname[TSDB_FILENAME_LEN];
|
||||
int32_t flag = TD_FILE_READ | TD_FILE_WRITE;
|
||||
|
||||
if (writer->ctx->offset == 0) {
|
||||
flag |= (TD_FILE_CREATE | TD_FILE_TRUNC);
|
||||
}
|
||||
|
||||
tsdbTFileName(writer->config->tsdb, &writer->file, fname);
|
||||
code = tsdbOpenFile(fname, writer->config->tsdb, flag, &writer->fd);
|
||||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
|
||||
_exit:
|
||||
if (code) {
|
||||
TSDB_ERROR_LOG(TD_VID(writer->config->tsdb->pVnode), lino, code);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
int32_t tsdbDataFileRAWWriterDoOpen(SDataFileRAWWriter *writer) {
|
||||
int32_t code = 0;
|
||||
int32_t lino = 0;
|
||||
|
||||
writer->file = writer->config->file;
|
||||
writer->ctx->offset = 0;
|
||||
|
||||
code = tsdbDataFileRAWWriterOpenDataFD(writer);
|
||||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
|
||||
writer->ctx->opened = true;
|
||||
_exit:
|
||||
if (code) {
|
||||
TSDB_ERROR_LOG(TD_VID(writer->config->tsdb->pVnode), lino, code);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
int32_t tsdbDataFileRAWWriterClose(SDataFileRAWWriter **writer, bool abort, TFileOpArray *opArr) {
|
||||
if (writer[0] == NULL) return 0;
|
||||
|
||||
int32_t code = 0;
|
||||
int32_t lino = 0;
|
||||
|
||||
if (writer[0]->ctx->opened) {
|
||||
if (abort) {
|
||||
code = tsdbDataFileRAWWriterCloseAbort(writer[0]);
|
||||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
} else {
|
||||
code = tsdbDataFileRAWWriterCloseCommit(writer[0], opArr);
|
||||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
}
|
||||
tsdbDataFileRAWWriterDoClose(writer[0]);
|
||||
}
|
||||
taosMemoryFree(writer[0]);
|
||||
writer[0] = NULL;
|
||||
|
||||
_exit:
|
||||
if (code) {
|
||||
TSDB_ERROR_LOG(TD_VID(writer[0]->config->tsdb->pVnode), lino, code);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
int32_t tsdbDataFileRAWWriteBlockData(SDataFileRAWWriter *writer, const STsdbDataRAWBlockHeader *pDataBlock) {
|
||||
int32_t code = 0;
|
||||
int32_t lino = 0;
|
||||
|
||||
code = tsdbWriteFile(writer->fd, writer->ctx->offset, (const uint8_t *)pDataBlock->data, pDataBlock->dataLength);
|
||||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
|
||||
writer->ctx->offset += pDataBlock->dataLength;
|
||||
|
||||
_exit:
|
||||
if (code) {
|
||||
TSDB_ERROR_LOG(TD_VID(writer->config->tsdb->pVnode), lino, code);
|
||||
}
|
||||
return code;
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* 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 "tarray2.h"
|
||||
#include "tsdbDef.h"
|
||||
#include "tsdbFSet2.h"
|
||||
#include "tsdbFile2.h"
|
||||
#include "tsdbUtil2.h"
|
||||
|
||||
#ifndef _TSDB_DATA_FILE_RAW_H
|
||||
#define _TSDB_DATA_FILE_RAW_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// STsdbDataRAWBlockHeader =======================================
|
||||
typedef struct STsdbDataRAWBlockHeader {
|
||||
struct {
|
||||
int32_t type;
|
||||
int64_t fid;
|
||||
int64_t cid;
|
||||
int64_t size;
|
||||
int64_t minVer;
|
||||
int64_t maxVer;
|
||||
union {
|
||||
struct {
|
||||
int32_t level;
|
||||
} stt[1];
|
||||
};
|
||||
} file;
|
||||
|
||||
int64_t offset;
|
||||
int64_t dataLength;
|
||||
uint8_t data[0];
|
||||
} STsdbDataRAWBlockHeader;
|
||||
|
||||
// SDataFileRAWReader =============================================
|
||||
typedef struct SDataFileRAWReaderConfig {
|
||||
STsdb *tsdb;
|
||||
int32_t szPage;
|
||||
|
||||
STFile file;
|
||||
} SDataFileRAWReaderConfig;
|
||||
|
||||
typedef struct SDataFileRAWReader {
|
||||
SDataFileRAWReaderConfig config[1];
|
||||
|
||||
struct {
|
||||
bool opened;
|
||||
int64_t offset;
|
||||
} ctx[1];
|
||||
|
||||
STsdbFD *fd;
|
||||
} SDataFileRAWReader;
|
||||
|
||||
typedef TARRAY2(SDataFileRAWReader *) SDataFileRAWReaderArray;
|
||||
|
||||
int32_t tsdbDataFileRAWReaderOpen(const char *fname, const SDataFileRAWReaderConfig *config,
|
||||
SDataFileRAWReader **reader);
|
||||
int32_t tsdbDataFileRAWReaderClose(SDataFileRAWReader **reader);
|
||||
|
||||
int32_t tsdbDataFileRAWReadBlockData(SDataFileRAWReader *reader, STsdbDataRAWBlockHeader *bHdr);
|
||||
|
||||
// SDataFileRAWWriter =============================================
|
||||
typedef struct SDataFileRAWWriterConfig {
|
||||
STsdb *tsdb;
|
||||
int32_t szPage;
|
||||
|
||||
SDiskID did;
|
||||
int64_t fid;
|
||||
int64_t cid;
|
||||
int32_t level;
|
||||
|
||||
STFile file;
|
||||
} SDataFileRAWWriterConfig;
|
||||
|
||||
typedef struct SDataFileRAWWriter {
|
||||
SDataFileRAWWriterConfig config[1];
|
||||
|
||||
struct {
|
||||
bool opened;
|
||||
int64_t offset;
|
||||
} ctx[1];
|
||||
|
||||
STFile file;
|
||||
STsdbFD *fd;
|
||||
} SDataFileRAWWriter;
|
||||
|
||||
typedef struct SDataFileRAWWriter SDataFileRAWWriter;
|
||||
|
||||
int32_t tsdbDataFileRAWWriterOpen(const SDataFileRAWWriterConfig *config, SDataFileRAWWriter **writer);
|
||||
int32_t tsdbDataFileRAWWriterClose(SDataFileRAWWriter **writer, bool abort, TFileOpArray *opArr);
|
||||
|
||||
int32_t tsdbDataFileRAWWriterDoOpen(SDataFileRAWWriter *writer);
|
||||
int32_t tsdbDataFileRAWWriteBlockData(SDataFileRAWWriter *writer, const STsdbDataRAWBlockHeader *bHdr);
|
||||
int32_t tsdbDataFileRAWFlush(SDataFileRAWWriter *writer);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*_TSDB_DATA_FILE_RAW_H*/
|
|
@ -1072,7 +1072,25 @@ int32_t tsdbFSDestroyRefSnapshot(TFileSetArray **fsetArr) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int32_t tsdbFSCreateCopyRangedSnapshot(STFileSystem *fs, TSnapRangeArray *pRanges, TFileSetArray **fsetArr,
|
||||
static SHashObj *tsdbFSetRangeArrayToHash(TFileSetRangeArray *pRanges) {
|
||||
int32_t capacity = TARRAY2_SIZE(pRanges) * 2;
|
||||
SHashObj *pHash = taosHashInit(capacity, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), false, HASH_ENTRY_LOCK);
|
||||
if (pHash == NULL) {
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < TARRAY2_SIZE(pRanges); i++) {
|
||||
STFileSetRange *u = TARRAY2_GET(pRanges, i);
|
||||
int32_t fid = u->fid;
|
||||
int32_t code = taosHashPut(pHash, &fid, sizeof(fid), u, sizeof(*u));
|
||||
ASSERT(code == 0);
|
||||
tsdbDebug("range diff hash fid:%d, sver:%" PRId64 ", ever:%" PRId64, u->fid, u->sver, u->ever);
|
||||
}
|
||||
return pHash;
|
||||
}
|
||||
|
||||
int32_t tsdbFSCreateCopyRangedSnapshot(STFileSystem *fs, TFileSetRangeArray *pRanges, TFileSetArray **fsetArr,
|
||||
TFileOpArray *fopArr) {
|
||||
int32_t code = 0;
|
||||
STFileSet *fset;
|
||||
|
@ -1084,7 +1102,7 @@ int32_t tsdbFSCreateCopyRangedSnapshot(STFileSystem *fs, TSnapRangeArray *pRange
|
|||
TARRAY2_INIT(fsetArr[0]);
|
||||
|
||||
if (pRanges) {
|
||||
pHash = tsdbGetSnapRangeHash(pRanges);
|
||||
pHash = tsdbFSetRangeArrayToHash(pRanges);
|
||||
if (pHash == NULL) {
|
||||
code = TSDB_CODE_OUT_OF_MEMORY;
|
||||
goto _out;
|
||||
|
@ -1096,7 +1114,7 @@ int32_t tsdbFSCreateCopyRangedSnapshot(STFileSystem *fs, TSnapRangeArray *pRange
|
|||
int64_t ever = VERSION_MAX;
|
||||
if (pHash) {
|
||||
int32_t fid = fset->fid;
|
||||
STSnapRange *u = taosHashGet(pHash, &fid, sizeof(fid));
|
||||
STFileSetRange *u = taosHashGet(pHash, &fid, sizeof(fid));
|
||||
if (u) {
|
||||
ever = u->sver - 1;
|
||||
}
|
||||
|
@ -1123,29 +1141,13 @@ _out:
|
|||
return code;
|
||||
}
|
||||
|
||||
SHashObj *tsdbGetSnapRangeHash(TSnapRangeArray *pRanges) {
|
||||
int32_t capacity = TARRAY2_SIZE(pRanges) * 2;
|
||||
SHashObj *pHash = taosHashInit(capacity, taosGetDefaultHashFunction(TSDB_DATA_TYPE_INT), false, HASH_ENTRY_LOCK);
|
||||
if (pHash == NULL) {
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
return NULL;
|
||||
}
|
||||
int32_t tsdbFSDestroyCopyRangedSnapshot(TFileSetArray **fsetArr) { return tsdbFSDestroyCopySnapshot(fsetArr); }
|
||||
|
||||
for (int32_t i = 0; i < TARRAY2_SIZE(pRanges); i++) {
|
||||
STSnapRange *u = TARRAY2_GET(pRanges, i);
|
||||
int32_t fid = u->fid;
|
||||
int32_t code = taosHashPut(pHash, &fid, sizeof(fid), u, sizeof(*u));
|
||||
ASSERT(code == 0);
|
||||
tsdbDebug("range diff hash fid:%d, sver:%" PRId64 ", ever:%" PRId64, u->fid, u->sver, u->ever);
|
||||
}
|
||||
return pHash;
|
||||
}
|
||||
|
||||
int32_t tsdbFSCreateRefRangedSnapshot(STFileSystem *fs, int64_t sver, int64_t ever, TSnapRangeArray *pRanges,
|
||||
TSnapRangeArray **fsrArr) {
|
||||
int32_t tsdbFSCreateRefRangedSnapshot(STFileSystem *fs, int64_t sver, int64_t ever, TFileSetRangeArray *pRanges,
|
||||
TFileSetRangeArray **fsrArr) {
|
||||
int32_t code = 0;
|
||||
STFileSet *fset;
|
||||
STSnapRange *fsr1 = NULL;
|
||||
STFileSetRange *fsr1 = NULL;
|
||||
SHashObj *pHash = NULL;
|
||||
|
||||
fsrArr[0] = taosMemoryCalloc(1, sizeof(*fsrArr[0]));
|
||||
|
@ -1156,7 +1158,7 @@ int32_t tsdbFSCreateRefRangedSnapshot(STFileSystem *fs, int64_t sver, int64_t ev
|
|||
|
||||
tsdbInfo("pRanges size:%d", (pRanges == NULL ? 0 : TARRAY2_SIZE(pRanges)));
|
||||
if (pRanges) {
|
||||
pHash = tsdbGetSnapRangeHash(pRanges);
|
||||
pHash = tsdbFSetRangeArrayToHash(pRanges);
|
||||
if (pHash == NULL) {
|
||||
code = TSDB_CODE_OUT_OF_MEMORY;
|
||||
goto _out;
|
||||
|
@ -1170,7 +1172,7 @@ int32_t tsdbFSCreateRefRangedSnapshot(STFileSystem *fs, int64_t sver, int64_t ev
|
|||
|
||||
if (pHash) {
|
||||
int32_t fid = fset->fid;
|
||||
STSnapRange *u = taosHashGet(pHash, &fid, sizeof(fid));
|
||||
STFileSetRange *u = taosHashGet(pHash, &fid, sizeof(fid));
|
||||
if (u) {
|
||||
sver1 = u->sver;
|
||||
tsdbDebug("range hash get fid:%d, sver:%" PRId64 ", ever:%" PRId64, u->fid, u->sver, u->ever);
|
||||
|
@ -1184,7 +1186,7 @@ int32_t tsdbFSCreateRefRangedSnapshot(STFileSystem *fs, int64_t sver, int64_t ev
|
|||
|
||||
tsdbDebug("fsrArr:%p, fid:%d, sver:%" PRId64 ", ever:%" PRId64, fsrArr, fset->fid, sver1, ever1);
|
||||
|
||||
code = tsdbTSnapRangeInitRef(fs->tsdb, fset, sver1, ever1, &fsr1);
|
||||
code = tsdbTFileSetRangeInitRef(fs->tsdb, fset, sver1, ever1, &fsr1);
|
||||
if (code) break;
|
||||
|
||||
code = TARRAY2_APPEND(fsrArr[0], fsr1);
|
||||
|
@ -1195,8 +1197,8 @@ int32_t tsdbFSCreateRefRangedSnapshot(STFileSystem *fs, int64_t sver, int64_t ev
|
|||
taosThreadMutexUnlock(&fs->tsdb->mutex);
|
||||
|
||||
if (code) {
|
||||
tsdbTSnapRangeClear(&fsr1);
|
||||
TARRAY2_DESTROY(fsrArr[0], tsdbTSnapRangeClear);
|
||||
tsdbTFileSetRangeClear(&fsr1);
|
||||
TARRAY2_DESTROY(fsrArr[0], tsdbTFileSetRangeClear);
|
||||
fsrArr[0] = NULL;
|
||||
}
|
||||
|
||||
|
@ -1206,4 +1208,6 @@ _out:
|
|||
pHash = NULL;
|
||||
}
|
||||
return code;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t tsdbFSDestroyRefRangedSnapshot(TFileSetRangeArray **fsrArr) { return tsdbTFileSetRangeArrayDestroy(fsrArr); }
|
||||
|
|
|
@ -44,13 +44,13 @@ int32_t tsdbFSCreateRefSnapshot(STFileSystem *fs, TFileSetArray **fsetArr);
|
|||
int32_t tsdbFSCreateRefSnapshotWithoutLock(STFileSystem *fs, TFileSetArray **fsetArr);
|
||||
int32_t tsdbFSDestroyRefSnapshot(TFileSetArray **fsetArr);
|
||||
|
||||
int32_t tsdbFSCreateCopyRangedSnapshot(STFileSystem *fs, TSnapRangeArray *pExclude, TFileSetArray **fsetArr,
|
||||
int32_t tsdbFSCreateCopyRangedSnapshot(STFileSystem *fs, TFileSetRangeArray *pExclude, TFileSetArray **fsetArr,
|
||||
TFileOpArray *fopArr);
|
||||
int32_t tsdbFSDestroyCopyRangedSnapshot(TFileSetArray **fsetArr, TFileOpArray *fopArr);
|
||||
int32_t tsdbFSCreateRefRangedSnapshot(STFileSystem *fs, int64_t sver, int64_t ever, TSnapRangeArray *pRanges,
|
||||
TSnapRangeArray **fsrArr);
|
||||
int32_t tsdbFSDestroyRefRangedSnapshot(TSnapRangeArray **fsrArr);
|
||||
// txn
|
||||
int32_t tsdbFSDestroyCopyRangedSnapshot(TFileSetArray **fsetArr);
|
||||
int32_t tsdbFSCreateRefRangedSnapshot(STFileSystem *fs, int64_t sver, int64_t ever, TFileSetRangeArray *pRanges,
|
||||
TFileSetRangeArray **fsrArr);
|
||||
int32_t tsdbFSDestroyRefRangedSnapshot(TFileSetRangeArray **fsrArr);
|
||||
// txn
|
||||
int64_t tsdbFSAllocEid(STFileSystem *fs);
|
||||
int32_t tsdbFSEditBegin(STFileSystem *fs, const TFileOpArray *opArray, EFEditT etype);
|
||||
int32_t tsdbFSEditCommit(STFileSystem *fs);
|
||||
|
|
|
@ -533,7 +533,8 @@ int32_t tsdbTFileSetFilteredInitDup(STsdb *pTsdb, const STFileSet *fset1, int64_
|
|||
return 0;
|
||||
}
|
||||
|
||||
int32_t tsdbTSnapRangeInitRef(STsdb *pTsdb, const STFileSet *fset1, int64_t sver, int64_t ever, STSnapRange **fsr) {
|
||||
int32_t tsdbTFileSetRangeInitRef(STsdb *pTsdb, const STFileSet *fset1, int64_t sver, int64_t ever,
|
||||
STFileSetRange **fsr) {
|
||||
fsr[0] = taosMemoryCalloc(1, sizeof(*fsr[0]));
|
||||
if (fsr[0] == NULL) return TSDB_CODE_OUT_OF_MEMORY;
|
||||
fsr[0]->fid = fset1->fid;
|
||||
|
@ -575,7 +576,7 @@ int32_t tsdbTFileSetInitRef(STsdb *pTsdb, const STFileSet *fset1, STFileSet **fs
|
|||
return 0;
|
||||
}
|
||||
|
||||
int32_t tsdbTSnapRangeClear(STSnapRange **fsr) {
|
||||
int32_t tsdbTFileSetRangeClear(STFileSetRange **fsr) {
|
||||
if (!fsr[0]) return 0;
|
||||
|
||||
tsdbTFileSetClear(&fsr[0]->fset);
|
||||
|
@ -584,6 +585,15 @@ int32_t tsdbTSnapRangeClear(STSnapRange **fsr) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int32_t tsdbTFileSetRangeArrayDestroy(TFileSetRangeArray** ppArr) {
|
||||
if (ppArr && ppArr[0]) {
|
||||
TARRAY2_DESTROY(ppArr[0], tsdbTFileSetRangeClear);
|
||||
taosMemoryFree(ppArr[0]);
|
||||
ppArr[0] = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t tsdbTFileSetClear(STFileSet **fset) {
|
||||
if (!fset[0]) return 0;
|
||||
|
||||
|
|
|
@ -49,8 +49,8 @@ int32_t tsdbTFileSetRemove(STFileSet *fset);
|
|||
int32_t tsdbTFileSetFilteredInitDup(STsdb *pTsdb, const STFileSet *fset1, int64_t ever, STFileSet **fset,
|
||||
TFileOpArray *fopArr);
|
||||
|
||||
int32_t tsdbTSnapRangeInitRef(STsdb *pTsdb, const STFileSet *fset1, int64_t sver, int64_t ever, STSnapRange **fsr);
|
||||
int32_t tsdbTSnapRangeClear(STSnapRange **fsr);
|
||||
int32_t tsdbTFileSetRangeInitRef(STsdb *pTsdb, const STFileSet *fset1, int64_t sver, int64_t ever,
|
||||
STFileSetRange **fsr);
|
||||
|
||||
// to/from json
|
||||
int32_t tsdbTFileSetToJson(const STFileSet *fset, cJSON *json);
|
||||
|
@ -101,7 +101,7 @@ struct STFileSet {
|
|||
bool blockCommit;
|
||||
};
|
||||
|
||||
struct STSnapRange {
|
||||
struct STFileSetRange {
|
||||
int32_t fid;
|
||||
int64_t sver;
|
||||
int64_t ever;
|
||||
|
|
|
@ -0,0 +1,178 @@
|
|||
/*
|
||||
* 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 "tsdbFSetRAW.h"
|
||||
|
||||
// SFSetRAWWriter ==================================================
|
||||
typedef struct SFSetRAWWriter {
|
||||
SFSetRAWWriterConfig config[1];
|
||||
|
||||
struct {
|
||||
TFileOpArray fopArr[1];
|
||||
STFile file;
|
||||
int64_t offset;
|
||||
} ctx[1];
|
||||
|
||||
// writer
|
||||
SDataFileRAWWriter *dataWriter;
|
||||
} SFSetRAWWriter;
|
||||
|
||||
int32_t tsdbFSetRAWWriterOpen(SFSetRAWWriterConfig *config, SFSetRAWWriter **writer) {
|
||||
int32_t code = 0;
|
||||
int32_t lino = 0;
|
||||
|
||||
writer[0] = taosMemoryCalloc(1, sizeof(SFSetRAWWriter));
|
||||
if (writer[0] == NULL) return TSDB_CODE_OUT_OF_MEMORY;
|
||||
|
||||
writer[0]->config[0] = config[0];
|
||||
|
||||
TARRAY2_INIT(writer[0]->ctx->fopArr);
|
||||
|
||||
_exit:
|
||||
if (code) {
|
||||
TSDB_ERROR_LOG(TD_VID(config->tsdb->pVnode), lino, code);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t tsdbFSetRAWWriterFinish(SFSetRAWWriter *writer, TFileOpArray *fopArr) {
|
||||
int32_t code = 0;
|
||||
int32_t lino = 0;
|
||||
|
||||
STsdb *tsdb = writer->config->tsdb;
|
||||
|
||||
STFileOp op;
|
||||
TARRAY2_FOREACH(writer->ctx->fopArr, op) {
|
||||
code = TARRAY2_APPEND(fopArr, op);
|
||||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
}
|
||||
|
||||
TARRAY2_CLEAR(writer->ctx->fopArr, NULL);
|
||||
_exit:
|
||||
if (code) {
|
||||
TSDB_ERROR_LOG(TD_VID(tsdb->pVnode), lino, code);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t tsdbFSetRAWWriteFileDataBegin(SFSetRAWWriter *writer, STsdbDataRAWBlockHeader *bHdr) {
|
||||
int32_t code = 0;
|
||||
int32_t lino = 0;
|
||||
|
||||
SDataFileRAWWriterConfig config = {
|
||||
.tsdb = writer->config->tsdb,
|
||||
.szPage = writer->config->szPage,
|
||||
.fid = bHdr->file.fid,
|
||||
.did = writer->config->did,
|
||||
.cid = writer->config->cid,
|
||||
.level = writer->config->level,
|
||||
|
||||
.file =
|
||||
{
|
||||
.type = bHdr->file.type,
|
||||
.fid = bHdr->file.fid,
|
||||
.did = writer->config->did,
|
||||
.cid = writer->config->cid,
|
||||
.size = bHdr->file.size,
|
||||
.minVer = bHdr->file.minVer,
|
||||
.maxVer = bHdr->file.maxVer,
|
||||
.stt = {{
|
||||
.level = bHdr->file.stt->level,
|
||||
}},
|
||||
},
|
||||
};
|
||||
|
||||
writer->ctx->offset = 0;
|
||||
writer->ctx->file = config.file;
|
||||
|
||||
code = tsdbDataFileRAWWriterOpen(&config, &writer->dataWriter);
|
||||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
|
||||
_exit:
|
||||
if (code) {
|
||||
TSDB_ERROR_LOG(TD_VID(writer->config->tsdb->pVnode), lino, code);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t tsdbFSetRAWWriteFileDataEnd(SFSetRAWWriter *writer) {
|
||||
int32_t code = 0;
|
||||
int32_t lino = 0;
|
||||
|
||||
code = tsdbDataFileRAWWriterClose(&writer->dataWriter, false, writer->ctx->fopArr);
|
||||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
|
||||
_exit:
|
||||
if (code) {
|
||||
TSDB_ERROR_LOG(TD_VID(writer->config->tsdb->pVnode), lino, code);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
int32_t tsdbFSetRAWWriterClose(SFSetRAWWriter **writer, bool abort, TFileOpArray *fopArr) {
|
||||
if (writer[0] == NULL) return 0;
|
||||
|
||||
int32_t code = 0;
|
||||
int32_t lino = 0;
|
||||
|
||||
STsdb *tsdb = writer[0]->config->tsdb;
|
||||
|
||||
// end
|
||||
code = tsdbFSetRAWWriteFileDataEnd(writer[0]);
|
||||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
|
||||
code = tsdbDataFileRAWWriterClose(&writer[0]->dataWriter, abort, writer[0]->ctx->fopArr);
|
||||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
|
||||
code = tsdbFSetRAWWriterFinish(writer[0], fopArr);
|
||||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
// free
|
||||
TARRAY2_DESTROY(writer[0]->ctx->fopArr, NULL);
|
||||
taosMemoryFree(writer[0]);
|
||||
writer[0] = NULL;
|
||||
|
||||
_exit:
|
||||
if (code) {
|
||||
TSDB_ERROR_LOG(TD_VID(tsdb->pVnode), lino, code);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
int32_t tsdbFSetRAWWriteBlockData(SFSetRAWWriter *writer, STsdbDataRAWBlockHeader *bHdr) {
|
||||
int32_t code = 0;
|
||||
int32_t lino = 0;
|
||||
|
||||
ASSERT(writer->ctx->offset >= 0 && writer->ctx->offset <= writer->ctx->file.size);
|
||||
|
||||
if (writer->ctx->offset == writer->ctx->file.size) {
|
||||
code = tsdbFSetRAWWriteFileDataEnd(writer);
|
||||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
|
||||
code = tsdbFSetRAWWriteFileDataBegin(writer, bHdr);
|
||||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
}
|
||||
|
||||
code = tsdbDataFileRAWWriteBlockData(writer->dataWriter, bHdr);
|
||||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
|
||||
writer->ctx->offset += bHdr->dataLength;
|
||||
ASSERT(writer->ctx->offset == writer->dataWriter->ctx->offset);
|
||||
|
||||
_exit:
|
||||
if (code) {
|
||||
TSDB_ERROR_LOG(TD_VID(writer->config->tsdb->pVnode), lino, code);
|
||||
}
|
||||
return code;
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* 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 "tsdbDataFileRAW.h"
|
||||
|
||||
#ifndef _TSDB_FSET_RAW_H
|
||||
#define _TSDB_FSET_RAW_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct SFSetRAWWriterConfig {
|
||||
STsdb *tsdb;
|
||||
int32_t szPage;
|
||||
|
||||
SDiskID did;
|
||||
int64_t fid;
|
||||
int64_t cid;
|
||||
int32_t level;
|
||||
} SFSetRAWWriterConfig;
|
||||
|
||||
typedef struct SFSetRAWWriter SFSetRAWWriter;
|
||||
|
||||
int32_t tsdbFSetRAWWriterOpen(SFSetRAWWriterConfig *config, SFSetRAWWriter **writer);
|
||||
int32_t tsdbFSetRAWWriterClose(SFSetRAWWriter **writer, bool abort, TFileOpArray *fopArr);
|
||||
int32_t tsdbFSetRAWWriteBlockData(SFSetRAWWriter *writer, STsdbDataRAWBlockHeader *bHdr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*_TSDB_FSET_RAW_H*/
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include "tsdb.h"
|
||||
#include "tsdbFSet2.h"
|
||||
#include "tsdbUtil2.h"
|
||||
#include "tsdbMerge.h"
|
||||
#include "tsdbReadUtil.h"
|
||||
#include "tsdbSttFileRW.h"
|
||||
|
@ -52,15 +53,6 @@ SSttBlockLoadInfo *tCreateSttBlockLoadInfo(STSchema *pSchema, int16_t *colList,
|
|||
return pLoadInfo;
|
||||
}
|
||||
|
||||
void getSttBlockLoadInfo(SSttBlockLoadInfo *pLoadInfo, SSttBlockLoadCostInfo* pLoadCost) {
|
||||
for (int32_t i = 0; i < 1; ++i) {
|
||||
pLoadCost->blockElapsedTime += pLoadInfo[i].cost.blockElapsedTime;
|
||||
pLoadCost->loadBlocks += pLoadInfo[i].cost.loadBlocks;
|
||||
pLoadCost->loadStatisBlocks += pLoadInfo[i].cost.loadStatisBlocks;
|
||||
pLoadCost->statisElapsedTime += pLoadInfo[i].cost.statisElapsedTime;
|
||||
}
|
||||
}
|
||||
|
||||
void *destroySttBlockLoadInfo(SSttBlockLoadInfo *pLoadInfo) {
|
||||
if (pLoadInfo == NULL) {
|
||||
return NULL;
|
||||
|
@ -78,9 +70,11 @@ void *destroySttBlockLoadInfo(SSttBlockLoadInfo *pLoadInfo) {
|
|||
pInfo->sttBlockIndex = -1;
|
||||
pInfo->pin = false;
|
||||
|
||||
if (pLoadInfo->statisBlock != NULL) {
|
||||
tStatisBlockDestroy(pLoadInfo->statisBlock);
|
||||
taosMemoryFreeClear(pLoadInfo->statisBlock);
|
||||
if (pLoadInfo->info.pCount != NULL) {
|
||||
taosArrayDestroy(pLoadInfo->info.pUid);
|
||||
taosArrayDestroy(pLoadInfo->info.pFirstKey);
|
||||
taosArrayDestroy(pLoadInfo->info.pLastKey);
|
||||
taosArrayDestroy(pLoadInfo->info.pCount);
|
||||
}
|
||||
|
||||
taosArrayDestroy(pLoadInfo->aSttBlk);
|
||||
|
@ -172,7 +166,7 @@ static SBlockData *loadLastBlock(SLDataIter *pIter, const char *idStr) {
|
|||
pInfo->cost.blockElapsedTime += el;
|
||||
pInfo->cost.loadBlocks += 1;
|
||||
|
||||
tsdbDebug("read last block, total load:%" PRId64 ", trigger by uid:%" PRIu64 ", stt-fileVer:%" PRId64
|
||||
tsdbDebug("read stt block, total load:%" PRId64 ", trigger by uid:%" PRIu64 ", stt-fileVer:%" PRId64
|
||||
", last block index:%d, entry:%d, rows:%d, uidRange:%" PRId64 "-%" PRId64 " tsRange:%" PRId64 "-%" PRId64
|
||||
" %p, elapsed time:%.2f ms, %s",
|
||||
pInfo->cost.loadBlocks, pIter->uid, pIter->cid, pIter->iSttBlk, pInfo->currentLoadBlockIndex, pBlock->nRow,
|
||||
|
@ -323,95 +317,77 @@ static int32_t extractSttBlockInfo(SLDataIter *pIter, const TSttBlkArray *pArray
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t suidComparFn(const void *target, const void *p2) {
|
||||
const uint64_t *targetUid = target;
|
||||
const uint64_t *uid2 = p2;
|
||||
if (*uid2 == (*targetUid)) {
|
||||
static int32_t loadSttStatisticsBlockData(SSttFileReader *pSttFileReader, SSttBlockLoadInfo *pBlockLoadInfo,
|
||||
TStatisBlkArray *pStatisBlkArray, uint64_t suid, const char *id) {
|
||||
int32_t numOfBlocks = TARRAY2_SIZE(pStatisBlkArray);
|
||||
if (numOfBlocks <= 0) {
|
||||
return 0;
|
||||
} else {
|
||||
return (*targetUid) < (*uid2) ? -1 : 1;
|
||||
}
|
||||
}
|
||||
|
||||
static bool existsFromSttBlkStatis(SSttBlockLoadInfo *pBlockLoadInfo, uint64_t suid, uint64_t uid,
|
||||
SSttFileReader *pReader) {
|
||||
const TStatisBlkArray *pStatisBlkArray = pBlockLoadInfo->pSttStatisBlkArray;
|
||||
if (TARRAY2_SIZE(pStatisBlkArray) <= 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int32_t i = 0;
|
||||
for (i = 0; i < TARRAY2_SIZE(pStatisBlkArray); ++i) {
|
||||
SStatisBlk *p = &pStatisBlkArray->data[i];
|
||||
if (p->minTbid.suid <= suid && p->maxTbid.suid >= suid) {
|
||||
break;
|
||||
}
|
||||
int32_t startIndex = 0;
|
||||
while((startIndex < numOfBlocks) && (pStatisBlkArray->data[startIndex].maxTbid.suid < suid)) {
|
||||
++startIndex;
|
||||
}
|
||||
|
||||
if (i >= TARRAY2_SIZE(pStatisBlkArray)) {
|
||||
return false;
|
||||
if (startIndex >= numOfBlocks || pStatisBlkArray->data[startIndex].minTbid.suid > suid) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (i < TARRAY2_SIZE(pStatisBlkArray)) {
|
||||
SStatisBlk *p = &pStatisBlkArray->data[i];
|
||||
if (p->minTbid.suid > suid) {
|
||||
return false;
|
||||
int32_t endIndex = startIndex;
|
||||
while(endIndex < numOfBlocks && pStatisBlkArray->data[endIndex].minTbid.suid <= suid) {
|
||||
++endIndex;
|
||||
}
|
||||
|
||||
int32_t num = endIndex - startIndex;
|
||||
pBlockLoadInfo->cost.loadStatisBlocks += num;
|
||||
|
||||
STbStatisBlock block;
|
||||
tStatisBlockInit(&block);
|
||||
|
||||
int64_t st = taosGetTimestampUs();
|
||||
|
||||
for(int32_t k = startIndex; k < endIndex; ++k) {
|
||||
tsdbSttFileReadStatisBlock(pSttFileReader, &pStatisBlkArray->data[k], &block);
|
||||
|
||||
int32_t i = 0;
|
||||
int32_t rows = TARRAY2_SIZE(block.suid);
|
||||
while (i < rows && block.suid->data[i] != suid) {
|
||||
++i;
|
||||
}
|
||||
|
||||
// if (pBlockLoadInfo->statisBlock == NULL) {
|
||||
// pBlockLoadInfo->statisBlock = taosMemoryCalloc(1, sizeof(STbStatisBlock));
|
||||
//
|
||||
// int64_t st = taosGetTimestampMs();
|
||||
// tsdbSttFileReadStatisBlock(pReader, p, pBlockLoadInfo->statisBlock);
|
||||
// pBlockLoadInfo->statisBlockIndex = i;
|
||||
//
|
||||
// double el = (taosGetTimestampMs() - st) / 1000.0;
|
||||
// pBlockLoadInfo->cost.loadStatisBlocks += 1;
|
||||
// pBlockLoadInfo->cost.statisElapsedTime += el;
|
||||
// } else if (pBlockLoadInfo->statisBlockIndex != i) {
|
||||
// tStatisBlockDestroy(pBlockLoadInfo->statisBlock);
|
||||
//
|
||||
// int64_t st = taosGetTimestampMs();
|
||||
// tsdbSttFileReadStatisBlock(pReader, p, pBlockLoadInfo->statisBlock);
|
||||
// pBlockLoadInfo->statisBlockIndex = i;
|
||||
//
|
||||
// double el = (taosGetTimestampMs() - st) / 1000.0;
|
||||
// pBlockLoadInfo->cost.loadStatisBlocks += 1;
|
||||
// pBlockLoadInfo->cost.statisElapsedTime += el;
|
||||
// }
|
||||
|
||||
STbStatisBlock* pBlock = pBlockLoadInfo->statisBlock;
|
||||
int32_t index = tarray2SearchIdx(pBlock->suid, &suid, sizeof(int64_t), suidComparFn, TD_EQ);
|
||||
if (index == -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int32_t j = index;
|
||||
if (pBlock->uid->data[j] == uid) {
|
||||
return true;
|
||||
} else if (pBlock->uid->data[j] > uid) {
|
||||
while (j >= 0 && pBlock->suid->data[j] == suid) {
|
||||
if (pBlock->uid->data[j] == uid) {
|
||||
return true;
|
||||
} else {
|
||||
j -= 1;
|
||||
}
|
||||
// existed
|
||||
if (i < rows) {
|
||||
if (pBlockLoadInfo->info.pUid == NULL) {
|
||||
pBlockLoadInfo->info.pUid = taosArrayInit(rows, sizeof(int64_t));
|
||||
pBlockLoadInfo->info.pFirstKey = taosArrayInit(rows, sizeof(int64_t));
|
||||
pBlockLoadInfo->info.pLastKey = taosArrayInit(rows, sizeof(int64_t));
|
||||
pBlockLoadInfo->info.pCount = taosArrayInit(rows, sizeof(int64_t));
|
||||
}
|
||||
} else {
|
||||
j = index + 1;
|
||||
while (j < pBlock->suid->size && pBlock->suid->data[j] == suid) {
|
||||
if (pBlock->uid->data[j] == uid) {
|
||||
return true;
|
||||
} else {
|
||||
j += 1;
|
||||
|
||||
if (pStatisBlkArray->data[k].maxTbid.suid == suid) {
|
||||
taosArrayAddBatch(pBlockLoadInfo->info.pUid, &block.uid->data[i], rows - i);
|
||||
taosArrayAddBatch(pBlockLoadInfo->info.pFirstKey, &block.firstKey->data[i], rows - i);
|
||||
taosArrayAddBatch(pBlockLoadInfo->info.pLastKey, &block.lastKey->data[i], rows - i);
|
||||
taosArrayAddBatch(pBlockLoadInfo->info.pCount, &block.count->data[i], rows - i);
|
||||
} else {
|
||||
while (i < rows && block.suid->data[i] == suid) {
|
||||
taosArrayPush(pBlockLoadInfo->info.pUid, &block.uid->data[i]);
|
||||
taosArrayPush(pBlockLoadInfo->info.pFirstKey, &block.firstKey->data[i]);
|
||||
taosArrayPush(pBlockLoadInfo->info.pLastKey, &block.lastKey->data[i]);
|
||||
taosArrayPush(pBlockLoadInfo->info.pCount, &block.count->data[i]);
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
i += 1;
|
||||
}
|
||||
|
||||
return false;
|
||||
tStatisBlockDestroy(&block);
|
||||
|
||||
double el = (taosGetTimestampUs() - st) / 1000.0;
|
||||
pBlockLoadInfo->cost.statisElapsedTime += el;
|
||||
|
||||
tsdbDebug("%s load %d statis blocks into buf, elapsed time:%.2fms", id, num, el);
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t doLoadSttFilesBlk(SSttBlockLoadInfo *pBlockLoadInfo, SLDataIter *pIter, int64_t suid,
|
||||
|
@ -428,19 +404,28 @@ static int32_t doLoadSttFilesBlk(SSttBlockLoadInfo *pBlockLoadInfo, SLDataIter *
|
|||
return code;
|
||||
}
|
||||
|
||||
// load the stt block info for each stt file block
|
||||
code = extractSttBlockInfo(pIter, pSttBlkArray, pBlockLoadInfo, suid);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
tsdbError("load stt block info failed, code:%s, %s", tstrerror(code), idStr);
|
||||
return code;
|
||||
}
|
||||
|
||||
// load stt blocks statis for all stt-blocks, to decide if the data of queried table exists in current stt file
|
||||
code = tsdbSttFileReadStatisBlk(pIter->pReader, (const TStatisBlkArray **)&pBlockLoadInfo->pSttStatisBlkArray);
|
||||
// load stt statistics block for all stt-blocks, to decide if the data of queried table exists in current stt file
|
||||
TStatisBlkArray *pStatisBlkArray = NULL;
|
||||
code = tsdbSttFileReadStatisBlk(pIter->pReader, (const TStatisBlkArray **)&pStatisBlkArray);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
tsdbError("failed to load stt block statistics, code:%s, %s", tstrerror(code), idStr);
|
||||
return code;
|
||||
}
|
||||
|
||||
// load statistics block for all tables in current stt file
|
||||
code = loadSttStatisticsBlockData(pIter->pReader, pIter->pBlockLoadInfo, pStatisBlkArray, suid, idStr);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
tsdbError("failed to load stt statistics block data, code:%s, %s", tstrerror(code), idStr);
|
||||
return code;
|
||||
}
|
||||
|
||||
code = loadTombFn(pReader1, pIter->pReader, pIter->pBlockLoadInfo);
|
||||
|
||||
double el = (taosGetTimestampUs() - st) / 1000.0;
|
||||
|
@ -448,19 +433,44 @@ static int32_t doLoadSttFilesBlk(SSttBlockLoadInfo *pBlockLoadInfo, SLDataIter *
|
|||
return code;
|
||||
}
|
||||
|
||||
static int32_t uidComparFn(const void* p1, const void* p2) {
|
||||
const uint64_t *pFirst = p1;
|
||||
const uint64_t *pVal = p2;
|
||||
|
||||
if (*pFirst == *pVal) {
|
||||
return 0;
|
||||
} else {
|
||||
return *pFirst < *pVal? -1:1;
|
||||
}
|
||||
}
|
||||
|
||||
static void setSttInfoForCurrentTable(SSttBlockLoadInfo *pLoadInfo, uint64_t uid, STimeWindow *pTimeWindow,
|
||||
int64_t *numOfRows) {
|
||||
if (pTimeWindow == NULL || taosArrayGetSize(pLoadInfo->info.pUid) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t index = taosArraySearchIdx(pLoadInfo->info.pUid, &uid, uidComparFn, TD_EQ);
|
||||
if (index >= 0) {
|
||||
pTimeWindow->skey = *(int64_t *)taosArrayGet(pLoadInfo->info.pFirstKey, index);
|
||||
pTimeWindow->ekey = *(int64_t *)taosArrayGet(pLoadInfo->info.pLastKey, index);
|
||||
|
||||
*numOfRows += *(int64_t*) taosArrayGet(pLoadInfo->info.pCount, index);
|
||||
}
|
||||
}
|
||||
|
||||
int32_t tLDataIterOpen2(SLDataIter *pIter, SSttFileReader *pSttFileReader, int32_t cid, int8_t backward,
|
||||
uint64_t suid, uint64_t uid, STimeWindow *pTimeWindow, SVersionRange *pRange,
|
||||
SSttBlockLoadInfo *pBlockLoadInfo, const char *idStr, bool strictTimeRange,
|
||||
_load_tomb_fn loadTombFn, void *pReader1) {
|
||||
SMergeTreeConf *pConf, SSttBlockLoadInfo *pBlockLoadInfo, STimeWindow *pTimeWindow,
|
||||
int64_t *numOfRows, const char *idStr) {
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
|
||||
pIter->uid = uid;
|
||||
pIter->uid = pConf->uid;
|
||||
pIter->cid = cid;
|
||||
pIter->backward = backward;
|
||||
pIter->verRange.minVer = pRange->minVer;
|
||||
pIter->verRange.maxVer = pRange->maxVer;
|
||||
pIter->timeWindow.skey = pTimeWindow->skey;
|
||||
pIter->timeWindow.ekey = pTimeWindow->ekey;
|
||||
pIter->verRange.minVer = pConf->verRange.minVer;
|
||||
pIter->verRange.maxVer = pConf->verRange.maxVer;
|
||||
pIter->timeWindow.skey = pConf->timewindow.skey;
|
||||
pIter->timeWindow.ekey = pConf->timewindow.ekey;
|
||||
pIter->pReader = pSttFileReader;
|
||||
pIter->pBlockLoadInfo = pBlockLoadInfo;
|
||||
|
||||
|
@ -473,34 +483,29 @@ int32_t tLDataIterOpen2(SLDataIter *pIter, SSttFileReader *pSttFileReader, int32
|
|||
}
|
||||
|
||||
if (!pBlockLoadInfo->sttBlockLoaded) {
|
||||
code = doLoadSttFilesBlk(pBlockLoadInfo, pIter, suid, loadTombFn, pReader1, idStr);
|
||||
code = doLoadSttFilesBlk(pBlockLoadInfo, pIter, pConf->suid, pConf->loadTombFn, pConf->pReader, idStr);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
|
||||
// bool exists = existsFromSttBlkStatis(pBlockLoadInfo, suid, uid, pIter->pReader);
|
||||
// if (!exists) {
|
||||
// pIter->iSttBlk = -1;
|
||||
// pIter->pSttBlk = NULL;
|
||||
// return TSDB_CODE_SUCCESS;
|
||||
// }
|
||||
setSttInfoForCurrentTable(pBlockLoadInfo, pConf->uid, pTimeWindow, numOfRows);
|
||||
|
||||
// find the start block, actually we could load the position to avoid repeatly searching for the start position when
|
||||
// the skey is updated.
|
||||
size_t size = taosArrayGetSize(pBlockLoadInfo->aSttBlk);
|
||||
pIter->iSttBlk = binarySearchForStartBlock(pBlockLoadInfo->aSttBlk->pData, size, uid, backward);
|
||||
pIter->iSttBlk = binarySearchForStartBlock(pBlockLoadInfo->aSttBlk->pData, size, pConf->uid, backward);
|
||||
if (pIter->iSttBlk != -1) {
|
||||
pIter->pSttBlk = taosArrayGet(pBlockLoadInfo->aSttBlk, pIter->iSttBlk);
|
||||
pIter->iRow = (pIter->backward) ? pIter->pSttBlk->nRow : -1;
|
||||
|
||||
if ((!backward) && ((strictTimeRange && pIter->pSttBlk->minKey >= pIter->timeWindow.ekey) ||
|
||||
(!strictTimeRange && pIter->pSttBlk->minKey > pIter->timeWindow.ekey))) {
|
||||
if ((!backward) && ((pConf->strictTimeRange && pIter->pSttBlk->minKey >= pIter->timeWindow.ekey) ||
|
||||
(!pConf->strictTimeRange && pIter->pSttBlk->minKey > pIter->timeWindow.ekey))) {
|
||||
pIter->pSttBlk = NULL;
|
||||
}
|
||||
|
||||
if (backward && ((strictTimeRange && pIter->pSttBlk->maxKey <= pIter->timeWindow.skey) ||
|
||||
(!strictTimeRange && pIter->pSttBlk->maxKey < pIter->timeWindow.skey))) {
|
||||
if (backward && ((pConf->strictTimeRange && pIter->pSttBlk->maxKey <= pIter->timeWindow.skey) ||
|
||||
(!pConf->strictTimeRange && pIter->pSttBlk->maxKey < pIter->timeWindow.skey))) {
|
||||
pIter->pSttBlk = NULL;
|
||||
pIter->ignoreEarlierTs = true;
|
||||
}
|
||||
|
@ -708,8 +713,6 @@ bool tLDataIterNextRow(SLDataIter *pIter, const char *idStr) {
|
|||
return (terrno == TSDB_CODE_SUCCESS) && (pIter->pSttBlk != NULL) && (pBlockData != NULL);
|
||||
}
|
||||
|
||||
SRowInfo *tLDataIterGet(SLDataIter *pIter) { return &pIter->rInfo; }
|
||||
|
||||
// SMergeTree =================================================
|
||||
static FORCE_INLINE int32_t tLDataIterCmprFn(const SRBTreeNode *p1, const SRBTreeNode *p2) {
|
||||
SLDataIter *pIter1 = (SLDataIter *)(((uint8_t *)p1) - offsetof(SLDataIter, node));
|
||||
|
@ -737,7 +740,7 @@ static FORCE_INLINE int32_t tLDataIterDescCmprFn(const SRBTreeNode *p1, const SR
|
|||
return -1 * tLDataIterCmprFn(p1, p2);
|
||||
}
|
||||
|
||||
int32_t tMergeTreeOpen2(SMergeTree *pMTree, SMergeTreeConf *pConf) {
|
||||
int32_t tMergeTreeOpen2(SMergeTree *pMTree, SMergeTreeConf *pConf, SSttDataInfoForTable* pSttDataInfo) {
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
|
||||
pMTree->pIter = NULL;
|
||||
|
@ -758,17 +761,16 @@ int32_t tMergeTreeOpen2(SMergeTree *pMTree, SMergeTreeConf *pConf) {
|
|||
goto _end;
|
||||
}
|
||||
|
||||
// add the list/iter placeholder
|
||||
adjustLDataIters(pConf->pSttFileBlockIterArray, pConf->pCurrentFileset);
|
||||
adjustSttDataIters(pConf->pSttFileBlockIterArray, pConf->pCurrentFileset);
|
||||
|
||||
for (int32_t j = 0; j < numOfLevels; ++j) {
|
||||
SSttLvl *pSttLevel = ((STFileSet *)pConf->pCurrentFileset)->lvlArr->data[j];
|
||||
SArray *pList = taosArrayGetP(pConf->pSttFileBlockIterArray, j);
|
||||
SArray * pList = taosArrayGetP(pConf->pSttFileBlockIterArray, j);
|
||||
|
||||
for (int32_t i = 0; i < TARRAY2_SIZE(pSttLevel->fobjArr); ++i) { // open all last file
|
||||
SLDataIter *pIter = taosArrayGetP(pList, i);
|
||||
|
||||
SSttFileReader *pSttFileReader = pIter->pReader;
|
||||
SSttFileReader * pSttFileReader = pIter->pReader;
|
||||
SSttBlockLoadInfo *pLoadInfo = pIter->pBlockLoadInfo;
|
||||
|
||||
// open stt file reader if not opened yet
|
||||
|
@ -790,10 +792,11 @@ int32_t tMergeTreeOpen2(SMergeTree *pMTree, SMergeTreeConf *pConf) {
|
|||
|
||||
memset(pIter, 0, sizeof(SLDataIter));
|
||||
|
||||
STimeWindow w = {0};
|
||||
int64_t numOfRows = 0;
|
||||
|
||||
int64_t cid = pSttLevel->fobjArr->data[i]->f->cid;
|
||||
code = tLDataIterOpen2(pIter, pSttFileReader, cid, pMTree->backward, pConf->suid, pConf->uid, &pConf->timewindow,
|
||||
&pConf->verRange, pLoadInfo, pMTree->idStr, pConf->strictTimeRange, pConf->loadTombFn,
|
||||
pConf->pReader);
|
||||
code = tLDataIterOpen2(pIter, pSttFileReader, cid, pMTree->backward, pConf, pLoadInfo, &w, &numOfRows, pMTree->idStr);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
goto _end;
|
||||
}
|
||||
|
@ -801,6 +804,12 @@ int32_t tMergeTreeOpen2(SMergeTree *pMTree, SMergeTreeConf *pConf) {
|
|||
bool hasVal = tLDataIterNextRow(pIter, pMTree->idStr);
|
||||
if (hasVal) {
|
||||
tMergeTreeAddIter(pMTree, pIter);
|
||||
|
||||
// let's record the time window for current table of uid in the stt files
|
||||
if (pSttDataInfo != NULL) {
|
||||
taosArrayPush(pSttDataInfo->pTimeWindowList, &w);
|
||||
pSttDataInfo->numOfRows += numOfRows;
|
||||
}
|
||||
} else {
|
||||
if (!pMTree->ignoreEarlierTs) {
|
||||
pMTree->ignoreEarlierTs = pIter->ignoreEarlierTs;
|
||||
|
|
|
@ -25,6 +25,16 @@
|
|||
#define ASCENDING_TRAVERSE(o) (o == TSDB_ORDER_ASC)
|
||||
#define getCurrentKeyInSttBlock(_r) ((_r)->currentKey)
|
||||
|
||||
typedef struct {
|
||||
bool overlapWithNeighborBlock;
|
||||
bool hasDupTs;
|
||||
bool overlapWithDelInfo;
|
||||
bool overlapWithSttBlock;
|
||||
bool overlapWithKeyInBuf;
|
||||
bool partiallyRequired;
|
||||
bool moreThanCapcity;
|
||||
} SDataBlockToLoadInfo;
|
||||
|
||||
static SFileDataBlockInfo* getCurrentBlockInfo(SDataBlockIter* pBlockIter);
|
||||
static int32_t buildDataBlockFromBufImpl(STableBlockScanInfo* pBlockScanInfo, int64_t endKey, int32_t capacity,
|
||||
STsdbReader* pReader);
|
||||
|
@ -60,6 +70,8 @@ static bool hasDataInFileBlock(const SBlockData* pBlockData, const SFil
|
|||
static bool hasDataInSttBlock(SSttBlockReader* pSttBlockReader);
|
||||
static void initBlockDumpInfo(STsdbReader* pReader, SDataBlockIter* pBlockIter);
|
||||
static int32_t getInitialDelIndex(const SArray* pDelSkyline, int32_t order);
|
||||
static void resetTableListIndex(SReaderStatus* pStatus);
|
||||
static void getMemTableTimeRange(STsdbReader* pReader, int64_t* pMaxKey, int64_t* pMinKey);
|
||||
static void updateComposedBlockInfo(STsdbReader* pReader, double el, STableBlockScanInfo* pBlockScanInfo);
|
||||
|
||||
static bool outOfTimeWindow(int64_t ts, STimeWindow* pWindow) { return (ts > pWindow->ekey) || (ts < pWindow->skey); }
|
||||
|
@ -244,6 +256,7 @@ static int32_t filesetIteratorNext(SFilesetIter* pIter, STsdbReader* pReader, bo
|
|||
|
||||
tsdbDebug("%p file found fid:%d for qrange:%" PRId64 "-%" PRId64 ", %s", pReader, fid, pReader->info.window.skey,
|
||||
pReader->info.window.ekey, pReader->idStr);
|
||||
|
||||
*hasNext = true;
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
@ -422,6 +435,8 @@ static int32_t tsdbReaderCreate(SVnode* pVnode, SQueryTableDataCond* pCond, void
|
|||
goto _end;
|
||||
}
|
||||
|
||||
pReader->bFilesetDelimited = false;
|
||||
|
||||
tsdbInitReaderLock(pReader);
|
||||
tsem_init(&pReader->resumeAfterSuspend, 0, 0);
|
||||
|
||||
|
@ -591,6 +606,13 @@ static int32_t doLoadFileBlock(STsdbReader* pReader, SArray* pIndexList, SBlockN
|
|||
return TSDB_CODE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
if (pScanInfo->filesetWindow.skey > pRecord->firstKey) {
|
||||
pScanInfo->filesetWindow.skey = pRecord->firstKey;
|
||||
}
|
||||
if (pScanInfo->filesetWindow.ekey < pRecord->lastKey) {
|
||||
pScanInfo->filesetWindow.ekey = pRecord->lastKey;
|
||||
}
|
||||
|
||||
pBlockNum->numOfBlocks += 1;
|
||||
if (taosArrayGetSize(pTableScanInfoList) == 0) {
|
||||
taosArrayPush(pTableScanInfoList, &pScanInfo);
|
||||
|
@ -609,7 +631,7 @@ static int32_t doLoadFileBlock(STsdbReader* pReader, SArray* pIndexList, SBlockN
|
|||
|
||||
double el = (taosGetTimestampUs() - st) / 1000.0;
|
||||
tsdbDebug(
|
||||
"load block of %d tables completed, blocks:%d in %d tables, last-files:%d, block-info-size:%.2f Kb, elapsed "
|
||||
"load block of %d tables completed, blocks:%d in %d tables, stt-files:%d, block-info-size:%.2f Kb, elapsed "
|
||||
"time:%.2f ms %s",
|
||||
numOfTables, pBlockNum->numOfBlocks, (int32_t)taosArrayGetSize(pTableScanInfoList), pBlockNum->numOfSttFiles,
|
||||
sizeInDisk / 1000.0, el, pReader->idStr);
|
||||
|
@ -1221,78 +1243,6 @@ static bool keyOverlapFileBlock(TSDBKEY key, SFileDataBlockInfo* pBlock, SVersio
|
|||
(pBlock->record.maxVer >= pVerRange->minVer) && (pBlock->record.minVer <= pVerRange->maxVer);
|
||||
}
|
||||
|
||||
static bool doCheckforDatablockOverlap(STableBlockScanInfo* pBlockScanInfo, const SBrinRecord* pRecord,
|
||||
int32_t startIndex) {
|
||||
size_t num = taosArrayGetSize(pBlockScanInfo->delSkyline);
|
||||
|
||||
for (int32_t i = startIndex; i < num; i += 1) {
|
||||
TSDBKEY* p = taosArrayGet(pBlockScanInfo->delSkyline, i);
|
||||
if (p->ts >= pRecord->firstKey && p->ts <= pRecord->lastKey) {
|
||||
if (p->version >= pRecord->minVer) {
|
||||
return true;
|
||||
}
|
||||
} else if (p->ts < pRecord->firstKey) { // p->ts < pBlock->minKey.ts
|
||||
if (p->version >= pRecord->minVer) {
|
||||
if (i < num - 1) {
|
||||
TSDBKEY* pnext = taosArrayGet(pBlockScanInfo->delSkyline, i + 1);
|
||||
if (pnext->ts >= pRecord->firstKey) {
|
||||
return true;
|
||||
}
|
||||
} else { // it must be the last point
|
||||
ASSERT(p->version == 0);
|
||||
}
|
||||
}
|
||||
} else { // (p->ts > pBlock->maxKey.ts) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool overlapWithDelSkyline(STableBlockScanInfo* pBlockScanInfo, const SBrinRecord* pRecord, int32_t order) {
|
||||
if (pBlockScanInfo->delSkyline == NULL || (taosArrayGetSize(pBlockScanInfo->delSkyline) == 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// ts is not overlap
|
||||
TSDBKEY* pFirst = taosArrayGet(pBlockScanInfo->delSkyline, 0);
|
||||
TSDBKEY* pLast = taosArrayGetLast(pBlockScanInfo->delSkyline);
|
||||
if (pRecord->firstKey > pLast->ts || pRecord->lastKey < pFirst->ts) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// version is not overlap
|
||||
if (ASCENDING_TRAVERSE(order)) {
|
||||
return doCheckforDatablockOverlap(pBlockScanInfo, pRecord, pBlockScanInfo->fileDelIndex);
|
||||
} else {
|
||||
int32_t index = pBlockScanInfo->fileDelIndex;
|
||||
while (1) {
|
||||
TSDBKEY* p = taosArrayGet(pBlockScanInfo->delSkyline, index);
|
||||
if (p->ts > pRecord->firstKey && index > 0) {
|
||||
index -= 1;
|
||||
} else { // find the first point that is smaller than the minKey.ts of dataBlock.
|
||||
if (p->ts == pRecord->firstKey && p->version < pRecord->maxVer && index > 0) {
|
||||
index -= 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return doCheckforDatablockOverlap(pBlockScanInfo, pRecord, index);
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
bool overlapWithNeighborBlock;
|
||||
bool hasDupTs;
|
||||
bool overlapWithDelInfo;
|
||||
bool overlapWithLastBlock;
|
||||
bool overlapWithKeyInBuf;
|
||||
bool partiallyRequired;
|
||||
bool moreThanCapcity;
|
||||
} SDataBlockToLoadInfo;
|
||||
|
||||
static void getBlockToLoadInfo(SDataBlockToLoadInfo* pInfo, SFileDataBlockInfo* pBlockInfo,
|
||||
STableBlockScanInfo* pScanInfo, TSDBKEY keyInBuf, STsdbReader* pReader) {
|
||||
SBrinRecord rec = {0};
|
||||
|
@ -1313,7 +1263,7 @@ static void getBlockToLoadInfo(SDataBlockToLoadInfo* pInfo, SFileDataBlockInfo*
|
|||
ASSERT(pScanInfo->sttKeyInfo.status != STT_FILE_READER_UNINIT);
|
||||
if (pScanInfo->sttKeyInfo.status == STT_FILE_HAS_DATA) {
|
||||
int64_t nextProcKeyInStt = pScanInfo->sttKeyInfo.nextProcKey;
|
||||
pInfo->overlapWithLastBlock =
|
||||
pInfo->overlapWithSttBlock =
|
||||
!(pBlockInfo->record.lastKey < nextProcKeyInStt || pBlockInfo->record.firstKey > nextProcKeyInStt);
|
||||
}
|
||||
|
||||
|
@ -1335,15 +1285,15 @@ static bool fileBlockShouldLoad(STsdbReader* pReader, SFileDataBlockInfo* pBlock
|
|||
|
||||
bool loadDataBlock =
|
||||
(info.overlapWithNeighborBlock || info.hasDupTs || info.partiallyRequired || info.overlapWithKeyInBuf ||
|
||||
info.moreThanCapcity || info.overlapWithDelInfo || info.overlapWithLastBlock);
|
||||
info.moreThanCapcity || info.overlapWithDelInfo || info.overlapWithSttBlock);
|
||||
|
||||
// log the reason why load the datablock for profile
|
||||
if (loadDataBlock) {
|
||||
tsdbDebug("%p uid:%" PRIu64
|
||||
" need to load the datablock, overlapneighbor:%d, hasDup:%d, partiallyRequired:%d, "
|
||||
"overlapWithKey:%d, greaterThanBuf:%d, overlapWithDel:%d, overlapWithlastBlock:%d, %s",
|
||||
"overlapWithKey:%d, greaterThanBuf:%d, overlapWithDel:%d, overlapWithSttBlock:%d, %s",
|
||||
pReader, pBlockInfo->uid, info.overlapWithNeighborBlock, info.hasDupTs, info.partiallyRequired,
|
||||
info.overlapWithKeyInBuf, info.moreThanCapcity, info.overlapWithDelInfo, info.overlapWithLastBlock,
|
||||
info.overlapWithKeyInBuf, info.moreThanCapcity, info.overlapWithDelInfo, info.overlapWithSttBlock,
|
||||
pReader->idStr);
|
||||
}
|
||||
|
||||
|
@ -1355,7 +1305,7 @@ static bool isCleanFileDataBlock(STsdbReader* pReader, SFileDataBlockInfo* pBloc
|
|||
SDataBlockToLoadInfo info = {0};
|
||||
getBlockToLoadInfo(&info, pBlockInfo, pScanInfo, keyInBuf, pReader);
|
||||
bool isCleanFileBlock = !(info.overlapWithNeighborBlock || info.hasDupTs || info.overlapWithKeyInBuf ||
|
||||
info.overlapWithDelInfo || info.overlapWithLastBlock);
|
||||
info.overlapWithDelInfo || info.overlapWithSttBlock);
|
||||
return isCleanFileBlock;
|
||||
}
|
||||
|
||||
|
@ -2110,27 +2060,34 @@ static bool isValidFileBlockRow(SBlockData* pBlockData, SFileBlockDumpInfo* pDum
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool initSttBlockReader(SSttBlockReader* pLBlockReader, STableBlockScanInfo* pScanInfo, STsdbReader* pReader) {
|
||||
// the last block reader has been initialized for this table.
|
||||
if (pLBlockReader->uid == pScanInfo->uid) {
|
||||
return hasDataInSttBlock(pLBlockReader);
|
||||
static bool initSttBlockReader(SSttBlockReader* pSttBlockReader, STableBlockScanInfo* pScanInfo, STsdbReader* pReader) {
|
||||
bool hasData = true;
|
||||
|
||||
// the stt block reader has been initialized for this table.
|
||||
if (pSttBlockReader->uid == pScanInfo->uid) {
|
||||
return hasDataInSttBlock(pSttBlockReader);
|
||||
}
|
||||
|
||||
if (pLBlockReader->uid != 0) {
|
||||
tMergeTreeClose(&pLBlockReader->mergeTree);
|
||||
if (pSttBlockReader->uid != 0) {
|
||||
tMergeTreeClose(&pSttBlockReader->mergeTree);
|
||||
}
|
||||
|
||||
pLBlockReader->uid = pScanInfo->uid;
|
||||
pSttBlockReader->uid = pScanInfo->uid;
|
||||
|
||||
STimeWindow w = pLBlockReader->window;
|
||||
if (ASCENDING_TRAVERSE(pLBlockReader->order)) {
|
||||
// second time init stt block reader
|
||||
if (pScanInfo->cleanSttBlocks && pReader->info.execMode == READER_EXEC_ROWS) {
|
||||
return !pScanInfo->sttBlockReturned;
|
||||
}
|
||||
|
||||
STimeWindow w = pSttBlockReader->window;
|
||||
if (ASCENDING_TRAVERSE(pSttBlockReader->order)) {
|
||||
w.skey = pScanInfo->sttKeyInfo.nextProcKey;
|
||||
} else {
|
||||
w.ekey = pScanInfo->sttKeyInfo.nextProcKey;
|
||||
}
|
||||
|
||||
int64_t st = taosGetTimestampUs();
|
||||
tsdbDebug("init last block reader, window:%" PRId64 "-%" PRId64 ", uid:%" PRIu64 ", %s", w.skey, w.ekey,
|
||||
tsdbDebug("init stt block reader, window:%" PRId64 "-%" PRId64 ", uid:%" PRIu64 ", %s", w.skey, w.ekey,
|
||||
pScanInfo->uid, pReader->idStr);
|
||||
|
||||
SMergeTreeConf conf = {
|
||||
|
@ -2138,20 +2095,22 @@ static bool initSttBlockReader(SSttBlockReader* pLBlockReader, STableBlockScanIn
|
|||
.suid = pReader->info.suid,
|
||||
.pTsdb = pReader->pTsdb,
|
||||
.timewindow = w,
|
||||
.verRange = pLBlockReader->verRange,
|
||||
.verRange = pSttBlockReader->verRange,
|
||||
.strictTimeRange = false,
|
||||
.pSchema = pReader->info.pSchema,
|
||||
.pCurrentFileset = pReader->status.pCurrentFileset,
|
||||
.backward = (pLBlockReader->order == TSDB_ORDER_DESC),
|
||||
.backward = (pSttBlockReader->order == TSDB_ORDER_DESC),
|
||||
.pSttFileBlockIterArray = pReader->status.pLDataIterArray,
|
||||
.pCols = pReader->suppInfo.colId,
|
||||
.numOfCols = pReader->suppInfo.numOfCols,
|
||||
.loadTombFn = loadSttTombDataForAll,
|
||||
.pReader = pReader,
|
||||
.idstr = pReader->idStr,
|
||||
.rspRows = (pReader->info.execMode == READER_EXEC_ROWS),
|
||||
};
|
||||
|
||||
int32_t code = tMergeTreeOpen2(&pLBlockReader->mergeTree, &conf);
|
||||
SSttDataInfoForTable info = {.pTimeWindowList = taosArrayInit(4, sizeof(STimeWindow))};
|
||||
int32_t code = tMergeTreeOpen2(&pSttBlockReader->mergeTree, &conf, &info);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
|
@ -2159,13 +2118,44 @@ static bool initSttBlockReader(SSttBlockReader* pLBlockReader, STableBlockScanIn
|
|||
initMemDataIterator(pScanInfo, pReader);
|
||||
initDelSkylineIterator(pScanInfo, pReader->info.order, &pReader->cost);
|
||||
|
||||
code = nextRowFromSttBlocks(pLBlockReader, pScanInfo, &pReader->info.verRange);
|
||||
if (conf.rspRows) {
|
||||
pScanInfo->cleanSttBlocks =
|
||||
isCleanSttBlock(info.pTimeWindowList, &pReader->info.window, pScanInfo, pReader->info.order);
|
||||
|
||||
if (pScanInfo->cleanSttBlocks) {
|
||||
pScanInfo->numOfRowsInStt = info.numOfRows;
|
||||
pScanInfo->sttWindow.skey = INT64_MAX;
|
||||
pScanInfo->sttWindow.ekey = INT64_MIN;
|
||||
|
||||
// calculate the time window for data in stt files
|
||||
for(int32_t i = 0; i < taosArrayGetSize(info.pTimeWindowList); ++i) {
|
||||
STimeWindow* pWindow = taosArrayGet(info.pTimeWindowList, i);
|
||||
if (pScanInfo->sttWindow.skey > pWindow->skey) {
|
||||
pScanInfo->sttWindow.skey = pWindow->skey;
|
||||
}
|
||||
|
||||
if (pScanInfo->sttWindow.ekey < pWindow->ekey) {
|
||||
pScanInfo->sttWindow.ekey = pWindow->ekey;
|
||||
}
|
||||
}
|
||||
|
||||
pScanInfo->sttKeyInfo.status = taosArrayGetSize(info.pTimeWindowList)? STT_FILE_HAS_DATA:STT_FILE_NO_DATA;
|
||||
pScanInfo->sttKeyInfo.nextProcKey = ASCENDING_TRAVERSE(pReader->info.order)? pScanInfo->sttWindow.skey:pScanInfo->sttWindow.ekey;
|
||||
hasData = true;
|
||||
} else {
|
||||
hasData = nextRowFromSttBlocks(pSttBlockReader, pScanInfo, &pReader->info.verRange);
|
||||
}
|
||||
} else {
|
||||
hasData = nextRowFromSttBlocks(pSttBlockReader, pScanInfo, &pReader->info.verRange);
|
||||
}
|
||||
|
||||
taosArrayDestroy(info.pTimeWindowList);
|
||||
|
||||
int64_t el = taosGetTimestampUs() - st;
|
||||
pReader->cost.initSttBlockReader += (el / 1000.0);
|
||||
|
||||
tsdbDebug("init last block reader completed, elapsed time:%" PRId64 "us %s", el, pReader->idStr);
|
||||
return code;
|
||||
tsdbDebug("init stt block reader completed, elapsed time:%" PRId64 "us %s", el, pReader->idStr);
|
||||
return hasData;
|
||||
}
|
||||
|
||||
static bool hasDataInSttBlock(SSttBlockReader* pSttBlockReader) { return pSttBlockReader->mergeTree.pIter != NULL; }
|
||||
|
@ -2356,18 +2346,15 @@ void updateComposedBlockInfo(STsdbReader* pReader, double el, STableBlockScanInf
|
|||
|
||||
static int32_t buildComposedDataBlock(STsdbReader* pReader) {
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
bool asc = ASCENDING_TRAVERSE(pReader->info.order);
|
||||
int64_t st = taosGetTimestampUs();
|
||||
int32_t step = asc ? 1 : -1;
|
||||
double el = 0;
|
||||
|
||||
SSDataBlock* pResBlock = pReader->resBlockInfo.pResBlock;
|
||||
|
||||
SSDataBlock* pResBlock = pReader->resBlockInfo.pResBlock;
|
||||
SFileDataBlockInfo* pBlockInfo = getCurrentBlockInfo(&pReader->status.blockIter);
|
||||
SSttBlockReader* pSttBlockReader = pReader->status.fileIter.pSttBlockReader;
|
||||
|
||||
bool asc = ASCENDING_TRAVERSE(pReader->info.order);
|
||||
int64_t st = taosGetTimestampUs();
|
||||
int32_t step = asc ? 1 : -1;
|
||||
double el = 0;
|
||||
SBrinRecord* pRecord = &pBlockInfo->record;
|
||||
|
||||
SSttBlockReader* pSttBlockReader = pReader->status.fileIter.pSttBlockReader;
|
||||
SBrinRecord* pRecord = &pBlockInfo->record;
|
||||
SFileBlockDumpInfo* pDumpInfo = &pReader->status.fBlockDumpInfo;
|
||||
|
||||
STableBlockScanInfo* pBlockScanInfo = NULL;
|
||||
|
@ -2556,6 +2543,41 @@ TSDBKEY getCurrentKeyInBuf(STableBlockScanInfo* pScanInfo, STsdbReader* pReader)
|
|||
}
|
||||
}
|
||||
|
||||
static void prepareDurationForNextFileSet(STsdbReader* pReader) {
|
||||
if (pReader->status.bProcMemFirstFileset) {
|
||||
pReader->status.prevFilesetStartKey = INT64_MIN;
|
||||
pReader->status.prevFilesetEndKey = INT64_MAX;
|
||||
pReader->status.bProcMemFirstFileset = false;
|
||||
}
|
||||
|
||||
int32_t fid = pReader->status.pCurrentFileset->fid;
|
||||
STimeWindow winFid = {0};
|
||||
tsdbFidKeyRange(fid, pReader->pTsdb->keepCfg.days, pReader->pTsdb->keepCfg.precision, &winFid.skey, &winFid.ekey);
|
||||
|
||||
if (ASCENDING_TRAVERSE(pReader->info.order)) {
|
||||
pReader->status.bProcMemPreFileset = !(pReader->status.memTableMaxKey < pReader->status.prevFilesetStartKey ||
|
||||
(winFid.skey-1) < pReader->status.memTableMinKey);
|
||||
} else {
|
||||
pReader->status.bProcMemPreFileset = !( pReader->status.memTableMaxKey < (winFid.ekey+1) ||
|
||||
pReader->status.prevFilesetEndKey < pReader->status.memTableMinKey);
|
||||
}
|
||||
|
||||
if (pReader->status.bProcMemPreFileset) {
|
||||
resetTableListIndex(&pReader->status);
|
||||
}
|
||||
|
||||
if (!pReader->status.bProcMemPreFileset) {
|
||||
if (pReader->notifyFn) {
|
||||
STsdReaderNotifyInfo info = {0};
|
||||
info.duration.filesetId = fid;
|
||||
pReader->notifyFn(TSD_READER_NOTIFY_DURATION_START, &info, pReader->notifyParam);
|
||||
}
|
||||
}
|
||||
|
||||
pReader->status.prevFilesetStartKey = winFid.skey;
|
||||
pReader->status.prevFilesetEndKey = winFid.ekey;
|
||||
}
|
||||
|
||||
static int32_t moveToNextFile(STsdbReader* pReader, SBlockNumber* pBlockNum, SArray* pTableList) {
|
||||
SReaderStatus* pStatus = &pReader->status;
|
||||
pBlockNum->numOfBlocks = 0;
|
||||
|
@ -2597,6 +2619,9 @@ static int32_t moveToNextFile(STsdbReader* pReader, SBlockNumber* pBlockNum, SAr
|
|||
}
|
||||
|
||||
if (pBlockNum->numOfBlocks + pBlockNum->numOfSttFiles > 0) {
|
||||
if (pReader->bFilesetDelimited) {
|
||||
prepareDurationForNextFileSet(pReader);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -2629,10 +2654,10 @@ static bool moveToNextTable(STableUidList* pOrderedCheckInfo, SReaderStatus* pSt
|
|||
}
|
||||
|
||||
static int32_t doLoadSttBlockSequentially(STsdbReader* pReader) {
|
||||
SReaderStatus* pStatus = &pReader->status;
|
||||
SReaderStatus* pStatus = &pReader->status;
|
||||
SSttBlockReader* pSttBlockReader = pStatus->fileIter.pSttBlockReader;
|
||||
STableUidList* pUidList = &pStatus->uidList;
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
STableUidList* pUidList = &pStatus->uidList;
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
|
||||
if (tSimpleHashGetSize(pStatus->pTableMap) == 0) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
|
@ -2668,8 +2693,8 @@ static int32_t doLoadSttBlockSequentially(STsdbReader* pReader) {
|
|||
continue;
|
||||
}
|
||||
|
||||
bool hasDataInLastFile = initSttBlockReader(pSttBlockReader, pScanInfo, pReader);
|
||||
if (!hasDataInLastFile) {
|
||||
bool hasDataInSttFile = initSttBlockReader(pSttBlockReader, pScanInfo, pReader);
|
||||
if (!hasDataInSttFile) {
|
||||
bool hasNexTable = moveToNextTable(pUidList, pStatus);
|
||||
if (!hasNexTable) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
|
@ -2678,12 +2703,37 @@ static int32_t doLoadSttBlockSequentially(STsdbReader* pReader) {
|
|||
continue;
|
||||
}
|
||||
|
||||
// if only require the total rows, no need to load data from stt file if it is clean stt blocks
|
||||
if (pReader->info.execMode == READER_EXEC_ROWS && pScanInfo->cleanSttBlocks) {
|
||||
bool asc = ASCENDING_TRAVERSE(pReader->info.order);
|
||||
|
||||
SDataBlockInfo* pInfo = &pResBlock->info;
|
||||
blockDataEnsureCapacity(pResBlock, pScanInfo->numOfRowsInStt);
|
||||
|
||||
pInfo->rows = pScanInfo->numOfRowsInStt;
|
||||
pInfo->id.uid = pScanInfo->uid;
|
||||
pInfo->dataLoad = 1;
|
||||
pInfo->window = pScanInfo->sttWindow;
|
||||
|
||||
setComposedBlockFlag(pReader, true);
|
||||
|
||||
pScanInfo->sttKeyInfo.nextProcKey = asc ? pScanInfo->sttWindow.ekey + 1 : pScanInfo->sttWindow.skey - 1;
|
||||
pScanInfo->sttKeyInfo.status = STT_FILE_NO_DATA;
|
||||
pScanInfo->lastProcKey = asc ? pScanInfo->sttWindow.ekey : pScanInfo->sttWindow.skey;
|
||||
pScanInfo->sttBlockReturned = true;
|
||||
|
||||
pSttBlockReader->mergeTree.pIter = NULL;
|
||||
|
||||
tsdbDebug("%p uid:%" PRId64 " return clean stt block as one, brange:%" PRId64 "-%" PRId64 " rows:%" PRId64 " %s",
|
||||
pReader, pResBlock->info.id.uid, pResBlock->info.window.skey, pResBlock->info.window.ekey,
|
||||
pResBlock->info.rows, pReader->idStr);
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
int64_t st = taosGetTimestampUs();
|
||||
while (1) {
|
||||
bool hasBlockLData = hasDataInSttBlock(pSttBlockReader);
|
||||
|
||||
// no data in last block and block, no need to proceed.
|
||||
if (hasBlockLData == false) {
|
||||
// no data in stt block and block, no need to proceed.
|
||||
if (!hasDataInSttBlock(pSttBlockReader)) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -2728,14 +2778,13 @@ static bool notOverlapWithSttFiles(SFileDataBlockInfo* pBlockInfo, STableBlockSc
|
|||
}
|
||||
|
||||
static int32_t doBuildDataBlock(STsdbReader* pReader) {
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
|
||||
SReaderStatus* pStatus = &pReader->status;
|
||||
SDataBlockIter* pBlockIter = &pStatus->blockIter;
|
||||
STableBlockScanInfo* pScanInfo = NULL;
|
||||
SFileDataBlockInfo* pBlockInfo = getCurrentBlockInfo(pBlockIter);
|
||||
SSttBlockReader* pSttBlockReader = pReader->status.fileIter.pSttBlockReader;
|
||||
SSttBlockReader* pSttBlockReader = pReader->status.fileIter.pSttBlockReader;
|
||||
bool asc = ASCENDING_TRAVERSE(pReader->info.order);
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
|
||||
if (pReader->pIgnoreTables && taosHashGet(*pReader->pIgnoreTables, &pBlockInfo->uid, sizeof(pBlockInfo->uid))) {
|
||||
setBlockAllDumped(&pStatus->fBlockDumpInfo, pBlockInfo->record.lastKey, pReader->info.order);
|
||||
|
@ -2793,13 +2842,14 @@ static int32_t doBuildDataBlock(STsdbReader* pReader) {
|
|||
|
||||
SSDataBlock* pResBlock = pReader->resBlockInfo.pResBlock;
|
||||
|
||||
tsdbDebug("load data in last block firstly %s", pReader->idStr);
|
||||
tsdbDebug("load data in stt block firstly %s", pReader->idStr);
|
||||
int64_t st = taosGetTimestampUs();
|
||||
|
||||
// let's load data from stt files
|
||||
// let's load data from stt files, make sure clear the cleanStt block flag before load the data from stt files
|
||||
pScanInfo->cleanSttBlocks = false;
|
||||
initSttBlockReader(pSttBlockReader, pScanInfo, pReader);
|
||||
|
||||
// no data in last block, no need to proceed.
|
||||
// no data in stt block, no need to proceed.
|
||||
while (hasDataInSttBlock(pSttBlockReader)) {
|
||||
ASSERT(pScanInfo->sttKeyInfo.status == STT_FILE_HAS_DATA);
|
||||
|
||||
|
@ -2837,148 +2887,7 @@ static int32_t doBuildDataBlock(STsdbReader* pReader) {
|
|||
return (pReader->code != TSDB_CODE_SUCCESS) ? pReader->code : code;
|
||||
}
|
||||
|
||||
static int32_t doSumFileBlockRows(STsdbReader* pReader, SDataFReader* pFileReader) {
|
||||
int64_t st = taosGetTimestampUs();
|
||||
LRUHandle* handle = NULL;
|
||||
int32_t code = tsdbCacheGetBlockIdx(pFileReader->pTsdb->biCache, pFileReader, &handle);
|
||||
if (code != TSDB_CODE_SUCCESS || handle == NULL) {
|
||||
goto _end;
|
||||
}
|
||||
|
||||
#if 0
|
||||
int32_t numOfTables = tSimpleHashGetSize(pReader->status.pTableMap);
|
||||
|
||||
SArray* aBlockIdx = (SArray*)taosLRUCacheValue(pFileReader->pTsdb->biCache, handle);
|
||||
size_t num = taosArrayGetSize(aBlockIdx);
|
||||
if (num == 0) {
|
||||
tsdbBICacheRelease(pFileReader->pTsdb->biCache, handle);
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
SBlockIdx* pBlockIdx = NULL;
|
||||
for (int32_t i = 0; i < num; ++i) {
|
||||
pBlockIdx = (SBlockIdx*)taosArrayGet(aBlockIdx, i);
|
||||
if (pBlockIdx->suid != pReader->info.suid) {
|
||||
continue;
|
||||
}
|
||||
|
||||
STableBlockScanInfo** p = tSimpleHashGet(pReader->status.pTableMap, &pBlockIdx->uid, sizeof(pBlockIdx->uid));
|
||||
if (p == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
STableBlockScanInfo* pScanInfo = *p;
|
||||
SDataBlk block = {0};
|
||||
// for (int32_t j = 0; j < pScanInfo->mapData.nItem; ++j) {
|
||||
// tGetDataBlk(pScanInfo->mapData.pData + pScanInfo->mapData.aOffset[j], &block);
|
||||
// pReader->rowsNum += block.nRow;
|
||||
// }
|
||||
}
|
||||
#endif
|
||||
|
||||
_end:
|
||||
tsdbBICacheRelease(pFileReader->pTsdb->biCache, handle);
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t doSumSttBlockRows(STsdbReader* pReader) {
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
SSttBlockReader* pSttBlockReader = pReader->status.fileIter.pSttBlockReader;
|
||||
SSttBlockLoadInfo* pBlockLoadInfo = NULL;
|
||||
#if 0
|
||||
for (int32_t i = 0; i < pReader->pFileReader->pSet->nSttF; ++i) { // open all last file
|
||||
pBlockLoadInfo = &pSttBlockReader->pInfo[i];
|
||||
|
||||
code = tsdbReadSttBlk(pReader->pFileReader, i, pBlockLoadInfo->aSttBlk);
|
||||
if (code) {
|
||||
return code;
|
||||
}
|
||||
|
||||
size_t size = taosArrayGetSize(pBlockLoadInfo->aSttBlk);
|
||||
if (size >= 1) {
|
||||
SSttBlk* pStart = taosArrayGet(pBlockLoadInfo->aSttBlk, 0);
|
||||
SSttBlk* pEnd = taosArrayGet(pBlockLoadInfo->aSttBlk, size - 1);
|
||||
|
||||
// all identical
|
||||
if (pStart->suid == pEnd->suid) {
|
||||
if (pStart->suid != pReader->info.suid) {
|
||||
// no qualified stt block existed
|
||||
taosArrayClear(pBlockLoadInfo->aSttBlk);
|
||||
continue;
|
||||
}
|
||||
for (int32_t j = 0; j < size; ++j) {
|
||||
SSttBlk* p = taosArrayGet(pBlockLoadInfo->aSttBlk, j);
|
||||
pReader->rowsNum += p->nRow;
|
||||
}
|
||||
} else {
|
||||
for (int32_t j = 0; j < size; ++j) {
|
||||
SSttBlk* p = taosArrayGet(pBlockLoadInfo->aSttBlk, j);
|
||||
uint64_t s = p->suid;
|
||||
if (s < pReader->info.suid) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (s == pReader->info.suid) {
|
||||
pReader->rowsNum += p->nRow;
|
||||
} else if (s > pReader->info.suid) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t readRowsCountFromFiles(STsdbReader* pReader) {
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
|
||||
while (1) {
|
||||
bool hasNext = false;
|
||||
code = filesetIteratorNext(&pReader->status.fileIter, pReader, &hasNext);
|
||||
if (code) {
|
||||
return code;
|
||||
}
|
||||
|
||||
if (!hasNext) { // no data files on disk
|
||||
break;
|
||||
}
|
||||
|
||||
// code = doSumFileBlockRows(pReader, pReader->pFileReader);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
|
||||
code = doSumSttBlockRows(pReader);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
|
||||
pReader->status.loadFromFile = false;
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t readRowsCountFromMem(STsdbReader* pReader) {
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
int64_t memNum = 0, imemNum = 0;
|
||||
if (pReader->pReadSnap->pMem != NULL) {
|
||||
tsdbMemTableCountRows(pReader->pReadSnap->pMem, pReader->status.pTableMap, &memNum);
|
||||
}
|
||||
|
||||
if (pReader->pReadSnap->pIMem != NULL) {
|
||||
tsdbMemTableCountRows(pReader->pReadSnap->pIMem, pReader->status.pTableMap, &imemNum);
|
||||
}
|
||||
|
||||
pReader->rowsNum += memNum + imemNum;
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t buildBlockFromBufferSequentially(STsdbReader* pReader) {
|
||||
static int32_t buildBlockFromBufferSequentially(STsdbReader* pReader, int64_t endKey) {
|
||||
SReaderStatus* pStatus = &pReader->status;
|
||||
STableUidList* pUidList = &pStatus->uidList;
|
||||
|
||||
|
@ -2997,13 +2906,12 @@ static int32_t buildBlockFromBufferSequentially(STsdbReader* pReader) {
|
|||
if (!hasNexTable) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
pBlockScanInfo = pStatus->pTableIter;
|
||||
continue;
|
||||
}
|
||||
|
||||
initMemDataIterator(*pBlockScanInfo, pReader);
|
||||
initDelSkylineIterator(*pBlockScanInfo, pReader->info.order, &pReader->cost);
|
||||
|
||||
int64_t endKey = (ASCENDING_TRAVERSE(pReader->info.order)) ? INT64_MAX : INT64_MIN;
|
||||
int32_t code = buildDataBlockFromBuf(pReader, *pBlockScanInfo, endKey);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
|
@ -3107,7 +3015,7 @@ static ERetrieveType doReadDataFromSttFiles(STsdbReader* pReader) {
|
|||
return TSDB_READ_RETURN;
|
||||
}
|
||||
|
||||
// all data blocks are checked in this last block file, now let's try the next file
|
||||
// all data blocks are checked in this stt file, now let's try the next file set
|
||||
ASSERT(pReader->status.pTableIter == NULL);
|
||||
code = initForFirstBlockInFile(pReader, pBlockIter);
|
||||
|
||||
|
@ -3833,7 +3741,7 @@ int32_t buildDataBlockFromBufImpl(STableBlockScanInfo* pBlockScanInfo, int64_t e
|
|||
}
|
||||
|
||||
if (row.type == TSDBROW_ROW_FMT) {
|
||||
int64_t ts = row.pTSRow->ts;;
|
||||
int64_t ts = row.pTSRow->ts;
|
||||
code = doAppendRowFromTSRow(pBlock, pReader, row.pTSRow, pBlockScanInfo);
|
||||
|
||||
if (freeTSRow) {
|
||||
|
@ -3940,13 +3848,18 @@ static int32_t doOpenReaderImpl(STsdbReader* pReader) {
|
|||
SReaderStatus* pStatus = &pReader->status;
|
||||
SDataBlockIter* pBlockIter = &pStatus->blockIter;
|
||||
|
||||
if (pReader->bFilesetDelimited) {
|
||||
getMemTableTimeRange(pReader, &pReader->status.memTableMaxKey, &pReader->status.memTableMinKey);
|
||||
pReader->status.bProcMemFirstFileset = true;
|
||||
}
|
||||
|
||||
initFilesetIterator(&pStatus->fileIter, pReader->pReadSnap->pfSetArray, pReader);
|
||||
resetDataBlockIterator(&pStatus->blockIter, pReader->info.order);
|
||||
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
if (pStatus->fileIter.numOfFiles == 0) {
|
||||
pStatus->loadFromFile = false;
|
||||
} else if (READ_MODE_COUNT_ONLY == pReader->info.readMode) {
|
||||
// } else if (READER_EXEC_DATA == pReader->info.readMode) {
|
||||
// DO NOTHING
|
||||
} else {
|
||||
code = initForFirstBlockInFile(pReader, pBlockIter);
|
||||
|
@ -3987,8 +3900,7 @@ static void setSharedPtr(STsdbReader* pDst, const STsdbReader* pSrc) {
|
|||
|
||||
// ====================================== EXPOSED APIs ======================================
|
||||
int32_t tsdbReaderOpen2(void* pVnode, SQueryTableDataCond* pCond, void* pTableList, int32_t numOfTables,
|
||||
SSDataBlock* pResBlock, void** ppReader, const char* idstr, bool countOnly,
|
||||
SHashObj** pIgnoreTables) {
|
||||
SSDataBlock* pResBlock, void** ppReader, const char* idstr, SHashObj** pIgnoreTables) {
|
||||
STimeWindow window = pCond->twindows;
|
||||
SVnodeCfg* pConf = &(((SVnode*)pVnode)->config);
|
||||
|
||||
|
@ -4094,13 +4006,9 @@ int32_t tsdbReaderOpen2(void* pVnode, SQueryTableDataCond* pCond, void* pTableLi
|
|||
}
|
||||
|
||||
pReader->flag = READER_STATUS_SUSPEND;
|
||||
|
||||
if (countOnly) {
|
||||
pReader->info.readMode = READ_MODE_COUNT_ONLY;
|
||||
}
|
||||
pReader->info.execMode = pCond->notLoadData? READER_EXEC_ROWS : READER_EXEC_DATA;
|
||||
|
||||
pReader->pIgnoreTables = pIgnoreTables;
|
||||
|
||||
tsdbDebug("%p total numOfTable:%d, window:%" PRId64 " - %" PRId64 ", verRange:%" PRId64 " - %" PRId64
|
||||
" in this query %s",
|
||||
pReader, numOfTables, pReader->info.window.skey, pReader->info.window.ekey, pReader->info.verRange.minVer,
|
||||
|
@ -4210,8 +4118,6 @@ int32_t tsdbReaderSuspend2(STsdbReader* pReader) {
|
|||
SReaderStatus* pStatus = &pReader->status;
|
||||
STableBlockScanInfo* pBlockScanInfo = NULL;
|
||||
|
||||
pReader->status.suspendInvoked = true; // record the suspend status
|
||||
|
||||
if (pStatus->loadFromFile) {
|
||||
SFileDataBlockInfo* pBlockInfo = getCurrentBlockInfo(&pReader->status.blockIter);
|
||||
if (pBlockInfo != NULL) {
|
||||
|
@ -4247,6 +4153,10 @@ int32_t tsdbReaderSuspend2(STsdbReader* pReader) {
|
|||
|
||||
tsdbUntakeReadSnap2(pReader, pReader->pReadSnap, false);
|
||||
pReader->pReadSnap = NULL;
|
||||
if (pReader->bFilesetDelimited) {
|
||||
pReader->status.memTableMinKey = INT64_MAX;
|
||||
pReader->status.memTableMaxKey = INT64_MIN;
|
||||
}
|
||||
pReader->flag = READER_STATUS_SUSPEND;
|
||||
|
||||
#if SUSPEND_RESUME_TEST
|
||||
|
@ -4332,30 +4242,70 @@ _err:
|
|||
return code;
|
||||
}
|
||||
|
||||
static bool tsdbReadRowsCountOnly(STsdbReader* pReader) {
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
static int32_t doTsdbNextDataBlockFilesetDelimited(STsdbReader* pReader) {
|
||||
SReaderStatus* pStatus = &pReader->status;
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
SSDataBlock* pBlock = pReader->resBlockInfo.pResBlock;
|
||||
|
||||
if (pReader->status.loadFromFile == false) {
|
||||
return false;
|
||||
if (pStatus->loadFromFile) {
|
||||
if (pStatus->bProcMemPreFileset) {
|
||||
int32_t fid = pReader->status.pCurrentFileset->fid;
|
||||
STimeWindow win = {0};
|
||||
tsdbFidKeyRange(fid, pReader->pTsdb->keepCfg.days, pReader->pTsdb->keepCfg.precision, &win.skey, &win.ekey);
|
||||
|
||||
int64_t endKey = (ASCENDING_TRAVERSE(pReader->info.order)) ? win.skey : win.ekey;
|
||||
code = buildBlockFromBufferSequentially(pReader, endKey);
|
||||
if (code != TSDB_CODE_SUCCESS || pBlock->info.rows > 0) {
|
||||
return code;
|
||||
} else {
|
||||
pStatus->bProcMemPreFileset = false;
|
||||
if (pReader->notifyFn) {
|
||||
STsdReaderNotifyInfo info = {0};
|
||||
info.duration.filesetId = fid;
|
||||
pReader->notifyFn(TSD_READER_NOTIFY_DURATION_START, &info, pReader->notifyParam);
|
||||
}
|
||||
resetTableListIndex(pStatus);
|
||||
}
|
||||
}
|
||||
|
||||
code = buildBlockFromFiles(pReader);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
|
||||
if (pBlock->info.rows <= 0) {
|
||||
resetTableListIndex(&pReader->status);
|
||||
int64_t endKey = (ASCENDING_TRAVERSE(pReader->info.order)) ? INT64_MAX : INT64_MIN;
|
||||
code = buildBlockFromBufferSequentially(pReader, endKey);
|
||||
}
|
||||
} else { // no data in files, let's try the buffer
|
||||
int64_t endKey = (ASCENDING_TRAVERSE(pReader->info.order)) ? INT64_MAX : INT64_MIN;
|
||||
code = buildBlockFromBufferSequentially(pReader, endKey);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
code = readRowsCountFromFiles(pReader);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return false;
|
||||
static int32_t doTsdbNextDataBlockFilesFirst(STsdbReader* pReader) {
|
||||
SReaderStatus* pStatus = &pReader->status;
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
SSDataBlock* pBlock = pReader->resBlockInfo.pResBlock;
|
||||
|
||||
if (pStatus->loadFromFile) {
|
||||
code = buildBlockFromFiles(pReader);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
|
||||
if (pBlock->info.rows <= 0) {
|
||||
resetTableListIndex(&pReader->status);
|
||||
int64_t endKey = (ASCENDING_TRAVERSE(pReader->info.order)) ? INT64_MAX : INT64_MIN;
|
||||
code = buildBlockFromBufferSequentially(pReader, endKey);
|
||||
}
|
||||
} else { // no data in files, let's try the buffer
|
||||
int64_t endKey = (ASCENDING_TRAVERSE(pReader->info.order)) ? INT64_MAX : INT64_MIN;
|
||||
code = buildBlockFromBufferSequentially(pReader, endKey);
|
||||
}
|
||||
|
||||
code = readRowsCountFromMem(pReader);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
pBlock->info.rows = pReader->rowsNum;
|
||||
pBlock->info.id.uid = 0;
|
||||
pBlock->info.dataLoad = 0;
|
||||
pReader->rowsNum = 0;
|
||||
|
||||
return pBlock->info.rows > 0;
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t doTsdbNextDataBlock2(STsdbReader* pReader, bool* hasNext) {
|
||||
|
@ -4372,22 +4322,10 @@ static int32_t doTsdbNextDataBlock2(STsdbReader* pReader, bool* hasNext) {
|
|||
return code;
|
||||
}
|
||||
|
||||
if (READ_MODE_COUNT_ONLY == pReader->info.readMode) {
|
||||
return tsdbReadRowsCountOnly(pReader);
|
||||
}
|
||||
|
||||
if (pStatus->loadFromFile) {
|
||||
code = buildBlockFromFiles(pReader);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
|
||||
if (pBlock->info.rows <= 0) {
|
||||
resetTableListIndex(&pReader->status);
|
||||
code = buildBlockFromBufferSequentially(pReader);
|
||||
}
|
||||
} else { // no data in files, let's try the buffer
|
||||
code = buildBlockFromBufferSequentially(pReader);
|
||||
if (!pReader->bFilesetDelimited) {
|
||||
code = doTsdbNextDataBlockFilesFirst(pReader);
|
||||
} else {
|
||||
code = doTsdbNextDataBlockFilesetDelimited(pReader);
|
||||
}
|
||||
|
||||
*hasNext = pBlock->info.rows > 0;
|
||||
|
@ -4685,7 +4623,7 @@ SSDataBlock* tsdbRetrieveDataBlock2(STsdbReader* pReader, SArray* pIdList) {
|
|||
}
|
||||
|
||||
SReaderStatus* pStatus = &pTReader->status;
|
||||
if (pStatus->composedDataBlock) {
|
||||
if (pStatus->composedDataBlock || pReader->info.execMode == READER_EXEC_ROWS) {
|
||||
return pTReader->resBlockInfo.pResBlock;
|
||||
}
|
||||
|
||||
|
@ -4722,9 +4660,9 @@ int32_t tsdbReaderReset2(STsdbReader* pReader, SQueryTableDataCond* pCond) {
|
|||
|
||||
pReader->info.order = pCond->order;
|
||||
pReader->type = TIMEWINDOW_RANGE_CONTAINED;
|
||||
pReader->info.window = updateQueryTimeWindow(pReader->pTsdb, &pCond->twindows);
|
||||
pStatus->loadFromFile = true;
|
||||
pStatus->pTableIter = NULL;
|
||||
pReader->info.window = updateQueryTimeWindow(pReader->pTsdb, &pCond->twindows);
|
||||
|
||||
// allocate buffer in order to load data blocks from file
|
||||
memset(&pReader->suppInfo.tsColAgg, 0, sizeof(SColumnDataAgg));
|
||||
|
@ -4875,6 +4813,54 @@ int32_t tsdbGetFileBlocksDistInfo2(STsdbReader* pReader, STableBlockDistInfo* pT
|
|||
return code;
|
||||
}
|
||||
|
||||
static void getMemTableTimeRange(STsdbReader* pReader, int64_t* pMaxKey, int64_t* pMinKey) {
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
int64_t rows = 0;
|
||||
|
||||
SReaderStatus* pStatus = &pReader->status;
|
||||
|
||||
int32_t iter = 0;
|
||||
int64_t maxKey = INT64_MIN;
|
||||
int64_t minKey = INT64_MAX;
|
||||
|
||||
void* pHashIter = tSimpleHashIterate(pStatus->pTableMap, NULL, &iter);
|
||||
while (pHashIter!= NULL) {
|
||||
STableBlockScanInfo* pBlockScanInfo = *(STableBlockScanInfo**)pHashIter;
|
||||
|
||||
STbData* d = NULL;
|
||||
if (pReader->pReadSnap->pMem != NULL) {
|
||||
d = tsdbGetTbDataFromMemTable(pReader->pReadSnap->pMem, pReader->info.suid, pBlockScanInfo->uid);
|
||||
if (d != NULL) {
|
||||
if (d->maxKey > maxKey) {
|
||||
maxKey = d->maxKey;
|
||||
}
|
||||
if (d->minKey < minKey) {
|
||||
minKey = d->minKey;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
STbData* di = NULL;
|
||||
if (pReader->pReadSnap->pIMem != NULL) {
|
||||
di = tsdbGetTbDataFromMemTable(pReader->pReadSnap->pIMem, pReader->info.suid, pBlockScanInfo->uid);
|
||||
if (di != NULL) {
|
||||
if (di->maxKey > maxKey) {
|
||||
maxKey = di->maxKey;
|
||||
}
|
||||
if (di->minKey < minKey) {
|
||||
minKey = di->minKey;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// current table is exhausted, let's try the next table
|
||||
pHashIter = tSimpleHashIterate(pStatus->pTableMap, pHashIter, &iter);
|
||||
}
|
||||
|
||||
*pMaxKey = maxKey;
|
||||
*pMinKey = minKey;
|
||||
}
|
||||
|
||||
int64_t tsdbGetNumOfRowsInMemTable2(STsdbReader* pReader) {
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
int64_t rows = 0;
|
||||
|
@ -5062,3 +5048,12 @@ void tsdbReaderSetId2(STsdbReader* pReader, const char* idstr) {
|
|||
|
||||
void tsdbReaderSetCloseFlag(STsdbReader* pReader) { /*pReader->code = TSDB_CODE_TSC_QUERY_CANCELLED;*/
|
||||
}
|
||||
|
||||
void tsdbSetFilesetDelimited(STsdbReader* pReader) {
|
||||
pReader->bFilesetDelimited = true;
|
||||
}
|
||||
|
||||
void tsdbReaderSetNotifyCb(STsdbReader* pReader, TsdReaderNotifyCbFn notifyFn, void* param) {
|
||||
pReader->notifyFn = notifyFn;
|
||||
pReader->notifyParam = param;
|
||||
}
|
||||
|
|
|
@ -22,15 +22,9 @@
|
|||
#include "tsdbUtil2.h"
|
||||
#include "tsimplehash.h"
|
||||
|
||||
int32_t uidComparFunc(const void* p1, const void* p2) {
|
||||
uint64_t pu1 = *(uint64_t*)p1;
|
||||
uint64_t pu2 = *(uint64_t*)p2;
|
||||
if (pu1 == pu2) {
|
||||
return 0;
|
||||
} else {
|
||||
return (pu1 < pu2) ? -1 : 1;
|
||||
}
|
||||
}
|
||||
#define INIT_TIMEWINDOW(_w) do { (_w)->skey = INT64_MAX; (_w)->ekey = INT64_MIN;} while(0);
|
||||
|
||||
static bool overlapWithDelSkylineWithoutVer(STableBlockScanInfo* pBlockScanInfo, const SBrinRecord* pRecord, int32_t order);
|
||||
|
||||
static int32_t initBlockScanInfoBuf(SBlockInfoBuf* pBuf, int32_t numOfTables) {
|
||||
int32_t num = numOfTables / pBuf->numPerBucket;
|
||||
|
@ -61,6 +55,16 @@ static int32_t initBlockScanInfoBuf(SBlockInfoBuf* pBuf, int32_t numOfTables) {
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t uidComparFunc(const void* p1, const void* p2) {
|
||||
uint64_t pu1 = *(uint64_t*)p1;
|
||||
uint64_t pu2 = *(uint64_t*)p2;
|
||||
if (pu1 == pu2) {
|
||||
return 0;
|
||||
} else {
|
||||
return (pu1 < pu2) ? -1 : 1;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t ensureBlockScanInfoBuf(SBlockInfoBuf* pBuf, int32_t numOfTables) {
|
||||
if (numOfTables <= pBuf->numOfTables) {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
|
@ -153,6 +157,9 @@ SSHashObj* createDataBlockScanInfo(STsdbReader* pTsdbReader, SBlockInfoBuf* pBuf
|
|||
STableBlockScanInfo* pScanInfo = getPosInBlockInfoBuf(pBuf, j);
|
||||
|
||||
pScanInfo->uid = idList[j].uid;
|
||||
INIT_TIMEWINDOW(&pScanInfo->sttWindow);
|
||||
INIT_TIMEWINDOW(&pScanInfo->filesetWindow);
|
||||
|
||||
pUidList->tableUidList[j] = idList[j].uid;
|
||||
|
||||
if (ASCENDING_TRAVERSE(pTsdbReader->info.order)) {
|
||||
|
@ -243,6 +250,10 @@ static void doCleanupInfoForNextFileset(STableBlockScanInfo* pScanInfo) {
|
|||
taosArrayClear(pScanInfo->pBlockList);
|
||||
taosArrayClear(pScanInfo->pBlockIdxList);
|
||||
taosArrayClear(pScanInfo->pFileDelData); // del data from each file set
|
||||
pScanInfo->cleanSttBlocks = false;
|
||||
pScanInfo->numOfRowsInStt = 0;
|
||||
INIT_TIMEWINDOW(&pScanInfo->sttWindow);
|
||||
INIT_TIMEWINDOW(&pScanInfo->filesetWindow);
|
||||
pScanInfo->sttKeyInfo.status = STT_FILE_READER_UNINIT;
|
||||
}
|
||||
|
||||
|
@ -403,12 +414,10 @@ int32_t initBlockIterator(STsdbReader* pReader, SDataBlockIter* pBlockIter, int3
|
|||
blockInfo.record = *(SBrinRecord*)taosArrayGet(sup.pDataBlockInfo[0][i].pInfo->pBlockList, i);
|
||||
|
||||
taosArrayPush(pBlockIter->blockList, &blockInfo);
|
||||
|
||||
STableDataBlockIdx tableDataBlockIdx = {.globalIndex = i};
|
||||
taosArrayPush(pTableScanInfo->pBlockIdxList, &tableDataBlockIdx);
|
||||
}
|
||||
taosArrayDestroy(pTableScanInfo->pBlockList);
|
||||
pTableScanInfo->pBlockList = NULL;
|
||||
pTableScanInfo->pBlockList = taosArrayDestroy(pTableScanInfo->pBlockList);
|
||||
|
||||
int64_t et = taosGetTimestampUs();
|
||||
tsdbDebug("%p create blocks info struct completed for one table, %d blocks not sorted, elapsed time:%.2f ms %s",
|
||||
|
@ -457,8 +466,7 @@ int32_t initBlockIterator(STsdbReader* pReader, SDataBlockIter* pBlockIter, int3
|
|||
|
||||
for (int32_t i = 0; i < numOfTables; ++i) {
|
||||
STableBlockScanInfo* pTableScanInfo = taosArrayGetP(pTableList, i);
|
||||
taosArrayDestroy(pTableScanInfo->pBlockList);
|
||||
pTableScanInfo->pBlockList = NULL;
|
||||
pTableScanInfo->pBlockList = taosArrayDestroy(pTableScanInfo->pBlockList);
|
||||
}
|
||||
|
||||
int64_t et = taosGetTimestampUs();
|
||||
|
@ -488,7 +496,7 @@ typedef enum {
|
|||
BLK_CHECK_QUIT = 0x2,
|
||||
} ETombBlkCheckEnum;
|
||||
|
||||
static void loadNextStatisticsBlock(SSttFileReader* pSttFileReader, const SSttBlockLoadInfo* pBlockLoadInfo,
|
||||
static void loadNextStatisticsBlock(SSttFileReader* pSttFileReader, STbStatisBlock* pStatisBlock,
|
||||
const TStatisBlkArray* pStatisBlkArray, int32_t numOfRows, int32_t* i, int32_t* j);
|
||||
static int32_t doCheckTombBlock(STombBlock* pBlock, STsdbReader* pReader, int32_t numOfTables, int32_t* j,
|
||||
ETombBlkCheckEnum* pRet) {
|
||||
|
@ -662,17 +670,17 @@ void loadMemTombData(SArray** ppMemDelData, STbData* pMemTbData, STbData* piMemT
|
|||
}
|
||||
}
|
||||
|
||||
int32_t getNumOfRowsInSttBlock(SSttFileReader *pSttFileReader, SSttBlockLoadInfo *pBlockLoadInfo, uint64_t suid,
|
||||
const uint64_t* pUidList, int32_t numOfTables) {
|
||||
int32_t getNumOfRowsInSttBlock(SSttFileReader* pSttFileReader, SSttBlockLoadInfo* pBlockLoadInfo,
|
||||
TStatisBlkArray* pStatisBlkArray, uint64_t suid, const uint64_t* pUidList,
|
||||
int32_t numOfTables) {
|
||||
int32_t num = 0;
|
||||
|
||||
const TStatisBlkArray *pStatisBlkArray = pBlockLoadInfo->pSttStatisBlkArray;
|
||||
if (TARRAY2_SIZE(pStatisBlkArray) <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t i = 0;
|
||||
while((i < TARRAY2_SIZE(pStatisBlkArray)) && (pStatisBlkArray->data[i].minTbid.suid < suid)) {
|
||||
while((i < TARRAY2_SIZE(pStatisBlkArray)) && (pStatisBlkArray->data[i].maxTbid.suid < suid)) {
|
||||
++i;
|
||||
}
|
||||
|
||||
|
@ -681,64 +689,65 @@ int32_t getNumOfRowsInSttBlock(SSttFileReader *pSttFileReader, SSttBlockLoadInfo
|
|||
}
|
||||
|
||||
SStatisBlk *p = &pStatisBlkArray->data[i];
|
||||
if (pBlockLoadInfo->statisBlock == NULL) {
|
||||
pBlockLoadInfo->statisBlock = taosMemoryCalloc(1, sizeof(STbStatisBlock));
|
||||
tStatisBlockInit(pBlockLoadInfo->statisBlock);
|
||||
}
|
||||
STbStatisBlock* pStatisBlock = taosMemoryCalloc(1, sizeof(STbStatisBlock));
|
||||
tStatisBlockInit(pStatisBlock);
|
||||
|
||||
int64_t st = taosGetTimestampMs();
|
||||
tsdbSttFileReadStatisBlock(pSttFileReader, p, pBlockLoadInfo->statisBlock);
|
||||
pBlockLoadInfo->statisBlockIndex = i;
|
||||
tsdbSttFileReadStatisBlock(pSttFileReader, p, pStatisBlock);
|
||||
|
||||
double el = (taosGetTimestampMs() - st) / 1000.0;
|
||||
pBlockLoadInfo->cost.loadStatisBlocks += 1;
|
||||
pBlockLoadInfo->cost.statisElapsedTime += el;
|
||||
|
||||
STbStatisBlock *pBlock = pBlockLoadInfo->statisBlock;
|
||||
|
||||
int32_t index = 0;
|
||||
while (index < TARRAY2_SIZE(pBlock->suid) && pBlock->suid->data[index] < suid) {
|
||||
while (index < TARRAY2_SIZE(pStatisBlock->suid) && pStatisBlock->suid->data[index] < suid) {
|
||||
++index;
|
||||
}
|
||||
|
||||
if (index >= TARRAY2_SIZE(pBlock->suid)) {
|
||||
if (index >= TARRAY2_SIZE(pStatisBlock->suid)) {
|
||||
tStatisBlockDestroy(pStatisBlock);
|
||||
taosMemoryFreeClear(pStatisBlock);
|
||||
return num;
|
||||
}
|
||||
|
||||
int32_t j = index;
|
||||
int32_t uidIndex = 0;
|
||||
while (i < TARRAY2_SIZE(pStatisBlkArray) && uidIndex <= numOfTables) {
|
||||
while (i < TARRAY2_SIZE(pStatisBlkArray) && uidIndex < numOfTables) {
|
||||
p = &pStatisBlkArray->data[i];
|
||||
if (p->minTbid.suid > suid) {
|
||||
tStatisBlockDestroy(pStatisBlock);
|
||||
taosMemoryFreeClear(pStatisBlock);
|
||||
return num;
|
||||
}
|
||||
|
||||
uint64_t uid = pUidList[uidIndex];
|
||||
|
||||
if (pBlock->uid->data[j] == uid) {
|
||||
num += pBlock->count->data[j];
|
||||
if (pStatisBlock->uid->data[j] == uid) {
|
||||
num += pStatisBlock->count->data[j];
|
||||
uidIndex += 1;
|
||||
j += 1;
|
||||
loadNextStatisticsBlock(pSttFileReader, pBlockLoadInfo, pStatisBlkArray, pBlock->suid->size, &i, &j);
|
||||
} else if (pBlock->uid->data[j] < uid) {
|
||||
loadNextStatisticsBlock(pSttFileReader, pStatisBlock, pStatisBlkArray, pStatisBlock->suid->size, &i, &j);
|
||||
} else if (pStatisBlock->uid->data[j] < uid) {
|
||||
j += 1;
|
||||
loadNextStatisticsBlock(pSttFileReader, pBlockLoadInfo, pStatisBlkArray, pBlock->suid->size, &i, &j);
|
||||
loadNextStatisticsBlock(pSttFileReader, pStatisBlock, pStatisBlkArray, pStatisBlock->suid->size, &i, &j);
|
||||
} else {
|
||||
uidIndex += 1;
|
||||
}
|
||||
}
|
||||
|
||||
tStatisBlockDestroy(pStatisBlock);
|
||||
taosMemoryFreeClear(pStatisBlock);
|
||||
return num;
|
||||
}
|
||||
|
||||
// load next stt statistics block
|
||||
static void loadNextStatisticsBlock(SSttFileReader* pSttFileReader, const SSttBlockLoadInfo* pBlockLoadInfo,
|
||||
static void loadNextStatisticsBlock(SSttFileReader* pSttFileReader, STbStatisBlock* pStatisBlock,
|
||||
const TStatisBlkArray* pStatisBlkArray, int32_t numOfRows, int32_t* i, int32_t* j) {
|
||||
if ((*j) >= numOfRows) {
|
||||
(*i) += 1;
|
||||
(*j) = 0;
|
||||
if ((*i) < TARRAY2_SIZE(pStatisBlkArray)) {
|
||||
tsdbSttFileReadStatisBlock(pSttFileReader, &pStatisBlkArray->data[(*i)], pBlockLoadInfo->statisBlock);
|
||||
tsdbSttFileReadStatisBlock(pSttFileReader, &pStatisBlkArray->data[(*i)], pStatisBlock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -762,7 +771,7 @@ void doAdjustValidDataIters(SArray* pLDIterList, int32_t numOfFileObj) {
|
|||
}
|
||||
}
|
||||
|
||||
int32_t adjustLDataIters(SArray* pSttFileBlockIterArray, STFileSet* pFileSet) {
|
||||
int32_t adjustSttDataIters(SArray* pSttFileBlockIterArray, STFileSet* pFileSet) {
|
||||
int32_t numOfLevels = pFileSet->lvlArr->size;
|
||||
|
||||
// add the list/iter placeholder
|
||||
|
@ -791,7 +800,7 @@ int32_t tsdbGetRowsInSttFiles(STFileSet* pFileSet, SArray* pSttFileBlockIterArra
|
|||
}
|
||||
|
||||
// add the list/iter placeholder
|
||||
adjustLDataIters(pSttFileBlockIterArray, pFileSet);
|
||||
adjustSttDataIters(pSttFileBlockIterArray, pFileSet);
|
||||
|
||||
for (int32_t j = 0; j < numOfLevels; ++j) {
|
||||
SSttLvl* pSttLevel = pFileSet->lvlArr->data[j];
|
||||
|
@ -819,7 +828,8 @@ int32_t tsdbGetRowsInSttFiles(STFileSet* pFileSet, SArray* pSttFileBlockIterArra
|
|||
}
|
||||
|
||||
// load stt blocks statis for all stt-blocks, to decide if the data of queried table exists in current stt file
|
||||
int32_t code = tsdbSttFileReadStatisBlk(pIter->pReader, (const TStatisBlkArray **)&pIter->pBlockLoadInfo->pSttStatisBlkArray);
|
||||
TStatisBlkArray *pStatisBlkArray = NULL;
|
||||
int32_t code = tsdbSttFileReadStatisBlk(pIter->pReader, (const TStatisBlkArray **)&pStatisBlkArray);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
tsdbError("failed to load stt block statistics, code:%s, %s", tstrerror(code), pstr);
|
||||
continue;
|
||||
|
@ -829,9 +839,214 @@ int32_t tsdbGetRowsInSttFiles(STFileSet* pFileSet, SArray* pSttFileBlockIterArra
|
|||
STsdbReader* pReader = pConf->pReader;
|
||||
int32_t numOfTables = tSimpleHashGetSize(pReader->status.pTableMap);
|
||||
uint64_t* pUidList = pReader->status.uidList.tableUidList;
|
||||
numOfRows += getNumOfRowsInSttBlock(pIter->pReader, pIter->pBlockLoadInfo, pConf->suid, pUidList, numOfTables);
|
||||
numOfRows += getNumOfRowsInSttBlock(pIter->pReader, pIter->pBlockLoadInfo, pStatisBlkArray, pConf->suid, pUidList,
|
||||
numOfTables);
|
||||
}
|
||||
}
|
||||
|
||||
return numOfRows;
|
||||
}
|
||||
|
||||
static bool overlapHelper(const STimeWindow* pLeft, TSKEY minKey, TSKEY maxKey) {
|
||||
return (pLeft->ekey >= minKey) && (pLeft->skey <= maxKey);
|
||||
}
|
||||
|
||||
static bool overlapWithTimeWindow(STimeWindow* p1, STimeWindow* pQueryWindow, STableBlockScanInfo* pBlockScanInfo,
|
||||
int32_t order) {
|
||||
// overlap with query window
|
||||
if (!(p1->skey >= pQueryWindow->skey && p1->ekey <= pQueryWindow->ekey)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
SIterInfo* pMemIter = &pBlockScanInfo->iter;
|
||||
SIterInfo* pIMemIter = &pBlockScanInfo->iiter;
|
||||
|
||||
// overlap with mem data
|
||||
if (pMemIter->hasVal) {
|
||||
STbData* pTbData = pMemIter->iter->pTbData;
|
||||
if (overlapHelper(p1, pTbData->minKey, pTbData->maxKey)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// overlap with imem data
|
||||
if (pIMemIter->hasVal) {
|
||||
STbData* pITbData = pIMemIter->iter->pTbData;
|
||||
if (overlapHelper(p1, pITbData->minKey, pITbData->maxKey)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// overlap with data file block
|
||||
STimeWindow* pFileWin = &pBlockScanInfo->filesetWindow;
|
||||
if ((taosArrayGetSize(pBlockScanInfo->pBlockIdxList) > 0) && overlapHelper(p1, pFileWin->skey, pFileWin->ekey)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// overlap with deletion skyline
|
||||
SBrinRecord record = {.firstKey = p1->skey, .lastKey = p1->ekey};
|
||||
if (overlapWithDelSkylineWithoutVer(pBlockScanInfo, &record, order)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int32_t sortUidComparFn(const void* p1, const void* p2) {
|
||||
const STimeWindow* px1 = p1;
|
||||
const STimeWindow* px2 = p2;
|
||||
if (px1->skey == px2->skey) {
|
||||
return 0;
|
||||
} else {
|
||||
return px1->skey < px2->skey? -1:1;
|
||||
}
|
||||
}
|
||||
|
||||
bool isCleanSttBlock(SArray* pTimewindowList, STimeWindow* pQueryWindow, STableBlockScanInfo *pScanInfo, int32_t order) {
|
||||
// check if it overlap with del skyline
|
||||
taosArraySort(pTimewindowList, sortUidComparFn);
|
||||
|
||||
int32_t num = taosArrayGetSize(pTimewindowList);
|
||||
if (num == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
STimeWindow* p = taosArrayGet(pTimewindowList, 0);
|
||||
if (overlapWithTimeWindow(p, pQueryWindow, pScanInfo, order)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < num - 1; ++i) {
|
||||
STimeWindow* p1 = taosArrayGet(pTimewindowList, i);
|
||||
STimeWindow* p2 = taosArrayGet(pTimewindowList, i + 1);
|
||||
|
||||
if (p1->ekey >= p2->skey) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool overlap = overlapWithTimeWindow(p2, pQueryWindow, pScanInfo, order);
|
||||
if (overlap) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool doCheckDatablockOverlap(STableBlockScanInfo* pBlockScanInfo, const SBrinRecord* pRecord,
|
||||
int32_t startIndex) {
|
||||
size_t num = taosArrayGetSize(pBlockScanInfo->delSkyline);
|
||||
|
||||
for (int32_t i = startIndex; i < num; i += 1) {
|
||||
TSDBKEY* p = taosArrayGet(pBlockScanInfo->delSkyline, i);
|
||||
if (p->ts >= pRecord->firstKey && p->ts <= pRecord->lastKey) {
|
||||
if (p->version >= pRecord->minVer) {
|
||||
return true;
|
||||
}
|
||||
} else if (p->ts < pRecord->firstKey) { // p->ts < pBlock->minKey.ts
|
||||
if (p->version >= pRecord->minVer) {
|
||||
if (i < num - 1) {
|
||||
TSDBKEY* pnext = taosArrayGet(pBlockScanInfo->delSkyline, i + 1);
|
||||
if (pnext->ts >= pRecord->firstKey) {
|
||||
return true;
|
||||
}
|
||||
} else { // it must be the last point
|
||||
ASSERT(p->version == 0);
|
||||
}
|
||||
}
|
||||
} else { // (p->ts > pBlock->maxKey.ts) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool doCheckDatablockOverlapWithoutVersion(STableBlockScanInfo* pBlockScanInfo, const SBrinRecord* pRecord,
|
||||
int32_t startIndex) {
|
||||
size_t num = taosArrayGetSize(pBlockScanInfo->delSkyline);
|
||||
|
||||
for (int32_t i = startIndex; i < num; i += 1) {
|
||||
TSDBKEY* p = taosArrayGet(pBlockScanInfo->delSkyline, i);
|
||||
if (p->ts >= pRecord->firstKey && p->ts <= pRecord->lastKey) {
|
||||
return true;
|
||||
} else if (p->ts < pRecord->firstKey) { // p->ts < pBlock->minKey.ts
|
||||
if (i < num - 1) {
|
||||
TSDBKEY* pnext = taosArrayGet(pBlockScanInfo->delSkyline, i + 1);
|
||||
if (pnext->ts >= pRecord->firstKey) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else { // (p->ts > pBlock->maxKey.ts) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool overlapWithDelSkyline(STableBlockScanInfo* pBlockScanInfo, const SBrinRecord* pRecord, int32_t order) {
|
||||
if (pBlockScanInfo->delSkyline == NULL || (taosArrayGetSize(pBlockScanInfo->delSkyline) == 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// ts is not overlap
|
||||
TSDBKEY* pFirst = taosArrayGet(pBlockScanInfo->delSkyline, 0);
|
||||
TSDBKEY* pLast = taosArrayGetLast(pBlockScanInfo->delSkyline);
|
||||
if (pRecord->firstKey > pLast->ts || pRecord->lastKey < pFirst->ts) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// version is not overlap
|
||||
if (ASCENDING_TRAVERSE(order)) {
|
||||
return doCheckDatablockOverlap(pBlockScanInfo, pRecord, pBlockScanInfo->fileDelIndex);
|
||||
} else {
|
||||
int32_t index = pBlockScanInfo->fileDelIndex;
|
||||
while (1) {
|
||||
TSDBKEY* p = taosArrayGet(pBlockScanInfo->delSkyline, index);
|
||||
if (p->ts > pRecord->firstKey && index > 0) {
|
||||
index -= 1;
|
||||
} else { // find the first point that is smaller than the minKey.ts of dataBlock.
|
||||
if (p->ts == pRecord->firstKey && p->version < pRecord->maxVer && index > 0) {
|
||||
index -= 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return doCheckDatablockOverlap(pBlockScanInfo, pRecord, index);
|
||||
}
|
||||
}
|
||||
|
||||
bool overlapWithDelSkylineWithoutVer(STableBlockScanInfo* pBlockScanInfo, const SBrinRecord* pRecord, int32_t order) {
|
||||
if (pBlockScanInfo->delSkyline == NULL || (taosArrayGetSize(pBlockScanInfo->delSkyline) == 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// ts is not overlap
|
||||
TSDBKEY* pFirst = taosArrayGet(pBlockScanInfo->delSkyline, 0);
|
||||
TSDBKEY* pLast = taosArrayGetLast(pBlockScanInfo->delSkyline);
|
||||
if (pRecord->firstKey > pLast->ts || pRecord->lastKey < pFirst->ts) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// version is not overlap
|
||||
if (ASCENDING_TRAVERSE(order)) {
|
||||
return doCheckDatablockOverlapWithoutVersion(pBlockScanInfo, pRecord, pBlockScanInfo->fileDelIndex);
|
||||
} else {
|
||||
int32_t index = pBlockScanInfo->fileDelIndex;
|
||||
while (1) {
|
||||
TSDBKEY* p = taosArrayGet(pBlockScanInfo->delSkyline, index);
|
||||
if (p->ts > pRecord->firstKey && index > 0) {
|
||||
index -= 1;
|
||||
} else { // find the first point that is smaller than the minKey.ts of dataBlock.
|
||||
if (p->ts == pRecord->firstKey && index > 0) {
|
||||
index -= 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return doCheckDatablockOverlapWithoutVersion(pBlockScanInfo, pRecord, index);
|
||||
}
|
||||
}
|
|
@ -22,6 +22,7 @@ extern "C" {
|
|||
|
||||
#include "tsdbDataFileRW.h"
|
||||
#include "tsdbUtil2.h"
|
||||
#include "storageapi.h"
|
||||
|
||||
#define ASCENDING_TRAVERSE(o) (o == TSDB_ORDER_ASC)
|
||||
|
||||
|
@ -39,8 +40,7 @@ typedef enum {
|
|||
typedef struct STsdbReaderInfo {
|
||||
uint64_t suid;
|
||||
STSchema* pSchema;
|
||||
EReadMode readMode;
|
||||
uint64_t rowsNum;
|
||||
EExecMode execMode;
|
||||
STimeWindow window;
|
||||
SVersionRange verRange;
|
||||
int16_t order;
|
||||
|
@ -74,6 +74,11 @@ typedef struct SSttKeyInfo {
|
|||
int64_t nextProcKey;
|
||||
} SSttKeyInfo;
|
||||
|
||||
// clean stt file blocks:
|
||||
// 1. not overlap with stt blocks in other stt files of the same fileset
|
||||
// 2. not overlap with delete skyline
|
||||
// 3. not overlap with in-memory data (mem/imem)
|
||||
// 4. not overlap with data file blocks
|
||||
typedef struct STableBlockScanInfo {
|
||||
uint64_t uid;
|
||||
TSKEY lastProcKey;
|
||||
|
@ -88,6 +93,11 @@ typedef struct STableBlockScanInfo {
|
|||
int32_t fileDelIndex; // file block delete index
|
||||
int32_t sttBlockDelIndex; // delete index for last block
|
||||
bool iterInit; // whether to initialize the in-memory skip list iterator or not
|
||||
bool cleanSttBlocks; // stt block is clean in current fileset
|
||||
bool sttBlockReturned; // result block returned alreay
|
||||
int64_t numOfRowsInStt;
|
||||
STimeWindow sttWindow; // timestamp window for current stt files
|
||||
STimeWindow filesetWindow; // timestamp window for current file set
|
||||
} STableBlockScanInfo;
|
||||
|
||||
typedef struct SResultBlockInfo {
|
||||
|
@ -145,6 +155,7 @@ typedef struct SBlockLoadSuppInfo {
|
|||
bool smaValid; // the sma on all queried columns are activated
|
||||
} SBlockLoadSuppInfo;
|
||||
|
||||
// each blocks in stt file not overlaps with in-memory/data-file/tomb-files, and not overlap with any other blocks in stt-file
|
||||
typedef struct SSttBlockReader {
|
||||
STimeWindow window;
|
||||
SVersionRange verRange;
|
||||
|
@ -186,7 +197,6 @@ typedef struct SFileBlockDumpInfo {
|
|||
} SFileBlockDumpInfo;
|
||||
|
||||
typedef struct SReaderStatus {
|
||||
bool suspendInvoked;
|
||||
bool loadFromFile; // check file stage
|
||||
bool composedDataBlock; // the returned data block is a composed block or not
|
||||
SSHashObj* pTableMap; // SHash<STableBlockScanInfo>
|
||||
|
@ -200,6 +210,12 @@ typedef struct SReaderStatus {
|
|||
SArray* pLDataIterArray;
|
||||
SRowMerger merger;
|
||||
SColumnInfoData* pPrimaryTsCol; // primary time stamp output col info data
|
||||
bool bProcMemPreFileset;
|
||||
int64_t memTableMaxKey;
|
||||
int64_t memTableMinKey;
|
||||
int64_t prevFilesetStartKey;
|
||||
int64_t prevFilesetEndKey;
|
||||
bool bProcMemFirstFileset;
|
||||
} SReaderStatus;
|
||||
|
||||
struct STsdbReader {
|
||||
|
@ -223,6 +239,9 @@ struct STsdbReader {
|
|||
SBlockInfoBuf blockInfoBuf;
|
||||
EContentData step;
|
||||
STsdbReader* innerReader[2];
|
||||
bool bFilesetDelimited; // duration by duration output
|
||||
TsdReaderNotifyCbFn notifyFn;
|
||||
void* notifyParam;
|
||||
};
|
||||
|
||||
typedef struct SBrinRecordIter {
|
||||
|
@ -262,12 +281,17 @@ bool blockIteratorNext(SDataBlockIter* pBlockIter, const char* idStr);
|
|||
void loadMemTombData(SArray** ppMemDelData, STbData* pMemTbData, STbData* piMemTbData, int64_t ver);
|
||||
int32_t loadDataFileTombDataForAll(STsdbReader* pReader);
|
||||
int32_t loadSttTombDataForAll(STsdbReader* pReader, SSttFileReader* pSttFileReader, SSttBlockLoadInfo* pLoadInfo);
|
||||
int32_t getNumOfRowsInSttBlock(SSttFileReader *pSttFileReader, SSttBlockLoadInfo *pBlockLoadInfo, uint64_t suid,
|
||||
const uint64_t* pUidList, int32_t numOfTables);
|
||||
int32_t getNumOfRowsInSttBlock(SSttFileReader* pSttFileReader, SSttBlockLoadInfo* pBlockLoadInfo,
|
||||
TStatisBlkArray* pStatisBlkArray, uint64_t suid, const uint64_t* pUidList,
|
||||
int32_t numOfTables);
|
||||
|
||||
void destroyLDataIter(SLDataIter* pIter);
|
||||
int32_t adjustLDataIters(SArray* pSttFileBlockIterArray, STFileSet* pFileSet);
|
||||
int32_t adjustSttDataIters(SArray* pSttFileBlockIterArray, STFileSet* pFileSet);
|
||||
int32_t tsdbGetRowsInSttFiles(STFileSet* pFileSet, SArray* pSttFileBlockIterArray, STsdb* pTsdb, SMergeTreeConf* pConf,
|
||||
const char* pstr);
|
||||
bool isCleanSttBlock(SArray* pTimewindowList, STimeWindow* pQueryWindow, STableBlockScanInfo* pScanInfo, int32_t order);
|
||||
bool overlapWithDelSkyline(STableBlockScanInfo* pBlockScanInfo, const SBrinRecord* pRecord, int32_t order);
|
||||
|
||||
typedef struct {
|
||||
SArray* pTombData;
|
||||
} STableLoadInfo;
|
||||
|
|
|
@ -0,0 +1,627 @@
|
|||
/*
|
||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||
*
|
||||
* This program is free software: you can use, redistribute, and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3
|
||||
* or later ("AGPL"), as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "tsdb.h"
|
||||
#include "tsdbFS2.h"
|
||||
|
||||
#define TSDB_SNAP_MSG_VER 1
|
||||
|
||||
// fset partition
|
||||
static int32_t tsdbFSetPartCmprFn(STsdbFSetPartition* x, STsdbFSetPartition* y) {
|
||||
if (x->fid < y->fid) return -1;
|
||||
if (x->fid > y->fid) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t tVersionRangeCmprFn(SVersionRange* x, SVersionRange* y) {
|
||||
if (x->minVer < y->minVer) return -1;
|
||||
if (x->minVer > y->minVer) return 1;
|
||||
if (x->maxVer < y->maxVer) return -1;
|
||||
if (x->maxVer > y->maxVer) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t tsdbTFileSetRangeCmprFn(STFileSetRange* x, STFileSetRange* y) {
|
||||
if (x->fid < y->fid) return -1;
|
||||
if (x->fid > y->fid) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
STsdbFSetPartition* tsdbFSetPartitionCreate() {
|
||||
STsdbFSetPartition* pSP = taosMemoryCalloc(1, sizeof(STsdbFSetPartition));
|
||||
if (pSP == NULL) {
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
return NULL;
|
||||
}
|
||||
for (int32_t i = 0; i < TSDB_FSET_RANGE_TYP_MAX; i++) {
|
||||
TARRAY2_INIT(&pSP->verRanges[i]);
|
||||
}
|
||||
return pSP;
|
||||
}
|
||||
|
||||
void tsdbFSetPartitionClear(STsdbFSetPartition** ppSP) {
|
||||
if (ppSP == NULL || ppSP[0] == NULL) {
|
||||
return;
|
||||
}
|
||||
for (int32_t i = 0; i < TSDB_FSET_RANGE_TYP_MAX; i++) {
|
||||
TARRAY2_DESTROY(&ppSP[0]->verRanges[i], NULL);
|
||||
}
|
||||
taosMemoryFree(ppSP[0]);
|
||||
ppSP[0] = NULL;
|
||||
}
|
||||
|
||||
static int32_t tsdbFTypeToFRangeType(tsdb_ftype_t ftype) {
|
||||
switch (ftype) {
|
||||
case TSDB_FTYPE_HEAD:
|
||||
return TSDB_FSET_RANGE_TYP_HEAD;
|
||||
case TSDB_FTYPE_DATA:
|
||||
return TSDB_FSET_RANGE_TYP_DATA;
|
||||
case TSDB_FTYPE_SMA:
|
||||
return TSDB_FSET_RANGE_TYP_SMA;
|
||||
case TSDB_FTYPE_TOMB:
|
||||
return TSDB_FSET_RANGE_TYP_TOMB;
|
||||
case TSDB_FTYPE_STT:
|
||||
return TSDB_FSET_RANGE_TYP_STT;
|
||||
}
|
||||
return TSDB_FSET_RANGE_TYP_MAX;
|
||||
}
|
||||
|
||||
static int32_t tsdbTFileSetToFSetPartition(STFileSet* fset, STsdbFSetPartition** ppSP) {
|
||||
STsdbFSetPartition* p = tsdbFSetPartitionCreate();
|
||||
if (p == NULL) {
|
||||
goto _err;
|
||||
}
|
||||
|
||||
p->fid = fset->fid;
|
||||
|
||||
int32_t code = 0;
|
||||
int32_t typ = 0;
|
||||
int32_t corrupt = false;
|
||||
int32_t count = 0;
|
||||
for (int32_t ftype = TSDB_FTYPE_MIN; ftype < TSDB_FTYPE_MAX; ++ftype) {
|
||||
if (fset->farr[ftype] == NULL) continue;
|
||||
typ = tsdbFTypeToFRangeType(ftype);
|
||||
ASSERT(typ < TSDB_FSET_RANGE_TYP_MAX);
|
||||
STFile* f = fset->farr[ftype]->f;
|
||||
if (f->maxVer > fset->maxVerValid) {
|
||||
corrupt = true;
|
||||
tsdbError("skip incomplete data file: fid:%d, maxVerValid:%" PRId64 ", minVer:%" PRId64 ", maxVer:%" PRId64
|
||||
", ftype: %d",
|
||||
fset->fid, fset->maxVerValid, f->minVer, f->maxVer, ftype);
|
||||
continue;
|
||||
}
|
||||
count++;
|
||||
SVersionRange vr = {.minVer = f->minVer, .maxVer = f->maxVer};
|
||||
code = TARRAY2_SORT_INSERT(&p->verRanges[typ], vr, tVersionRangeCmprFn);
|
||||
ASSERT(code == 0);
|
||||
}
|
||||
|
||||
typ = TSDB_FSET_RANGE_TYP_STT;
|
||||
const SSttLvl* lvl;
|
||||
TARRAY2_FOREACH(fset->lvlArr, lvl) {
|
||||
STFileObj* fobj;
|
||||
TARRAY2_FOREACH(lvl->fobjArr, fobj) {
|
||||
STFile* f = fobj->f;
|
||||
if (f->maxVer > fset->maxVerValid) {
|
||||
corrupt = true;
|
||||
tsdbError("skip incomplete stt file.fid:%d, maxVerValid:%" PRId64 ", minVer:%" PRId64 ", maxVer:%" PRId64
|
||||
", ftype: %d",
|
||||
fset->fid, fset->maxVerValid, f->minVer, f->maxVer, typ);
|
||||
continue;
|
||||
}
|
||||
count++;
|
||||
SVersionRange vr = {.minVer = f->minVer, .maxVer = f->maxVer};
|
||||
code = TARRAY2_SORT_INSERT(&p->verRanges[typ], vr, tVersionRangeCmprFn);
|
||||
ASSERT(code == 0);
|
||||
}
|
||||
}
|
||||
if (corrupt && count == 0) {
|
||||
SVersionRange vr = {.minVer = VERSION_MIN, .maxVer = fset->maxVerValid};
|
||||
code = TARRAY2_SORT_INSERT(&p->verRanges[typ], vr, tVersionRangeCmprFn);
|
||||
ASSERT(code == 0);
|
||||
}
|
||||
ppSP[0] = p;
|
||||
return 0;
|
||||
|
||||
_err:
|
||||
tsdbFSetPartitionClear(&p);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// fset partition list
|
||||
STsdbFSetPartList* tsdbFSetPartListCreate() {
|
||||
STsdbFSetPartList* pList = taosMemoryCalloc(1, sizeof(STsdbFSetPartList));
|
||||
if (pList == NULL) {
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
return NULL;
|
||||
}
|
||||
TARRAY2_INIT(pList);
|
||||
return pList;
|
||||
}
|
||||
|
||||
void tsdbFSetPartListDestroy(STsdbFSetPartList** ppList) {
|
||||
if (ppList == NULL || ppList[0] == NULL) return;
|
||||
|
||||
TARRAY2_DESTROY(ppList[0], tsdbFSetPartitionClear);
|
||||
taosMemoryFree(ppList[0]);
|
||||
ppList[0] = NULL;
|
||||
}
|
||||
|
||||
int32_t tsdbFSetPartListToRangeDiff(STsdbFSetPartList* pList, TFileSetRangeArray** ppRanges) {
|
||||
TFileSetRangeArray* pDiff = taosMemoryCalloc(1, sizeof(TFileSetRangeArray));
|
||||
if (pDiff == NULL) {
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
goto _err;
|
||||
}
|
||||
TARRAY2_INIT(pDiff);
|
||||
|
||||
STsdbFSetPartition* part;
|
||||
TARRAY2_FOREACH(pList, part) {
|
||||
STFileSetRange* r = taosMemoryCalloc(1, sizeof(STFileSetRange));
|
||||
if (r == NULL) {
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
goto _err;
|
||||
}
|
||||
int64_t maxVerValid = -1;
|
||||
int32_t typMax = TSDB_FSET_RANGE_TYP_MAX;
|
||||
for (int32_t i = 0; i < typMax; i++) {
|
||||
SVerRangeList* iList = &part->verRanges[i];
|
||||
SVersionRange vr = {0};
|
||||
TARRAY2_FOREACH(iList, vr) {
|
||||
if (vr.maxVer < vr.minVer) {
|
||||
continue;
|
||||
}
|
||||
maxVerValid = TMAX(maxVerValid, vr.maxVer);
|
||||
}
|
||||
}
|
||||
r->fid = part->fid;
|
||||
r->sver = maxVerValid + 1;
|
||||
r->ever = VERSION_MAX;
|
||||
tsdbDebug("range diff fid:%" PRId64 ", sver:%" PRId64 ", ever:%" PRId64, part->fid, r->sver, r->ever);
|
||||
int32_t code = TARRAY2_SORT_INSERT(pDiff, r, tsdbTFileSetRangeCmprFn);
|
||||
ASSERT(code == 0);
|
||||
}
|
||||
ppRanges[0] = pDiff;
|
||||
|
||||
tsdbInfo("pDiff size:%d", TARRAY2_SIZE(pDiff));
|
||||
return 0;
|
||||
|
||||
_err:
|
||||
if (pDiff) {
|
||||
tsdbTFileSetRangeArrayDestroy(&pDiff);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// serialization
|
||||
int32_t tTsdbFSetPartListDataLenCalc(STsdbFSetPartList* pList) {
|
||||
int32_t hdrLen = sizeof(int32_t);
|
||||
int32_t datLen = 0;
|
||||
|
||||
int8_t msgVer = 1;
|
||||
int32_t len = TARRAY2_SIZE(pList);
|
||||
hdrLen += sizeof(msgVer);
|
||||
hdrLen += sizeof(len);
|
||||
datLen += hdrLen;
|
||||
|
||||
for (int32_t u = 0; u < len; u++) {
|
||||
STsdbFSetPartition* p = TARRAY2_GET(pList, u);
|
||||
int32_t typMax = TSDB_FSET_RANGE_TYP_MAX;
|
||||
int32_t uItem = 0;
|
||||
uItem += sizeof(STsdbFSetPartition);
|
||||
uItem += sizeof(typMax);
|
||||
|
||||
for (int32_t i = 0; i < typMax; i++) {
|
||||
int32_t iLen = TARRAY2_SIZE(&p->verRanges[i]);
|
||||
int32_t jItem = 0;
|
||||
jItem += sizeof(SVersionRange);
|
||||
jItem += sizeof(int64_t);
|
||||
uItem += sizeof(iLen) + jItem * iLen;
|
||||
}
|
||||
datLen += uItem;
|
||||
}
|
||||
return datLen;
|
||||
}
|
||||
|
||||
int32_t tSerializeTsdbFSetPartList(void* buf, int32_t bufLen, STsdbFSetPartList* pList) {
|
||||
SEncoder encoder = {0};
|
||||
tEncoderInit(&encoder, buf, bufLen);
|
||||
|
||||
int8_t reserved8 = 0;
|
||||
int16_t reserved16 = 0;
|
||||
int64_t reserved64 = 0;
|
||||
|
||||
int8_t msgVer = TSDB_SNAP_MSG_VER;
|
||||
int32_t len = TARRAY2_SIZE(pList);
|
||||
|
||||
if (tStartEncode(&encoder) < 0) goto _err;
|
||||
if (tEncodeI8(&encoder, msgVer) < 0) goto _err;
|
||||
if (tEncodeI32(&encoder, len) < 0) goto _err;
|
||||
|
||||
for (int32_t u = 0; u < len; u++) {
|
||||
STsdbFSetPartition* p = TARRAY2_GET(pList, u);
|
||||
if (tEncodeI64(&encoder, p->fid) < 0) goto _err;
|
||||
if (tEncodeI8(&encoder, p->stat) < 0) goto _err;
|
||||
if (tEncodeI8(&encoder, reserved8) < 0) goto _err;
|
||||
if (tEncodeI16(&encoder, reserved16) < 0) goto _err;
|
||||
|
||||
int32_t typMax = TSDB_FSET_RANGE_TYP_MAX;
|
||||
if (tEncodeI32(&encoder, typMax) < 0) goto _err;
|
||||
|
||||
for (int32_t i = 0; i < typMax; i++) {
|
||||
SVerRangeList* iList = &p->verRanges[i];
|
||||
int32_t iLen = TARRAY2_SIZE(iList);
|
||||
|
||||
if (tEncodeI32(&encoder, iLen) < 0) goto _err;
|
||||
for (int32_t j = 0; j < iLen; j++) {
|
||||
SVersionRange r = TARRAY2_GET(iList, j);
|
||||
if (tEncodeI64(&encoder, r.minVer) < 0) goto _err;
|
||||
if (tEncodeI64(&encoder, r.maxVer) < 0) goto _err;
|
||||
if (tEncodeI64(&encoder, reserved64) < 0) goto _err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tEndEncode(&encoder);
|
||||
int32_t tlen = encoder.pos;
|
||||
tEncoderClear(&encoder);
|
||||
return tlen;
|
||||
|
||||
_err:
|
||||
tEncoderClear(&encoder);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t tDeserializeTsdbFSetPartList(void* buf, int32_t bufLen, STsdbFSetPartList* pList) {
|
||||
SDecoder decoder = {0};
|
||||
tDecoderInit(&decoder, buf, bufLen);
|
||||
|
||||
int8_t reserved8 = 0;
|
||||
int16_t reserved16 = 0;
|
||||
int64_t reserved64 = 0;
|
||||
|
||||
STsdbFSetPartition* p = NULL;
|
||||
|
||||
int8_t msgVer = 0;
|
||||
int32_t len = 0;
|
||||
if (tStartDecode(&decoder) < 0) goto _err;
|
||||
if (tDecodeI8(&decoder, &msgVer) < 0) goto _err;
|
||||
if (msgVer != TSDB_SNAP_MSG_VER) goto _err;
|
||||
if (tDecodeI32(&decoder, &len) < 0) goto _err;
|
||||
|
||||
for (int32_t u = 0; u < len; u++) {
|
||||
p = tsdbFSetPartitionCreate();
|
||||
if (p == NULL) goto _err;
|
||||
if (tDecodeI64(&decoder, &p->fid) < 0) goto _err;
|
||||
if (tDecodeI8(&decoder, &p->stat) < 0) goto _err;
|
||||
if (tDecodeI8(&decoder, &reserved8) < 0) goto _err;
|
||||
if (tDecodeI16(&decoder, &reserved16) < 0) goto _err;
|
||||
|
||||
int32_t typMax = 0;
|
||||
if (tDecodeI32(&decoder, &typMax) < 0) goto _err;
|
||||
|
||||
for (int32_t i = 0; i < typMax; i++) {
|
||||
SVerRangeList* iList = &p->verRanges[i];
|
||||
int32_t iLen = 0;
|
||||
if (tDecodeI32(&decoder, &iLen) < 0) goto _err;
|
||||
for (int32_t j = 0; j < iLen; j++) {
|
||||
SVersionRange r = {0};
|
||||
if (tDecodeI64(&decoder, &r.minVer) < 0) goto _err;
|
||||
if (tDecodeI64(&decoder, &r.maxVer) < 0) goto _err;
|
||||
if (tDecodeI64(&decoder, &reserved64) < 0) goto _err;
|
||||
TARRAY2_APPEND(iList, r);
|
||||
}
|
||||
}
|
||||
TARRAY2_APPEND(pList, p);
|
||||
p = NULL;
|
||||
}
|
||||
|
||||
tEndDecode(&decoder);
|
||||
tDecoderClear(&decoder);
|
||||
return 0;
|
||||
|
||||
_err:
|
||||
if (p) {
|
||||
tsdbFSetPartitionClear(&p);
|
||||
}
|
||||
tDecoderClear(&decoder);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// fs state
|
||||
static STsdbFSetPartList* tsdbSnapGetFSetPartList(STFileSystem* fs) {
|
||||
STsdbFSetPartList* pList = tsdbFSetPartListCreate();
|
||||
if (pList == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int32_t code = 0;
|
||||
taosThreadMutexLock(&fs->tsdb->mutex);
|
||||
STFileSet* fset;
|
||||
TARRAY2_FOREACH(fs->fSetArr, fset) {
|
||||
STsdbFSetPartition* pItem = NULL;
|
||||
if (tsdbTFileSetToFSetPartition(fset, &pItem) < 0) {
|
||||
code = -1;
|
||||
break;
|
||||
}
|
||||
ASSERT(pItem != NULL);
|
||||
code = TARRAY2_SORT_INSERT(pList, pItem, tsdbFSetPartCmprFn);
|
||||
ASSERT(code == 0);
|
||||
}
|
||||
taosThreadMutexUnlock(&fs->tsdb->mutex);
|
||||
|
||||
if (code) {
|
||||
TARRAY2_DESTROY(pList, tsdbFSetPartitionClear);
|
||||
taosMemoryFree(pList);
|
||||
pList = NULL;
|
||||
}
|
||||
return pList;
|
||||
}
|
||||
|
||||
ETsdbFsState tsdbSnapGetFsState(SVnode* pVnode) {
|
||||
if (!VND_IS_RSMA(pVnode)) {
|
||||
return pVnode->pTsdb->pFS->fsstate;
|
||||
}
|
||||
for (int32_t lvl = 0; lvl < TSDB_RETENTION_MAX; ++lvl) {
|
||||
STsdb* pTsdb = SMA_RSMA_GET_TSDB(pVnode, lvl);
|
||||
if (pTsdb && pTsdb->pFS->fsstate != TSDB_FS_STATE_NORMAL) {
|
||||
return TSDB_FS_STATE_INCOMPLETE;
|
||||
}
|
||||
}
|
||||
return TSDB_FS_STATE_NORMAL;
|
||||
}
|
||||
|
||||
// description
|
||||
typedef struct STsdbPartitionInfo {
|
||||
int32_t vgId;
|
||||
int32_t tsdbMaxCnt;
|
||||
int32_t subTyps[TSDB_RETENTION_MAX];
|
||||
STsdbFSetPartList* pLists[TSDB_RETENTION_MAX];
|
||||
} STsdbPartitionInfo;
|
||||
|
||||
static int32_t tsdbPartitionInfoInit(SVnode* pVnode, STsdbPartitionInfo* pInfo) {
|
||||
int32_t subTyps[TSDB_RETENTION_MAX] = {SNAP_DATA_TSDB, SNAP_DATA_RSMA1, SNAP_DATA_RSMA2};
|
||||
pInfo->vgId = TD_VID(pVnode);
|
||||
pInfo->tsdbMaxCnt = (!VND_IS_RSMA(pVnode) ? 1 : TSDB_RETENTION_MAX);
|
||||
|
||||
ASSERT(sizeof(pInfo->subTyps) == sizeof(subTyps));
|
||||
memcpy(pInfo->subTyps, (char*)subTyps, sizeof(subTyps));
|
||||
|
||||
// fset partition list
|
||||
memset(pInfo->pLists, 0, sizeof(pInfo->pLists[0]) * TSDB_RETENTION_MAX);
|
||||
for (int32_t j = 0; j < pInfo->tsdbMaxCnt; ++j) {
|
||||
STsdb* pTsdb = SMA_RSMA_GET_TSDB(pVnode, j);
|
||||
pInfo->pLists[j] = tsdbSnapGetFSetPartList(pTsdb->pFS);
|
||||
if (pInfo->pLists[j] == NULL) return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void tsdbPartitionInfoClear(STsdbPartitionInfo* pInfo) {
|
||||
for (int32_t j = 0; j < pInfo->tsdbMaxCnt; ++j) {
|
||||
if (pInfo->pLists[j] == NULL) continue;
|
||||
tsdbFSetPartListDestroy(&pInfo->pLists[j]);
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t tsdbPartitionInfoEstSize(STsdbPartitionInfo* pInfo) {
|
||||
int32_t dataLen = 0;
|
||||
for (int32_t j = 0; j < pInfo->tsdbMaxCnt; ++j) {
|
||||
dataLen += sizeof(SSyncTLV); // subTyps[j]
|
||||
dataLen += tTsdbFSetPartListDataLenCalc(pInfo->pLists[j]);
|
||||
}
|
||||
return dataLen;
|
||||
}
|
||||
|
||||
static int32_t tsdbPartitionInfoSerialize(STsdbPartitionInfo* pInfo, uint8_t* buf, int32_t bufLen) {
|
||||
int32_t tlen = 0;
|
||||
int32_t offset = 0;
|
||||
for (int32_t j = 0; j < pInfo->tsdbMaxCnt; ++j) {
|
||||
SSyncTLV* pSubHead = (void*)((char*)buf + offset);
|
||||
int32_t valOffset = offset + sizeof(*pSubHead);
|
||||
ASSERT(pSubHead->val == (char*)buf + valOffset);
|
||||
if ((tlen = tSerializeTsdbFSetPartList(pSubHead->val, bufLen - valOffset, pInfo->pLists[j])) < 0) {
|
||||
tsdbError("vgId:%d, failed to serialize fset partition list of tsdb %d since %s", pInfo->vgId, j, terrstr());
|
||||
return -1;
|
||||
}
|
||||
pSubHead->typ = pInfo->subTyps[j];
|
||||
pSubHead->len = tlen;
|
||||
offset += sizeof(*pSubHead) + tlen;
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
// tsdb replication opts
|
||||
static int32_t tTsdbRepOptsDataLenCalc(STsdbRepOpts* pInfo) {
|
||||
int32_t hdrLen = sizeof(int32_t);
|
||||
int32_t datLen = 0;
|
||||
|
||||
int8_t msgVer = 0;
|
||||
int64_t reserved64 = 0;
|
||||
int16_t format = 0;
|
||||
hdrLen += sizeof(msgVer);
|
||||
datLen += hdrLen;
|
||||
datLen += sizeof(format);
|
||||
datLen += sizeof(reserved64);
|
||||
datLen += sizeof(*pInfo);
|
||||
return datLen;
|
||||
}
|
||||
|
||||
int32_t tSerializeTsdbRepOpts(void* buf, int32_t bufLen, STsdbRepOpts* pOpts) {
|
||||
SEncoder encoder = {0};
|
||||
tEncoderInit(&encoder, buf, bufLen);
|
||||
|
||||
int64_t reserved64 = 0;
|
||||
int8_t msgVer = TSDB_SNAP_MSG_VER;
|
||||
|
||||
if (tStartEncode(&encoder) < 0) goto _err;
|
||||
if (tEncodeI8(&encoder, msgVer) < 0) goto _err;
|
||||
int16_t format = pOpts->format;
|
||||
if (tEncodeI16(&encoder, format) < 0) goto _err;
|
||||
if (tEncodeI64(&encoder, reserved64) < 0) goto _err;
|
||||
|
||||
tEndEncode(&encoder);
|
||||
int32_t tlen = encoder.pos;
|
||||
tEncoderClear(&encoder);
|
||||
return tlen;
|
||||
|
||||
_err:
|
||||
tEncoderClear(&encoder);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t tDeserializeTsdbRepOpts(void* buf, int32_t bufLen, STsdbRepOpts* pOpts) {
|
||||
SDecoder decoder = {0};
|
||||
tDecoderInit(&decoder, buf, bufLen);
|
||||
|
||||
int64_t reserved64 = 0;
|
||||
int8_t msgVer = 0;
|
||||
|
||||
if (tStartDecode(&decoder) < 0) goto _err;
|
||||
if (tDecodeI8(&decoder, &msgVer) < 0) goto _err;
|
||||
if (msgVer != TSDB_SNAP_MSG_VER) goto _err;
|
||||
int16_t format = 0;
|
||||
if (tDecodeI16(&decoder, &format) < 0) goto _err;
|
||||
pOpts->format = format;
|
||||
if (tDecodeI64(&decoder, &reserved64) < 0) goto _err;
|
||||
|
||||
tEndDecode(&decoder);
|
||||
tDecoderClear(&decoder);
|
||||
return 0;
|
||||
|
||||
_err:
|
||||
tDecoderClear(&decoder);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int32_t tsdbRepOptsEstSize(STsdbRepOpts* pOpts) {
|
||||
int32_t dataLen = 0;
|
||||
dataLen += sizeof(SSyncTLV);
|
||||
dataLen += tTsdbRepOptsDataLenCalc(pOpts);
|
||||
return dataLen;
|
||||
}
|
||||
|
||||
static int32_t tsdbRepOptsSerialize(STsdbRepOpts* pOpts, void* buf, int32_t bufLen) {
|
||||
SSyncTLV* pSubHead = buf;
|
||||
int32_t offset = 0;
|
||||
int32_t tlen = 0;
|
||||
if ((tlen = tSerializeTsdbRepOpts(pSubHead->val, bufLen, pOpts)) < 0) {
|
||||
return -1;
|
||||
}
|
||||
pSubHead->typ = SNAP_DATA_RAW;
|
||||
pSubHead->len = tlen;
|
||||
offset += sizeof(*pSubHead) + tlen;
|
||||
return offset;
|
||||
}
|
||||
|
||||
// snap info
|
||||
static int32_t tsdbSnapPrepDealWithSnapInfo(SVnode* pVnode, SSnapshot* pSnap, STsdbRepOpts* pInfo) {
|
||||
if (!pSnap->data) return 0;
|
||||
int32_t code = -1;
|
||||
|
||||
SSyncTLV* pHead = (void*)pSnap->data;
|
||||
int32_t offset = 0;
|
||||
|
||||
while (offset + sizeof(*pHead) < pHead->len) {
|
||||
SSyncTLV* pField = (void*)(pHead->val + offset);
|
||||
offset += sizeof(*pField) + pField->len;
|
||||
void* buf = pField->val;
|
||||
int32_t bufLen = pField->len;
|
||||
|
||||
switch (pField->typ) {
|
||||
case SNAP_DATA_TSDB:
|
||||
case SNAP_DATA_RSMA1:
|
||||
case SNAP_DATA_RSMA2: {
|
||||
} break;
|
||||
case SNAP_DATA_RAW: {
|
||||
if (tDeserializeTsdbRepOpts(buf, bufLen, pInfo) < 0) {
|
||||
terrno = TSDB_CODE_INVALID_DATA_FMT;
|
||||
tsdbError("vgId:%d, failed to deserialize tsdb rep opts since %s", TD_VID(pVnode), terrstr());
|
||||
goto _out;
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
tsdbError("vgId:%d, unexpected subfield type of snap info. typ:%d", TD_VID(pVnode), pField->typ);
|
||||
goto _out;
|
||||
}
|
||||
}
|
||||
|
||||
code = 0;
|
||||
_out:
|
||||
return code;
|
||||
}
|
||||
|
||||
int32_t tsdbSnapPrepDescription(SVnode* pVnode, SSnapshot* pSnap) {
|
||||
ASSERT(pSnap->type == TDMT_SYNC_PREP_SNAPSHOT || pSnap->type == TDMT_SYNC_PREP_SNAPSHOT_REPLY);
|
||||
STsdbPartitionInfo partitionInfo = {0};
|
||||
int code = -1;
|
||||
STsdbPartitionInfo* pInfo = &partitionInfo;
|
||||
|
||||
if (tsdbPartitionInfoInit(pVnode, pInfo) != 0) {
|
||||
goto _out;
|
||||
}
|
||||
|
||||
// deal with snap info for reply
|
||||
STsdbRepOpts opts = {.format = TSDB_SNAP_REP_FMT_RAW};
|
||||
if (pSnap->type == TDMT_SYNC_PREP_SNAPSHOT_REPLY) {
|
||||
STsdbRepOpts leaderOpts = {0};
|
||||
if (tsdbSnapPrepDealWithSnapInfo(pVnode, pSnap, &leaderOpts) < 0) {
|
||||
tsdbError("vgId:%d, failed to deal with snap info for reply since %s", TD_VID(pVnode), terrstr());
|
||||
goto _out;
|
||||
}
|
||||
opts.format = TMIN(opts.format, leaderOpts.format);
|
||||
}
|
||||
|
||||
// info data realloc
|
||||
const int32_t headLen = sizeof(SSyncTLV);
|
||||
int32_t bufLen = headLen;
|
||||
bufLen += tsdbPartitionInfoEstSize(pInfo);
|
||||
bufLen += tsdbRepOptsEstSize(&opts);
|
||||
if (syncSnapInfoDataRealloc(pSnap, bufLen) != 0) {
|
||||
tsdbError("vgId:%d, failed to realloc memory for data of snap info. bytes:%d", TD_VID(pVnode), bufLen);
|
||||
goto _out;
|
||||
}
|
||||
|
||||
// serialization
|
||||
char* buf = (void*)pSnap->data;
|
||||
int32_t offset = headLen;
|
||||
int32_t tlen = 0;
|
||||
|
||||
if ((tlen = tsdbPartitionInfoSerialize(pInfo, buf + offset, bufLen - offset)) < 0) {
|
||||
tsdbError("vgId:%d, failed to serialize tsdb partition info since %s", TD_VID(pVnode), terrstr());
|
||||
goto _out;
|
||||
}
|
||||
offset += tlen;
|
||||
ASSERT(offset <= bufLen);
|
||||
|
||||
if ((tlen = tsdbRepOptsSerialize(&opts, buf + offset, bufLen - offset)) < 0) {
|
||||
tsdbError("vgId:%d, failed to serialize tsdb rep opts since %s", TD_VID(pVnode), terrstr());
|
||||
goto _out;
|
||||
}
|
||||
offset += tlen;
|
||||
ASSERT(offset <= bufLen);
|
||||
|
||||
// set header of info data
|
||||
SSyncTLV* pHead = pSnap->data;
|
||||
pHead->typ = pSnap->type;
|
||||
pHead->len = offset - headLen;
|
||||
|
||||
tsdbInfo("vgId:%d, tsdb snap info prepared. type:%s, val length:%d", TD_VID(pVnode), TMSG_INFO(pHead->typ),
|
||||
pHead->len);
|
||||
code = 0;
|
||||
_out:
|
||||
tsdbPartitionInfoClear(pInfo);
|
||||
return code;
|
||||
}
|
|
@ -32,12 +32,12 @@ struct STsdbSnapReader {
|
|||
uint8_t* aBuf[5];
|
||||
SSkmInfo skmTb[1];
|
||||
|
||||
TSnapRangeArray* fsrArr;
|
||||
TFileSetRangeArray* fsrArr;
|
||||
|
||||
// context
|
||||
struct {
|
||||
int32_t fsrArrIdx;
|
||||
STSnapRange* fsr;
|
||||
STFileSetRange* fsr;
|
||||
bool isDataDone;
|
||||
bool isTombDone;
|
||||
} ctx[1];
|
||||
|
@ -331,7 +331,7 @@ static int32_t tsdbSnapReadTimeSeriesData(STsdbSnapReader* reader, uint8_t** dat
|
|||
|
||||
if (!(reader->blockData->nRow % 16)) {
|
||||
int64_t nData = tBlockDataSize(reader->blockData);
|
||||
if (nData >= 1 * 1024 * 1024) {
|
||||
if (nData >= TSDB_SNAP_DATA_PAYLOAD_SIZE) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -437,14 +437,14 @@ int32_t tsdbSnapReaderOpen(STsdb* tsdb, int64_t sver, int64_t ever, int8_t type,
|
|||
reader[0]->ever = ever;
|
||||
reader[0]->type = type;
|
||||
|
||||
code = tsdbFSCreateRefRangedSnapshot(tsdb->pFS, sver, ever, (TSnapRangeArray*)pRanges, &reader[0]->fsrArr);
|
||||
code = tsdbFSCreateRefRangedSnapshot(tsdb->pFS, sver, ever, (TFileSetRangeArray*)pRanges, &reader[0]->fsrArr);
|
||||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
|
||||
_exit:
|
||||
if (code) {
|
||||
tsdbError("vgId:%d %s failed at line %d since %s, sver:%" PRId64 " ever:%" PRId64 " type:%d", TD_VID(tsdb->pVnode),
|
||||
__func__, lino, tstrerror(code), sver, ever, type);
|
||||
tsdbSnapRangeArrayDestroy(&reader[0]->fsrArr);
|
||||
tsdbTFileSetRangeArrayDestroy(&reader[0]->fsrArr);
|
||||
taosMemoryFree(reader[0]);
|
||||
reader[0] = NULL;
|
||||
} else {
|
||||
|
@ -472,7 +472,7 @@ int32_t tsdbSnapReaderClose(STsdbSnapReader** reader) {
|
|||
TARRAY2_DESTROY(reader[0]->sttReaderArr, tsdbSttFileReaderClose);
|
||||
tsdbDataFileReaderClose(&reader[0]->dataReader);
|
||||
|
||||
tsdbSnapRangeArrayDestroy(&reader[0]->fsrArr);
|
||||
tsdbFSDestroyRefRangedSnapshot(&reader[0]->fsrArr);
|
||||
tDestroyTSchema(reader[0]->skmTb->pTSchema);
|
||||
|
||||
for (int32_t i = 0; i < ARRAY_SIZE(reader[0]->aBuf); ++i) {
|
||||
|
@ -1061,7 +1061,7 @@ int32_t tsdbSnapWriterOpen(STsdb* pTsdb, int64_t sver, int64_t ever, void* pRang
|
|||
writer[0]->compactVersion = INT64_MAX;
|
||||
writer[0]->now = taosGetTimestampMs();
|
||||
|
||||
code = tsdbFSCreateCopyRangedSnapshot(pTsdb->pFS, (TSnapRangeArray*)pRanges, &writer[0]->fsetArr, writer[0]->fopArr);
|
||||
code = tsdbFSCreateCopyRangedSnapshot(pTsdb->pFS, (TFileSetRangeArray*)pRanges, &writer[0]->fsetArr, writer[0]->fopArr);
|
||||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
|
||||
_exit:
|
||||
|
@ -1125,7 +1125,7 @@ int32_t tsdbSnapWriterClose(STsdbSnapWriter** writer, int8_t rollback) {
|
|||
tsdbDataFileReaderClose(&writer[0]->ctx->dataReader);
|
||||
|
||||
TARRAY2_DESTROY(writer[0]->fopArr, NULL);
|
||||
tsdbFSDestroyCopySnapshot(&writer[0]->fsetArr);
|
||||
tsdbFSDestroyCopyRangedSnapshot(&writer[0]->fsetArr);
|
||||
|
||||
for (int32_t i = 0; i < ARRAY_SIZE(writer[0]->aBuf); ++i) {
|
||||
tFree(writer[0]->aBuf[i]);
|
||||
|
@ -1167,439 +1167,3 @@ _exit:
|
|||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
// snap part
|
||||
static int32_t tsdbSnapPartCmprFn(STsdbSnapPartition* x, STsdbSnapPartition* y) {
|
||||
if (x->fid < y->fid) return -1;
|
||||
if (x->fid > y->fid) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t tVersionRangeCmprFn(SVersionRange* x, SVersionRange* y) {
|
||||
if (x->minVer < y->minVer) return -1;
|
||||
if (x->minVer > y->minVer) return 1;
|
||||
if (x->maxVer < y->maxVer) return -1;
|
||||
if (x->maxVer > y->maxVer) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t tsdbSnapRangeCmprFn(STSnapRange* x, STSnapRange* y) {
|
||||
if (x->fid < y->fid) return -1;
|
||||
if (x->fid > y->fid) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
STsdbSnapPartition* tsdbSnapPartitionCreate() {
|
||||
STsdbSnapPartition* pSP = taosMemoryCalloc(1, sizeof(STsdbSnapPartition));
|
||||
if (pSP == NULL) {
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
return NULL;
|
||||
}
|
||||
for (int32_t i = 0; i < TSDB_SNAP_RANGE_TYP_MAX; i++) {
|
||||
TARRAY2_INIT(&pSP->verRanges[i]);
|
||||
}
|
||||
return pSP;
|
||||
}
|
||||
|
||||
void tsdbSnapPartitionClear(STsdbSnapPartition** ppSP) {
|
||||
if (ppSP == NULL || ppSP[0] == NULL) {
|
||||
return;
|
||||
}
|
||||
for (int32_t i = 0; i < TSDB_SNAP_RANGE_TYP_MAX; i++) {
|
||||
TARRAY2_DESTROY(&ppSP[0]->verRanges[i], NULL);
|
||||
}
|
||||
taosMemoryFree(ppSP[0]);
|
||||
ppSP[0] = NULL;
|
||||
}
|
||||
|
||||
static int32_t tsdbFTypeToSRangeTyp(tsdb_ftype_t ftype) {
|
||||
switch (ftype) {
|
||||
case TSDB_FTYPE_HEAD:
|
||||
return TSDB_SNAP_RANGE_TYP_HEAD;
|
||||
case TSDB_FTYPE_DATA:
|
||||
return TSDB_SNAP_RANGE_TYP_DATA;
|
||||
case TSDB_FTYPE_SMA:
|
||||
return TSDB_SNAP_RANGE_TYP_SMA;
|
||||
case TSDB_FTYPE_TOMB:
|
||||
return TSDB_SNAP_RANGE_TYP_TOMB;
|
||||
case TSDB_FTYPE_STT:
|
||||
return TSDB_SNAP_RANGE_TYP_STT;
|
||||
}
|
||||
return TSDB_SNAP_RANGE_TYP_MAX;
|
||||
}
|
||||
|
||||
static int32_t tsdbTFileSetToSnapPart(STFileSet* fset, STsdbSnapPartition** ppSP) {
|
||||
STsdbSnapPartition* p = tsdbSnapPartitionCreate();
|
||||
if (p == NULL) {
|
||||
goto _err;
|
||||
}
|
||||
|
||||
p->fid = fset->fid;
|
||||
|
||||
int32_t code = 0;
|
||||
int32_t typ = 0;
|
||||
int32_t corrupt = false;
|
||||
int32_t count = 0;
|
||||
for (int32_t ftype = TSDB_FTYPE_MIN; ftype < TSDB_FTYPE_MAX; ++ftype) {
|
||||
if (fset->farr[ftype] == NULL) continue;
|
||||
typ = tsdbFTypeToSRangeTyp(ftype);
|
||||
ASSERT(typ < TSDB_SNAP_RANGE_TYP_MAX);
|
||||
STFile* f = fset->farr[ftype]->f;
|
||||
if (f->maxVer > fset->maxVerValid) {
|
||||
corrupt = true;
|
||||
tsdbError("skip incomplete data file: fid:%d, maxVerValid:%" PRId64 ", minVer:%" PRId64 ", maxVer:%" PRId64
|
||||
", ftype: %d",
|
||||
fset->fid, fset->maxVerValid, f->minVer, f->maxVer, ftype);
|
||||
continue;
|
||||
}
|
||||
count++;
|
||||
SVersionRange vr = {.minVer = f->minVer, .maxVer = f->maxVer};
|
||||
code = TARRAY2_SORT_INSERT(&p->verRanges[typ], vr, tVersionRangeCmprFn);
|
||||
ASSERT(code == 0);
|
||||
}
|
||||
|
||||
typ = TSDB_SNAP_RANGE_TYP_STT;
|
||||
const SSttLvl* lvl;
|
||||
TARRAY2_FOREACH(fset->lvlArr, lvl) {
|
||||
STFileObj* fobj;
|
||||
TARRAY2_FOREACH(lvl->fobjArr, fobj) {
|
||||
STFile* f = fobj->f;
|
||||
if (f->maxVer > fset->maxVerValid) {
|
||||
corrupt = true;
|
||||
tsdbError("skip incomplete stt file.fid:%d, maxVerValid:%" PRId64 ", minVer:%" PRId64 ", maxVer:%" PRId64
|
||||
", ftype: %d",
|
||||
fset->fid, fset->maxVerValid, f->minVer, f->maxVer, typ);
|
||||
continue;
|
||||
}
|
||||
count++;
|
||||
SVersionRange vr = {.minVer = f->minVer, .maxVer = f->maxVer};
|
||||
code = TARRAY2_SORT_INSERT(&p->verRanges[typ], vr, tVersionRangeCmprFn);
|
||||
ASSERT(code == 0);
|
||||
}
|
||||
}
|
||||
if (corrupt && count == 0) {
|
||||
SVersionRange vr = {.minVer = VERSION_MIN, .maxVer = fset->maxVerValid};
|
||||
code = TARRAY2_SORT_INSERT(&p->verRanges[typ], vr, tVersionRangeCmprFn);
|
||||
ASSERT(code == 0);
|
||||
}
|
||||
ppSP[0] = p;
|
||||
return 0;
|
||||
|
||||
_err:
|
||||
tsdbSnapPartitionClear(&p);
|
||||
return -1;
|
||||
}
|
||||
|
||||
STsdbSnapPartList* tsdbSnapPartListCreate() {
|
||||
STsdbSnapPartList* pList = taosMemoryCalloc(1, sizeof(STsdbSnapPartList));
|
||||
if (pList == NULL) {
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
return NULL;
|
||||
}
|
||||
TARRAY2_INIT(pList);
|
||||
return pList;
|
||||
}
|
||||
|
||||
static STsdbSnapPartList* tsdbGetSnapPartList(STFileSystem* fs) {
|
||||
STsdbSnapPartList* pList = tsdbSnapPartListCreate();
|
||||
if (pList == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int32_t code = 0;
|
||||
taosThreadMutexLock(&fs->tsdb->mutex);
|
||||
STFileSet* fset;
|
||||
TARRAY2_FOREACH(fs->fSetArr, fset) {
|
||||
STsdbSnapPartition* pItem = NULL;
|
||||
if (tsdbTFileSetToSnapPart(fset, &pItem) < 0) {
|
||||
code = -1;
|
||||
break;
|
||||
}
|
||||
ASSERT(pItem != NULL);
|
||||
code = TARRAY2_SORT_INSERT(pList, pItem, tsdbSnapPartCmprFn);
|
||||
ASSERT(code == 0);
|
||||
}
|
||||
taosThreadMutexUnlock(&fs->tsdb->mutex);
|
||||
|
||||
if (code) {
|
||||
TARRAY2_DESTROY(pList, tsdbSnapPartitionClear);
|
||||
taosMemoryFree(pList);
|
||||
pList = NULL;
|
||||
}
|
||||
return pList;
|
||||
}
|
||||
|
||||
int32_t tTsdbSnapPartListDataLenCalc(STsdbSnapPartList* pList) {
|
||||
int32_t hdrLen = sizeof(int32_t);
|
||||
int32_t datLen = 0;
|
||||
|
||||
int8_t msgVer = 1;
|
||||
int32_t len = TARRAY2_SIZE(pList);
|
||||
hdrLen += sizeof(msgVer);
|
||||
hdrLen += sizeof(len);
|
||||
datLen += hdrLen;
|
||||
|
||||
for (int32_t u = 0; u < len; u++) {
|
||||
STsdbSnapPartition* p = TARRAY2_GET(pList, u);
|
||||
int32_t typMax = TSDB_SNAP_RANGE_TYP_MAX;
|
||||
int32_t uItem = 0;
|
||||
uItem += sizeof(STsdbSnapPartition);
|
||||
uItem += sizeof(typMax);
|
||||
|
||||
for (int32_t i = 0; i < typMax; i++) {
|
||||
int32_t iLen = TARRAY2_SIZE(&p->verRanges[i]);
|
||||
int32_t jItem = 0;
|
||||
jItem += sizeof(SVersionRange);
|
||||
jItem += sizeof(int64_t);
|
||||
uItem += sizeof(iLen) + jItem * iLen;
|
||||
}
|
||||
datLen += uItem;
|
||||
}
|
||||
return datLen;
|
||||
}
|
||||
|
||||
int32_t tSerializeTsdbSnapPartList(void* buf, int32_t bufLen, STsdbSnapPartList* pList) {
|
||||
SEncoder encoder = {0};
|
||||
tEncoderInit(&encoder, buf, bufLen);
|
||||
|
||||
int8_t reserved8 = 0;
|
||||
int16_t reserved16 = 0;
|
||||
int64_t reserved64 = 0;
|
||||
|
||||
int8_t msgVer = 1;
|
||||
int32_t len = TARRAY2_SIZE(pList);
|
||||
|
||||
if (tStartEncode(&encoder) < 0) goto _err;
|
||||
if (tEncodeI8(&encoder, msgVer) < 0) goto _err;
|
||||
if (tEncodeI32(&encoder, len) < 0) goto _err;
|
||||
|
||||
for (int32_t u = 0; u < len; u++) {
|
||||
STsdbSnapPartition* p = TARRAY2_GET(pList, u);
|
||||
if (tEncodeI64(&encoder, p->fid) < 0) goto _err;
|
||||
if (tEncodeI8(&encoder, p->stat) < 0) goto _err;
|
||||
if (tEncodeI8(&encoder, reserved8) < 0) goto _err;
|
||||
if (tEncodeI16(&encoder, reserved16) < 0) goto _err;
|
||||
|
||||
int32_t typMax = TSDB_SNAP_RANGE_TYP_MAX;
|
||||
if (tEncodeI32(&encoder, typMax) < 0) goto _err;
|
||||
|
||||
for (int32_t i = 0; i < typMax; i++) {
|
||||
SVerRangeList* iList = &p->verRanges[i];
|
||||
int32_t iLen = TARRAY2_SIZE(iList);
|
||||
|
||||
if (tEncodeI32(&encoder, iLen) < 0) goto _err;
|
||||
for (int32_t j = 0; j < iLen; j++) {
|
||||
SVersionRange r = TARRAY2_GET(iList, j);
|
||||
if (tEncodeI64(&encoder, r.minVer) < 0) goto _err;
|
||||
if (tEncodeI64(&encoder, r.maxVer) < 0) goto _err;
|
||||
if (tEncodeI64(&encoder, reserved64) < 0) goto _err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tEndEncode(&encoder);
|
||||
int32_t tlen = encoder.pos;
|
||||
tEncoderClear(&encoder);
|
||||
return tlen;
|
||||
|
||||
_err:
|
||||
tEncoderClear(&encoder);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t tDeserializeTsdbSnapPartList(void* buf, int32_t bufLen, STsdbSnapPartList* pList) {
|
||||
SDecoder decoder = {0};
|
||||
tDecoderInit(&decoder, buf, bufLen);
|
||||
|
||||
int8_t reserved8 = 0;
|
||||
int16_t reserved16 = 0;
|
||||
int64_t reserved64 = 0;
|
||||
|
||||
STsdbSnapPartition* p = NULL;
|
||||
|
||||
int8_t msgVer = 0;
|
||||
int32_t len = 0;
|
||||
if (tStartDecode(&decoder) < 0) goto _err;
|
||||
if (tDecodeI8(&decoder, &msgVer) < 0) goto _err;
|
||||
if (tDecodeI32(&decoder, &len) < 0) goto _err;
|
||||
|
||||
for (int32_t u = 0; u < len; u++) {
|
||||
p = tsdbSnapPartitionCreate();
|
||||
if (p == NULL) goto _err;
|
||||
if (tDecodeI64(&decoder, &p->fid) < 0) goto _err;
|
||||
if (tDecodeI8(&decoder, &p->stat) < 0) goto _err;
|
||||
if (tDecodeI8(&decoder, &reserved8) < 0) goto _err;
|
||||
if (tDecodeI16(&decoder, &reserved16) < 0) goto _err;
|
||||
|
||||
int32_t typMax = 0;
|
||||
if (tDecodeI32(&decoder, &typMax) < 0) goto _err;
|
||||
|
||||
for (int32_t i = 0; i < typMax; i++) {
|
||||
SVerRangeList* iList = &p->verRanges[i];
|
||||
int32_t iLen = 0;
|
||||
if (tDecodeI32(&decoder, &iLen) < 0) goto _err;
|
||||
for (int32_t j = 0; j < iLen; j++) {
|
||||
SVersionRange r = {0};
|
||||
if (tDecodeI64(&decoder, &r.minVer) < 0) goto _err;
|
||||
if (tDecodeI64(&decoder, &r.maxVer) < 0) goto _err;
|
||||
if (tDecodeI64(&decoder, &reserved64) < 0) goto _err;
|
||||
TARRAY2_APPEND(iList, r);
|
||||
}
|
||||
}
|
||||
TARRAY2_APPEND(pList, p);
|
||||
p = NULL;
|
||||
}
|
||||
|
||||
tEndDecode(&decoder);
|
||||
tDecoderClear(&decoder);
|
||||
return 0;
|
||||
|
||||
_err:
|
||||
if (p) {
|
||||
tsdbSnapPartitionClear(&p);
|
||||
}
|
||||
tDecoderClear(&decoder);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t tsdbSnapPartListToRangeDiff(STsdbSnapPartList* pList, TSnapRangeArray** ppRanges) {
|
||||
TSnapRangeArray* pDiff = taosMemoryCalloc(1, sizeof(TSnapRangeArray));
|
||||
if (pDiff == NULL) {
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
goto _err;
|
||||
}
|
||||
TARRAY2_INIT(pDiff);
|
||||
|
||||
STsdbSnapPartition* part;
|
||||
TARRAY2_FOREACH(pList, part) {
|
||||
STSnapRange* r = taosMemoryCalloc(1, sizeof(STSnapRange));
|
||||
if (r == NULL) {
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
goto _err;
|
||||
}
|
||||
int64_t maxVerValid = -1;
|
||||
int32_t typMax = TSDB_SNAP_RANGE_TYP_MAX;
|
||||
for (int32_t i = 0; i < typMax; i++) {
|
||||
SVerRangeList* iList = &part->verRanges[i];
|
||||
SVersionRange vr = {0};
|
||||
TARRAY2_FOREACH(iList, vr) {
|
||||
if (vr.maxVer < vr.minVer) {
|
||||
continue;
|
||||
}
|
||||
maxVerValid = TMAX(maxVerValid, vr.maxVer);
|
||||
}
|
||||
}
|
||||
r->fid = part->fid;
|
||||
r->sver = maxVerValid + 1;
|
||||
r->ever = VERSION_MAX;
|
||||
tsdbDebug("range diff fid:%" PRId64 ", sver:%" PRId64 ", ever:%" PRId64, part->fid, r->sver, r->ever);
|
||||
int32_t code = TARRAY2_SORT_INSERT(pDiff, r, tsdbSnapRangeCmprFn);
|
||||
ASSERT(code == 0);
|
||||
}
|
||||
ppRanges[0] = pDiff;
|
||||
|
||||
tsdbInfo("pDiff size:%d", TARRAY2_SIZE(pDiff));
|
||||
return 0;
|
||||
|
||||
_err:
|
||||
if (pDiff) {
|
||||
tsdbSnapRangeArrayDestroy(&pDiff);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void tsdbSnapRangeArrayDestroy(TSnapRangeArray** ppSnap) {
|
||||
if (ppSnap && ppSnap[0]) {
|
||||
TARRAY2_DESTROY(ppSnap[0], tsdbTSnapRangeClear);
|
||||
taosMemoryFree(ppSnap[0]);
|
||||
ppSnap[0] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void tsdbSnapPartListDestroy(STsdbSnapPartList** ppList) {
|
||||
if (ppList == NULL || ppList[0] == NULL) return;
|
||||
|
||||
TARRAY2_DESTROY(ppList[0], tsdbSnapPartitionClear);
|
||||
taosMemoryFree(ppList[0]);
|
||||
ppList[0] = NULL;
|
||||
}
|
||||
|
||||
ETsdbFsState tsdbSnapGetFsState(SVnode* pVnode) {
|
||||
if (!VND_IS_RSMA(pVnode)) {
|
||||
return pVnode->pTsdb->pFS->fsstate;
|
||||
}
|
||||
for (int32_t lvl = 0; lvl < TSDB_RETENTION_MAX; ++lvl) {
|
||||
STsdb* pTsdb = SMA_RSMA_GET_TSDB(pVnode, lvl);
|
||||
if (pTsdb && pTsdb->pFS->fsstate != TSDB_FS_STATE_NORMAL) {
|
||||
return TSDB_FS_STATE_INCOMPLETE;
|
||||
}
|
||||
}
|
||||
return TSDB_FS_STATE_NORMAL;
|
||||
}
|
||||
|
||||
int32_t tsdbSnapGetDetails(SVnode* pVnode, SSnapshot* pSnap) {
|
||||
int code = -1;
|
||||
int32_t tsdbMaxCnt = (!VND_IS_RSMA(pVnode) ? 1 : TSDB_RETENTION_MAX);
|
||||
int32_t subTyps[TSDB_RETENTION_MAX] = {SNAP_DATA_TSDB, SNAP_DATA_RSMA1, SNAP_DATA_RSMA2};
|
||||
STsdbSnapPartList* pLists[TSDB_RETENTION_MAX] = {0};
|
||||
|
||||
for (int32_t j = 0; j < tsdbMaxCnt; ++j) {
|
||||
STsdb* pTsdb = SMA_RSMA_GET_TSDB(pVnode, j);
|
||||
pLists[j] = tsdbGetSnapPartList(pTsdb->pFS);
|
||||
if (pLists[j] == NULL) goto _out;
|
||||
}
|
||||
|
||||
// estimate bufLen and prepare
|
||||
int32_t bufLen = sizeof(SSyncTLV); // typ: TDMT_SYNC_PREP_SNAPSHOT or TDMT_SYNC_PREP_SNAPSOT_REPLY
|
||||
for (int32_t j = 0; j < tsdbMaxCnt; ++j) {
|
||||
bufLen += sizeof(SSyncTLV); // subTyps[j]
|
||||
bufLen += tTsdbSnapPartListDataLenCalc(pLists[j]);
|
||||
}
|
||||
|
||||
tsdbInfo("vgId:%d, allocate %d bytes for data of snapshot info.", TD_VID(pVnode), bufLen);
|
||||
|
||||
void* data = taosMemoryRealloc(pSnap->data, bufLen);
|
||||
if (data == NULL) {
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
tsdbError("vgId:%d, failed to realloc memory for data of snapshot info. bytes:%d", TD_VID(pVnode), bufLen);
|
||||
goto _out;
|
||||
}
|
||||
pSnap->data = data;
|
||||
|
||||
// header
|
||||
SSyncTLV* head = data;
|
||||
head->len = 0;
|
||||
head->typ = pSnap->type;
|
||||
int32_t offset = sizeof(SSyncTLV);
|
||||
int32_t tlen = 0;
|
||||
|
||||
// fill snapshot info
|
||||
for (int32_t j = 0; j < tsdbMaxCnt; ++j) {
|
||||
if (pSnap->type == TDMT_SYNC_PREP_SNAPSHOT_REPLY) {
|
||||
}
|
||||
|
||||
// subHead
|
||||
SSyncTLV* subHead = (void*)((char*)data + offset);
|
||||
subHead->typ = subTyps[j];
|
||||
ASSERT(subHead->val == (char*)data + offset + sizeof(SSyncTLV));
|
||||
|
||||
if ((tlen = tSerializeTsdbSnapPartList(subHead->val, bufLen - offset - sizeof(SSyncTLV), pLists[j])) < 0) {
|
||||
tsdbError("vgId:%d, failed to serialize snap partition list of tsdb %d since %s", TD_VID(pVnode), j, terrstr());
|
||||
goto _out;
|
||||
}
|
||||
subHead->len = tlen;
|
||||
offset += sizeof(SSyncTLV) + tlen;
|
||||
}
|
||||
|
||||
head->len = offset - sizeof(SSyncTLV);
|
||||
ASSERT(offset <= bufLen);
|
||||
code = 0;
|
||||
|
||||
_out:
|
||||
for (int32_t j = 0; j < tsdbMaxCnt; ++j) {
|
||||
if (pLists[j] == NULL) continue;
|
||||
tsdbSnapPartListDestroy(&pLists[j]);
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
|
@ -0,0 +1,599 @@
|
|||
/*
|
||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||
*
|
||||
* This program is free software: you can use, redistribute, and/or modify
|
||||
* it under the terms of the GNU Affero General Public License, version 3
|
||||
* or later ("AGPL"), as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "tsdb.h"
|
||||
#include "tsdbDataFileRAW.h"
|
||||
#include "tsdbFS2.h"
|
||||
#include "tsdbFSetRAW.h"
|
||||
|
||||
static int32_t tsdbSnapRAWReadFileSetCloseReader(STsdbSnapRAWReader* reader);
|
||||
|
||||
// reader
|
||||
typedef struct SDataFileRAWReaderIter {
|
||||
int32_t count;
|
||||
int32_t idx;
|
||||
} SDataFileRAWReaderIter;
|
||||
|
||||
typedef struct STsdbSnapRAWReader {
|
||||
STsdb* tsdb;
|
||||
int64_t ever;
|
||||
int8_t type;
|
||||
|
||||
TFileSetArray* fsetArr;
|
||||
|
||||
// context
|
||||
struct {
|
||||
int32_t fsetArrIdx;
|
||||
STFileSet* fset;
|
||||
bool isDataDone;
|
||||
} ctx[1];
|
||||
|
||||
// reader
|
||||
SDataFileRAWReaderArray dataReaderArr[1];
|
||||
|
||||
// iter
|
||||
SDataFileRAWReaderIter dataIter[1];
|
||||
} STsdbSnapRAWReader;
|
||||
|
||||
int32_t tsdbSnapRAWReaderOpen(STsdb* tsdb, int64_t ever, int8_t type, STsdbSnapRAWReader** reader) {
|
||||
int32_t code = 0;
|
||||
int32_t lino = 0;
|
||||
|
||||
reader[0] = taosMemoryCalloc(1, sizeof(STsdbSnapRAWReader));
|
||||
if (reader[0] == NULL) return TSDB_CODE_OUT_OF_MEMORY;
|
||||
|
||||
reader[0]->tsdb = tsdb;
|
||||
reader[0]->ever = ever;
|
||||
reader[0]->type = type;
|
||||
|
||||
code = tsdbFSCreateRefSnapshot(tsdb->pFS, &reader[0]->fsetArr);
|
||||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
|
||||
_exit:
|
||||
if (code) {
|
||||
tsdbError("vgId:%d %s failed at line %d since %s, sver:0, ever:%" PRId64 " type:%d", TD_VID(tsdb->pVnode), __func__,
|
||||
lino, tstrerror(code), ever, type);
|
||||
tsdbFSDestroyRefSnapshot(&reader[0]->fsetArr);
|
||||
taosMemoryFree(reader[0]);
|
||||
reader[0] = NULL;
|
||||
} else {
|
||||
tsdbInfo("vgId:%d tsdb snapshot reader opened. sver:0, ever:%" PRId64 " type:%d", TD_VID(tsdb->pVnode), ever, type);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
int32_t tsdbSnapRAWReaderClose(STsdbSnapRAWReader** reader) {
|
||||
if (reader[0] == NULL) return 0;
|
||||
|
||||
int32_t code = 0;
|
||||
int32_t lino = 0;
|
||||
|
||||
STsdb* tsdb = reader[0]->tsdb;
|
||||
|
||||
TARRAY2_DESTROY(reader[0]->dataReaderArr, tsdbDataFileRAWReaderClose);
|
||||
tsdbFSDestroyRefSnapshot(&reader[0]->fsetArr);
|
||||
taosMemoryFree(reader[0]);
|
||||
reader[0] = NULL;
|
||||
|
||||
_exit:
|
||||
if (code) {
|
||||
TSDB_ERROR_LOG(TD_VID(tsdb->pVnode), lino, code);
|
||||
} else {
|
||||
tsdbDebug("vgId:%d %s done", TD_VID(tsdb->pVnode), __func__);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t tsdbSnapRAWReadFileSetOpenReader(STsdbSnapRAWReader* reader) {
|
||||
int32_t code = 0;
|
||||
int32_t lino = 0;
|
||||
|
||||
// data
|
||||
for (int32_t ftype = 0; ftype < TSDB_FTYPE_MAX; ftype++) {
|
||||
if (reader->ctx->fset->farr[ftype] == NULL) {
|
||||
continue;
|
||||
}
|
||||
STFileObj* fobj = reader->ctx->fset->farr[ftype];
|
||||
SDataFileRAWReader* dataReader;
|
||||
SDataFileRAWReaderConfig config = {
|
||||
.tsdb = reader->tsdb,
|
||||
.szPage = reader->tsdb->pVnode->config.tsdbPageSize,
|
||||
.file = fobj->f[0],
|
||||
};
|
||||
code = tsdbDataFileRAWReaderOpen(NULL, &config, &dataReader);
|
||||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
|
||||
code = TARRAY2_APPEND(reader->dataReaderArr, dataReader);
|
||||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
}
|
||||
|
||||
// stt
|
||||
SSttLvl* lvl;
|
||||
TARRAY2_FOREACH(reader->ctx->fset->lvlArr, lvl) {
|
||||
STFileObj* fobj;
|
||||
TARRAY2_FOREACH(lvl->fobjArr, fobj) {
|
||||
SDataFileRAWReader* dataReader;
|
||||
SDataFileRAWReaderConfig config = {
|
||||
.tsdb = reader->tsdb,
|
||||
.szPage = reader->tsdb->pVnode->config.tsdbPageSize,
|
||||
.file = fobj->f[0],
|
||||
};
|
||||
code = tsdbDataFileRAWReaderOpen(NULL, &config, &dataReader);
|
||||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
|
||||
code = TARRAY2_APPEND(reader->dataReaderArr, dataReader);
|
||||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
}
|
||||
}
|
||||
|
||||
_exit:
|
||||
if (code) {
|
||||
TSDB_ERROR_LOG(TD_VID(reader->tsdb->pVnode), code, lino);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t tsdbSnapRAWReadFileSetCloseReader(STsdbSnapRAWReader* reader) {
|
||||
int32_t code = 0;
|
||||
int32_t lino = 0;
|
||||
|
||||
TARRAY2_CLEAR(reader->dataReaderArr, tsdbDataFileRAWReaderClose);
|
||||
|
||||
_exit:
|
||||
if (code) {
|
||||
TSDB_ERROR_LOG(TD_VID(reader->tsdb->pVnode), code, lino);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t tsdbSnapRAWReadFileSetOpenIter(STsdbSnapRAWReader* reader) {
|
||||
int32_t code = 0;
|
||||
int32_t lino = 0;
|
||||
|
||||
reader->dataIter->count = TARRAY2_SIZE(reader->dataReaderArr);
|
||||
reader->dataIter->idx = 0;
|
||||
|
||||
_exit:
|
||||
if (code) {
|
||||
TSDB_ERROR_LOG(TD_VID(reader->tsdb->pVnode), code, lino);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t tsdbSnapRAWReadFileSetCloseIter(STsdbSnapRAWReader* reader) {
|
||||
reader->dataIter->count = 0;
|
||||
reader->dataIter->idx = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int64_t tsdbSnapRAWReadPeek(SDataFileRAWReader* reader) {
|
||||
int64_t size = TMIN(reader->config->file.size - reader->ctx->offset, TSDB_SNAP_DATA_PAYLOAD_SIZE);
|
||||
return size;
|
||||
}
|
||||
|
||||
static SDataFileRAWReader* tsdbSnapRAWReaderIterNext(STsdbSnapRAWReader* reader) {
|
||||
ASSERT(reader->dataIter->idx <= reader->dataIter->count);
|
||||
|
||||
while (reader->dataIter->idx < reader->dataIter->count) {
|
||||
SDataFileRAWReader* dataReader = TARRAY2_GET(reader->dataReaderArr, reader->dataIter->idx);
|
||||
ASSERT(dataReader);
|
||||
if (dataReader->ctx->offset < dataReader->config->file.size) {
|
||||
return dataReader;
|
||||
}
|
||||
reader->dataIter->idx++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int32_t tsdbSnapRAWReadNext(STsdbSnapRAWReader* reader, SSnapDataHdr** ppData) {
|
||||
int32_t code = 0;
|
||||
int32_t lino = 0;
|
||||
int8_t type = reader->type;
|
||||
ppData[0] = NULL;
|
||||
|
||||
SDataFileRAWReader* dataReader = tsdbSnapRAWReaderIterNext(reader);
|
||||
if (dataReader == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// prepare
|
||||
int64_t dataLength = tsdbSnapRAWReadPeek(dataReader);
|
||||
ASSERT(dataLength > 0);
|
||||
|
||||
void* pBuf = taosMemoryCalloc(1, sizeof(SSnapDataHdr) + sizeof(STsdbDataRAWBlockHeader) + dataLength);
|
||||
if (pBuf == NULL) {
|
||||
code = TSDB_CODE_OUT_OF_MEMORY;
|
||||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
}
|
||||
SSnapDataHdr* pHdr = pBuf;
|
||||
pHdr->type = type;
|
||||
pHdr->size = sizeof(STsdbDataRAWBlockHeader) + dataLength;
|
||||
|
||||
// read
|
||||
STsdbDataRAWBlockHeader* pBlock = (void*)pHdr->data;
|
||||
pBlock->offset = dataReader->ctx->offset;
|
||||
pBlock->dataLength = dataLength;
|
||||
|
||||
code = tsdbDataFileRAWReadBlockData(dataReader, pBlock);
|
||||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
|
||||
// finish
|
||||
dataReader->ctx->offset += pBlock->dataLength;
|
||||
ASSERT(dataReader->ctx->offset <= dataReader->config->file.size);
|
||||
ppData[0] = pBuf;
|
||||
|
||||
_exit:
|
||||
if (code) {
|
||||
taosMemoryFree(pBuf);
|
||||
pBuf = NULL;
|
||||
TSDB_ERROR_LOG(TD_VID(reader->tsdb->pVnode), code, lino);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t tsdbSnapRAWReadData(STsdbSnapRAWReader* reader, uint8_t** ppData) {
|
||||
int32_t code = 0;
|
||||
int32_t lino = 0;
|
||||
|
||||
code = tsdbSnapRAWReadNext(reader, (SSnapDataHdr**)ppData);
|
||||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
|
||||
_exit:
|
||||
if (code) {
|
||||
TSDB_ERROR_LOG(TD_VID(reader->tsdb->pVnode), code, lino);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t tsdbSnapRAWReadBegin(STsdbSnapRAWReader* reader) {
|
||||
int32_t code = 0;
|
||||
int32_t lino = 0;
|
||||
|
||||
ASSERT(reader->ctx->fset == NULL);
|
||||
|
||||
if (reader->ctx->fsetArrIdx < TARRAY2_SIZE(reader->fsetArr)) {
|
||||
reader->ctx->fset = TARRAY2_GET(reader->fsetArr, reader->ctx->fsetArrIdx++);
|
||||
reader->ctx->isDataDone = false;
|
||||
|
||||
code = tsdbSnapRAWReadFileSetOpenReader(reader);
|
||||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
|
||||
code = tsdbSnapRAWReadFileSetOpenIter(reader);
|
||||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
}
|
||||
|
||||
_exit:
|
||||
if (code) {
|
||||
TSDB_ERROR_LOG(TD_VID(reader->tsdb->pVnode), code, lino);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t tsdbSnapRAWReadEnd(STsdbSnapRAWReader* reader) {
|
||||
tsdbSnapRAWReadFileSetCloseIter(reader);
|
||||
tsdbSnapRAWReadFileSetCloseReader(reader);
|
||||
reader->ctx->fset = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t tsdbSnapRAWRead(STsdbSnapRAWReader* reader, uint8_t** data) {
|
||||
int32_t code = 0;
|
||||
int32_t lino = 0;
|
||||
|
||||
data[0] = NULL;
|
||||
|
||||
for (;;) {
|
||||
if (reader->ctx->fset == NULL) {
|
||||
code = tsdbSnapRAWReadBegin(reader);
|
||||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
|
||||
if (reader->ctx->fset == NULL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!reader->ctx->isDataDone) {
|
||||
code = tsdbSnapRAWReadData(reader, data);
|
||||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
if (data[0]) {
|
||||
goto _exit;
|
||||
} else {
|
||||
reader->ctx->isDataDone = true;
|
||||
}
|
||||
}
|
||||
|
||||
code = tsdbSnapRAWReadEnd(reader);
|
||||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
}
|
||||
|
||||
_exit:
|
||||
if (code) {
|
||||
TSDB_ERROR_LOG(TD_VID(reader->tsdb->pVnode), code, lino);
|
||||
} else {
|
||||
tsdbDebug("vgId:%d %s done", TD_VID(reader->tsdb->pVnode), __func__);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
// writer
|
||||
struct STsdbSnapRAWWriter {
|
||||
STsdb* tsdb;
|
||||
int64_t sver;
|
||||
int64_t ever;
|
||||
int32_t minutes;
|
||||
int8_t precision;
|
||||
int32_t minRow;
|
||||
int32_t maxRow;
|
||||
int8_t cmprAlg;
|
||||
int64_t commitID;
|
||||
int32_t szPage;
|
||||
int64_t compactVersion;
|
||||
int64_t now;
|
||||
|
||||
TFileSetArray* fsetArr;
|
||||
TFileOpArray fopArr[1];
|
||||
|
||||
struct {
|
||||
bool fsetWriteBegin;
|
||||
int32_t fid;
|
||||
STFileSet* fset;
|
||||
SDiskID did;
|
||||
int64_t cid;
|
||||
int64_t level;
|
||||
|
||||
// writer
|
||||
SFSetRAWWriter* fsetWriter;
|
||||
} ctx[1];
|
||||
};
|
||||
|
||||
int32_t tsdbSnapRAWWriterOpen(STsdb* pTsdb, int64_t ever, STsdbSnapRAWWriter** writer) {
|
||||
int32_t code = 0;
|
||||
int32_t lino = 0;
|
||||
|
||||
// start to write
|
||||
writer[0] = taosMemoryCalloc(1, sizeof(*writer[0]));
|
||||
if (writer[0] == NULL) return TSDB_CODE_OUT_OF_MEMORY;
|
||||
|
||||
writer[0]->tsdb = pTsdb;
|
||||
writer[0]->ever = ever;
|
||||
writer[0]->minutes = pTsdb->keepCfg.days;
|
||||
writer[0]->precision = pTsdb->keepCfg.precision;
|
||||
writer[0]->minRow = pTsdb->pVnode->config.tsdbCfg.minRows;
|
||||
writer[0]->maxRow = pTsdb->pVnode->config.tsdbCfg.maxRows;
|
||||
writer[0]->cmprAlg = pTsdb->pVnode->config.tsdbCfg.compression;
|
||||
writer[0]->commitID = tsdbFSAllocEid(pTsdb->pFS);
|
||||
writer[0]->szPage = pTsdb->pVnode->config.tsdbPageSize;
|
||||
writer[0]->compactVersion = INT64_MAX;
|
||||
writer[0]->now = taosGetTimestampMs();
|
||||
|
||||
code = tsdbFSCreateCopySnapshot(pTsdb->pFS, &writer[0]->fsetArr);
|
||||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
|
||||
_exit:
|
||||
if (code) {
|
||||
tsdbError("vgId:%d %s failed at line %d since %s", TD_VID(pTsdb->pVnode), __func__, lino, tstrerror(code));
|
||||
} else {
|
||||
tsdbInfo("vgId:%d %s done, sver:0, ever:%" PRId64, TD_VID(pTsdb->pVnode), __func__, ever);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t tsdbSnapRAWWriteFileSetOpenIter(STsdbSnapRAWWriter* writer) {
|
||||
int32_t code = 0;
|
||||
int32_t lino = 0;
|
||||
|
||||
_exit:
|
||||
if (code) {
|
||||
TSDB_ERROR_LOG(TD_VID(writer->tsdb->pVnode), lino, code);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t tsdbSnapRAWWriteFileSetCloseIter(STsdbSnapRAWWriter* writer) { return 0; }
|
||||
|
||||
static int32_t tsdbSnapRAWWriteFileSetOpenWriter(STsdbSnapRAWWriter* writer) {
|
||||
int32_t code = 0;
|
||||
int32_t lino = 0;
|
||||
|
||||
SFSetRAWWriterConfig config = {
|
||||
.tsdb = writer->tsdb,
|
||||
.szPage = writer->szPage,
|
||||
.fid = writer->ctx->fid,
|
||||
.cid = writer->commitID,
|
||||
.did = writer->ctx->did,
|
||||
.level = writer->ctx->level,
|
||||
};
|
||||
|
||||
code = tsdbFSetRAWWriterOpen(&config, &writer->ctx->fsetWriter);
|
||||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
|
||||
_exit:
|
||||
if (code) {
|
||||
TSDB_ERROR_LOG(TD_VID(writer->tsdb->pVnode), lino, code);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t tsdbSnapRAWWriteFileSetCloseWriter(STsdbSnapRAWWriter* writer) {
|
||||
return tsdbFSetRAWWriterClose(&writer->ctx->fsetWriter, 0, writer->fopArr);
|
||||
}
|
||||
|
||||
static int32_t tsdbSnapRAWWriteFileSetBegin(STsdbSnapRAWWriter* writer, int32_t fid) {
|
||||
int32_t code = 0;
|
||||
int32_t lino = 0;
|
||||
|
||||
ASSERT(writer->ctx->fsetWriteBegin == false);
|
||||
|
||||
STFileSet* fset = &(STFileSet){.fid = fid};
|
||||
|
||||
writer->ctx->fid = fid;
|
||||
STFileSet** fsetPtr = TARRAY2_SEARCH(writer->fsetArr, &fset, tsdbTFileSetCmprFn, TD_EQ);
|
||||
writer->ctx->fset = (fsetPtr == NULL) ? NULL : *fsetPtr;
|
||||
|
||||
int32_t level = tsdbFidLevel(fid, &writer->tsdb->keepCfg, taosGetTimestampSec());
|
||||
if (tfsAllocDisk(writer->tsdb->pVnode->pTfs, level, &writer->ctx->did)) {
|
||||
code = TSDB_CODE_NO_AVAIL_DISK;
|
||||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
}
|
||||
tfsMkdirRecurAt(writer->tsdb->pVnode->pTfs, writer->tsdb->path, writer->ctx->did);
|
||||
|
||||
code = tsdbSnapRAWWriteFileSetOpenWriter(writer);
|
||||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
|
||||
writer->ctx->level = level;
|
||||
writer->ctx->fsetWriteBegin = true;
|
||||
|
||||
_exit:
|
||||
if (code) {
|
||||
TSDB_ERROR_LOG(TD_VID(writer->tsdb->pVnode), lino, code);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t tsdbSnapRAWWriteFileSetEnd(STsdbSnapRAWWriter* writer) {
|
||||
if (!writer->ctx->fsetWriteBegin) return 0;
|
||||
|
||||
int32_t code = 0;
|
||||
int32_t lino = 0;
|
||||
|
||||
// close write
|
||||
code = tsdbSnapRAWWriteFileSetCloseWriter(writer);
|
||||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
|
||||
writer->ctx->fsetWriteBegin = false;
|
||||
|
||||
_exit:
|
||||
if (code) {
|
||||
TSDB_ERROR_LOG(TD_VID(writer->tsdb->pVnode), lino, code);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
int32_t tsdbSnapRAWWriterPrepareClose(STsdbSnapRAWWriter* writer) {
|
||||
int32_t code = 0;
|
||||
int32_t lino = 0;
|
||||
|
||||
code = tsdbSnapRAWWriteFileSetEnd(writer);
|
||||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
|
||||
code = tsdbFSEditBegin(writer->tsdb->pFS, writer->fopArr, TSDB_FEDIT_COMMIT);
|
||||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
|
||||
_exit:
|
||||
if (code) {
|
||||
TSDB_ERROR_LOG(TD_VID(writer->tsdb->pVnode), lino, code);
|
||||
} else {
|
||||
tsdbDebug("vgId:%d %s done", TD_VID(writer->tsdb->pVnode), __func__);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
int32_t tsdbSnapRAWWriterClose(STsdbSnapRAWWriter** writer, int8_t rollback) {
|
||||
if (writer[0] == NULL) return 0;
|
||||
|
||||
int32_t code = 0;
|
||||
int32_t lino = 0;
|
||||
|
||||
STsdb* tsdb = writer[0]->tsdb;
|
||||
|
||||
if (rollback) {
|
||||
code = tsdbFSEditAbort(writer[0]->tsdb->pFS);
|
||||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
} else {
|
||||
taosThreadMutexLock(&writer[0]->tsdb->mutex);
|
||||
|
||||
code = tsdbFSEditCommit(writer[0]->tsdb->pFS);
|
||||
if (code) {
|
||||
taosThreadMutexUnlock(&writer[0]->tsdb->mutex);
|
||||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
}
|
||||
|
||||
writer[0]->tsdb->pFS->fsstate = TSDB_FS_STATE_NORMAL;
|
||||
|
||||
taosThreadMutexUnlock(&writer[0]->tsdb->mutex);
|
||||
}
|
||||
|
||||
TARRAY2_DESTROY(writer[0]->fopArr, NULL);
|
||||
tsdbFSDestroyCopySnapshot(&writer[0]->fsetArr);
|
||||
|
||||
taosMemoryFree(writer[0]);
|
||||
writer[0] = NULL;
|
||||
|
||||
_exit:
|
||||
if (code) {
|
||||
TSDB_ERROR_LOG(TD_VID(tsdb->pVnode), lino, code);
|
||||
} else {
|
||||
tsdbInfo("vgId:%d %s done", TD_VID(tsdb->pVnode), __func__);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t tsdbSnapRAWWriteTimeSeriesData(STsdbSnapRAWWriter* writer, STsdbDataRAWBlockHeader* bHdr) {
|
||||
int32_t code = 0;
|
||||
int32_t lino = 0;
|
||||
|
||||
code = tsdbFSetRAWWriteBlockData(writer->ctx->fsetWriter, bHdr);
|
||||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
|
||||
_exit:
|
||||
if (code) {
|
||||
TSDB_ERROR_LOG(TD_VID(writer->tsdb->pVnode), lino, code);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t tsdbSnapRAWWriteData(STsdbSnapRAWWriter* writer, SSnapDataHdr* hdr) {
|
||||
int32_t code = 0;
|
||||
int32_t lino = 0;
|
||||
|
||||
STsdbDataRAWBlockHeader* bHdr = (void*)hdr->data;
|
||||
int32_t fid = bHdr->file.fid;
|
||||
if (!writer->ctx->fsetWriteBegin || fid != writer->ctx->fid) {
|
||||
code = tsdbSnapRAWWriteFileSetEnd(writer);
|
||||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
|
||||
code = tsdbSnapRAWWriteFileSetBegin(writer, fid);
|
||||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
}
|
||||
|
||||
code = tsdbSnapRAWWriteTimeSeriesData(writer, bHdr);
|
||||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
|
||||
_exit:
|
||||
if (code) {
|
||||
TSDB_ERROR_LOG(TD_VID(writer->tsdb->pVnode), lino, code);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
int32_t tsdbSnapRAWWrite(STsdbSnapRAWWriter* writer, SSnapDataHdr* hdr) {
|
||||
ASSERT(hdr->type == SNAP_DATA_RAW);
|
||||
|
||||
int32_t code = 0;
|
||||
int32_t lino = 0;
|
||||
|
||||
code = tsdbSnapRAWWriteData(writer, hdr);
|
||||
TSDB_CHECK_CODE(code, lino, _exit);
|
||||
|
||||
_exit:
|
||||
if (code) {
|
||||
tsdbError("vgId:%d %s failed at line %d since %s, type:%d index:%" PRId64 " size:%" PRId64,
|
||||
TD_VID(writer->tsdb->pVnode), __func__, lino, tstrerror(code), hdr->type, hdr->index, hdr->size);
|
||||
} else {
|
||||
tsdbDebug("vgId:%d %s done, type:%d index:%" PRId64 " size:%" PRId64, TD_VID(writer->tsdb->pVnode), __func__,
|
||||
hdr->type, hdr->index, hdr->size);
|
||||
}
|
||||
return code;
|
||||
}
|
|
@ -177,12 +177,15 @@ static int32_t vnodeAsyncTaskDone(SVAsync *async, SVATask *task) {
|
|||
}
|
||||
|
||||
static int32_t vnodeAsyncCancelAllTasks(SVAsync *async) {
|
||||
for (int32_t i = 0; i < EVA_PRIORITY_MAX; i++) {
|
||||
while (async->queue[i].next != &async->queue[i]) {
|
||||
SVATask *task = async->queue[i].next;
|
||||
task->prev->next = task->next;
|
||||
task->next->prev = task->prev;
|
||||
vnodeAsyncTaskDone(async, task);
|
||||
while (async->queue[0].next != &async->queue[0] || async->queue[1].next != &async->queue[1] ||
|
||||
async->queue[2].next != &async->queue[2]) {
|
||||
for (int32_t i = 0; i < EVA_PRIORITY_MAX; i++) {
|
||||
while (async->queue[i].next != &async->queue[i]) {
|
||||
SVATask *task = async->queue[i].next;
|
||||
task->prev->next = task->next;
|
||||
task->next->prev = task->prev;
|
||||
vnodeAsyncTaskDone(async, task);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
|
|
@ -42,7 +42,7 @@ void initStorageAPI(SStorageAPI* pAPI) {
|
|||
|
||||
void initTsdbReaderAPI(TsdReader* pReader) {
|
||||
pReader->tsdReaderOpen = (int32_t(*)(void*, SQueryTableDataCond*, void*, int32_t, SSDataBlock*, void**, const char*,
|
||||
bool, SHashObj**))tsdbReaderOpen2;
|
||||
SHashObj**))tsdbReaderOpen2;
|
||||
pReader->tsdReaderClose = tsdbReaderClose2;
|
||||
|
||||
pReader->tsdNextDataBlock = tsdbNextDataBlock2;
|
||||
|
@ -60,6 +60,9 @@ void initTsdbReaderAPI(TsdReader* pReader) {
|
|||
|
||||
pReader->tsdSetQueryTableList = tsdbSetTableList2;
|
||||
pReader->tsdSetReaderTaskId = (void (*)(void*, const char*))tsdbReaderSetId2;
|
||||
|
||||
pReader->tsdSetFilesetDelimited = (void (*)(void*))tsdbSetFilesetDelimited;
|
||||
pReader->tsdSetSetNotifyCb = (void (*)(void*, TsdReaderNotifyCbFn, void*))tsdbReaderSetNotifyCb;
|
||||
}
|
||||
|
||||
void initMetadataAPI(SStoreMeta* pMeta) {
|
||||
|
|
|
@ -16,6 +16,26 @@
|
|||
#include "tsdb.h"
|
||||
#include "vnd.h"
|
||||
|
||||
static int32_t vnodeExtractSnapInfoDiff(void *buf, int32_t bufLen, TFileSetRangeArray **ppRanges) {
|
||||
int32_t code = -1;
|
||||
STsdbFSetPartList *pList = tsdbFSetPartListCreate();
|
||||
if (pList == NULL) {
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
goto _out;
|
||||
}
|
||||
if (tDeserializeTsdbFSetPartList(buf, bufLen, pList) < 0) {
|
||||
terrno = TSDB_CODE_INVALID_DATA_FMT;
|
||||
goto _out;
|
||||
}
|
||||
if (tsdbFSetPartListToRangeDiff(pList, ppRanges) < 0) {
|
||||
goto _out;
|
||||
}
|
||||
code = 0;
|
||||
_out:
|
||||
tsdbFSetPartListDestroy(&pList);
|
||||
return code;
|
||||
}
|
||||
|
||||
// SVSnapReader ========================================================
|
||||
struct SVSnapReader {
|
||||
SVnode *pVnode;
|
||||
|
@ -29,8 +49,12 @@ struct SVSnapReader {
|
|||
SMetaSnapReader *pMetaReader;
|
||||
// tsdb
|
||||
int8_t tsdbDone;
|
||||
TSnapRangeArray *pRanges;
|
||||
TFileSetRangeArray *pRanges;
|
||||
STsdbSnapReader *pTsdbReader;
|
||||
// tsdb raw
|
||||
int8_t tsdbRAWDone;
|
||||
STsdbSnapRAWReader *pTsdbRAWReader;
|
||||
|
||||
// tq
|
||||
int8_t tqHandleDone;
|
||||
STqSnapReader *pTqSnapReader;
|
||||
|
@ -45,31 +69,11 @@ struct SVSnapReader {
|
|||
SStreamStateReader *pStreamStateReader;
|
||||
// rsma
|
||||
int8_t rsmaDone;
|
||||
TSnapRangeArray *pRsmaRanges[TSDB_RETENTION_L2];
|
||||
TFileSetRangeArray *pRsmaRanges[TSDB_RETENTION_L2];
|
||||
SRSmaSnapReader *pRsmaReader;
|
||||
};
|
||||
|
||||
static int32_t vnodeExtractSnapInfoDiff(void *buf, int32_t bufLen, TSnapRangeArray **ppRanges) {
|
||||
int32_t code = -1;
|
||||
STsdbSnapPartList *pList = tsdbSnapPartListCreate();
|
||||
if (pList == NULL) {
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
goto _out;
|
||||
}
|
||||
if (tDeserializeTsdbSnapPartList(buf, bufLen, pList) < 0) {
|
||||
terrno = TSDB_CODE_INVALID_DATA_FMT;
|
||||
goto _out;
|
||||
}
|
||||
if (tsdbSnapPartListToRangeDiff(pList, ppRanges) < 0) {
|
||||
goto _out;
|
||||
}
|
||||
code = 0;
|
||||
_out:
|
||||
tsdbSnapPartListDestroy(&pList);
|
||||
return code;
|
||||
}
|
||||
|
||||
static TSnapRangeArray **vnodeSnapReaderGetTsdbRanges(SVSnapReader *pReader, int32_t tsdbTyp) {
|
||||
static TFileSetRangeArray **vnodeSnapReaderGetTsdbRanges(SVSnapReader *pReader, int32_t tsdbTyp) {
|
||||
ASSERTS(sizeof(pReader->pRsmaRanges) / sizeof(pReader->pRsmaRanges[0]) == 2, "Unexpected array size");
|
||||
switch (tsdbTyp) {
|
||||
case SNAP_DATA_TSDB:
|
||||
|
@ -83,37 +87,66 @@ static TSnapRangeArray **vnodeSnapReaderGetTsdbRanges(SVSnapReader *pReader, int
|
|||
}
|
||||
}
|
||||
|
||||
static int32_t vnodeSnapReaderDoSnapInfo(SVSnapReader *pReader, SSnapshotParam *pParam) {
|
||||
static int32_t vnodeSnapReaderDealWithSnapInfo(SVSnapReader *pReader, SSnapshotParam *pParam) {
|
||||
SVnode *pVnode = pReader->pVnode;
|
||||
int32_t code = -1;
|
||||
|
||||
if (pParam->data) {
|
||||
// decode
|
||||
SSyncTLV *datHead = (void *)pParam->data;
|
||||
if (datHead->typ != TDMT_SYNC_PREP_SNAPSHOT_REPLY) {
|
||||
terrno = TSDB_CODE_INVALID_DATA_FMT;
|
||||
goto _out;
|
||||
}
|
||||
|
||||
TSnapRangeArray **ppRanges = NULL;
|
||||
int32_t offset = 0;
|
||||
STsdbRepOpts tsdbOpts = {0};
|
||||
TFileSetRangeArray **ppRanges = NULL;
|
||||
int32_t offset = 0;
|
||||
|
||||
while (offset + sizeof(SSyncTLV) < datHead->len) {
|
||||
SSyncTLV *subField = (void *)(datHead->val + offset);
|
||||
offset += sizeof(SSyncTLV) + subField->len;
|
||||
void *buf = subField->val;
|
||||
int32_t bufLen = subField->len;
|
||||
ppRanges = vnodeSnapReaderGetTsdbRanges(pReader, subField->typ);
|
||||
if (ppRanges == NULL) {
|
||||
vError("vgId:%d, unexpected subfield type in data of snapshot param. subtyp:%d", TD_VID(pVnode), subField->typ);
|
||||
goto _out;
|
||||
}
|
||||
if (vnodeExtractSnapInfoDiff(buf, bufLen, ppRanges) < 0) {
|
||||
vError("vgId:%d, failed to get range diff since %s", TD_VID(pVnode), terrstr());
|
||||
goto _out;
|
||||
|
||||
switch (subField->typ) {
|
||||
case SNAP_DATA_TSDB:
|
||||
case SNAP_DATA_RSMA1:
|
||||
case SNAP_DATA_RSMA2: {
|
||||
ppRanges = vnodeSnapReaderGetTsdbRanges(pReader, subField->typ);
|
||||
if (ppRanges == NULL) {
|
||||
vError("vgId:%d, unexpected subfield type in snapshot param. subtyp:%d", TD_VID(pVnode), subField->typ);
|
||||
goto _out;
|
||||
}
|
||||
if (vnodeExtractSnapInfoDiff(buf, bufLen, ppRanges) < 0) {
|
||||
vError("vgId:%d, failed to get range diff since %s", TD_VID(pVnode), terrstr());
|
||||
goto _out;
|
||||
}
|
||||
} break;
|
||||
case SNAP_DATA_RAW: {
|
||||
if (tDeserializeTsdbRepOpts(buf, bufLen, &tsdbOpts) < 0) {
|
||||
vError("vgId:%d, failed to deserialize tsdb rep opts since %s", TD_VID(pVnode), terrstr());
|
||||
goto _out;
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
vError("vgId:%d, unexpected subfield type of snap info. typ:%d", TD_VID(pVnode), subField->typ);
|
||||
goto _out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// toggle snap replication mode
|
||||
vInfo("vgId:%d, vnode snap reader supported tsdb rep of format:%d", TD_VID(pVnode), tsdbOpts.format);
|
||||
if (pReader->sver == 0 && tsdbOpts.format == TSDB_SNAP_REP_FMT_RAW) {
|
||||
pReader->tsdbDone = true;
|
||||
} else {
|
||||
pReader->tsdbRAWDone = true;
|
||||
}
|
||||
|
||||
ASSERT(pReader->tsdbDone != pReader->tsdbRAWDone);
|
||||
vInfo("vgId:%d, vnode snap writer enabled replication mode: %s", TD_VID(pVnode),
|
||||
(pReader->tsdbDone ? "raw" : "normal"));
|
||||
}
|
||||
code = 0;
|
||||
_out:
|
||||
return code;
|
||||
|
@ -135,7 +168,7 @@ int32_t vnodeSnapReaderOpen(SVnode *pVnode, SSnapshotParam *pParam, SVSnapReader
|
|||
pReader->ever = ever;
|
||||
|
||||
// snapshot info
|
||||
if (vnodeSnapReaderDoSnapInfo(pReader, pParam) < 0) {
|
||||
if (vnodeSnapReaderDealWithSnapInfo(pReader, pParam) < 0) {
|
||||
goto _err;
|
||||
}
|
||||
|
||||
|
@ -152,9 +185,9 @@ _err:
|
|||
static void vnodeSnapReaderDestroyTsdbRanges(SVSnapReader *pReader) {
|
||||
int32_t tsdbTyps[TSDB_RETENTION_MAX] = {SNAP_DATA_TSDB, SNAP_DATA_RSMA1, SNAP_DATA_RSMA2};
|
||||
for (int32_t j = 0; j < TSDB_RETENTION_MAX; ++j) {
|
||||
TSnapRangeArray **ppRanges = vnodeSnapReaderGetTsdbRanges(pReader, tsdbTyps[j]);
|
||||
TFileSetRangeArray **ppRanges = vnodeSnapReaderGetTsdbRanges(pReader, tsdbTyps[j]);
|
||||
if (ppRanges == NULL) continue;
|
||||
tsdbSnapRangeArrayDestroy(ppRanges);
|
||||
tsdbTFileSetRangeArrayDestroy(ppRanges);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -170,6 +203,10 @@ void vnodeSnapReaderClose(SVSnapReader *pReader) {
|
|||
tsdbSnapReaderClose(&pReader->pTsdbReader);
|
||||
}
|
||||
|
||||
if (pReader->pTsdbRAWReader) {
|
||||
tsdbSnapRAWReaderClose(&pReader->pTsdbRAWReader);
|
||||
}
|
||||
|
||||
if (pReader->pMetaReader) {
|
||||
metaSnapReaderClose(&pReader->pMetaReader);
|
||||
}
|
||||
|
@ -285,6 +322,28 @@ int32_t vnodeSnapRead(SVSnapReader *pReader, uint8_t **ppData, uint32_t *nData)
|
|||
}
|
||||
}
|
||||
|
||||
if (!pReader->tsdbRAWDone) {
|
||||
// open if not
|
||||
if (pReader->pTsdbRAWReader == NULL) {
|
||||
ASSERT(pReader->sver == 0);
|
||||
code = tsdbSnapRAWReaderOpen(pReader->pVnode->pTsdb, pReader->ever, SNAP_DATA_RAW, &pReader->pTsdbRAWReader);
|
||||
if (code) goto _err;
|
||||
}
|
||||
|
||||
code = tsdbSnapRAWRead(pReader->pTsdbRAWReader, ppData);
|
||||
if (code) {
|
||||
goto _err;
|
||||
} else {
|
||||
if (*ppData) {
|
||||
goto _exit;
|
||||
} else {
|
||||
pReader->tsdbRAWDone = 1;
|
||||
code = tsdbSnapRAWReaderClose(&pReader->pTsdbRAWReader);
|
||||
if (code) goto _err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TQ ================
|
||||
vInfo("vgId:%d tq transform start", vgId);
|
||||
if (!pReader->tqHandleDone) {
|
||||
|
@ -455,8 +514,10 @@ struct SVSnapWriter {
|
|||
// meta
|
||||
SMetaSnapWriter *pMetaSnapWriter;
|
||||
// tsdb
|
||||
TSnapRangeArray *pRanges;
|
||||
TFileSetRangeArray *pRanges;
|
||||
STsdbSnapWriter *pTsdbSnapWriter;
|
||||
// tsdb raw
|
||||
STsdbSnapRAWWriter *pTsdbSnapRAWWriter;
|
||||
// tq
|
||||
STqSnapWriter *pTqSnapWriter;
|
||||
STqOffsetWriter *pTqOffsetWriter;
|
||||
|
@ -465,11 +526,11 @@ struct SVSnapWriter {
|
|||
SStreamTaskWriter *pStreamTaskWriter;
|
||||
SStreamStateWriter *pStreamStateWriter;
|
||||
// rsma
|
||||
TSnapRangeArray *pRsmaRanges[TSDB_RETENTION_L2];
|
||||
TFileSetRangeArray *pRsmaRanges[TSDB_RETENTION_L2];
|
||||
SRSmaSnapWriter *pRsmaSnapWriter;
|
||||
};
|
||||
|
||||
TSnapRangeArray **vnodeSnapWriterGetTsdbRanges(SVSnapWriter *pWriter, int32_t tsdbTyp) {
|
||||
TFileSetRangeArray **vnodeSnapWriterGetTsdbRanges(SVSnapWriter *pWriter, int32_t tsdbTyp) {
|
||||
ASSERTS(sizeof(pWriter->pRsmaRanges) / sizeof(pWriter->pRsmaRanges[0]) == 2, "Unexpected array size");
|
||||
switch (tsdbTyp) {
|
||||
case SNAP_DATA_TSDB:
|
||||
|
@ -483,7 +544,7 @@ TSnapRangeArray **vnodeSnapWriterGetTsdbRanges(SVSnapWriter *pWriter, int32_t ts
|
|||
}
|
||||
}
|
||||
|
||||
static int32_t vnodeSnapWriterDoSnapInfo(SVSnapWriter *pWriter, SSnapshotParam *pParam) {
|
||||
static int32_t vnodeSnapWriterDealWithSnapInfo(SVSnapWriter *pWriter, SSnapshotParam *pParam) {
|
||||
SVnode *pVnode = pWriter->pVnode;
|
||||
int32_t code = -1;
|
||||
|
||||
|
@ -494,7 +555,8 @@ static int32_t vnodeSnapWriterDoSnapInfo(SVSnapWriter *pWriter, SSnapshotParam *
|
|||
goto _out;
|
||||
}
|
||||
|
||||
TSnapRangeArray **ppRanges = NULL;
|
||||
STsdbRepOpts tsdbOpts = {0};
|
||||
TFileSetRangeArray **ppRanges = NULL;
|
||||
int32_t offset = 0;
|
||||
|
||||
while (offset + sizeof(SSyncTLV) < datHead->len) {
|
||||
|
@ -502,16 +564,34 @@ static int32_t vnodeSnapWriterDoSnapInfo(SVSnapWriter *pWriter, SSnapshotParam *
|
|||
offset += sizeof(SSyncTLV) + subField->len;
|
||||
void *buf = subField->val;
|
||||
int32_t bufLen = subField->len;
|
||||
ppRanges = vnodeSnapWriterGetTsdbRanges(pWriter, subField->typ);
|
||||
if (ppRanges == NULL) {
|
||||
vError("vgId:%d, unexpected subfield type in data of snapshot param. subtyp:%d", TD_VID(pVnode), subField->typ);
|
||||
goto _out;
|
||||
}
|
||||
if (vnodeExtractSnapInfoDiff(buf, bufLen, ppRanges) < 0) {
|
||||
vError("vgId:%d, failed to get range diff since %s", TD_VID(pVnode), terrstr());
|
||||
goto _out;
|
||||
|
||||
switch (subField->typ) {
|
||||
case SNAP_DATA_TSDB:
|
||||
case SNAP_DATA_RSMA1:
|
||||
case SNAP_DATA_RSMA2: {
|
||||
ppRanges = vnodeSnapWriterGetTsdbRanges(pWriter, subField->typ);
|
||||
if (ppRanges == NULL) {
|
||||
vError("vgId:%d, unexpected subfield type in snapshot param. subtyp:%d", TD_VID(pVnode), subField->typ);
|
||||
goto _out;
|
||||
}
|
||||
if (vnodeExtractSnapInfoDiff(buf, bufLen, ppRanges) < 0) {
|
||||
vError("vgId:%d, failed to get range diff since %s", TD_VID(pVnode), terrstr());
|
||||
goto _out;
|
||||
}
|
||||
} break;
|
||||
case SNAP_DATA_RAW: {
|
||||
if (tDeserializeTsdbRepOpts(buf, bufLen, &tsdbOpts) < 0) {
|
||||
vError("vgId:%d, failed to deserialize tsdb rep opts since %s", TD_VID(pVnode), terrstr());
|
||||
goto _out;
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
vError("vgId:%d, unexpected subfield type of snap info. typ:%d", TD_VID(pVnode), subField->typ);
|
||||
goto _out;
|
||||
}
|
||||
}
|
||||
|
||||
vInfo("vgId:%d, vnode snap writer supported tsdb rep of format:%d", TD_VID(pVnode), tsdbOpts.format);
|
||||
}
|
||||
|
||||
code = 0;
|
||||
|
@ -558,7 +638,7 @@ int32_t vnodeSnapWriterOpen(SVnode *pVnode, SSnapshotParam *pParam, SVSnapWriter
|
|||
pWriter->commitID = ++pVnode->state.commitID;
|
||||
|
||||
// snapshot info
|
||||
if (vnodeSnapWriterDoSnapInfo(pWriter, pParam) < 0) {
|
||||
if (vnodeSnapWriterDealWithSnapInfo(pWriter, pParam) < 0) {
|
||||
goto _err;
|
||||
}
|
||||
|
||||
|
@ -576,9 +656,9 @@ _err:
|
|||
static void vnodeSnapWriterDestroyTsdbRanges(SVSnapWriter *pWriter) {
|
||||
int32_t tsdbTyps[TSDB_RETENTION_MAX] = {SNAP_DATA_TSDB, SNAP_DATA_RSMA1, SNAP_DATA_RSMA2};
|
||||
for (int32_t j = 0; j < TSDB_RETENTION_MAX; ++j) {
|
||||
TSnapRangeArray **ppRanges = vnodeSnapWriterGetTsdbRanges(pWriter, tsdbTyps[j]);
|
||||
TFileSetRangeArray **ppRanges = vnodeSnapWriterGetTsdbRanges(pWriter, tsdbTyps[j]);
|
||||
if (ppRanges == NULL) continue;
|
||||
tsdbSnapRangeArrayDestroy(ppRanges);
|
||||
tsdbTFileSetRangeArrayDestroy(ppRanges);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -593,6 +673,10 @@ int32_t vnodeSnapWriterClose(SVSnapWriter *pWriter, int8_t rollback, SSnapshot *
|
|||
tsdbSnapWriterPrepareClose(pWriter->pTsdbSnapWriter);
|
||||
}
|
||||
|
||||
if (pWriter->pTsdbSnapRAWWriter) {
|
||||
tsdbSnapRAWWriterPrepareClose(pWriter->pTsdbSnapRAWWriter);
|
||||
}
|
||||
|
||||
if (pWriter->pRsmaSnapWriter) {
|
||||
rsmaSnapWriterPrepareClose(pWriter->pRsmaSnapWriter);
|
||||
}
|
||||
|
@ -629,6 +713,11 @@ int32_t vnodeSnapWriterClose(SVSnapWriter *pWriter, int8_t rollback, SSnapshot *
|
|||
if (code) goto _exit;
|
||||
}
|
||||
|
||||
if (pWriter->pTsdbSnapRAWWriter) {
|
||||
code = tsdbSnapRAWWriterClose(&pWriter->pTsdbSnapRAWWriter, rollback);
|
||||
if (code) goto _exit;
|
||||
}
|
||||
|
||||
if (pWriter->pTqSnapWriter) {
|
||||
code = tqSnapWriterClose(&pWriter->pTqSnapWriter, rollback);
|
||||
if (code) goto _exit;
|
||||
|
@ -752,6 +841,17 @@ int32_t vnodeSnapWrite(SVSnapWriter *pWriter, uint8_t *pData, uint32_t nData) {
|
|||
code = tsdbSnapWrite(pWriter->pTsdbSnapWriter, pHdr);
|
||||
if (code) goto _err;
|
||||
} break;
|
||||
case SNAP_DATA_RAW: {
|
||||
// tsdb
|
||||
if (pWriter->pTsdbSnapRAWWriter == NULL) {
|
||||
ASSERT(pWriter->sver == 0);
|
||||
code = tsdbSnapRAWWriterOpen(pVnode->pTsdb, pWriter->ever, &pWriter->pTsdbSnapRAWWriter);
|
||||
if (code) goto _err;
|
||||
}
|
||||
|
||||
code = tsdbSnapRAWWrite(pWriter->pTsdbSnapRAWWriter, pHdr);
|
||||
if (code) goto _err;
|
||||
} break;
|
||||
case SNAP_DATA_TQ_HANDLE: {
|
||||
// tq handle
|
||||
if (pWriter->pTqSnapWriter == NULL) {
|
||||
|
|
|
@ -804,7 +804,7 @@ int32_t vnodeGetSnapshot(SVnode *pVnode, SSnapshot *pSnap) {
|
|||
}
|
||||
|
||||
if (pSnap->type == TDMT_SYNC_PREP_SNAPSHOT || pSnap->type == TDMT_SYNC_PREP_SNAPSHOT_REPLY) {
|
||||
code = tsdbSnapGetDetails(pVnode, pSnap);
|
||||
code = tsdbSnapPrepDescription(pVnode, pSnap);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
|
|
@ -270,6 +270,7 @@ typedef struct STableScanInfo {
|
|||
bool hasGroupByTag;
|
||||
bool countOnly;
|
||||
// TsdReader readerAPI;
|
||||
bool filesetDelimited;
|
||||
} STableScanInfo;
|
||||
|
||||
typedef struct STableMergeScanInfo {
|
||||
|
@ -297,6 +298,9 @@ typedef struct STableMergeScanInfo {
|
|||
SHashObj* mSkipTables;
|
||||
int64_t mergeLimit;
|
||||
SSortExecInfo sortExecInfo;
|
||||
bool bNewFileset;
|
||||
bool bOnlyRetrieveBlock;
|
||||
bool filesetDelimited;
|
||||
} STableMergeScanInfo;
|
||||
|
||||
typedef struct STagScanFilterContext {
|
||||
|
@ -632,6 +636,7 @@ typedef struct SStreamEventAggOperatorInfo {
|
|||
bool isHistoryOp;
|
||||
SArray* historyWins;
|
||||
bool reCkBlock;
|
||||
bool recvGetAll;
|
||||
SSDataBlock* pCheckpointRes;
|
||||
SFilterInfo* pStartCondInfo;
|
||||
SFilterInfo* pEndCondInfo;
|
||||
|
@ -833,6 +838,8 @@ void compactTimeWindow(SExprSupp* pSup, SStreamAggSupporter* pAggSup, STimeW
|
|||
int32_t releaseOutputBuf(void* pState, SRowBuffPos* pPos, SStateStore* pAPI);
|
||||
void resetWinRange(STimeWindow* winRange);
|
||||
bool checkExpiredData(SStateStore* pAPI, SUpdateInfo* pUpdateInfo, STimeWindowAggSupp* pTwSup, uint64_t tableId, TSKEY ts);
|
||||
int64_t getDeleteMark(SWindowPhysiNode* pWinPhyNode, int64_t interval);
|
||||
void resetUnCloseSessionWinInfo(SSHashObj* winMap);
|
||||
|
||||
int32_t encodeSSessionKey(void** buf, SSessionKey* key);
|
||||
void* decodeSSessionKey(void* buf, SSessionKey* key);
|
||||
|
|
|
@ -1734,6 +1734,11 @@ int32_t initQueryTableDataCond(SQueryTableDataCond* pCond, const STableScanPhysi
|
|||
pCond->endVersion = -1;
|
||||
pCond->skipRollup = readHandle->skipRollup;
|
||||
|
||||
// allowed read stt file optimization mode
|
||||
pCond->notLoadData = (pTableScanNode->dataRequired == FUNC_DATA_REQUIRED_NOT_LOAD) &&
|
||||
(pTableScanNode->scan.node.pConditions == NULL) &&
|
||||
(pTableScanNode->interval == 0);
|
||||
|
||||
int32_t j = 0;
|
||||
for (int32_t i = 0; i < pCond->numOfCols; ++i) {
|
||||
STargetNode* pNode = (STargetNode*)nodesListGetNode(pTableScanNode->scan.pScanCols, i);
|
||||
|
|
|
@ -1232,7 +1232,7 @@ int32_t qStreamPrepareScan(qTaskInfo_t tinfo, STqOffsetVal* pOffset, int8_t subT
|
|||
if (pScanBaseInfo->dataReader == NULL) {
|
||||
int32_t code = pTaskInfo->storageAPI.tsdReader.tsdReaderOpen(
|
||||
pScanBaseInfo->readHandle.vnode, &pScanBaseInfo->cond, &keyInfo, 1, pScanInfo->pResBlock,
|
||||
(void**)&pScanBaseInfo->dataReader, id, false, NULL);
|
||||
(void**)&pScanBaseInfo->dataReader, id, NULL);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
qError("prepare read tsdb snapshot failed, uid:%" PRId64 ", code:%s %s", pOffset->uid, tstrerror(code), id);
|
||||
terrno = code;
|
||||
|
@ -1291,7 +1291,7 @@ int32_t qStreamPrepareScan(qTaskInfo_t tinfo, STqOffsetVal* pOffset, int8_t subT
|
|||
int32_t size = tableListGetSize(pTableListInfo);
|
||||
|
||||
pTaskInfo->storageAPI.tsdReader.tsdReaderOpen(pInfo->vnode, &pTaskInfo->streamInfo.tableCond, pList, size, NULL,
|
||||
(void**)&pInfo->dataReader, NULL, false, NULL);
|
||||
(void**)&pInfo->dataReader, NULL, NULL);
|
||||
|
||||
cleanupQueryTableDataCond(&pTaskInfo->streamInfo.tableCond);
|
||||
strcpy(pTaskInfo->streamInfo.tbName, mtInfo.tbName);
|
||||
|
|
|
@ -889,11 +889,13 @@ static SSDataBlock* groupSeqTableScan(SOperatorInfo* pOperator) {
|
|||
ASSERT(pInfo->base.dataReader == NULL);
|
||||
|
||||
int32_t code = pAPI->tsdReader.tsdReaderOpen(pInfo->base.readHandle.vnode, &pInfo->base.cond, pList, num, pInfo->pResBlock,
|
||||
(void**)&pInfo->base.dataReader, GET_TASKID(pTaskInfo), pInfo->countOnly, &pInfo->pIgnoreTables);
|
||||
(void**)&pInfo->base.dataReader, GET_TASKID(pTaskInfo), &pInfo->pIgnoreTables);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
T_LONG_JMP(pTaskInfo->env, code);
|
||||
}
|
||||
|
||||
if (pInfo->filesetDelimited) {
|
||||
pAPI->tsdReader.tsdSetFilesetDelimited(pInfo->base.dataReader);
|
||||
}
|
||||
if (pInfo->pResBlock->info.capacity > pOperator->resultInfo.capacity) {
|
||||
pOperator->resultInfo.capacity = pInfo->pResBlock->info.capacity;
|
||||
}
|
||||
|
@ -1059,7 +1061,6 @@ SOperatorInfo* createTableScanOperatorInfo(STableScanPhysiNode* pTableScanNode,
|
|||
pInfo->base.readerAPI = pTaskInfo->storageAPI.tsdReader;
|
||||
initResultSizeInfo(&pOperator->resultInfo, 4096);
|
||||
pInfo->pResBlock = createDataBlockFromDescNode(pDescNode);
|
||||
// blockDataEnsureCapacity(pInfo->pResBlock, pOperator->resultInfo.capacity);
|
||||
|
||||
code = filterInitFromNode((SNode*)pTableScanNode->scan.node.pConditions, &pOperator->exprSupp.pFilterInfo, 0);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
|
@ -1085,6 +1086,8 @@ SOperatorInfo* createTableScanOperatorInfo(STableScanPhysiNode* pTableScanNode,
|
|||
pInfo->countOnly = true;
|
||||
}
|
||||
|
||||
pInfo->filesetDelimited = pTableScanNode->filesetDelimited;
|
||||
|
||||
taosLRUCacheSetStrictCapacity(pInfo->base.metaCache.pTableMetaEntryCache, false);
|
||||
pOperator->fpSet = createOperatorFpSet(optrDummyOpenFn, doTableScan, NULL, destroyTableScanOperatorInfo,
|
||||
optrDefaultBufFn, getTableScannerExecInfo, optrDefaultGetNextExtFn, NULL);
|
||||
|
@ -1179,7 +1182,7 @@ static SSDataBlock* readPreVersionData(SOperatorInfo* pTableScanOp, uint64_t tbU
|
|||
SSDataBlock* pBlock = pTableScanInfo->pResBlock;
|
||||
STsdbReader* pReader = NULL;
|
||||
int32_t code = pAPI->tsdReader.tsdReaderOpen(pTableScanInfo->base.readHandle.vnode, &cond, &tblInfo, 1, pBlock,
|
||||
(void**)&pReader, GET_TASKID(pTaskInfo), false, NULL);
|
||||
(void**)&pReader, GET_TASKID(pTaskInfo), NULL);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
terrno = code;
|
||||
T_LONG_JMP(pTaskInfo->env, code);
|
||||
|
@ -3223,6 +3226,7 @@ static int32_t tableMergeScanDoSkipTable(STableMergeScanInfo* pInfo, SSDataBlock
|
|||
tSimpleHashPut(pInfo->mTableNumRows, &pBlock->info.id.uid, sizeof(pBlock->info.id.uid), &nRows, sizeof(nRows));
|
||||
} else {
|
||||
*(int64_t*)pNum = *(int64_t*)pNum + pBlock->info.rows;
|
||||
nRows = *(int64_t*)pNum;
|
||||
}
|
||||
|
||||
if (nRows >= pInfo->mergeLimit) {
|
||||
|
@ -3251,23 +3255,28 @@ static SSDataBlock* getBlockForTableMergeScan(void* param) {
|
|||
|
||||
STsdbReader* reader = pInfo->base.dataReader;
|
||||
while (true) {
|
||||
code = pAPI->tsdReader.tsdNextDataBlock(reader, &hasNext);
|
||||
if (code != 0) {
|
||||
pAPI->tsdReader.tsdReaderReleaseDataBlock(reader);
|
||||
qError("table merge scan fetch next data block error code: %d, %s", code, GET_TASKID(pTaskInfo));
|
||||
T_LONG_JMP(pTaskInfo->env, code);
|
||||
}
|
||||
if (!pInfo->bOnlyRetrieveBlock) {
|
||||
code = pAPI->tsdReader.tsdNextDataBlock(reader, &hasNext);
|
||||
if (code != 0) {
|
||||
pAPI->tsdReader.tsdReaderReleaseDataBlock(reader);
|
||||
qError("table merge scan fetch next data block error code: %d, %s", code, GET_TASKID(pTaskInfo));
|
||||
T_LONG_JMP(pTaskInfo->env, code);
|
||||
}
|
||||
|
||||
if (!hasNext) {
|
||||
break;
|
||||
}
|
||||
if (!hasNext || isTaskKilled(pTaskInfo)) {
|
||||
pInfo->bNewFileset = false;
|
||||
if (isTaskKilled(pTaskInfo)) {
|
||||
qInfo("table merge scan fetch next data block found task killed. %s", GET_TASKID(pTaskInfo));
|
||||
pAPI->tsdReader.tsdReaderReleaseDataBlock(reader);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (isTaskKilled(pTaskInfo)) {
|
||||
qInfo("table merge scan fetch next data block found task killed. %s", GET_TASKID(pTaskInfo));
|
||||
pAPI->tsdReader.tsdReaderReleaseDataBlock(reader);
|
||||
break;
|
||||
if (pInfo->bNewFileset) {
|
||||
pInfo->bOnlyRetrieveBlock = true;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// process this data block based on the probabilities
|
||||
bool processThisBlock = processBlockWithProbability(&pInfo->sample);
|
||||
if (!processThisBlock) {
|
||||
|
@ -3276,7 +3285,9 @@ static SSDataBlock* getBlockForTableMergeScan(void* param) {
|
|||
|
||||
uint32_t status = 0;
|
||||
code = loadDataBlock(pOperator, &pInfo->base, pBlock, &status);
|
||||
// code = loadDataBlockFromOneTable(pOperator, pTableScanInfo, pBlock, &status);
|
||||
if (pInfo->bOnlyRetrieveBlock) {
|
||||
pInfo->bOnlyRetrieveBlock = false;
|
||||
}
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
qInfo("table merge scan load datablock code %d, %s", code, GET_TASKID(pTaskInfo));
|
||||
T_LONG_JMP(pTaskInfo->env, code);
|
||||
|
@ -3335,6 +3346,60 @@ int32_t dumpQueryTableCond(const SQueryTableDataCond* src, SQueryTableDataCond*
|
|||
return 0;
|
||||
}
|
||||
|
||||
void tableMergeScanTsdbNotifyCb(ETsdReaderNotifyType type, STsdReaderNotifyInfo* info, void* param) {
|
||||
STableMergeScanInfo* pTmsInfo = param;
|
||||
pTmsInfo->bNewFileset = true;
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t startDurationForGroupTableMergeScan(SOperatorInfo* pOperator) {
|
||||
STableMergeScanInfo* pInfo = pOperator->info;
|
||||
SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
int32_t numOfTable = pInfo->tableEndIndex - pInfo->tableStartIndex + 1;
|
||||
|
||||
pInfo->bNewFileset = false;
|
||||
|
||||
pInfo->sortBufSize = 2048 * pInfo->bufPageSize;
|
||||
int32_t numOfBufPage = pInfo->sortBufSize / pInfo->bufPageSize;
|
||||
pInfo->pSortHandle = tsortCreateSortHandle(pInfo->pSortInfo, SORT_BLOCK_TS_MERGE, pInfo->bufPageSize, numOfBufPage,
|
||||
pInfo->pSortInputBlock, pTaskInfo->id.str, 0, 0, 0);
|
||||
|
||||
tsortSetMergeLimit(pInfo->pSortHandle, pInfo->mergeLimit);
|
||||
tsortSetAbortCheckFn(pInfo->pSortHandle, isTaskKilled, pOperator->pTaskInfo);
|
||||
|
||||
tsortSetFetchRawDataFp(pInfo->pSortHandle, getBlockForTableMergeScan, NULL, NULL);
|
||||
|
||||
STableMergeScanSortSourceParam *param = taosMemoryCalloc(1, sizeof(STableMergeScanSortSourceParam));
|
||||
param->pOperator = pOperator;
|
||||
|
||||
SSortSource* ps = taosMemoryCalloc(1, sizeof(SSortSource));
|
||||
ps->param = param;
|
||||
ps->onlyRef = false;
|
||||
tsortAddSource(pInfo->pSortHandle, ps);
|
||||
|
||||
if (numOfTable == 1) {
|
||||
tsortSetSingleTableMerge(pInfo->pSortHandle);
|
||||
} else {
|
||||
code = tsortOpen(pInfo->pSortHandle);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
void stopDurationForGroupTableMergeScan(SOperatorInfo* pOperator) {
|
||||
STableMergeScanInfo* pInfo = pOperator->info;
|
||||
|
||||
SSortExecInfo sortExecInfo = tsortGetSortExecInfo(pInfo->pSortHandle);
|
||||
pInfo->sortExecInfo.sortMethod = sortExecInfo.sortMethod;
|
||||
pInfo->sortExecInfo.sortBuffer = sortExecInfo.sortBuffer;
|
||||
pInfo->sortExecInfo.loops += sortExecInfo.loops;
|
||||
pInfo->sortExecInfo.readBytes += sortExecInfo.readBytes;
|
||||
pInfo->sortExecInfo.writeBytes += sortExecInfo.writeBytes;
|
||||
|
||||
tsortDestroySortHandle(pInfo->pSortHandle);
|
||||
pInfo->pSortHandle = NULL;
|
||||
}
|
||||
|
||||
int32_t startGroupTableMergeScan(SOperatorInfo* pOperator) {
|
||||
STableMergeScanInfo* pInfo = pOperator->info;
|
||||
SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
|
||||
|
@ -3358,43 +3423,16 @@ int32_t startGroupTableMergeScan(SOperatorInfo* pOperator) {
|
|||
|
||||
tSimpleHashClear(pInfo->mTableNumRows);
|
||||
|
||||
size_t szRow = blockDataGetRowSize(pInfo->pResBlock);
|
||||
// if (pInfo->mergeLimit != -1) {
|
||||
// pInfo->pSortHandle = tsortCreateSortHandle(pInfo->pSortInfo, SORT_SINGLESOURCE_SORT, -1, -1,
|
||||
// NULL, pTaskInfo->id.str, pInfo->mergeLimit, szRow+8, tsPQSortMemThreshold * 1024* 1024);
|
||||
// } else
|
||||
{
|
||||
pInfo->sortBufSize = 2048 * pInfo->bufPageSize;
|
||||
int32_t numOfBufPage = pInfo->sortBufSize / pInfo->bufPageSize;
|
||||
pInfo->pSortHandle = tsortCreateSortHandle(pInfo->pSortInfo, SORT_BLOCK_TS_MERGE, pInfo->bufPageSize, numOfBufPage,
|
||||
pInfo->pSortInputBlock, pTaskInfo->id.str, 0, 0, 0);
|
||||
|
||||
tsortSetMergeLimit(pInfo->pSortHandle, pInfo->mergeLimit);
|
||||
tsortSetAbortCheckFn(pInfo->pSortHandle, isTaskKilled, pOperator->pTaskInfo);
|
||||
}
|
||||
|
||||
tsortSetFetchRawDataFp(pInfo->pSortHandle, getBlockForTableMergeScan, NULL, NULL);
|
||||
|
||||
// one table has one data block
|
||||
int32_t numOfTable = tableEndIdx - tableStartIdx + 1;
|
||||
|
||||
STableMergeScanSortSourceParam *param = taosMemoryCalloc(1, sizeof(STableMergeScanSortSourceParam));
|
||||
param->pOperator = pOperator;
|
||||
STableKeyInfo* startKeyInfo = tableListGetInfo(pInfo->base.pTableListInfo, tableStartIdx);
|
||||
pAPI->tsdReader.tsdReaderOpen(pHandle->vnode, &pInfo->base.cond, startKeyInfo, numOfTable, pInfo->pReaderBlock,
|
||||
(void**)&pInfo->base.dataReader, GET_TASKID(pTaskInfo), false, &pInfo->mSkipTables);
|
||||
|
||||
SSortSource* ps = taosMemoryCalloc(1, sizeof(SSortSource));
|
||||
ps->param = param;
|
||||
ps->onlyRef = false;
|
||||
tsortAddSource(pInfo->pSortHandle, ps);
|
||||
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
if (numOfTable == 1) {
|
||||
tsortSetSingleTableMerge(pInfo->pSortHandle);
|
||||
} else {
|
||||
code = tsortOpen(pInfo->pSortHandle);
|
||||
(void**)&pInfo->base.dataReader, GET_TASKID(pTaskInfo), &pInfo->mSkipTables);
|
||||
if (pInfo->filesetDelimited) {
|
||||
pAPI->tsdReader.tsdSetFilesetDelimited(pInfo->base.dataReader);
|
||||
}
|
||||
pAPI->tsdReader.tsdSetSetNotifyCb(pInfo->base.dataReader, tableMergeScanTsdbNotifyCb, pInfo);
|
||||
|
||||
int32_t code = startDurationForGroupTableMergeScan(pOperator);
|
||||
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
T_LONG_JMP(pTaskInfo->env, terrno);
|
||||
|
@ -3408,21 +3446,13 @@ int32_t stopGroupTableMergeScan(SOperatorInfo* pOperator) {
|
|||
SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
|
||||
SStorageAPI* pAPI = &pTaskInfo->storageAPI;
|
||||
|
||||
SSortExecInfo sortExecInfo = tsortGetSortExecInfo(pInfo->pSortHandle);
|
||||
pInfo->sortExecInfo.sortMethod = sortExecInfo.sortMethod;
|
||||
pInfo->sortExecInfo.sortBuffer = sortExecInfo.sortBuffer;
|
||||
pInfo->sortExecInfo.loops += sortExecInfo.loops;
|
||||
pInfo->sortExecInfo.readBytes += sortExecInfo.readBytes;
|
||||
pInfo->sortExecInfo.writeBytes += sortExecInfo.writeBytes;
|
||||
stopDurationForGroupTableMergeScan(pOperator);
|
||||
|
||||
if (pInfo->base.dataReader != NULL) {
|
||||
pAPI->tsdReader.tsdReaderClose(pInfo->base.dataReader);
|
||||
pInfo->base.dataReader = NULL;
|
||||
}
|
||||
|
||||
tsortDestroySortHandle(pInfo->pSortHandle);
|
||||
pInfo->pSortHandle = NULL;
|
||||
|
||||
resetLimitInfoForNextGroup(&pInfo->limitInfo);
|
||||
taosHashCleanup(pInfo->mSkipTables);
|
||||
pInfo->mSkipTables = NULL;
|
||||
|
@ -3505,17 +3535,22 @@ SSDataBlock* doTableMergeScan(SOperatorInfo* pOperator) {
|
|||
pOperator->resultInfo.totalRows += pBlock->info.rows;
|
||||
return pBlock;
|
||||
} else {
|
||||
// Data of this group are all dumped, let's try the next group
|
||||
stopGroupTableMergeScan(pOperator);
|
||||
if (pInfo->tableEndIndex >= tableListSize - 1) {
|
||||
setOperatorCompleted(pOperator);
|
||||
break;
|
||||
}
|
||||
if (pInfo->bNewFileset) {
|
||||
stopDurationForGroupTableMergeScan(pOperator);
|
||||
startDurationForGroupTableMergeScan(pOperator);
|
||||
} else {
|
||||
// Data of this group are all dumped, let's try the next group
|
||||
stopGroupTableMergeScan(pOperator);
|
||||
if (pInfo->tableEndIndex >= tableListSize - 1) {
|
||||
setOperatorCompleted(pOperator);
|
||||
break;
|
||||
}
|
||||
|
||||
pInfo->tableStartIndex = pInfo->tableEndIndex + 1;
|
||||
pInfo->groupId = tableListGetInfo(pInfo->base.pTableListInfo, pInfo->tableStartIndex)->groupId;
|
||||
startGroupTableMergeScan(pOperator);
|
||||
resetLimitInfoForNextGroup(&pInfo->limitInfo);
|
||||
pInfo->tableStartIndex = pInfo->tableEndIndex + 1;
|
||||
pInfo->groupId = tableListGetInfo(pInfo->base.pTableListInfo, pInfo->tableStartIndex)->groupId;
|
||||
startGroupTableMergeScan(pOperator);
|
||||
resetLimitInfoForNextGroup(&pInfo->limitInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3641,6 +3676,7 @@ SOperatorInfo* createTableMergeScanOperatorInfo(STableScanPhysiNode* pTableScanN
|
|||
uint32_t nCols = taosArrayGetSize(pInfo->pResBlock->pDataBlock);
|
||||
pInfo->bufPageSize = getProperSortPageSize(rowSize, nCols);
|
||||
|
||||
pInfo->filesetDelimited = pTableScanNode->filesetDelimited;
|
||||
setOperatorInfo(pOperator, "TableMergeScanOperator", QUERY_NODE_PHYSICAL_PLAN_TABLE_MERGE_SCAN, false, OP_NOT_OPENED,
|
||||
pInfo, pTaskInfo);
|
||||
pOperator->exprSupp.numOfExprs = numOfCols;
|
||||
|
|
|
@ -195,6 +195,10 @@ int32_t updateEventWindowInfo(SStreamAggSupporter* pAggSup, SEventWindowInfo* pW
|
|||
pWinInfo->pWinFlag->endFlag = ends[i];
|
||||
} else if (pWin->ekey == pTsData[i]) {
|
||||
pWinInfo->pWinFlag->endFlag |= ends[i];
|
||||
} else {
|
||||
*pRebuild = true;
|
||||
pWinInfo->pWinFlag->endFlag |= ends[i];
|
||||
return i + 1 - start;
|
||||
}
|
||||
|
||||
memcpy(pWinInfo->winInfo.pStatePos->pKey, &pWinInfo->winInfo.sessionWin, sizeof(SSessionKey));
|
||||
|
@ -319,6 +323,9 @@ static void doStreamEventAggImpl(SOperatorInfo* pOperator, SSDataBlock* pSDataBl
|
|||
tSimpleHashRemove(pSeUpdated, &curWin.winInfo.sessionWin, sizeof(SSessionKey));
|
||||
doDeleteEventWindow(pAggSup, pSeUpdated, &curWin.winInfo.sessionWin);
|
||||
releaseOutputBuf(pAggSup->pState, curWin.winInfo.pStatePos, &pAPI->stateStore);
|
||||
SSessionKey tmpSeInfo = {0};
|
||||
getSessionHashKey(&curWin.winInfo.sessionWin, &tmpSeInfo);
|
||||
tSimpleHashPut(pStDeleted, &tmpSeInfo, sizeof(SSessionKey), NULL, 0);
|
||||
continue;
|
||||
}
|
||||
code = doOneWindowAggImpl(&pInfo->twAggSup.timeWindowData, &curWin.winInfo, &pResult, i, winRows, rows, numOfOutput,
|
||||
|
@ -479,6 +486,11 @@ static SSDataBlock* doStreamEventAgg(SOperatorInfo* pOperator) {
|
|||
return pInfo->pCheckpointRes;
|
||||
}
|
||||
|
||||
if (pInfo->recvGetAll) {
|
||||
pInfo->recvGetAll = false;
|
||||
resetUnCloseSessionWinInfo(pInfo->streamAggSup.pResultRows);
|
||||
}
|
||||
|
||||
setOperatorCompleted(pOperator);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -503,6 +515,7 @@ static SSDataBlock* doStreamEventAgg(SOperatorInfo* pOperator) {
|
|||
deleteSessionWinState(&pInfo->streamAggSup, pBlock, pInfo->pSeUpdated, pInfo->pSeDeleted);
|
||||
continue;
|
||||
} else if (pBlock->info.type == STREAM_GET_ALL) {
|
||||
pInfo->recvGetAll = true;
|
||||
getAllSessionWindow(pInfo->streamAggSup.pResultRows, pInfo->pSeUpdated);
|
||||
continue;
|
||||
} else if (pBlock->info.type == STREAM_CREATE_CHILD_TABLE) {
|
||||
|
@ -665,6 +678,7 @@ SOperatorInfo* createStreamEventAggOperatorInfo(SOperatorInfo* downstream, SPhys
|
|||
.calTrigger = pEventNode->window.triggerType,
|
||||
.maxTs = INT64_MIN,
|
||||
.minTs = INT64_MAX,
|
||||
.deleteMark = getDeleteMark(&pEventNode->window, 0),
|
||||
};
|
||||
|
||||
initExecTimeWindowInfo(&pInfo->twAggSup.timeWindowData, &pTaskInfo->window);
|
||||
|
@ -713,6 +727,7 @@ SOperatorInfo* createStreamEventAggOperatorInfo(SOperatorInfo* downstream, SPhys
|
|||
|
||||
pInfo->pCheckpointRes = createSpecialDataBlock(STREAM_CHECKPOINT);
|
||||
pInfo->reCkBlock = false;
|
||||
pInfo->recvGetAll = false;
|
||||
|
||||
// for stream
|
||||
void* buff = NULL;
|
||||
|
|
|
@ -1345,12 +1345,12 @@ static SSDataBlock* doStreamFinalIntervalAgg(SOperatorInfo* pOperator) {
|
|||
return buildIntervalResult(pOperator);
|
||||
}
|
||||
|
||||
static int64_t getDeleteMark(SIntervalPhysiNode* pIntervalPhyNode) {
|
||||
if (pIntervalPhyNode->window.deleteMark <= 0) {
|
||||
int64_t getDeleteMark(SWindowPhysiNode* pWinPhyNode, int64_t interval) {
|
||||
if (pWinPhyNode->deleteMark <= 0) {
|
||||
return DEAULT_DELETE_MARK;
|
||||
}
|
||||
int64_t deleteMark = TMAX(pIntervalPhyNode->window.deleteMark, pIntervalPhyNode->window.watermark);
|
||||
deleteMark = TMAX(deleteMark, pIntervalPhyNode->interval);
|
||||
int64_t deleteMark = TMAX(pWinPhyNode->deleteMark, pWinPhyNode->watermark);
|
||||
deleteMark = TMAX(deleteMark, interval);
|
||||
return deleteMark;
|
||||
}
|
||||
|
||||
|
@ -1442,7 +1442,7 @@ SOperatorInfo* createStreamFinalIntervalOperatorInfo(SOperatorInfo* downstream,
|
|||
.calTrigger = pIntervalPhyNode->window.triggerType,
|
||||
.maxTs = INT64_MIN,
|
||||
.minTs = INT64_MAX,
|
||||
.deleteMark = getDeleteMark(pIntervalPhyNode),
|
||||
.deleteMark = getDeleteMark(&pIntervalPhyNode->window, pIntervalPhyNode->interval),
|
||||
.deleteMarkSaved = 0,
|
||||
.calTriggerSaved = 0,
|
||||
};
|
||||
|
@ -2565,7 +2565,7 @@ void doStreamSessionSaveCheckpoint(SOperatorInfo* pOperator) {
|
|||
taosMemoryFree(buf);
|
||||
}
|
||||
|
||||
static void resetUnCloseSessionWinInfo(SSHashObj* winMap) {
|
||||
void resetUnCloseSessionWinInfo(SSHashObj* winMap) {
|
||||
void* pIte = NULL;
|
||||
int32_t iter = 0;
|
||||
while ((pIte = tSimpleHashIterate(winMap, pIte, &iter)) != NULL) {
|
||||
|
@ -3963,7 +3963,7 @@ SOperatorInfo* createStreamIntervalOperatorInfo(SOperatorInfo* downstream, SPhys
|
|||
.calTrigger = pIntervalPhyNode->window.triggerType,
|
||||
.maxTs = INT64_MIN,
|
||||
.minTs = INT64_MAX,
|
||||
.deleteMark = getDeleteMark(pIntervalPhyNode)};
|
||||
.deleteMark = getDeleteMark(&pIntervalPhyNode->window, pIntervalPhyNode->interval)};
|
||||
|
||||
ASSERTS(pInfo->twAggSup.calTrigger != STREAM_TRIGGER_MAX_DELAY, "trigger type should not be max delay");
|
||||
|
||||
|
|
|
@ -2304,7 +2304,7 @@ SOperatorInfo* createDataBlockInfoScanOperator(SReadHandle* readHandle, SBlockDi
|
|||
void* pList = tableListGetInfo(pTableListInfo, 0);
|
||||
|
||||
code = readHandle->api.tsdReader.tsdReaderOpen(readHandle->vnode, &cond, pList, num, pInfo->pResBlock,
|
||||
(void**)&pInfo->pHandle, pTaskInfo->id.str, false, NULL);
|
||||
(void**)&pInfo->pHandle, pTaskInfo->id.str, NULL);
|
||||
cleanupQueryTableDataCond(&cond);
|
||||
if (code != 0) {
|
||||
goto _error;
|
||||
|
|
|
@ -67,15 +67,19 @@ int32_t doGeomFromTextFunc(const char *input, unsigned char **output) {
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
// make input as a zero ending string
|
||||
char *end = varDataVal(input) + varDataLen(input);
|
||||
char endValue = *end;
|
||||
*end = 0;
|
||||
|
||||
char *inputGeom = NULL;
|
||||
unsigned char *outputGeom = NULL;
|
||||
size_t size = 0;
|
||||
|
||||
code = doGeomFromText(varDataVal(input), &outputGeom, &size);
|
||||
// make a zero ending string
|
||||
inputGeom = taosMemoryCalloc(1, varDataLen(input) + 1);
|
||||
if (inputGeom == NULL) {
|
||||
code = TSDB_CODE_OUT_OF_MEMORY;
|
||||
goto _exit;
|
||||
}
|
||||
memcpy(inputGeom, varDataVal(input), varDataLen(input));
|
||||
|
||||
code = doGeomFromText(inputGeom, &outputGeom, &size);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
goto _exit;
|
||||
}
|
||||
|
@ -92,8 +96,7 @@ int32_t doGeomFromTextFunc(const char *input, unsigned char **output) {
|
|||
|
||||
_exit:
|
||||
geosFreeBuffer(outputGeom);
|
||||
|
||||
*end = endValue; //recover the input string
|
||||
geosFreeBuffer(inputGeom);
|
||||
|
||||
return code;
|
||||
}
|
||||
|
|
|
@ -423,6 +423,7 @@ static int32_t logicScanCopy(const SScanLogicNode* pSrc, SScanLogicNode* pDst) {
|
|||
COPY_SCALAR_FIELD(igLastNull);
|
||||
COPY_SCALAR_FIELD(groupOrderScan);
|
||||
COPY_SCALAR_FIELD(onlyMetaCtbIdx);
|
||||
COPY_SCALAR_FIELD(filesetDelimited);
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -650,6 +651,7 @@ static int32_t physiTableScanCopy(const STableScanPhysiNode* pSrc, STableScanPhy
|
|||
COPY_SCALAR_FIELD(triggerType);
|
||||
COPY_SCALAR_FIELD(watermark);
|
||||
COPY_SCALAR_FIELD(igExpired);
|
||||
COPY_SCALAR_FIELD(filesetDelimited);
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -677,6 +677,7 @@ static const char* jkScanLogicPlanDataRequired = "DataRequired";
|
|||
static const char* jkScanLogicPlanTagCond = "TagCond";
|
||||
static const char* jkScanLogicPlanGroupTags = "GroupTags";
|
||||
static const char* jkScanLogicPlanOnlyMetaCtbIdx = "OnlyMetaCtbIdx";
|
||||
static const char* jkScanLogicPlanFilesetDelimited = "FilesetDelimited";
|
||||
|
||||
static int32_t logicScanNodeToJson(const void* pObj, SJson* pJson) {
|
||||
const SScanLogicNode* pNode = (const SScanLogicNode*)pObj;
|
||||
|
@ -721,6 +722,9 @@ static int32_t logicScanNodeToJson(const void* pObj, SJson* pJson) {
|
|||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = tjsonAddBoolToObject(pJson, jkScanLogicPlanOnlyMetaCtbIdx, pNode->onlyMetaCtbIdx);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = tjsonAddBoolToObject(pJson, jkScanLogicPlanFilesetDelimited, pNode->filesetDelimited);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
|
@ -768,7 +772,9 @@ static int32_t jsonToLogicScanNode(const SJson* pJson, void* pObj) {
|
|||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = tjsonGetBoolValue(pJson, jkScanLogicPlanOnlyMetaCtbIdx, &pNode->onlyMetaCtbIdx);
|
||||
}
|
||||
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = tjsonGetBoolValue(pJson, jkScanLogicPlanFilesetDelimited, &pNode->filesetDelimited);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
|
@ -1830,6 +1836,7 @@ static const char* jkTableScanPhysiPlanTags = "Tags";
|
|||
static const char* jkTableScanPhysiPlanSubtable = "Subtable";
|
||||
static const char* jkTableScanPhysiPlanAssignBlockUid = "AssignBlockUid";
|
||||
static const char* jkTableScanPhysiPlanIgnoreUpdate = "IgnoreUpdate";
|
||||
static const char* jkTableScanPhysiPlanFilesetDelimited = "FilesetDelimited";
|
||||
|
||||
static int32_t physiTableScanNodeToJson(const void* pObj, SJson* pJson) {
|
||||
const STableScanPhysiNode* pNode = (const STableScanPhysiNode*)pObj;
|
||||
|
@ -1898,6 +1905,9 @@ static int32_t physiTableScanNodeToJson(const void* pObj, SJson* pJson) {
|
|||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = tjsonAddIntegerToObject(pJson, jkTableScanPhysiPlanIgnoreUpdate, pNode->igCheckUpdate);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = tjsonAddBoolToObject(pJson, jkTableScanPhysiPlanFilesetDelimited, pNode->filesetDelimited);
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
@ -1969,6 +1979,9 @@ static int32_t jsonToPhysiTableScanNode(const SJson* pJson, void* pObj) {
|
|||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = tjsonGetTinyIntValue(pJson, jkTableScanPhysiPlanIgnoreUpdate, &pNode->igCheckUpdate);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = tjsonGetBoolValue(pJson, jkTableScanPhysiPlanFilesetDelimited, &pNode->filesetDelimited);
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
|
|
@ -2167,7 +2167,9 @@ static int32_t physiTableScanNodeInlineToMsg(const void* pObj, STlvEncoder* pEnc
|
|||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = tlvEncodeValueI8(pEncoder, pNode->igCheckUpdate);
|
||||
}
|
||||
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = tlvEncodeValueBool(pEncoder, pNode->filesetDelimited);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
|
@ -2246,6 +2248,9 @@ static int32_t msgToPhysiTableScanNodeInline(STlvDecoder* pDecoder, void* pObj)
|
|||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = tlvDecodeValueI8(pDecoder, &pNode->igCheckUpdate);
|
||||
}
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
code = tlvDecodeValueBool(pDecoder, &pNode->filesetDelimited);
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
|
|
@ -507,7 +507,8 @@ static int32_t parseTagToken(const char** end, SToken* pToken, SSchema* pSchema,
|
|||
}
|
||||
|
||||
case TSDB_DATA_TYPE_TINYINT: {
|
||||
if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &iv)) {
|
||||
code = toIntegerEx(pToken->z, pToken->n, pToken->type, &iv);
|
||||
if (TSDB_CODE_SUCCESS != code) {
|
||||
return buildSyntaxErrMsg(pMsgBuf, "invalid tinyint data", pToken->z);
|
||||
} else if (!IS_VALID_TINYINT(iv)) {
|
||||
return buildSyntaxErrMsg(pMsgBuf, "tinyint data overflow", pToken->z);
|
||||
|
@ -518,7 +519,8 @@ static int32_t parseTagToken(const char** end, SToken* pToken, SSchema* pSchema,
|
|||
}
|
||||
|
||||
case TSDB_DATA_TYPE_UTINYINT: {
|
||||
if (TSDB_CODE_SUCCESS != toUInteger(pToken->z, pToken->n, 10, &uv)) {
|
||||
code = toUIntegerEx(pToken->z, pToken->n, pToken->type, &uv);
|
||||
if (TSDB_CODE_SUCCESS != code) {
|
||||
return buildSyntaxErrMsg(pMsgBuf, "invalid unsigned tinyint data", pToken->z);
|
||||
} else if (uv > UINT8_MAX) {
|
||||
return buildSyntaxErrMsg(pMsgBuf, "unsigned tinyint data overflow", pToken->z);
|
||||
|
@ -528,7 +530,8 @@ static int32_t parseTagToken(const char** end, SToken* pToken, SSchema* pSchema,
|
|||
}
|
||||
|
||||
case TSDB_DATA_TYPE_SMALLINT: {
|
||||
if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &iv)) {
|
||||
code = toIntegerEx(pToken->z, pToken->n, pToken->type, &iv);
|
||||
if (TSDB_CODE_SUCCESS != code) {
|
||||
return buildSyntaxErrMsg(pMsgBuf, "invalid smallint data", pToken->z);
|
||||
} else if (!IS_VALID_SMALLINT(iv)) {
|
||||
return buildSyntaxErrMsg(pMsgBuf, "smallint data overflow", pToken->z);
|
||||
|
@ -538,7 +541,8 @@ static int32_t parseTagToken(const char** end, SToken* pToken, SSchema* pSchema,
|
|||
}
|
||||
|
||||
case TSDB_DATA_TYPE_USMALLINT: {
|
||||
if (TSDB_CODE_SUCCESS != toUInteger(pToken->z, pToken->n, 10, &uv)) {
|
||||
code = toUIntegerEx(pToken->z, pToken->n, pToken->type, &uv);
|
||||
if (TSDB_CODE_SUCCESS != code) {
|
||||
return buildSyntaxErrMsg(pMsgBuf, "invalid unsigned smallint data", pToken->z);
|
||||
} else if (uv > UINT16_MAX) {
|
||||
return buildSyntaxErrMsg(pMsgBuf, "unsigned smallint data overflow", pToken->z);
|
||||
|
@ -548,7 +552,8 @@ static int32_t parseTagToken(const char** end, SToken* pToken, SSchema* pSchema,
|
|||
}
|
||||
|
||||
case TSDB_DATA_TYPE_INT: {
|
||||
if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &iv)) {
|
||||
code = toIntegerEx(pToken->z, pToken->n, pToken->type, &iv);
|
||||
if (TSDB_CODE_SUCCESS != code) {
|
||||
return buildSyntaxErrMsg(pMsgBuf, "invalid int data", pToken->z);
|
||||
} else if (!IS_VALID_INT(iv)) {
|
||||
return buildSyntaxErrMsg(pMsgBuf, "int data overflow", pToken->z);
|
||||
|
@ -558,7 +563,8 @@ static int32_t parseTagToken(const char** end, SToken* pToken, SSchema* pSchema,
|
|||
}
|
||||
|
||||
case TSDB_DATA_TYPE_UINT: {
|
||||
if (TSDB_CODE_SUCCESS != toUInteger(pToken->z, pToken->n, 10, &uv)) {
|
||||
code = toUIntegerEx(pToken->z, pToken->n, pToken->type, &uv);
|
||||
if (TSDB_CODE_SUCCESS != code) {
|
||||
return buildSyntaxErrMsg(pMsgBuf, "invalid unsigned int data", pToken->z);
|
||||
} else if (uv > UINT32_MAX) {
|
||||
return buildSyntaxErrMsg(pMsgBuf, "unsigned int data overflow", pToken->z);
|
||||
|
@ -568,7 +574,8 @@ static int32_t parseTagToken(const char** end, SToken* pToken, SSchema* pSchema,
|
|||
}
|
||||
|
||||
case TSDB_DATA_TYPE_BIGINT: {
|
||||
if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &iv)) {
|
||||
code = toIntegerEx(pToken->z, pToken->n, pToken->type, &iv);
|
||||
if (TSDB_CODE_SUCCESS != code) {
|
||||
return buildSyntaxErrMsg(pMsgBuf, "invalid bigint data", pToken->z);
|
||||
}
|
||||
val->i64 = iv;
|
||||
|
@ -576,7 +583,8 @@ static int32_t parseTagToken(const char** end, SToken* pToken, SSchema* pSchema,
|
|||
}
|
||||
|
||||
case TSDB_DATA_TYPE_UBIGINT: {
|
||||
if (TSDB_CODE_SUCCESS != toUInteger(pToken->z, pToken->n, 10, &uv)) {
|
||||
code = toUIntegerEx(pToken->z, pToken->n, pToken->type, &uv);
|
||||
if (TSDB_CODE_SUCCESS != code) {
|
||||
return buildSyntaxErrMsg(pMsgBuf, "invalid unsigned bigint data", pToken->z);
|
||||
}
|
||||
*(uint64_t*)(&val->i64) = uv;
|
||||
|
@ -585,11 +593,11 @@ static int32_t parseTagToken(const char** end, SToken* pToken, SSchema* pSchema,
|
|||
|
||||
case TSDB_DATA_TYPE_FLOAT: {
|
||||
double dv;
|
||||
if (TK_NK_ILLEGAL == toDouble(pToken, &dv, &endptr)) {
|
||||
code = toDoubleEx(pToken->z, pToken->n, pToken->type, &dv);
|
||||
if (TSDB_CODE_SUCCESS != code) {
|
||||
return buildSyntaxErrMsg(pMsgBuf, "illegal float data", pToken->z);
|
||||
}
|
||||
if (((dv == HUGE_VAL || dv == -HUGE_VAL) && errno == ERANGE) || dv > FLT_MAX || dv < -FLT_MAX || isinf(dv) ||
|
||||
isnan(dv)) {
|
||||
if (dv > FLT_MAX || dv < -FLT_MAX || isinf(dv) || isnan(dv)) {
|
||||
return buildSyntaxErrMsg(pMsgBuf, "illegal float data", pToken->z);
|
||||
}
|
||||
*(float*)(&val->i64) = dv;
|
||||
|
@ -598,8 +606,9 @@ static int32_t parseTagToken(const char** end, SToken* pToken, SSchema* pSchema,
|
|||
|
||||
case TSDB_DATA_TYPE_DOUBLE: {
|
||||
double dv;
|
||||
if (TK_NK_ILLEGAL == toDouble(pToken, &dv, &endptr)) {
|
||||
return buildSyntaxErrMsg(pMsgBuf, "illegal double data", pToken->z);
|
||||
code = toDoubleEx(pToken->z, pToken->n, pToken->type, &dv);
|
||||
if (TSDB_CODE_SUCCESS != code) {
|
||||
return buildSyntaxErrMsg(pMsgBuf, "illegal float data", pToken->z);
|
||||
}
|
||||
if (((dv == HUGE_VAL || dv == -HUGE_VAL) && errno == ERANGE) || isinf(dv) || isnan(dv)) {
|
||||
return buildSyntaxErrMsg(pMsgBuf, "illegal double data", pToken->z);
|
||||
|
@ -1431,7 +1440,8 @@ static int32_t parseValueTokenImpl(SInsertParseContext* pCxt, const char** pSql,
|
|||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_TINYINT: {
|
||||
if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &pVal->value.val)) {
|
||||
int32_t code = toIntegerEx(pToken->z, pToken->n, pToken->type, &pVal->value.val);
|
||||
if (TSDB_CODE_SUCCESS != code) {
|
||||
return buildSyntaxErrMsg(&pCxt->msg, "invalid tinyint data", pToken->z);
|
||||
} else if (!IS_VALID_TINYINT(pVal->value.val)) {
|
||||
return buildSyntaxErrMsg(&pCxt->msg, "tinyint data overflow", pToken->z);
|
||||
|
@ -1439,7 +1449,8 @@ static int32_t parseValueTokenImpl(SInsertParseContext* pCxt, const char** pSql,
|
|||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_UTINYINT: {
|
||||
if (TSDB_CODE_SUCCESS != toUInteger(pToken->z, pToken->n, 10, &pVal->value.val)) {
|
||||
int32_t code = toUIntegerEx(pToken->z, pToken->n, pToken->type, &pVal->value.val);
|
||||
if (TSDB_CODE_SUCCESS != code) {
|
||||
return buildSyntaxErrMsg(&pCxt->msg, "invalid unsigned tinyint data", pToken->z);
|
||||
} else if (pVal->value.val > UINT8_MAX) {
|
||||
return buildSyntaxErrMsg(&pCxt->msg, "unsigned tinyint data overflow", pToken->z);
|
||||
|
@ -1447,7 +1458,8 @@ static int32_t parseValueTokenImpl(SInsertParseContext* pCxt, const char** pSql,
|
|||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_SMALLINT: {
|
||||
if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &pVal->value.val)) {
|
||||
int32_t code = toIntegerEx(pToken->z, pToken->n, pToken->type, &pVal->value.val);
|
||||
if (TSDB_CODE_SUCCESS != code) {
|
||||
return buildSyntaxErrMsg(&pCxt->msg, "invalid smallint data", pToken->z);
|
||||
} else if (!IS_VALID_SMALLINT(pVal->value.val)) {
|
||||
return buildSyntaxErrMsg(&pCxt->msg, "smallint data overflow", pToken->z);
|
||||
|
@ -1455,7 +1467,8 @@ static int32_t parseValueTokenImpl(SInsertParseContext* pCxt, const char** pSql,
|
|||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_USMALLINT: {
|
||||
if (TSDB_CODE_SUCCESS != toUInteger(pToken->z, pToken->n, 10, &pVal->value.val)) {
|
||||
int32_t code = toUIntegerEx(pToken->z, pToken->n, pToken->type, &pVal->value.val);
|
||||
if (TSDB_CODE_SUCCESS != code) {
|
||||
return buildSyntaxErrMsg(&pCxt->msg, "invalid unsigned smallint data", pToken->z);
|
||||
} else if (pVal->value.val > UINT16_MAX) {
|
||||
return buildSyntaxErrMsg(&pCxt->msg, "unsigned smallint data overflow", pToken->z);
|
||||
|
@ -1463,7 +1476,8 @@ static int32_t parseValueTokenImpl(SInsertParseContext* pCxt, const char** pSql,
|
|||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_INT: {
|
||||
if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &pVal->value.val)) {
|
||||
int32_t code = toIntegerEx(pToken->z, pToken->n, pToken->type, &pVal->value.val);
|
||||
if (TSDB_CODE_SUCCESS != code) {
|
||||
return buildSyntaxErrMsg(&pCxt->msg, "invalid int data", pToken->z);
|
||||
} else if (!IS_VALID_INT(pVal->value.val)) {
|
||||
return buildSyntaxErrMsg(&pCxt->msg, "int data overflow", pToken->z);
|
||||
|
@ -1471,7 +1485,8 @@ static int32_t parseValueTokenImpl(SInsertParseContext* pCxt, const char** pSql,
|
|||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_UINT: {
|
||||
if (TSDB_CODE_SUCCESS != toUInteger(pToken->z, pToken->n, 10, &pVal->value.val)) {
|
||||
int32_t code = toUIntegerEx(pToken->z, pToken->n, pToken->type, &pVal->value.val);
|
||||
if (TSDB_CODE_SUCCESS != code) {
|
||||
return buildSyntaxErrMsg(&pCxt->msg, "invalid unsigned int data", pToken->z);
|
||||
} else if (pVal->value.val > UINT32_MAX) {
|
||||
return buildSyntaxErrMsg(&pCxt->msg, "unsigned int data overflow", pToken->z);
|
||||
|
@ -1479,25 +1494,26 @@ static int32_t parseValueTokenImpl(SInsertParseContext* pCxt, const char** pSql,
|
|||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_BIGINT: {
|
||||
if (TSDB_CODE_SUCCESS != toInteger(pToken->z, pToken->n, 10, &pVal->value.val)) {
|
||||
int32_t code = toIntegerEx(pToken->z, pToken->n, pToken->type, &pVal->value.val);
|
||||
if (TSDB_CODE_SUCCESS != code) {
|
||||
return buildSyntaxErrMsg(&pCxt->msg, "invalid bigint data", pToken->z);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_UBIGINT: {
|
||||
if (TSDB_CODE_SUCCESS != toUInteger(pToken->z, pToken->n, 10, &pVal->value.val)) {
|
||||
int32_t code = toUIntegerEx(pToken->z, pToken->n, pToken->type, &pVal->value.val);
|
||||
if (TSDB_CODE_SUCCESS != code) {
|
||||
return buildSyntaxErrMsg(&pCxt->msg, "invalid unsigned bigint data", pToken->z);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_FLOAT: {
|
||||
char* endptr = NULL;
|
||||
double dv;
|
||||
if (TK_NK_ILLEGAL == toDouble(pToken, &dv, &endptr)) {
|
||||
int32_t code = toDoubleEx(pToken->z, pToken->n, pToken->type, &dv);
|
||||
if (TSDB_CODE_SUCCESS != code) {
|
||||
return buildSyntaxErrMsg(&pCxt->msg, "illegal float data", pToken->z);
|
||||
}
|
||||
if (((dv == HUGE_VAL || dv == -HUGE_VAL) && errno == ERANGE) || dv > FLT_MAX || dv < -FLT_MAX || isinf(dv) ||
|
||||
isnan(dv)) {
|
||||
if (dv > FLT_MAX || dv < -FLT_MAX || isinf(dv) || isnan(dv)) {
|
||||
return buildSyntaxErrMsg(&pCxt->msg, "illegal float data", pToken->z);
|
||||
}
|
||||
float f = dv;
|
||||
|
@ -1505,12 +1521,12 @@ static int32_t parseValueTokenImpl(SInsertParseContext* pCxt, const char** pSql,
|
|||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_DOUBLE: {
|
||||
char* endptr = NULL;
|
||||
double dv;
|
||||
if (TK_NK_ILLEGAL == toDouble(pToken, &dv, &endptr)) {
|
||||
return buildSyntaxErrMsg(&pCxt->msg, "illegal double data", pToken->z);
|
||||
int32_t code = toDoubleEx(pToken->z, pToken->n, pToken->type, &dv);
|
||||
if (TSDB_CODE_SUCCESS != code) {
|
||||
return buildSyntaxErrMsg(&pCxt->msg, "illegal float data", pToken->z);
|
||||
}
|
||||
if (((dv == HUGE_VAL || dv == -HUGE_VAL) && errno == ERANGE) || isinf(dv) || isnan(dv)) {
|
||||
if (isinf(dv) || isnan(dv)) {
|
||||
return buildSyntaxErrMsg(&pCxt->msg, "illegal double data", pToken->z);
|
||||
}
|
||||
pVal->value.val = *(int64_t*)&dv;
|
||||
|
|
|
@ -609,6 +609,11 @@ uint32_t tGetToken(const char* z, uint32_t* tokenId) {
|
|||
break;
|
||||
}
|
||||
|
||||
// support float with no decimal part after the decimal point
|
||||
if (z[i] == '.' && seg == 1) {
|
||||
*tokenId = TK_NK_FLOAT;
|
||||
i++;
|
||||
}
|
||||
if ((z[i] == 'e' || z[i] == 'E') &&
|
||||
(isdigit(z[i + 1]) || ((z[i + 1] == '+' || z[i + 1] == '-') && isdigit(z[i + 2])))) {
|
||||
i += 2;
|
||||
|
@ -751,7 +756,7 @@ SToken tStrGetToken(const char* str, int32_t* i, bool isPrevOptr, bool* pIgnoreC
|
|||
// support parse the -/+number format
|
||||
if ((isPrevOptr) && (t0.type == TK_NK_MINUS || t0.type == TK_NK_PLUS)) {
|
||||
len = tGetToken(&str[*i + t0.n], &type);
|
||||
if (type == TK_NK_INTEGER || type == TK_NK_FLOAT) {
|
||||
if (type == TK_NK_INTEGER || type == TK_NK_FLOAT || type == TK_NK_BIN || type == TK_NK_HEX) {
|
||||
t0.type = type;
|
||||
t0.n += len;
|
||||
}
|
||||
|
|
|
@ -1400,6 +1400,7 @@ static int32_t sortPriKeyOptApply(SOptimizeContext* pCxt, SLogicSubplan* pLogicS
|
|||
pScan->node.outputTsOrder = order;
|
||||
if (TSDB_SUPER_TABLE == pScan->tableType) {
|
||||
pScan->scanType = SCAN_TYPE_TABLE_MERGE;
|
||||
pScan->filesetDelimited = true;
|
||||
pScan->node.resultDataOrder = DATA_ORDER_LEVEL_GLOBAL;
|
||||
pScan->node.requireDataOrder = DATA_ORDER_LEVEL_GLOBAL;
|
||||
}
|
||||
|
|
|
@ -622,6 +622,7 @@ static int32_t createTableScanPhysiNode(SPhysiPlanContext* pCxt, SSubplan* pSubp
|
|||
pTableScan->igExpired = pScanLogicNode->igExpired;
|
||||
pTableScan->igCheckUpdate = pScanLogicNode->igCheckUpdate;
|
||||
pTableScan->assignBlockUid = pCxt->pPlanCxt->rSmaQuery ? true : false;
|
||||
pTableScan->filesetDelimited = pScanLogicNode->filesetDelimited;
|
||||
|
||||
int32_t code = createScanPhysiNodeFinalize(pCxt, pSubplan, pScanLogicNode, (SScanPhysiNode*)pTableScan, pPhyNode);
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
|
|
|
@ -692,6 +692,7 @@ static void stbSplSetTableMergeScan(SLogicNode* pNode) {
|
|||
if (QUERY_NODE_LOGIC_PLAN_SCAN == nodeType(pNode)) {
|
||||
SScanLogicNode* pScan = (SScanLogicNode*)pNode;
|
||||
pScan->scanType = SCAN_TYPE_TABLE_MERGE;
|
||||
pScan->filesetDelimited = true;
|
||||
if (NULL != pScan->pGroupTags) {
|
||||
pScan->groupSort = true;
|
||||
}
|
||||
|
@ -1243,6 +1244,7 @@ static int32_t stbSplCreateMergeScanNode(SScanLogicNode* pScan, SLogicNode** pOu
|
|||
SNodeList* pMergeKeys = NULL;
|
||||
if (TSDB_CODE_SUCCESS == code) {
|
||||
pMergeScan->scanType = SCAN_TYPE_TABLE_MERGE;
|
||||
pMergeScan->filesetDelimited = true;
|
||||
pMergeScan->node.pChildren = pChildren;
|
||||
splSetParent((SLogicNode*)pMergeScan);
|
||||
code = stbSplCreateMergeKeysByPrimaryKey(stbSplFindPrimaryKeyFromScan(pMergeScan),
|
||||
|
|
|
@ -164,6 +164,7 @@ static int32_t adjustScanDataRequirement(SScanLogicNode* pScan, EDataOrderLevel
|
|||
pScan->scanType = SCAN_TYPE_TABLE;
|
||||
} else if (TSDB_SUPER_TABLE == pScan->tableType) {
|
||||
pScan->scanType = SCAN_TYPE_TABLE_MERGE;
|
||||
pScan->filesetDelimited = true;
|
||||
}
|
||||
|
||||
if (TSDB_NORMAL_TABLE != pScan->tableType && TSDB_CHILD_TABLE != pScan->tableType) {
|
||||
|
|
|
@ -56,6 +56,10 @@ int32_t syncNodeReplicateWithoutLock(SSyncNode* pNode);
|
|||
|
||||
int32_t syncNodeSendAppendEntries(SSyncNode* pNode, const SRaftId* destRaftId, SRpcMsg* pRpcMsg);
|
||||
|
||||
int32_t syncSnapSendMsg(SSyncSnapshotSender* pSender, int32_t seq, void* pBlock, int32_t len, int32_t typ);
|
||||
int32_t syncSnapSendRsp(SSyncSnapshotReceiver* pReceiver, SyncSnapshotSend* pMsg, void* pBlock, int32_t len,
|
||||
int32_t typ, int32_t code);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -23,8 +23,6 @@
|
|||
#include "syncReplication.h"
|
||||
#include "syncUtil.h"
|
||||
|
||||
int32_t syncSnapSendMsg(SSyncSnapshotSender *pSender, int32_t seq, void *pBlock, int32_t len, int32_t typ);
|
||||
|
||||
static void syncSnapBufferReset(SSyncSnapBuffer *pBuf) {
|
||||
taosThreadMutexLock(&pBuf->mutex);
|
||||
for (int64_t i = pBuf->start; i < pBuf->end; ++i) {
|
||||
|
@ -123,6 +121,11 @@ void snapshotSenderDestroy(SSyncSnapshotSender *pSender) {
|
|||
if (pSender->pSndBuf) {
|
||||
syncSnapBufferDestroy(&pSender->pSndBuf);
|
||||
}
|
||||
|
||||
if (pSender->snapshotParam.data) {
|
||||
taosMemoryFree(pSender->snapshotParam.data);
|
||||
pSender->snapshotParam.data = NULL;
|
||||
}
|
||||
// free sender
|
||||
taosMemoryFree(pSender);
|
||||
}
|
||||
|
@ -153,7 +156,7 @@ int32_t snapshotSenderStart(SSyncSnapshotSender *pSender) {
|
|||
pSender->lastSendTime = taosGetTimestampMs();
|
||||
pSender->finish = false;
|
||||
|
||||
// Get full snapshot info
|
||||
// Get snapshot info
|
||||
SSyncNode *pSyncNode = pSender->pSyncNode;
|
||||
SSnapshot snapInfo = {.type = TDMT_SYNC_PREP_SNAPSHOT};
|
||||
if (pSyncNode->pFsm->FpGetSnapshotInfo(pSyncNode->pFsm, &snapInfo) != 0) {
|
||||
|
@ -161,11 +164,10 @@ int32_t snapshotSenderStart(SSyncSnapshotSender *pSender) {
|
|||
goto _out;
|
||||
}
|
||||
|
||||
int dataLen = 0;
|
||||
void *pData = snapInfo.data;
|
||||
int32_t type = 0;
|
||||
int32_t type = (pData) ? snapInfo.type : 0;
|
||||
int32_t dataLen = 0;
|
||||
if (pData) {
|
||||
type = snapInfo.type;
|
||||
SSyncTLV *datHead = pData;
|
||||
if (datHead->typ != TDMT_SYNC_PREP_SNAPSHOT) {
|
||||
sSError(pSender, "unexpected data typ in data of snapshot info. typ: %d", datHead->typ);
|
||||
|
@ -347,9 +349,6 @@ _out:;
|
|||
return code;
|
||||
}
|
||||
|
||||
// return 0, start ok
|
||||
// return 1, last snapshot finish ok
|
||||
// return -1, error
|
||||
int32_t syncNodeStartSnapshot(SSyncNode *pSyncNode, SRaftId *pDestId) {
|
||||
SSyncSnapshotSender *pSender = syncNodeGetSnapshotSender(pSyncNode, pDestId);
|
||||
if (pSender == NULL) {
|
||||
|
@ -380,6 +379,7 @@ int32_t syncNodeStartSnapshot(SSyncNode *pSyncNode, SRaftId *pDestId) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
// receiver
|
||||
SSyncSnapshotReceiver *snapshotReceiverCreate(SSyncNode *pSyncNode, SRaftId fromId) {
|
||||
bool condition = (pSyncNode->pFsm->FpSnapshotStartWrite != NULL) && (pSyncNode->pFsm->FpSnapshotStopWrite != NULL) &&
|
||||
(pSyncNode->pFsm->FpSnapshotDoWrite != NULL);
|
||||
|
@ -509,8 +509,6 @@ void snapshotReceiverStart(SSyncSnapshotReceiver *pReceiver, SyncSnapshotSend *p
|
|||
sRInfo(pReceiver, "snapshot receiver start, from dnode:%d.", DID(&pReceiver->fromId));
|
||||
}
|
||||
|
||||
// just set start = false
|
||||
// FpSnapshotStopWrite should not be called
|
||||
void snapshotReceiverStop(SSyncSnapshotReceiver *pReceiver) {
|
||||
sRDebug(pReceiver, "snapshot receiver stop, not apply, writer:%p", pReceiver->pWriter);
|
||||
|
||||
|
@ -531,7 +529,6 @@ void snapshotReceiverStop(SSyncSnapshotReceiver *pReceiver) {
|
|||
syncSnapBufferReset(pReceiver->pRcvBuf);
|
||||
}
|
||||
|
||||
// when recv last snapshot block, apply data into snapshot
|
||||
static int32_t snapshotReceiverFinish(SSyncSnapshotReceiver *pReceiver, SyncSnapshotSend *pMsg) {
|
||||
int32_t code = 0;
|
||||
if (pReceiver->pWriter != NULL) {
|
||||
|
@ -590,8 +587,6 @@ static int32_t snapshotReceiverFinish(SSyncSnapshotReceiver *pReceiver, SyncSnap
|
|||
return 0;
|
||||
}
|
||||
|
||||
// apply data block
|
||||
// update progress
|
||||
static int32_t snapshotReceiverGotData(SSyncSnapshotReceiver *pReceiver, SyncSnapshotSend *pMsg) {
|
||||
if (pMsg->seq != pReceiver->ack + 1) {
|
||||
sRError(pReceiver, "snapshot receiver invalid seq, ack:%d seq:%d", pReceiver->ack, pMsg->seq);
|
||||
|
@ -644,6 +639,50 @@ SyncIndex syncNodeGetSnapBeginIndex(SSyncNode *ths) {
|
|||
return snapStart;
|
||||
}
|
||||
|
||||
static int32_t syncSnapReceiverExchgSnapInfo(SSyncNode *pSyncNode, SSyncSnapshotReceiver *pReceiver,
|
||||
SyncSnapshotSend *pMsg, SSnapshot *pInfo) {
|
||||
ASSERT(pMsg->payloadType == TDMT_SYNC_PREP_SNAPSHOT);
|
||||
int32_t code = 0;
|
||||
|
||||
// copy snap info from leader
|
||||
void *data = taosMemoryCalloc(1, pMsg->dataLen);
|
||||
if (data == NULL) {
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
code = terrno;
|
||||
goto _out;
|
||||
}
|
||||
pInfo->data = data;
|
||||
data = NULL;
|
||||
memcpy(pInfo->data, pMsg->data, pMsg->dataLen);
|
||||
|
||||
// exchange snap info
|
||||
pSyncNode->pFsm->FpGetSnapshotInfo(pSyncNode->pFsm, pInfo);
|
||||
SSyncTLV *datHead = pInfo->data;
|
||||
if (datHead->typ != TDMT_SYNC_PREP_SNAPSHOT_REPLY) {
|
||||
sRError(pReceiver, "unexpected data typ in data of snapshot info. typ: %d", datHead->typ);
|
||||
code = TSDB_CODE_INVALID_DATA_FMT;
|
||||
goto _out;
|
||||
}
|
||||
int32_t dataLen = sizeof(SSyncTLV) + datHead->len;
|
||||
|
||||
// save exchanged snap info
|
||||
SSnapshotParam *pParam = &pReceiver->snapshotParam;
|
||||
data = taosMemoryRealloc(pParam->data, dataLen);
|
||||
if (data == NULL) {
|
||||
sError("vgId:%d, failed to realloc memory for snapshot prep due to %s. dataLen:%d", pSyncNode->vgId,
|
||||
strerror(errno), dataLen);
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
code = terrno;
|
||||
goto _out;
|
||||
}
|
||||
pParam->data = data;
|
||||
data = NULL;
|
||||
memcpy(pParam->data, pInfo->data, dataLen);
|
||||
|
||||
_out:
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t syncNodeOnSnapshotPrep(SSyncNode *pSyncNode, SyncSnapshotSend *pMsg) {
|
||||
SSyncSnapshotReceiver *pReceiver = pSyncNode->pNewNodeReceiver;
|
||||
int64_t timeNow = taosGetTimestampMs();
|
||||
|
@ -686,77 +725,27 @@ _START_RECEIVER:
|
|||
snapshotReceiverStop(pReceiver);
|
||||
}
|
||||
|
||||
snapshotReceiverStart(pReceiver, pMsg); // set start-time same with sender
|
||||
snapshotReceiverStart(pReceiver, pMsg);
|
||||
|
||||
_SEND_REPLY:
|
||||
// build msg
|
||||
; // make complier happy
|
||||
_SEND_REPLY:;
|
||||
|
||||
SSnapshot snapInfo = {.type = TDMT_SYNC_PREP_SNAPSHOT_REPLY};
|
||||
int32_t dataLen = 0;
|
||||
if (pMsg->dataLen > 0) {
|
||||
void *data = taosMemoryCalloc(1, pMsg->dataLen);
|
||||
if (data == NULL) {
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
code = terrno;
|
||||
if (pMsg->payloadType == TDMT_SYNC_PREP_SNAPSHOT) {
|
||||
if (syncSnapReceiverExchgSnapInfo(pSyncNode, pReceiver, pMsg, &snapInfo) != 0) {
|
||||
goto _out;
|
||||
}
|
||||
memcpy(data, pMsg->data, pMsg->dataLen);
|
||||
snapInfo.data = data;
|
||||
data = NULL;
|
||||
pSyncNode->pFsm->FpGetSnapshotInfo(pSyncNode->pFsm, &snapInfo);
|
||||
|
||||
SSyncTLV *datHead = snapInfo.data;
|
||||
if (datHead->typ != TDMT_SYNC_PREP_SNAPSHOT_REPLY) {
|
||||
sRError(pReceiver, "unexpected data typ in data of snapshot info. typ: %d", datHead->typ);
|
||||
code = TSDB_CODE_INVALID_DATA_FMT;
|
||||
goto _out;
|
||||
}
|
||||
dataLen = sizeof(SSyncTLV) + datHead->len;
|
||||
}
|
||||
|
||||
SRpcMsg rpcMsg = {0};
|
||||
if (syncBuildSnapshotSendRsp(&rpcMsg, dataLen, pSyncNode->vgId) != 0) {
|
||||
sRError(pReceiver, "snapshot receiver failed to build resp since %s", terrstr());
|
||||
// send response
|
||||
int32_t type = (snapInfo.data) ? snapInfo.type : 0;
|
||||
if (syncSnapSendRsp(pReceiver, pMsg, snapInfo.data, dataLen, type, code) != 0) {
|
||||
code = terrno;
|
||||
goto _out;
|
||||
}
|
||||
|
||||
SyncSnapshotRsp *pRspMsg = rpcMsg.pCont;
|
||||
pRspMsg->srcId = pSyncNode->myRaftId;
|
||||
pRspMsg->destId = pMsg->srcId;
|
||||
pRspMsg->term = raftStoreGetTerm(pSyncNode);
|
||||
pRspMsg->lastIndex = pMsg->lastIndex;
|
||||
pRspMsg->lastTerm = pMsg->lastTerm;
|
||||
pRspMsg->startTime = pMsg->startTime;
|
||||
pRspMsg->ack = pMsg->seq; // receiver maybe already closed
|
||||
pRspMsg->code = code;
|
||||
pRspMsg->snapBeginIndex = syncNodeGetSnapBeginIndex(pSyncNode);
|
||||
|
||||
if (snapInfo.data) {
|
||||
pRspMsg->payloadType = snapInfo.type;
|
||||
memcpy(pRspMsg->data, snapInfo.data, dataLen);
|
||||
|
||||
// save snapshot info
|
||||
SSnapshotParam *pParam = &pReceiver->snapshotParam;
|
||||
void *data = taosMemoryRealloc(pParam->data, dataLen);
|
||||
if (data == NULL) {
|
||||
sError("vgId:%d, failed to realloc memory for snapshot prep due to %s. dataLen:%d", pSyncNode->vgId,
|
||||
strerror(errno), dataLen);
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
code = terrno;
|
||||
goto _out;
|
||||
}
|
||||
pParam->data = data;
|
||||
memcpy(pParam->data, snapInfo.data, dataLen);
|
||||
}
|
||||
|
||||
// send msg
|
||||
if (syncNodeSendMsgById(&pRspMsg->destId, pSyncNode, &rpcMsg) != 0) {
|
||||
sRError(pReceiver, "failed to send resp since %s", terrstr());
|
||||
code = terrno;
|
||||
}
|
||||
|
||||
_out:
|
||||
if (snapInfo.data) {
|
||||
taosMemoryFree(snapInfo.data);
|
||||
|
@ -793,38 +782,20 @@ _SEND_REPLY:
|
|||
code = terrno;
|
||||
}
|
||||
|
||||
// build msg
|
||||
SRpcMsg rpcMsg = {0};
|
||||
if (syncBuildSnapshotSendRsp(&rpcMsg, 0, pSyncNode->vgId) != 0) {
|
||||
sRError(pReceiver, "failed to build snapshot receiver resp since %s", terrstr());
|
||||
return -1;
|
||||
}
|
||||
|
||||
SyncSnapshotRsp *pRspMsg = rpcMsg.pCont;
|
||||
pRspMsg->srcId = pSyncNode->myRaftId;
|
||||
pRspMsg->destId = pMsg->srcId;
|
||||
pRspMsg->term = raftStoreGetTerm(pSyncNode);
|
||||
pRspMsg->lastIndex = pMsg->lastIndex;
|
||||
pRspMsg->lastTerm = pMsg->lastTerm;
|
||||
pRspMsg->startTime = pMsg->startTime;
|
||||
pRspMsg->ack = pReceiver->ack; // receiver maybe already closed
|
||||
pRspMsg->code = code;
|
||||
pRspMsg->snapBeginIndex = pReceiver->snapshotParam.start;
|
||||
|
||||
// send msg
|
||||
if (syncNodeSendMsgById(&pRspMsg->destId, pSyncNode, &rpcMsg) != 0) {
|
||||
sRError(pReceiver, "failed to send snapshot receiver resp since %s", terrstr());
|
||||
// send response
|
||||
if (syncSnapSendRsp(pReceiver, pMsg, NULL, 0, 0, code) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t syncSnapSendRsp(SSyncSnapshotReceiver *pReceiver, SyncSnapshotSend *pMsg, int32_t code) {
|
||||
int32_t syncSnapSendRsp(SSyncSnapshotReceiver *pReceiver, SyncSnapshotSend *pMsg, void *pBlock, int32_t blockLen,
|
||||
int32_t type, int32_t code) {
|
||||
SSyncNode *pSyncNode = pReceiver->pSyncNode;
|
||||
// build msg
|
||||
SRpcMsg rpcMsg = {0};
|
||||
if (syncBuildSnapshotSendRsp(&rpcMsg, 0, pSyncNode->vgId)) {
|
||||
if (syncBuildSnapshotSendRsp(&rpcMsg, blockLen, pSyncNode->vgId)) {
|
||||
sRError(pReceiver, "failed to build snapshot receiver resp since %s", terrstr());
|
||||
return -1;
|
||||
}
|
||||
|
@ -832,13 +803,18 @@ static int32_t syncSnapSendRsp(SSyncSnapshotReceiver *pReceiver, SyncSnapshotSen
|
|||
SyncSnapshotRsp *pRspMsg = rpcMsg.pCont;
|
||||
pRspMsg->srcId = pSyncNode->myRaftId;
|
||||
pRspMsg->destId = pMsg->srcId;
|
||||
pRspMsg->term = raftStoreGetTerm(pSyncNode);
|
||||
pRspMsg->term = pMsg->term;
|
||||
pRspMsg->lastIndex = pMsg->lastIndex;
|
||||
pRspMsg->lastTerm = pMsg->lastTerm;
|
||||
pRspMsg->startTime = pMsg->startTime;
|
||||
pRspMsg->ack = pMsg->seq;
|
||||
pRspMsg->code = code;
|
||||
pRspMsg->snapBeginIndex = pReceiver->snapshotParam.start;
|
||||
pRspMsg->payloadType = type;
|
||||
|
||||
if (pBlock != NULL && blockLen > 0) {
|
||||
memcpy(pRspMsg->data, pBlock, blockLen);
|
||||
}
|
||||
|
||||
// send msg
|
||||
if (syncNodeSendMsgById(&pRspMsg->destId, pSyncNode, &rpcMsg) != 0) {
|
||||
|
@ -872,7 +848,7 @@ static int32_t syncSnapBufferRecv(SSyncSnapshotReceiver *pReceiver, SyncSnapshot
|
|||
ppMsg[0] = NULL;
|
||||
pRcvBuf->end = TMAX(pMsg->seq + 1, pRcvBuf->end);
|
||||
} else if (pMsg->seq < pRcvBuf->start) {
|
||||
syncSnapSendRsp(pReceiver, pMsg, code);
|
||||
syncSnapSendRsp(pReceiver, pMsg, NULL, 0, 0, code);
|
||||
goto _out;
|
||||
}
|
||||
|
||||
|
@ -892,7 +868,7 @@ static int32_t syncSnapBufferRecv(SSyncSnapshotReceiver *pReceiver, SyncSnapshot
|
|||
}
|
||||
}
|
||||
pRcvBuf->start = seq + 1;
|
||||
syncSnapSendRsp(pReceiver, pRcvBuf->entries[seq % pRcvBuf->size], code);
|
||||
syncSnapSendRsp(pReceiver, pRcvBuf->entries[seq % pRcvBuf->size], NULL, 0, 0, code);
|
||||
pRcvBuf->entryDeleteCb(pRcvBuf->entries[seq % pRcvBuf->size]);
|
||||
pRcvBuf->entries[seq % pRcvBuf->size] = NULL;
|
||||
if (code) goto _out;
|
||||
|
@ -915,7 +891,7 @@ static int32_t syncNodeOnSnapshotReceive(SSyncNode *pSyncNode, SyncSnapshotSend
|
|||
if (snapshotReceiverSignatureCmp(pReceiver, pMsg) != 0) {
|
||||
terrno = TSDB_CODE_SYN_MISMATCHED_SIGNATURE;
|
||||
sRError(pReceiver, "failed to receive snapshot data since %s.", terrstr());
|
||||
return syncSnapSendRsp(pReceiver, pMsg, terrno);
|
||||
return syncSnapSendRsp(pReceiver, pMsg, NULL, 0, 0, terrno);
|
||||
}
|
||||
|
||||
return syncSnapBufferRecv(pReceiver, ppMsg);
|
||||
|
@ -971,26 +947,6 @@ _SEND_REPLY:;
|
|||
return code;
|
||||
}
|
||||
|
||||
// receiver on message
|
||||
//
|
||||
// condition 1, recv SYNC_SNAPSHOT_SEQ_PREP
|
||||
// if receiver already start
|
||||
// if sender.start-time > receiver.start-time, restart receiver(reply snapshot start)
|
||||
// if sender.start-time = receiver.start-time, maybe duplicate msg
|
||||
// if sender.start-time < receiver.start-time, ignore
|
||||
// else
|
||||
// waiting for clock match
|
||||
// start receiver(reply snapshot start)
|
||||
//
|
||||
// condition 2, recv SYNC_SNAPSHOT_SEQ_BEGIN
|
||||
// a. create writer with <begin, end>
|
||||
//
|
||||
// condition 3, recv SYNC_SNAPSHOT_SEQ_END, finish receiver(apply snapshot data, update commit index, maybe reconfig)
|
||||
//
|
||||
// condition 4, recv SYNC_SNAPSHOT_SEQ_FORCE_CLOSE, force close
|
||||
//
|
||||
// condition 5, got data, update ack
|
||||
//
|
||||
int32_t syncNodeOnSnapshot(SSyncNode *pSyncNode, SRpcMsg *pRpcMsg) {
|
||||
SyncSnapshotSend **ppMsg = (SyncSnapshotSend **)&pRpcMsg->pCont;
|
||||
SyncSnapshotSend *pMsg = ppMsg[0];
|
||||
|
@ -1074,6 +1030,32 @@ _out:;
|
|||
return code;
|
||||
}
|
||||
|
||||
static int32_t syncSnapSenderExchgSnapInfo(SSyncNode *pSyncNode, SSyncSnapshotSender *pSender, SyncSnapshotRsp *pMsg) {
|
||||
ASSERT(pMsg->payloadType == TDMT_SYNC_PREP_SNAPSHOT_REPLY);
|
||||
|
||||
SSyncTLV *datHead = (void *)pMsg->data;
|
||||
if (datHead->typ != pMsg->payloadType) {
|
||||
sSError(pSender, "unexpected data type in data of SyncSnapshotRsp. typ: %d", datHead->typ);
|
||||
terrno = TSDB_CODE_INVALID_DATA_FMT;
|
||||
return -1;
|
||||
}
|
||||
int32_t dataLen = sizeof(SSyncTLV) + datHead->len;
|
||||
|
||||
SSnapshotParam *pParam = &pSender->snapshotParam;
|
||||
void *data = taosMemoryRealloc(pParam->data, dataLen);
|
||||
if (data == NULL) {
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
return -1;
|
||||
}
|
||||
memcpy(data, pMsg->data, dataLen);
|
||||
|
||||
pParam->data = data;
|
||||
data = NULL;
|
||||
sSInfo(pSender, "data of snapshot param. len: %d", datHead->len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// sender
|
||||
static int32_t syncNodeOnSnapshotPrepRsp(SSyncNode *pSyncNode, SSyncSnapshotSender *pSender, SyncSnapshotRsp *pMsg) {
|
||||
SSnapshot snapshot = {0};
|
||||
pSyncNode->pFsm->FpGetSnapshotInfo(pSyncNode->pFsm, &snapshot);
|
||||
|
@ -1090,14 +1072,9 @@ static int32_t syncNodeOnSnapshotPrepRsp(SSyncNode *pSyncNode, SSyncSnapshotSend
|
|||
|
||||
// start reader
|
||||
if (pMsg->payloadType == TDMT_SYNC_PREP_SNAPSHOT_REPLY) {
|
||||
SSyncTLV *datHead = (void *)pMsg->data;
|
||||
if (datHead->typ != pMsg->payloadType) {
|
||||
sSError(pSender, "unexpected data type in data of SyncSnapshotRsp. typ: %d", datHead->typ);
|
||||
terrno = TSDB_CODE_INVALID_DATA_FMT;
|
||||
if (syncSnapSenderExchgSnapInfo(pSyncNode, pSender, pMsg) != 0) {
|
||||
return -1;
|
||||
}
|
||||
pSender->snapshotParam.data = (void *)pMsg->data;
|
||||
sSInfo(pSender, "data of snapshot param. len: %d", datHead->len);
|
||||
}
|
||||
|
||||
int32_t code = pSyncNode->pFsm->FpSnapshotStartRead(pSyncNode->pFsm, &pSender->snapshotParam, &pSender->pReader);
|
||||
|
@ -1131,7 +1108,7 @@ static int32_t syncSnapBufferSend(SSyncSnapshotSender *pSender, SyncSnapshotRsp
|
|||
goto _out;
|
||||
}
|
||||
|
||||
if (pSender->pReader == NULL || pSender->finish) {
|
||||
if (pSender->pReader == NULL || pSender->finish || !snapshotSenderIsStart(pSender)) {
|
||||
code = terrno = TSDB_CODE_SYN_INTERNAL_ERROR;
|
||||
goto _out;
|
||||
}
|
||||
|
@ -1182,12 +1159,6 @@ _out:
|
|||
return code;
|
||||
}
|
||||
|
||||
// sender on message
|
||||
//
|
||||
// condition 1 sender receives SYNC_SNAPSHOT_SEQ_END, close sender
|
||||
// condition 2 sender receives ack, set seq = ack + 1, send msg from seq
|
||||
// condition 3 sender receives error msg, just print error log
|
||||
//
|
||||
int32_t syncNodeOnSnapshotRsp(SSyncNode *pSyncNode, SRpcMsg *pRpcMsg) {
|
||||
SyncSnapshotRsp **ppMsg = (SyncSnapshotRsp **)&pRpcMsg->pCont;
|
||||
SyncSnapshotRsp *pMsg = ppMsg[0];
|
||||
|
|
|
@ -487,3 +487,13 @@ void syncLogSendRequestVoteReply(SSyncNode* pSyncNode, const SyncRequestVoteRepl
|
|||
sNInfo(pSyncNode, "send sync-request-vote-reply to dnode:%d {term:%" PRId64 ", grant:%d}, %s", DID(&pMsg->destId),
|
||||
pMsg->term, pMsg->voteGranted, s);
|
||||
}
|
||||
|
||||
int32_t syncSnapInfoDataRealloc(SSnapshot* pSnap, int32_t size) {
|
||||
void* data = taosMemoryRealloc(pSnap->data, size);
|
||||
if (data == NULL) {
|
||||
terrno = TSDB_CODE_OUT_OF_MEMORY;
|
||||
return -1;
|
||||
}
|
||||
pSnap->data = data;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ typedef struct SHttpModule {
|
|||
SAsyncPool* asyncPool;
|
||||
TdThread thread;
|
||||
SHashObj* connStatusTable;
|
||||
int8_t quit;
|
||||
} SHttpModule;
|
||||
|
||||
typedef struct SHttpMsg {
|
||||
|
@ -166,7 +167,7 @@ _OVER:
|
|||
static FORCE_INLINE int32_t taosBuildDstAddr(const char* server, uint16_t port, struct sockaddr_in* dest) {
|
||||
uint32_t ip = taosGetIpv4FromFqdn(server);
|
||||
if (ip == 0xffffffff) {
|
||||
tError("http-report failed to get http server:%s since %s", server, errno == 0 ? "invalid http server" : terrstr());
|
||||
tError("http-report failed to resolving domain names: %s", server);
|
||||
return -1;
|
||||
}
|
||||
char buf[128] = {0};
|
||||
|
@ -190,19 +191,40 @@ static void httpDestroyMsg(SHttpMsg* msg) {
|
|||
taosMemoryFree(msg->cont);
|
||||
taosMemoryFree(msg);
|
||||
}
|
||||
|
||||
static void httpMayDiscardMsg(SHttpModule* http, SAsyncItem* item) {
|
||||
SHttpMsg *msg = NULL, *quitMsg = NULL;
|
||||
if (atomic_load_8(&http->quit) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (!QUEUE_IS_EMPTY(&item->qmsg)) {
|
||||
queue* h = QUEUE_HEAD(&item->qmsg);
|
||||
QUEUE_REMOVE(h);
|
||||
msg = QUEUE_DATA(h, SHttpMsg, q);
|
||||
if (!msg->quit) {
|
||||
httpDestroyMsg(msg);
|
||||
} else {
|
||||
quitMsg = msg;
|
||||
}
|
||||
}
|
||||
if (quitMsg != NULL) {
|
||||
QUEUE_PUSH(&item->qmsg, &quitMsg->q);
|
||||
}
|
||||
}
|
||||
static void httpAsyncCb(uv_async_t* handle) {
|
||||
SAsyncItem* item = handle->data;
|
||||
SHttpModule* http = item->pThrd;
|
||||
|
||||
SHttpMsg *msg = NULL, *quitMsg = NULL;
|
||||
|
||||
queue wq;
|
||||
queue wq;
|
||||
QUEUE_INIT(&wq);
|
||||
|
||||
static int32_t BATCH_SIZE = 5;
|
||||
int32_t count = 0;
|
||||
|
||||
taosThreadMutexLock(&item->mtx);
|
||||
httpMayDiscardMsg(http, item);
|
||||
|
||||
while (!QUEUE_IS_EMPTY(&item->qmsg) && count++ < BATCH_SIZE) {
|
||||
queue* h = QUEUE_HEAD(&item->qmsg);
|
||||
|
@ -497,9 +519,10 @@ static void transHttpDestroyHandle(void* handle) { taosMemoryFree(handle); }
|
|||
static void transHttpEnvInit() {
|
||||
httpRefMgt = taosOpenRef(1, transHttpDestroyHandle);
|
||||
|
||||
SHttpModule* http = taosMemoryMalloc(sizeof(SHttpModule));
|
||||
SHttpModule* http = taosMemoryCalloc(1, sizeof(SHttpModule));
|
||||
http->loop = taosMemoryMalloc(sizeof(uv_loop_t));
|
||||
http->connStatusTable = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_ENTRY_LOCK);
|
||||
http->quit = 0;
|
||||
|
||||
uv_loop_init(http->loop);
|
||||
|
||||
|
@ -526,6 +549,8 @@ void transHttpEnvDestroy() {
|
|||
return;
|
||||
}
|
||||
SHttpModule* load = taosAcquireRef(httpRefMgt, httpRef);
|
||||
|
||||
atomic_store_8(&load->quit, 1);
|
||||
httpSendQuit();
|
||||
taosThreadJoin(load->thread, NULL);
|
||||
|
||||
|
|
|
@ -250,6 +250,7 @@ e
|
|||
,,y,system-test,./pytest.sh python3 ./test.py -f 0-others/delete_check.py
|
||||
,,y,system-test,./pytest.sh python3 ./test.py -f 0-others/test_hot_refresh_configurations.py
|
||||
|
||||
,,y,system-test,./pytest.sh python3 ./test.py -f 1-insert/insert_double.py
|
||||
,,y,system-test,./pytest.sh python3 ./test.py -f 1-insert/alter_database.py
|
||||
,,y,system-test,./pytest.sh python3 ./test.py -f 1-insert/alter_replica.py -N 3
|
||||
,,y,system-test,./pytest.sh python3 ./test.py -f 1-insert/influxdb_line_taosc_insert.py
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
import time
|
||||
import os
|
||||
import platform
|
||||
import taos
|
||||
import threading
|
||||
from util.log import *
|
||||
from util.sql import *
|
||||
from util.cases import *
|
||||
from util.dnodes import *
|
||||
from util.common import *
|
||||
|
||||
|
||||
class TDTestCase:
|
||||
"""This test case is used to veirfy TD-25762
|
||||
"""
|
||||
def init(self, conn, logSql, replicaVar=1):
|
||||
self.replicaVar = int(replicaVar)
|
||||
tdLog.debug(f"start to excute {__file__}")
|
||||
tdSql.init(conn.cursor())
|
||||
self.db_name = "db"
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
# create same name database multiple times
|
||||
for i in range(100):
|
||||
tdLog.debug(f"round {str(i+1)} create database {self.db_name}")
|
||||
tdSql.execute(f"create database {self.db_name}")
|
||||
tdLog.debug(f"round {str(i+1)} drop database {self.db_name}")
|
||||
tdSql.execute(f"drop database {self.db_name}")
|
||||
except Exception as ex:
|
||||
tdLog.exit(str(ex))
|
||||
|
||||
def stop(self):
|
||||
tdSql.close()
|
||||
tdLog.success(f"{__file__} successfully executed")
|
||||
|
||||
tdCases.addLinux(__file__, TDTestCase())
|
||||
tdCases.addWindows(__file__, TDTestCase())
|
|
@ -0,0 +1,136 @@
|
|||
import taos
|
||||
import sys
|
||||
import datetime
|
||||
import inspect
|
||||
|
||||
from util.log import *
|
||||
from util.sql import *
|
||||
from util.cases import *
|
||||
import random
|
||||
|
||||
|
||||
class TDTestCase:
|
||||
|
||||
def init(self, conn, logSql, replicaVar=1):
|
||||
self.replicaVar = int(replicaVar)
|
||||
self.database = "db1"
|
||||
tdLog.debug(f"start to excute {__file__}")
|
||||
tdSql.init(conn.cursor(), False)
|
||||
|
||||
def prepare_db(self):
|
||||
tdSql.execute(f"drop database if exists {self.database}")
|
||||
tdSql.execute(f"create database {self.database}")
|
||||
tdSql.execute(f"use {self.database}")
|
||||
|
||||
def test_value(self, table_name, dtype, bits):
|
||||
tdSql.execute(f"drop table if exists {table_name}")
|
||||
tdSql.execute(f"create table {table_name}(ts timestamp, i1 {dtype}, i2 {dtype} unsigned)")
|
||||
|
||||
tdSql.execute(f"insert into {table_name} values(now, -16, +6)")
|
||||
tdSql.execute(f"insert into {table_name} values(now, 80.99, +0042)")
|
||||
tdSql.execute(f"insert into {table_name} values(now, -0042, +80.99)")
|
||||
tdSql.execute(f"insert into {table_name} values(now, 52.34354, 18.6)")
|
||||
tdSql.execute(f"insert into {table_name} values(now, -12., +3.)")
|
||||
tdSql.execute(f"insert into {table_name} values(now, -0.12, +3.0)")
|
||||
tdSql.execute(f"insert into {table_name} values(now, -2.3e1, +2.324e2)")
|
||||
tdSql.execute(f"insert into {table_name} values(now, -2e1, +2e2)")
|
||||
tdSql.execute(f"insert into {table_name} values(now, -2.e1, +2.e2)")
|
||||
tdSql.execute(f"insert into {table_name} values(now, -0x40, +0b10000)")
|
||||
tdSql.execute(f"insert into {table_name} values(now, -0b10000, +0x40)")
|
||||
|
||||
# str support
|
||||
tdSql.execute(f"insert into {table_name} values(now, '-16', '+6')")
|
||||
tdSql.execute(f"insert into {table_name} values(now, ' -80.99', ' +0042')")
|
||||
tdSql.execute(f"insert into {table_name} values(now, ' -0042', ' +80.99')")
|
||||
tdSql.execute(f"insert into {table_name} values(now, '52.34354', '18.6')")
|
||||
tdSql.execute(f"insert into {table_name} values(now, '-12.', '+5.')")
|
||||
tdSql.execute(f"insert into {table_name} values(now, '-.12', '+.5')")
|
||||
tdSql.execute(f"insert into {table_name} values(now, '-2.e1', '+2.e2')")
|
||||
tdSql.execute(f"insert into {table_name} values(now, '-2e1', '+2e2')")
|
||||
tdSql.execute(f"insert into {table_name} values(now, '-2.3e1', '+2.324e2')")
|
||||
tdSql.execute(f"insert into {table_name} values(now, '-0x40', '+0b10010')")
|
||||
tdSql.execute(f"insert into {table_name} values(now, '-0b10010', '+0x40')")
|
||||
|
||||
tdSql.query(f"select * from {table_name}")
|
||||
tdSql.checkRows(22)
|
||||
|
||||
baseval = 2**(bits/2)
|
||||
negval = -baseval + 1.645
|
||||
posval = baseval + 4.323
|
||||
bigval = 2**(bits-1)
|
||||
max_i = bigval - 1
|
||||
min_i = -bigval
|
||||
max_u = 2*bigval - 1
|
||||
min_u = 0
|
||||
print("val:", baseval, negval, posval, max_i)
|
||||
|
||||
tdSql.execute(f"insert into {table_name} values(now, {negval}, {posval})")
|
||||
tdSql.execute(f"insert into {table_name} values(now, -{baseval}, {baseval})")
|
||||
tdSql.execute(f"insert into {table_name} values(now, {max_i}, {max_u})")
|
||||
tdSql.execute(f"insert into {table_name} values(now, {min_i}, {min_u})")
|
||||
|
||||
tdSql.query(f"select * from {table_name}")
|
||||
tdSql.checkRows(26)
|
||||
|
||||
# error case
|
||||
tdSql.error(f"insert into {table_name} values(now, 0, {max_u+1})")
|
||||
tdSql.error(f"insert into {table_name} values(now, 0, -1)")
|
||||
tdSql.error(f"insert into {table_name} values(now, 0, -2.0)")
|
||||
tdSql.error(f"insert into {table_name} values(now, 0, '-2.0')")
|
||||
tdSql.error(f"insert into {table_name} values(now, {max_i+1}, 0)")
|
||||
tdSql.error(f"insert into {table_name} values(now, {min_i-1}, 0)")
|
||||
tdSql.error(f"insert into {table_name} values(now, '{min_i-1}', 0)")
|
||||
|
||||
def test_tags(self, stable_name, dtype, bits):
|
||||
tdSql.execute(f"create stable {stable_name}(ts timestamp, i1 {dtype}, i2 {dtype} unsigned) tags(id {dtype})")
|
||||
|
||||
baseval = 2**(bits/2)
|
||||
negval = -baseval + 1.645
|
||||
posval = baseval + 4.323
|
||||
bigval = 2**(bits-1)
|
||||
max_i = bigval - 1
|
||||
min_i = -bigval
|
||||
max_u = 2*bigval - 1
|
||||
min_u = 0
|
||||
|
||||
tdSql.execute(f"insert into {stable_name}_1 using {stable_name} tags('{negval}') values(now, {negval}, {posval})")
|
||||
tdSql.execute(f"insert into {stable_name}_2 using {stable_name} tags({posval}) values(now, -{baseval} , {baseval})")
|
||||
tdSql.execute(f"insert into {stable_name}_3 using {stable_name} tags('0x40') values(now, {max_i}, {max_u})")
|
||||
tdSql.execute(f"insert into {stable_name}_4 using {stable_name} tags(0b10000) values(now, {min_i}, {min_u})")
|
||||
|
||||
tdSql.execute(f"insert into {stable_name}_5 using {stable_name} tags({max_i}) values(now, '{negval}', '{posval}')")
|
||||
tdSql.execute(f"insert into {stable_name}_6 using {stable_name} tags('{min_i}') values(now, '-{baseval}' , '{baseval}')")
|
||||
tdSql.execute(f"insert into {stable_name}_7 using {stable_name} tags(-0x40) values(now, '{max_i}', '{max_u}')")
|
||||
tdSql.execute(f"insert into {stable_name}_8 using {stable_name} tags('-0b10000') values(now, '{min_i}', '{min_u}')")
|
||||
|
||||
tdSql.execute(f"insert into {stable_name}_9 using {stable_name} tags(12.) values(now, {negval}, {posval})")
|
||||
tdSql.execute(f"insert into {stable_name}_10 using {stable_name} tags('-8.3') values(now, -{baseval} , {baseval})")
|
||||
tdSql.execute(f"insert into {stable_name}_11 using {stable_name} tags(2.e1) values(now, {max_i}, {max_u})")
|
||||
tdSql.execute(f"insert into {stable_name}_12 using {stable_name} tags('-2.3e1') values(now, {min_i}, {min_u})")
|
||||
|
||||
tdSql.query(f"select * from {stable_name}")
|
||||
tdSql.checkRows(12)
|
||||
|
||||
def run(self): # sourcery skip: extract-duplicate-method, remove-redundant-fstring
|
||||
tdSql.prepare(replica = self.replicaVar)
|
||||
self.prepare_db()
|
||||
|
||||
self.test_value("t1", "bigint", 64)
|
||||
self.test_value("t2", "int", 32)
|
||||
self.test_value("t3", "smallint", 16)
|
||||
self.test_value("t4", "tinyint", 8)
|
||||
tdLog.printNoPrefix("==========end case1 run ...............")
|
||||
|
||||
self.test_tags("t_big", "bigint", 64)
|
||||
self.test_tags("t_int", "int", 32)
|
||||
self.test_tags("t_small", "smallint", 16)
|
||||
self.test_tags("t_tiny", "tinyint", 8)
|
||||
tdLog.printNoPrefix("==========end case2 run ...............")
|
||||
|
||||
def stop(self):
|
||||
tdSql.close()
|
||||
tdLog.success(f"{__file__} successfully executed")
|
||||
|
||||
|
||||
tdCases.addLinux(__file__, TDTestCase())
|
||||
tdCases.addWindows(__file__, TDTestCase())
|
|
@ -0,0 +1,146 @@
|
|||
import taos
|
||||
import sys
|
||||
import random
|
||||
import time
|
||||
import csv
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from util.log import *
|
||||
from util.sql import *
|
||||
from util.cases import *
|
||||
|
||||
|
||||
|
||||
class TDTestCase:
|
||||
|
||||
def init(self, conn, logSql, replicaVar=1):
|
||||
self.replicaVar = int(replicaVar)
|
||||
|
||||
self.testcasePath = os.path.split(__file__)[0]
|
||||
self.testcasefilename = os.path.split(__file__)[-1]
|
||||
self.file1 = f"{self.testcasePath}/int.csv"
|
||||
self.file2 = f"{self.testcasePath}/double.csv"
|
||||
self.file3 = f"{self.testcasePath}/d+.csv"
|
||||
self.file4 = f"{self.testcasePath}/uint.csv"
|
||||
self.ts = 1700638570000 # 2023-11-22T07:36:10.000Z
|
||||
self.database = "db1"
|
||||
self.tb1 = "t1"
|
||||
self.tb2 = "t2"
|
||||
self.tb3 = "t3"
|
||||
self.once = 1000
|
||||
tdLog.debug(f"start to excute {__file__}")
|
||||
tdSql.init(conn.cursor(), False)
|
||||
|
||||
def prepare_db(self):
|
||||
tdSql.execute(f"drop database if exists {self.database}")
|
||||
tdSql.execute(f"create database {self.database}")
|
||||
tdSql.execute(f"use {self.database}")
|
||||
tdSql.execute(f"create table {self.tb1} (ts timestamp, i0 bigint , i1 bigint, i2 bigint, i3 bigint, i4 bigint, i5 bigint, i6 bigint, i7 bigint, i8 bigint, i9 bigint)")
|
||||
tdSql.execute(f"create table {self.tb2} (ts timestamp, f0 double, f1 double, f2 double, f3 double, f4 double, f5 double, f6 double, f7 double, f8 double, f9 double)")
|
||||
tdSql.execute(f"create table {self.tb3} (ts timestamp, i0 int unsigned , i1 int unsigned, i2 int unsigned, i3 int unsigned, i4 int unsigned, i5 int unsigned, i6 int unsigned, i7 int unsigned, i8 int unsigned, i9 int unsigned)")
|
||||
|
||||
def make_csv(self, once, intype):
|
||||
filepath = self.file1
|
||||
if intype == 2:
|
||||
filepath = self.file2
|
||||
elif intype == 3:
|
||||
filepath = self.file3
|
||||
elif intype == 4:
|
||||
filepath = self.file4
|
||||
|
||||
f = open(filepath, 'w')
|
||||
with f:
|
||||
writer = csv.writer(f)
|
||||
rows = []
|
||||
for i in range(once):
|
||||
r = []
|
||||
if intype == 1:
|
||||
for k in range(10):
|
||||
r.append(random.randint(-2147483648, 2147483647))
|
||||
elif intype == 2:
|
||||
for k in range(10):
|
||||
r.append(random.randint(-2147483648, 2147483646) + random.random())
|
||||
elif intype == 3:
|
||||
for k in range(10):
|
||||
r.append(random.randint(0, 4294967294) + random.random())
|
||||
else:
|
||||
for k in range(10):
|
||||
r.append(random.randint(0, 4294967295))
|
||||
rows.append(r)
|
||||
writer.writerows(rows)
|
||||
f.close()
|
||||
print(f"{filepath} ready!")
|
||||
|
||||
def test_insert(self, tbname, qtime, startts, intype, outtype):
|
||||
filepath = self.file1
|
||||
dinfo = "int"
|
||||
if intype == 2:
|
||||
filepath = self.file2
|
||||
dinfo = "double"
|
||||
elif intype == 3:
|
||||
filepath = self.file3
|
||||
dinfo = "+double"
|
||||
elif intype == 4:
|
||||
filepath = self.file4
|
||||
dinfo = "uint"
|
||||
|
||||
f = open(filepath, 'r')
|
||||
rows = []
|
||||
with f:
|
||||
reader = csv.reader(f, delimiter=',', quotechar='|')
|
||||
for row in reader:
|
||||
rows.append(row)
|
||||
f.close()
|
||||
self.once = len(rows)
|
||||
|
||||
sum = 0
|
||||
for j in range(qtime):
|
||||
offset = j * self.once
|
||||
ts = startts + offset
|
||||
sql = f"insert into {self.database}.{tbname} values"
|
||||
for i in range(self.once):
|
||||
r = rows[i]
|
||||
sql +=f"({ts + i},'{r[0]}','{r[1]}','{r[2]}','{r[3]}','{r[4]}','{r[5]}','{r[6]}','{r[7]}','{r[8]}','{r[9]}')"
|
||||
|
||||
t1 = time.time()
|
||||
tdSql.execute(f"{sql};", 1)
|
||||
t2 = time.time()
|
||||
#print(f"{t2} insert test {j}.")
|
||||
#print(sql)
|
||||
sum += t2 - t1
|
||||
|
||||
sum = sum
|
||||
tbinfo = "10 bigint col/per row"
|
||||
if outtype == 2:
|
||||
tbinfo = "10 double col/per row"
|
||||
elif outtype == 3:
|
||||
tbinfo = "10 uint col/per row"
|
||||
print(f" insert {self.once} * {qtime} rows: {sum} s, {dinfo} -> {tbinfo}")
|
||||
|
||||
# tdSql.query(f"select count(*) from {self.database}.{tbname};")
|
||||
# tdSql.checkData(0, 0, once*qtime)
|
||||
|
||||
def run(self):
|
||||
tdSql.prepare(replica = self.replicaVar)
|
||||
# self.make_csv(self.once, 1)
|
||||
# self.make_csv(self.once, 2)
|
||||
# self.make_csv(self.once, 3)
|
||||
# self.make_csv(self.once, 4)
|
||||
|
||||
self.prepare_db()
|
||||
self.test_insert(self.tb1, 1000, self.ts-10000000, 1, 1)
|
||||
self.test_insert(self.tb2, 1000, self.ts-10000000, 2, 2)
|
||||
self.test_insert(self.tb3, 1000, self.ts-10000000, 4, 3)
|
||||
self.test_insert(self.tb2, 1000, self.ts, 1, 2)
|
||||
|
||||
self.test_insert(self.tb1, 1000, self.ts, 2, 1)
|
||||
self.test_insert(self.tb3, 1000, self.ts, 3, 3)
|
||||
|
||||
def stop(self):
|
||||
tdSql.close()
|
||||
tdLog.success(f"{__file__} successfully executed")
|
||||
|
||||
|
||||
tdCases.addLinux(__file__, TDTestCase())
|
||||
tdCases.addWindows(__file__, TDTestCase())
|
|
@ -36,7 +36,21 @@ class TDTestCase:
|
|||
buildPath = tdCom.getBuildPath()
|
||||
cmdStr = '%s/build/bin/write_raw_block_test'%(buildPath)
|
||||
tdLog.info(cmdStr)
|
||||
os.system(cmdStr)
|
||||
retCode = os.system(cmdStr)
|
||||
# run program code from system return , 0 is success
|
||||
runCode = retCode & 0xFF
|
||||
# program retur code from main function
|
||||
progCode = retCode >> 8
|
||||
|
||||
tdLog.info(f"{cmdStr} ret={retCode} runCode={runCode} progCode={progCode}")
|
||||
|
||||
if runCode != 0:
|
||||
tdLog.exit(f"run {cmdStr} failed, have system error.")
|
||||
return
|
||||
|
||||
if progCode != 0:
|
||||
tdLog.exit(f"{cmdStr} found problem, return code = {progCode}.")
|
||||
return
|
||||
|
||||
self.checkData()
|
||||
|
||||
|
|
|
@ -79,7 +79,8 @@ else
|
|||
|
||||
unset LD_PRELOAD
|
||||
#export LD_PRELOAD=libasan.so.5
|
||||
export LD_PRELOAD=$(gcc -print-file-name=libasan.so)
|
||||
#export LD_PRELOAD=$(gcc -print-file-name=libasan.so)
|
||||
export LD_PRELOAD="$(realpath "$(gcc -print-file-name=libasan.so)") $(realpath "$(gcc -print-file-name=libstdc++.so)")"
|
||||
echo "Preload AsanSo:" $?
|
||||
|
||||
$* -a 2>$AsanFile
|
||||
|
@ -104,4 +105,4 @@ else
|
|||
echo "Execute script failure"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
|
|
@ -1091,7 +1091,12 @@ void shellSourceFile(const char *file) {
|
|||
|
||||
char *line = taosMemoryMalloc(TSDB_MAX_ALLOWED_SQL_LEN + 1);
|
||||
while ((read_len = taosGetsFile(pFile, TSDB_MAX_ALLOWED_SQL_LEN, line)) != -1) {
|
||||
if (read_len >= TSDB_MAX_ALLOWED_SQL_LEN) continue;
|
||||
if ( cmd_len + read_len >= TSDB_MAX_ALLOWED_SQL_LEN) {
|
||||
printf("read command line too long over 1M, ignore this line. cmd_len = %d read_len=%d \n", (int32_t)cmd_len, read_len);
|
||||
cmd_len = 0;
|
||||
memset(line, 0, TSDB_MAX_ALLOWED_SQL_LEN + 1);
|
||||
continue;
|
||||
}
|
||||
line[--read_len] = '\0';
|
||||
|
||||
if (read_len == 0 || shellIsCommentLine(line)) { // line starts with #
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
#include "taos.h"
|
||||
#include "types.h"
|
||||
|
||||
int buildStable(TAOS* pConn, TAOS_RES* pRes) {
|
||||
pRes = taos_query(pConn,
|
||||
int buildStable(TAOS* pConn) {
|
||||
TAOS_RES* pRes = taos_query(pConn,
|
||||
"CREATE STABLE `meters` (`ts` TIMESTAMP, `current` INT, `voltage` INT, `phase` FLOAT) TAGS "
|
||||
"(`groupid` INT, `location` VARCHAR(16))");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
|
@ -57,6 +57,34 @@ int buildStable(TAOS* pConn, TAOS_RES* pRes) {
|
|||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
pRes = taos_query(pConn, "create table ntba(ts timestamp, addr binary(32))");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("failed to create ntba, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
pRes = taos_query(pConn, "create table ntbb(ts timestamp, addr binary(8))");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("failed to create ntbb, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
pRes = taos_query(pConn, "insert into ntba values(now,'123456789abcdefg123456789')");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("failed to insert table ntba, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
pRes = taos_query(pConn, "insert into ntba values(now,'hello')");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("failed to insert table ntba, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -65,40 +93,43 @@ int32_t init_env() {
|
|||
if (pConn == NULL) {
|
||||
return -1;
|
||||
}
|
||||
int32_t ret = -1;
|
||||
|
||||
TAOS_RES* pRes = taos_query(pConn, "drop database if exists db_raw");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("error in drop db_taosx, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
goto END;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
pRes = taos_query(pConn, "create database if not exists db_raw vgroups 2");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("error in create db_taosx, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
goto END;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
pRes = taos_query(pConn, "use db_raw");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("error in create db_taosx, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
goto END;
|
||||
}
|
||||
taos_free_result(pRes);
|
||||
|
||||
buildStable(pConn, pRes);
|
||||
buildStable(pConn);
|
||||
|
||||
pRes = taos_query(pConn, "select * from d0");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("error in drop db_taosx, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
goto END;
|
||||
}
|
||||
void *data = NULL;
|
||||
int32_t numOfRows = 0;
|
||||
int error_code = taos_fetch_raw_block(pRes, &numOfRows, &data);
|
||||
ASSERT(error_code == 0);
|
||||
ASSERT(numOfRows == 1);
|
||||
if(error_code !=0 ){
|
||||
printf("error fetch raw block, reason:%s\n", taos_errstr(pRes));
|
||||
goto END;
|
||||
}
|
||||
|
||||
taos_write_raw_block(pConn, numOfRows, data, "d1");
|
||||
taos_free_result(pRes);
|
||||
|
@ -106,23 +137,78 @@ int32_t init_env() {
|
|||
pRes = taos_query(pConn, "select ts,phase from d0");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("error in drop db_taosx, reason:%s\n", taos_errstr(pRes));
|
||||
return -1;
|
||||
goto END;
|
||||
}
|
||||
error_code = taos_fetch_raw_block(pRes, &numOfRows, &data);
|
||||
ASSERT(error_code == 0);
|
||||
ASSERT(numOfRows == 1);
|
||||
if(error_code !=0 ){
|
||||
printf("error fetch raw block, reason:%s\n", taos_errstr(pRes));
|
||||
goto END;
|
||||
}
|
||||
|
||||
int numFields = taos_num_fields(pRes);
|
||||
TAOS_FIELD *fields = taos_fetch_fields(pRes);
|
||||
taos_write_raw_block_with_fields(pConn, numOfRows, data, "d2", fields, numFields);
|
||||
taos_free_result(pRes);
|
||||
|
||||
taos_close(pConn);
|
||||
return 0;
|
||||
// check error msg
|
||||
pRes = taos_query(pConn, "select * from ntba");
|
||||
if (taos_errno(pRes) != 0) {
|
||||
printf("error select * from ntba, reason:%s\n", taos_errstr(pRes));
|
||||
goto END;
|
||||
}
|
||||
|
||||
data = NULL;
|
||||
numOfRows = 0;
|
||||
error_code = taos_fetch_raw_block(pRes, &numOfRows, &data);
|
||||
if(error_code !=0 ){
|
||||
printf("error fetch select * from ntba, reason:%s\n", taos_errstr(pRes));
|
||||
goto END;
|
||||
}
|
||||
error_code = taos_write_raw_block(pConn, numOfRows, data, "ntbb");
|
||||
if(error_code == 0) {
|
||||
printf(" taos_write_raw_block to ntbb expect failed , but success!\n");
|
||||
goto END;
|
||||
}
|
||||
|
||||
// pass NULL return last error code describe
|
||||
const char* err = taos_errstr(NULL);
|
||||
printf("write_raw_block return code =0x%x err=%s\n", error_code, err);
|
||||
if(strcmp(err, "success") == 0) {
|
||||
printf("expect failed , but error string is success! err=%s\n", err);
|
||||
goto END;
|
||||
}
|
||||
|
||||
// no exist table
|
||||
error_code = taos_write_raw_block(pConn, numOfRows, data, "no-exist-table");
|
||||
if(error_code == 0) {
|
||||
printf(" taos_write_raw_block to no-exist-table expect failed , but success!\n");
|
||||
goto END;
|
||||
}
|
||||
|
||||
err = taos_errstr(NULL);
|
||||
printf("write_raw_block no exist table return code =0x%x err=%s\n", error_code, err);
|
||||
if(strcmp(err, "success") == 0) {
|
||||
printf("expect failed write no exist table, but error string is success! err=%s\n", err);
|
||||
goto END;
|
||||
}
|
||||
|
||||
// success
|
||||
ret = 0;
|
||||
|
||||
END:
|
||||
// free
|
||||
if(pRes) taos_free_result(pRes);
|
||||
if(pConn) taos_close(pConn);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
if (init_env() < 0) {
|
||||
return -1;
|
||||
printf("test write_raw_block...\n");
|
||||
int ret = init_env();
|
||||
if (ret < 0) {
|
||||
printf("test write_raw_block failed.\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
printf("test write_raw_block ok.\n");
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue