diff --git a/docs/en/07-develop/07-tmq.mdx b/docs/en/07-develop/07-tmq.mdx
index 7465cc0a12..739eabd1cf 100644
--- a/docs/en/07-develop/07-tmq.mdx
+++ b/docs/en/07-develop/07-tmq.mdx
@@ -222,7 +222,7 @@ A database including one supertable and two subtables is created as follows:
```sql
DROP DATABASE IF EXISTS tmqdb;
-CREATE DATABASE tmqdb;
+CREATE DATABASE tmqdb WAL_RETENTION_PERIOD 3600;
CREATE TABLE tmqdb.stb (ts TIMESTAMP, c1 INT, c2 FLOAT, c3 VARCHAR(16)) TAGS(t1 INT, t3 VARCHAR(16));
CREATE TABLE tmqdb.ctb0 USING tmqdb.stb TAGS(0, "subtable0");
CREATE TABLE tmqdb.ctb1 USING tmqdb.stb TAGS(1, "subtable1");
diff --git a/docs/en/14-reference/03-connector/index.mdx b/docs/en/14-reference/03-connector/index.mdx
index a35d5bc2d1..28b7b83b58 100644
--- a/docs/en/14-reference/03-connector/index.mdx
+++ b/docs/en/14-reference/03-connector/index.mdx
@@ -62,7 +62,7 @@ The different database framework specifications for various programming language
| **Regular Query** | Support | Support | Support | Support | Support | Support |
| **Parameter Binding** | Not Supported | Not Supported | Support | Support | Not Supported | Support |
| **Subscription (TMQ) ** | Supported | Support | Support | Not Supported | Not Supported | Support |
-| **Schemaless** | Not Supported | Not Supported | Not Supported | Not Supported | Not Supported | Not Supported |
+| **Schemaless** | Supported | Not Supported | Not Supported | Not Supported | Not Supported | Not Supported |
| **Bulk Pulling (based on WebSocket) ** | Support | Support | Support | Support | Support | Support |
| **DataFrame** | Not Supported | Support | Not Supported | Not Supported | Not Supported | Not Supported |
diff --git a/docs/en/14-reference/14-taosKeeper.md b/docs/en/14-reference/14-taosKeeper.md
index 9c4a2da921..cfc2554387 100644
--- a/docs/en/14-reference/14-taosKeeper.md
+++ b/docs/en/14-reference/14-taosKeeper.md
@@ -223,3 +223,29 @@ Content-Length: 19
{"version":"1.0.0"}
```
+
+### taoskeeper with Prometheus
+
+There is `/metrics` api in taoskeeper provide TDengine metric data for Prometheus.
+
+#### scrape config
+
+Scrape config in Prometheus specifies a set of targets and parameters describing how to scrape metric data from endpoint. For more information, please reference to [Prometheus documents](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#scrape_config).
+
+```
+# A scrape configuration containing exactly one endpoint to scrape:
+# Here it's Prometheus itself.
+scrape_configs:
+ - job_name: "taoskeeper"
+ # metrics_path defaults to '/metrics'
+ # scheme defaults to 'http'.
+ static_configs:
+ - targets: ["localhost:6043"]
+```
+
+#### Dashboard
+
+There is a dashboard named `TaosKeeper Prometheus Dashboard for 3.x`, which provides a monitoring dashboard similar to TInsight.
+
+In Grafana, click the Dashboard menu and click `import`, enter the dashboard ID `18587` and click the `Load` button. Then finished importing `TaosKeeper Prometheus Dashboard for 3.x` dashboard.
+
diff --git a/docs/zh/07-develop/07-tmq.mdx b/docs/zh/07-develop/07-tmq.mdx
index 036c9aa86e..a3833438a2 100644
--- a/docs/zh/07-develop/07-tmq.mdx
+++ b/docs/zh/07-develop/07-tmq.mdx
@@ -221,7 +221,7 @@ void Close()
```sql
DROP DATABASE IF EXISTS tmqdb;
-CREATE DATABASE tmqdb;
+CREATE DATABASE tmqdb WAL_RETENTION_PERIOD 3600;
CREATE TABLE tmqdb.stb (ts TIMESTAMP, c1 INT, c2 FLOAT, c3 VARCHAR(16)) TAGS(t1 INT, t3 VARCHAR(16));
CREATE TABLE tmqdb.ctb0 USING tmqdb.stb TAGS(0, "subtable0");
CREATE TABLE tmqdb.ctb1 USING tmqdb.stb TAGS(1, "subtable1");
diff --git a/docs/zh/08-connector/index.md b/docs/zh/08-connector/index.md
index eb1f3a9a9a..bb8c95a15a 100644
--- a/docs/zh/08-connector/index.md
+++ b/docs/zh/08-connector/index.md
@@ -61,7 +61,7 @@ TDengine 版本更新往往会增加新的功能特性,列表中的连接器
| **普通查询** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |
| **参数绑定** | 暂不支持 | 暂不支持 | 支持 | 支持 | 暂不支持 | 支持 |
| **数据订阅(TMQ)** | 支持 | 支持 | 支持 | 暂不支持 | 暂不支持 | 支持 |
-| **Schemaless** | 暂不支持 | 暂不支持 | 暂不支持 | 暂不支持 | 暂不支持 | 暂不支持 |
+| **Schemaless** | 支持 | 暂不支持 | 暂不支持 | 暂不支持 | 暂不支持 | 暂不支持 |
| **批量拉取(基于 WebSocket)** | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |
| **DataFrame** | 不支持 | 支持 | 不支持 | 不支持 | 不支持 | 不支持 |
diff --git a/docs/zh/12-taos-sql/14-stream.md b/docs/zh/12-taos-sql/14-stream.md
index 12e466f349..b08804e5c4 100644
--- a/docs/zh/12-taos-sql/14-stream.md
+++ b/docs/zh/12-taos-sql/14-stream.md
@@ -213,3 +213,29 @@ DELETE_MARK time
```
DELETE_MARK用于删除缓存的窗口状态,也就是删除流计算的中间结果。如果不设置,默认值是10年
T = 最新事件时间 - DELETE_MARK
+
+## 流式计算支持的函数
+
+1. 所有的 [单行函数](../function/#单行函数) 均可用于流计算。
+2. 以下 19 个聚合/选择函数 不能 应用在创建流计算的 SQL 语句,[系统信息函数](../function/#系统信息函数) 也不能用于流计算中。此外的其他类型的函数均可用于流计算。
+
+- [leastsquares](../function/#leastsquares)
+- [percentile](../function/#percentile)
+- [top](../function/#leastsquares)
+- [bottom](../function/#top)
+- [elapsed](../function/#leastsquares)
+- [interp](../function/#elapsed)
+- [derivative](../function/#derivative)
+- [irate](../function/#irate)
+- [twa](../function/#twa)
+- [histogram](../function/#histogram)
+- [diff](../function/#diff)
+- [statecount](../function/#statecount)
+- [stateduration](../function/#stateduration)
+- [csum](../function/#csum)
+- [mavg](../function/#mavg)
+- [sample](../function/#sample)
+- [tail](../function/#tail)
+- [unique](../function/#unique)
+- [mode](../function/#mode)
+
diff --git a/docs/zh/14-reference/14-taosKeeper.md b/docs/zh/14-reference/14-taosKeeper.md
index 03ca30781f..b4d35fb240 100644
--- a/docs/zh/14-reference/14-taosKeeper.md
+++ b/docs/zh/14-reference/14-taosKeeper.md
@@ -226,3 +226,29 @@ Content-Length: 19
{"version":"1.0.0"}
```
+
+### 集成 Prometheus
+
+taoskeeper 提供了 `/metrics` 接口,返回了 Prometheus 格式的监控数据,Prometheus 可以从 taoskeeper 抽取监控数据,实现通过 Prometheus 监控 TDengine 的目的。
+
+#### 抽取配置
+
+Prometheus 提供了 `scrape_configs` 配置如何从 endpoint 抽取监控数据,通常只需要修改 `static_configs` 中的 targets 配置为 taoskeeper 的 endpoint 地址,更多配置信息请参考 [Prometheus 配置文档](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#scrape_config)。
+
+```
+# A scrape configuration containing exactly one endpoint to scrape:
+# Here it's Prometheus itself.
+scrape_configs:
+ - job_name: "taoskeeper"
+ # metrics_path defaults to '/metrics'
+ # scheme defaults to 'http'.
+ static_configs:
+ - targets: ["localhost:6043"]
+```
+
+#### Dashboard
+
+我们提供了 `TaosKeeper Prometheus Dashboard for 3.x` dashboard,提供了和 TDinsight 类似的监控 dashboard。
+
+在 Grafana Dashboard 菜单点击 `import`,dashboard ID 填写 `18587`,点击 `Load` 按钮即可导入 `TaosKeeper Prometheus Dashboard for 3.x` dashboard。
+
diff --git a/examples/c/tmq.c b/examples/c/tmq.c
index 83b40c4f20..94545dfaad 100644
--- a/examples/c/tmq.c
+++ b/examples/c/tmq.c
@@ -20,7 +20,8 @@
#include
#include "taos.h"
-static int running = 1;
+static int running = 1;
+const char* topic_name = "topicname";
static int32_t msg_process(TAOS_RES* msg) {
char buf[1024];
@@ -243,7 +244,7 @@ _end:
tmq_list_t* build_topic_list() {
tmq_list_t* topicList = tmq_list_new();
- int32_t code = tmq_list_append(topicList, "topicname");
+ int32_t code = tmq_list_append(topicList, topic_name);
if (code) {
tmq_list_destroy(topicList);
return NULL;
@@ -269,6 +270,31 @@ void basic_consume_loop(tmq_t* tmq) {
fprintf(stderr, "%d msg consumed, include %d rows\n", msgCnt, totalRows);
}
+void consume_repeatly(tmq_t* tmq) {
+ int32_t numOfAssignment = 0;
+ tmq_topic_assignment* pAssign = NULL;
+
+ int32_t code = tmq_get_topic_assignment(tmq, topic_name, &pAssign, &numOfAssignment);
+ if (code != 0) {
+ fprintf(stderr, "failed to get assignment, reason:%s", tmq_err2str(code));
+ }
+
+ // seek to the earliest offset
+ for(int32_t i = 0; i < numOfAssignment; ++i) {
+ tmq_topic_assignment* p = &pAssign[i];
+
+ code = tmq_offset_seek(tmq, topic_name, p->vgId, p->begin);
+ if (code != 0) {
+ fprintf(stderr, "failed to seek to %ld, reason:%s", p->begin, tmq_err2str(code));
+ }
+ }
+
+ free(pAssign);
+
+ // let's do it again
+ basic_consume_loop(tmq);
+}
+
int main(int argc, char* argv[]) {
int32_t code;
@@ -294,10 +320,13 @@ int main(int argc, char* argv[]) {
if ((code = tmq_subscribe(tmq, topic_list))) {
fprintf(stderr, "Failed to tmq_subscribe(): %s\n", tmq_err2str(code));
}
+
tmq_list_destroy(topic_list);
basic_consume_loop(tmq);
+ consume_repeatly(tmq);
+
code = tmq_consumer_close(tmq);
if (code) {
fprintf(stderr, "Failed to close consumer: %s\n", tmq_err2str(code));
diff --git a/include/client/taos.h b/include/client/taos.h
index cf410a42da..44703c2797 100644
--- a/include/client/taos.h
+++ b/include/client/taos.h
@@ -101,6 +101,7 @@ typedef struct TAOS_FIELD_E {
#endif
typedef void (*__taos_async_fn_t)(void *param, TAOS_RES *res, int code);
+typedef void (*__taos_notify_fn_t)(void *param, void *ext, int type);
typedef struct TAOS_MULTI_BIND {
int buffer_type;
@@ -121,6 +122,10 @@ typedef enum {
SET_CONF_RET_ERR_TOO_LONG = -6
} SET_CONF_RET_CODE;
+typedef enum {
+ TAOS_NOTIFY_PASSVER = 0,
+} TAOS_NOTIFY_TYPE;
+
#define RET_MSG_LENGTH 1024
typedef struct setConfRet {
SET_CONF_RET_CODE retCode;
@@ -225,6 +230,8 @@ DLL_EXPORT int taos_get_tables_vgId(TAOS *taos, const char *db, const char *tabl
DLL_EXPORT int taos_load_table_info(TAOS *taos, const char *tableNameList);
+DLL_EXPORT int taos_set_notify_cb(TAOS *taos, __taos_notify_fn_t fp, void *param, int type);
+
/* --------------------------schemaless INTERFACE------------------------------- */
DLL_EXPORT TAOS_RES *taos_schemaless_insert(TAOS *taos, char *lines[], int numLines, int protocol, int precision);
@@ -262,6 +269,12 @@ DLL_EXPORT tmq_t *tmq_consumer_new(tmq_conf_t *conf, char *errstr, int32_t errst
DLL_EXPORT const char *tmq_err2str(int32_t code);
/* ------------------------TMQ CONSUMER INTERFACE------------------------ */
+typedef struct tmq_topic_assignment {
+ int32_t vgId;
+ int64_t currentOffset;
+ int64_t begin;
+ int64_t end;
+} tmq_topic_assignment;
DLL_EXPORT int32_t tmq_subscribe(tmq_t *tmq, const tmq_list_t *topic_list);
DLL_EXPORT int32_t tmq_unsubscribe(tmq_t *tmq);
@@ -270,6 +283,8 @@ DLL_EXPORT TAOS_RES *tmq_consumer_poll(tmq_t *tmq, int64_t timeout);
DLL_EXPORT int32_t tmq_consumer_close(tmq_t *tmq);
DLL_EXPORT int32_t tmq_commit_sync(tmq_t *tmq, const TAOS_RES *msg);
DLL_EXPORT void tmq_commit_async(tmq_t *tmq, const TAOS_RES *msg, tmq_commit_cb *cb, void *param);
+DLL_EXPORT int32_t tmq_get_topic_assignment(tmq_t *tmq, const char* pTopicName, tmq_topic_assignment **assignment, int32_t *numOfAssignment);
+DLL_EXPORT int32_t tmq_offset_seek(tmq_t *tmq, const char* pTopicName, int32_t vgId, int64_t offset);
/* ----------------------TMQ CONFIGURATION INTERFACE---------------------- */
diff --git a/include/common/tcommon.h b/include/common/tcommon.h
index a97c68be49..3d0dac7c3d 100644
--- a/include/common/tcommon.h
+++ b/include/common/tcommon.h
@@ -128,6 +128,7 @@ enum {
TMQ_MSG_TYPE__POLL_META_RSP,
TMQ_MSG_TYPE__EP_RSP,
TMQ_MSG_TYPE__TAOSX_RSP,
+ TMQ_MSG_TYPE__WALINFO_RSP,
TMQ_MSG_TYPE__END_RSP,
};
diff --git a/include/common/tglobal.h b/include/common/tglobal.h
index 6fde7b48a2..25a386b23d 100644
--- a/include/common/tglobal.h
+++ b/include/common/tglobal.h
@@ -24,6 +24,12 @@
extern "C" {
#endif
+#define SLOW_LOG_TYPE_QUERY 0x1
+#define SLOW_LOG_TYPE_INSERT 0x2
+#define SLOW_LOG_TYPE_OTHERS 0x4
+#define SLOW_LOG_TYPE_ALL 0xFFFFFFFF
+
+
// cluster
extern char tsFirst[];
extern char tsSecond[];
@@ -118,6 +124,8 @@ extern int32_t tsRedirectFactor;
extern int32_t tsRedirectMaxPeriod;
extern int32_t tsMaxRetryWaitTime;
extern bool tsUseAdapter;
+extern int32_t tsSlowLogThreshold;
+extern int32_t tsSlowLogScope;
// client
extern int32_t tsMinSlidingTime;
diff --git a/include/common/tmsg.h b/include/common/tmsg.h
index 4a1d8d71f1..f377ad0d63 100644
--- a/include/common/tmsg.h
+++ b/include/common/tmsg.h
@@ -106,6 +106,7 @@ enum {
HEARTBEAT_KEY_DBINFO,
HEARTBEAT_KEY_STBINFO,
HEARTBEAT_KEY_TMQ,
+ HEARTBEAT_KEY_USER_PASSINFO,
};
typedef enum _mgmt_table {
@@ -634,6 +635,7 @@ typedef struct {
int8_t connType;
SEpSet epSet;
int32_t svrTimestamp;
+ int32_t passVer;
char sVer[TSDB_VERSION_LEN];
char sDetailVer[128];
} SConnectRsp;
@@ -716,6 +718,14 @@ int32_t tSerializeSGetUserAuthRsp(void* buf, int32_t bufLen, SGetUserAuthRsp* pR
int32_t tDeserializeSGetUserAuthRsp(void* buf, int32_t bufLen, SGetUserAuthRsp* pRsp);
void tFreeSGetUserAuthRsp(SGetUserAuthRsp* pRsp);
+typedef struct SUserPassVersion {
+ char user[TSDB_USER_LEN];
+ int32_t version;
+} SUserPassVersion;
+
+typedef SGetUserAuthReq SGetUserPassReq;
+typedef SUserPassVersion SGetUserPassRsp;
+
/*
* for client side struct, only column id, type, bytes are necessary
* But for data in vnode side, we need all the following information.
@@ -1046,6 +1056,14 @@ int32_t tSerializeSUserAuthBatchRsp(void* buf, int32_t bufLen, SUserAuthBatchRsp
int32_t tDeserializeSUserAuthBatchRsp(void* buf, int32_t bufLen, SUserAuthBatchRsp* pRsp);
void tFreeSUserAuthBatchRsp(SUserAuthBatchRsp* pRsp);
+typedef struct {
+ SArray* pArray; // Array of SGetUserPassRsp
+} SUserPassBatchRsp;
+
+int32_t tSerializeSUserPassBatchRsp(void* buf, int32_t bufLen, SUserPassBatchRsp* pRsp);
+int32_t tDeserializeSUserPassBatchRsp(void* buf, int32_t bufLen, SUserPassBatchRsp* pRsp);
+void tFreeSUserPassBatchRsp(SUserPassBatchRsp* pRsp);
+
typedef struct {
char db[TSDB_DB_FNAME_LEN];
STimeWindow timeRange;
@@ -2814,6 +2832,7 @@ typedef struct {
} SMqOffset;
typedef struct {
+ int64_t consumerId;
int32_t num;
SMqOffset* offsets;
} SMqCMCommitOffsetReq;
@@ -2881,6 +2900,14 @@ typedef struct {
int32_t tEncodeSTqOffset(SEncoder* pEncoder, const STqOffset* pOffset);
int32_t tDecodeSTqOffset(SDecoder* pDecoder, STqOffset* pOffset);
+typedef struct SMqVgOffset {
+ int64_t consumerId;
+ STqOffset offset;
+} SMqVgOffset;
+
+int32_t tEncodeMqVgOffset(SEncoder* pEncoder, const SMqVgOffset* pOffset);
+int32_t tDecodeMqVgOffset(SDecoder* pDecoder, SMqVgOffset* pOffset);
+
typedef struct {
char name[TSDB_TABLE_FNAME_LEN];
char stb[TSDB_TABLE_FNAME_LEN];
@@ -3110,18 +3137,19 @@ typedef struct {
int32_t code;
int32_t epoch;
int64_t consumerId;
+ int64_t walsver;
+ int64_t walever;
} SMqRspHead;
typedef struct {
- SMsgHead head;
- char subKey[TSDB_SUBSCRIBE_KEY_LEN];
- int8_t withTbName;
- int8_t useSnapshot;
- int32_t epoch;
- uint64_t reqId;
- int64_t consumerId;
- int64_t timeout;
- // int64_t currentOffset;
+ SMsgHead head;
+ char subKey[TSDB_SUBSCRIBE_KEY_LEN];
+ int8_t withTbName;
+ int8_t useSnapshot;
+ int32_t epoch;
+ uint64_t reqId;
+ int64_t consumerId;
+ int64_t timeout;
STqOffsetVal reqOffset;
} SMqPollReq;
@@ -3156,43 +3184,9 @@ typedef struct {
SSchemaWrapper schema;
} SMqSubTopicEp;
-static FORCE_INLINE int32_t tEncodeSMqSubTopicEp(void** buf, const SMqSubTopicEp* pTopicEp) {
- int32_t tlen = 0;
- tlen += taosEncodeString(buf, pTopicEp->topic);
- tlen += taosEncodeString(buf, pTopicEp->db);
- int32_t sz = taosArrayGetSize(pTopicEp->vgs);
- tlen += taosEncodeFixedI32(buf, sz);
- for (int32_t i = 0; i < sz; i++) {
- SMqSubVgEp* pVgEp = (SMqSubVgEp*)taosArrayGet(pTopicEp->vgs, i);
- tlen += tEncodeSMqSubVgEp(buf, pVgEp);
- }
- tlen += taosEncodeSSchemaWrapper(buf, &pTopicEp->schema);
- return tlen;
-}
-
-static FORCE_INLINE void* tDecodeSMqSubTopicEp(void* buf, SMqSubTopicEp* pTopicEp) {
- buf = taosDecodeStringTo(buf, pTopicEp->topic);
- buf = taosDecodeStringTo(buf, pTopicEp->db);
- int32_t sz;
- buf = taosDecodeFixedI32(buf, &sz);
- pTopicEp->vgs = taosArrayInit(sz, sizeof(SMqSubVgEp));
- if (pTopicEp->vgs == NULL) {
- return NULL;
- }
- for (int32_t i = 0; i < sz; i++) {
- SMqSubVgEp vgEp;
- buf = tDecodeSMqSubVgEp(buf, &vgEp);
- taosArrayPush(pTopicEp->vgs, &vgEp);
- }
- buf = taosDecodeSSchemaWrapper(buf, &pTopicEp->schema);
- return buf;
-}
-
-static FORCE_INLINE void tDeleteSMqSubTopicEp(SMqSubTopicEp* pSubTopicEp) {
- taosMemoryFreeClear(pSubTopicEp->schema.pSchema);
- pSubTopicEp->schema.nCols = 0;
- taosArrayDestroy(pSubTopicEp->vgs);
-}
+int32_t tEncodeMqSubTopicEp(void** buf, const SMqSubTopicEp* pTopicEp);
+void* tDecodeMqSubTopicEp(void* buf, SMqSubTopicEp* pTopicEp);
+void tDeleteMqSubTopicEp(SMqSubTopicEp* pSubTopicEp);
typedef struct {
SMqRspHead head;
@@ -3202,8 +3196,8 @@ typedef struct {
void* metaRsp;
} SMqMetaRsp;
-int32_t tEncodeSMqMetaRsp(SEncoder* pEncoder, const SMqMetaRsp* pRsp);
-int32_t tDecodeSMqMetaRsp(SDecoder* pDecoder, SMqMetaRsp* pRsp);
+int32_t tEncodeMqMetaRsp(SEncoder* pEncoder, const SMqMetaRsp* pRsp);
+int32_t tDecodeMqMetaRsp(SDecoder* pDecoder, SMqMetaRsp* pRsp);
typedef struct {
SMqRspHead head;
@@ -3218,9 +3212,9 @@ typedef struct {
SArray* blockSchema;
} SMqDataRsp;
-int32_t tEncodeSMqDataRsp(SEncoder* pEncoder, const SMqDataRsp* pRsp);
-int32_t tDecodeSMqDataRsp(SDecoder* pDecoder, SMqDataRsp* pRsp);
-void tDeleteSMqDataRsp(SMqDataRsp* pRsp);
+int32_t tEncodeMqDataRsp(SEncoder* pEncoder, const SMqDataRsp* pRsp);
+int32_t tDecodeMqDataRsp(SDecoder* pDecoder, SMqDataRsp* pRsp);
+void tDeleteMqDataRsp(SMqDataRsp* pRsp);
typedef struct {
SMqRspHead head;
@@ -3256,7 +3250,7 @@ static FORCE_INLINE int32_t tEncodeSMqAskEpRsp(void** buf, const SMqAskEpRsp* pR
tlen += taosEncodeFixedI32(buf, sz);
for (int32_t i = 0; i < sz; i++) {
SMqSubTopicEp* pVgEp = (SMqSubTopicEp*)taosArrayGet(pRsp->topics, i);
- tlen += tEncodeSMqSubTopicEp(buf, pVgEp);
+ tlen += tEncodeMqSubTopicEp(buf, pVgEp);
}
return tlen;
}
@@ -3271,14 +3265,14 @@ static FORCE_INLINE void* tDecodeSMqAskEpRsp(void* buf, SMqAskEpRsp* pRsp) {
}
for (int32_t i = 0; i < sz; i++) {
SMqSubTopicEp topicEp;
- buf = tDecodeSMqSubTopicEp(buf, &topicEp);
+ buf = tDecodeMqSubTopicEp(buf, &topicEp);
taosArrayPush(pRsp->topics, &topicEp);
}
return buf;
}
static FORCE_INLINE void tDeleteSMqAskEpRsp(SMqAskEpRsp* pRsp) {
- taosArrayDestroyEx(pRsp->topics, (FDelete)tDeleteSMqSubTopicEp);
+ taosArrayDestroyEx(pRsp->topics, (FDelete)tDeleteMqSubTopicEp);
}
#define TD_AUTO_CREATE_TABLE 0x1
diff --git a/include/common/tmsgdef.h b/include/common/tmsgdef.h
index 9dca9ea322..ffad6f6646 100644
--- a/include/common/tmsgdef.h
+++ b/include/common/tmsgdef.h
@@ -302,9 +302,11 @@ enum {
TD_DEF_MSG_TYPE(TDMT_VND_TMQ_SUBSCRIBE, "vnode-tmq-subscribe", SMqRebVgReq, SMqRebVgRsp)
TD_DEF_MSG_TYPE(TDMT_VND_TMQ_DELETE_SUB, "vnode-tmq-delete-sub", SMqVDeleteReq, SMqVDeleteRsp)
TD_DEF_MSG_TYPE(TDMT_VND_TMQ_COMMIT_OFFSET, "vnode-tmq-commit-offset", STqOffset, STqOffset)
+ TD_DEF_MSG_TYPE(TDMT_VND_TMQ_SEEK_TO_OFFSET, "vnode-tmq-seekto-offset", STqOffset, STqOffset)
TD_DEF_MSG_TYPE(TDMT_VND_TMQ_ADD_CHECKINFO, "vnode-tmq-add-checkinfo", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_VND_TMQ_DEL_CHECKINFO, "vnode-del-checkinfo", NULL, NULL)
TD_DEF_MSG_TYPE(TDMT_VND_TMQ_CONSUME, "vnode-tmq-consume", SMqPollReq, SMqDataBlkRsp)
+ TD_DEF_MSG_TYPE(TDMT_VND_TMQ_VG_WALINFO, "vnode-tmq-vg-walinfo", SMqPollReq, SMqDataBlkRsp)
TD_DEF_MSG_TYPE(TDMT_VND_TMQ_MAX_MSG, "vnd-tmq-max", NULL, NULL)
diff --git a/include/dnode/mnode/mnode.h b/include/dnode/mnode/mnode.h
index 07a0ca952a..6c3c7497b1 100644
--- a/include/dnode/mnode/mnode.h
+++ b/include/dnode/mnode/mnode.h
@@ -20,6 +20,7 @@
#include "tmsg.h"
#include "tmsgcb.h"
#include "trpc.h"
+#include "sync.h"
#ifdef __cplusplus
extern "C" {
@@ -73,6 +74,7 @@ int32_t mndStart(SMnode *pMnode);
void mndStop(SMnode *pMnode);
int32_t mndIsCatchUp(SMnode *pMnode);
+ESyncRole mndGetRole(SMnode *pMnode);
/**
* @brief Get mnode monitor info.
diff --git a/include/libs/executor/dataSinkMgt.h b/include/libs/executor/dataSinkMgt.h
index ed7cbc8125..ce7d038d42 100644
--- a/include/libs/executor/dataSinkMgt.h
+++ b/include/libs/executor/dataSinkMgt.h
@@ -29,7 +29,6 @@ extern "C" {
#define DS_BUF_FULL 2
#define DS_BUF_EMPTY 3
-struct SDataSink;
struct SSDataBlock;
typedef struct SDeleterRes {
diff --git a/include/libs/stream/tstream.h b/include/libs/stream/tstream.h
index 103f807191..aade34e965 100644
--- a/include/libs/stream/tstream.h
+++ b/include/libs/stream/tstream.h
@@ -335,18 +335,17 @@ struct SStreamTask {
// meta
typedef struct SStreamMeta {
- char* path;
- TDB* db;
- TTB* pTaskDb;
- TTB* pCheckpointDb;
- SHashObj* pTasks;
- void* ahandle;
- TXN* txn;
- FTaskExpand* expandFunc;
- int32_t vgId;
- SRWLatch lock;
- int8_t walScan;
- bool quit;
+ char* path;
+ TDB* db;
+ TTB* pTaskDb;
+ TTB* pCheckpointDb;
+ SHashObj* pTasks;
+ void* ahandle;
+ TXN* txn;
+ FTaskExpand* expandFunc;
+ int32_t vgId;
+ SRWLatch lock;
+ int8_t walScan;
} SStreamMeta;
int32_t tEncodeStreamEpInfo(SEncoder* pEncoder, const SStreamChildEpInfo* pInfo);
@@ -359,10 +358,6 @@ void tFreeStreamTask(SStreamTask* pTask);
int32_t tAppendDataToInputQueue(SStreamTask* pTask, SStreamQueueItem* pItem);
bool tInputQueueIsFull(const SStreamTask* pTask);
-static FORCE_INLINE void streamTaskInputFail(SStreamTask* pTask) {
- atomic_store_8(&pTask->inputStatus, TASK_INPUT_STATUS__FAILED);
-}
-
typedef struct {
SMsgHead head;
int64_t streamId;
@@ -538,6 +533,7 @@ int32_t streamProcessDispatchRsp(SStreamTask* pTask, SStreamDispatchRsp* pRsp, i
int32_t streamProcessRetrieveReq(SStreamTask* pTask, SStreamRetrieveReq* pReq, SRpcMsg* pMsg);
// int32_t streamProcessRetrieveRsp(SStreamTask* pTask, SStreamRetrieveRsp* pRsp);
+void streamTaskInputFail(SStreamTask* pTask);
int32_t streamTryExec(SStreamTask* pTask);
int32_t streamSchedExec(SStreamTask* pTask);
int32_t streamTaskOutput(SStreamTask* pTask, SStreamDataBlock* pBlock);
diff --git a/include/libs/sync/sync.h b/include/libs/sync/sync.h
index 33cef538d2..e86a4f9690 100644
--- a/include/libs/sync/sync.h
+++ b/include/libs/sync/sync.h
@@ -250,6 +250,7 @@ void syncPreStop(int64_t rid);
void syncPostStop(int64_t rid);
int32_t syncPropose(int64_t rid, SRpcMsg* pMsg, bool isWeak, int64_t* seq);
int32_t syncIsCatchUp(int64_t rid);
+ESyncRole syncGetRole(int64_t rid);
int32_t syncProcessMsg(int64_t rid, SRpcMsg* pMsg);
int32_t syncReconfig(int64_t rid, SSyncCfg* pCfg);
int32_t syncBeginSnapshot(int64_t rid, int64_t lastApplyIndex);
diff --git a/include/libs/wal/wal.h b/include/libs/wal/wal.h
index b51289de5e..1e3974f5cc 100644
--- a/include/libs/wal/wal.h
+++ b/include/libs/wal/wal.h
@@ -190,7 +190,7 @@ int32_t walApplyVer(SWal *, int64_t ver);
// int32_t walDataCorrupted(SWal*);
-// read
+// wal reader
SWalReader *walOpenReader(SWal *, SWalFilterCond *pCond);
void walCloseReader(SWalReader *pRead);
void walReadReset(SWalReader *pReader);
@@ -198,6 +198,7 @@ int32_t walReadVer(SWalReader *pRead, int64_t ver);
int32_t walReadSeekVer(SWalReader *pRead, int64_t ver);
int32_t walNextValidMsg(SWalReader *pRead);
int64_t walReaderGetCurrentVer(const SWalReader* pReader);
+void walReaderValidVersionRange(SWalReader* pReader, int64_t *sver, int64_t *ever);
// only for tq usage
void walSetReaderCapacity(SWalReader *pRead, int32_t capacity);
diff --git a/include/util/taoserror.h b/include/util/taoserror.h
index 0d9292cc6b..a709ccf10c 100644
--- a/include/util/taoserror.h
+++ b/include/util/taoserror.h
@@ -103,7 +103,7 @@ int32_t* taosGetErrno();
#define TSDB_CODE_CHECKSUM_ERROR TAOS_DEF_ERROR_CODE(0, 0x011F) // internal
#define TSDB_CODE_COMPRESS_ERROR TAOS_DEF_ERROR_CODE(0, 0x0120)
-#define TSDB_CODE_MSG_NOT_PROCESSED TAOS_DEF_ERROR_CODE(0, 0x0121) //
+#define TSDB_CODE_MSG_NOT_PROCESSED TAOS_DEF_ERROR_CODE(0, 0x0121)
#define TSDB_CODE_CFG_NOT_FOUND TAOS_DEF_ERROR_CODE(0, 0x0122)
#define TSDB_CODE_REPEAT_INIT TAOS_DEF_ERROR_CODE(0, 0x0123)
#define TSDB_CODE_DUP_KEY TAOS_DEF_ERROR_CODE(0, 0x0124)
@@ -118,9 +118,10 @@ int32_t* taosGetErrno();
#define TSDB_CODE_MSG_ENCODE_ERROR TAOS_DEF_ERROR_CODE(0, 0x012D)
#define TSDB_CODE_NO_ENOUGH_DISKSPACE TAOS_DEF_ERROR_CODE(0, 0x012E)
-#define TSDB_CODE_APP_IS_STARTING TAOS_DEF_ERROR_CODE(0, 0x0130) //
-#define TSDB_CODE_APP_IS_STOPPING TAOS_DEF_ERROR_CODE(0, 0x0131) //
-#define TSDB_CODE_IVLD_DATA_FMT TAOS_DEF_ERROR_CODE(0, 0x0132) //
+#define TSDB_CODE_APP_IS_STARTING TAOS_DEF_ERROR_CODE(0, 0x0130)
+#define TSDB_CODE_APP_IS_STOPPING TAOS_DEF_ERROR_CODE(0, 0x0131)
+#define TSDB_CODE_INVALID_DATA_FMT TAOS_DEF_ERROR_CODE(0, 0x0132)
+#define TSDB_CODE_INVALID_CFG_VALUE TAOS_DEF_ERROR_CODE(0, 0x0133)
//client
#define TSDB_CODE_TSC_INVALID_OPERATION TAOS_DEF_ERROR_CODE(0, 0x0200)
@@ -403,6 +404,8 @@ int32_t* taosGetErrno();
#define TSDB_CODE_SNODE_ALREADY_DEPLOYED TAOS_DEF_ERROR_CODE(0, 0x040F)
#define TSDB_CODE_SNODE_NOT_FOUND TAOS_DEF_ERROR_CODE(0, 0x0410)
#define TSDB_CODE_SNODE_NOT_DEPLOYED TAOS_DEF_ERROR_CODE(0, 0x0411)
+#define TSDB_CODE_MNODE_NOT_CATCH_UP TAOS_DEF_ERROR_CODE(0, 0x0412) // internal
+#define TSDB_CODE_MNODE_ALREADY_IS_VOTER TAOS_DEF_ERROR_CODE(0, 0x0413) // internal
// vnode
// #define TSDB_CODE_VND_ACTION_IN_PROGRESS TAOS_DEF_ERROR_CODE(0, 0x0500) // 2.x
@@ -437,6 +440,8 @@ int32_t* taosGetErrno();
#define TSDB_CODE_VND_STOPPED TAOS_DEF_ERROR_CODE(0, 0x0529)
#define TSDB_CODE_VND_DUP_REQUEST TAOS_DEF_ERROR_CODE(0, 0x0530)
#define TSDB_CODE_VND_QUERY_BUSY TAOS_DEF_ERROR_CODE(0, 0x0531)
+#define TSDB_CODE_VND_NOT_CATCH_UP TAOS_DEF_ERROR_CODE(0, 0x0532) // internal
+#define TSDB_CODE_VND_ALREADY_IS_VOTER TAOS_DEF_ERROR_CODE(0, 0x0533) // internal
// tsdb
#define TSDB_CODE_TDB_INVALID_TABLE_ID TAOS_DEF_ERROR_CODE(0, 0x0600)
@@ -534,20 +539,20 @@ int32_t* taosGetErrno();
// #define TSDB_CODE_SYN_INVALID_CHECKSUM TAOS_DEF_ERROR_CODE(0, 0x0908) // 2.x
// #define TSDB_CODE_SYN_INVALID_MSGLEN TAOS_DEF_ERROR_CODE(0, 0x0909) // 2.x
// #define TSDB_CODE_SYN_INVALID_MSGTYPE TAOS_DEF_ERROR_CODE(0, 0x090A) // 2.x
-#define TSDB_CODE_SYN_IS_LEADER TAOS_DEF_ERROR_CODE(0, 0x090B)
+// #define TSDB_CODE_SYN_IS_LEADER TAOS_DEF_ERROR_CODE(0, 0x090B) // unused
#define TSDB_CODE_SYN_NOT_LEADER TAOS_DEF_ERROR_CODE(0, 0x090C)
-#define TSDB_CODE_SYN_ONE_REPLICA TAOS_DEF_ERROR_CODE(0, 0x090D)
-#define TSDB_CODE_SYN_NOT_IN_NEW_CONFIG TAOS_DEF_ERROR_CODE(0, 0x090E)
-#define TSDB_CODE_SYN_NEW_CONFIG_ERROR TAOS_DEF_ERROR_CODE(0, 0x090F) // internal
-#define TSDB_CODE_SYN_RECONFIG_NOT_READY TAOS_DEF_ERROR_CODE(0, 0x0910)
+// #define TSDB_CODE_SYN_ONE_REPLICA TAOS_DEF_ERROR_CODE(0, 0x090D) // unused
+// #define TSDB_CODE_SYN_NOT_IN_NEW_CONFIG TAOS_DEF_ERROR_CODE(0, 0x090E) // unused
+#define TSDB_CODE_SYN_NEW_CONFIG_ERROR TAOS_DEF_ERROR_CODE(0, 0x090F) // internal
+// #define TSDB_CODE_SYN_RECONFIG_NOT_READY TAOS_DEF_ERROR_CODE(0, 0x0910) // unused
#define TSDB_CODE_SYN_PROPOSE_NOT_READY TAOS_DEF_ERROR_CODE(0, 0x0911)
-#define TSDB_CODE_SYN_STANDBY_NOT_READY TAOS_DEF_ERROR_CODE(0, 0x0912)
-#define TSDB_CODE_SYN_BATCH_ERROR TAOS_DEF_ERROR_CODE(0, 0x0913)
+// #define TSDB_CODE_SYN_STANDBY_NOT_READY TAOS_DEF_ERROR_CODE(0, 0x0912) // unused
+// #define TSDB_CODE_SYN_BATCH_ERROR TAOS_DEF_ERROR_CODE(0, 0x0913) // unused
#define TSDB_CODE_SYN_RESTORING TAOS_DEF_ERROR_CODE(0, 0x0914)
-#define TSDB_CODE_SYN_INVALID_SNAPSHOT_MSG TAOS_DEF_ERROR_CODE(0, 0x0915) // internal
+#define TSDB_CODE_SYN_INVALID_SNAPSHOT_MSG TAOS_DEF_ERROR_CODE(0, 0x0915) // internal
#define TSDB_CODE_SYN_BUFFER_FULL TAOS_DEF_ERROR_CODE(0, 0x0916)
#define TSDB_CODE_SYN_WRITE_STALL TAOS_DEF_ERROR_CODE(0, 0x0917)
-#define TSDB_CODE_SYN_NEGO_WIN_EXCEEDED TAOS_DEF_ERROR_CODE(0, 0X0918)
+#define TSDB_CODE_SYN_NEGOTIATION_WIN_FULL TAOS_DEF_ERROR_CODE(0, 0x0918)
#define TSDB_CODE_SYN_INTERNAL_ERROR TAOS_DEF_ERROR_CODE(0, 0x09FF)
// tq
@@ -568,7 +573,7 @@ int32_t* taosGetErrno();
// wal
// #define TSDB_CODE_WAL_APP_ERROR TAOS_DEF_ERROR_CODE(0, 0x1000) // 2.x
#define TSDB_CODE_WAL_FILE_CORRUPTED TAOS_DEF_ERROR_CODE(0, 0x1001)
-#define TSDB_CODE_WAL_SIZE_LIMIT TAOS_DEF_ERROR_CODE(0, 0x1002)
+// #define TSDB_CODE_WAL_SIZE_LIMIT TAOS_DEF_ERROR_CODE(0, 0x1002) // unused
#define TSDB_CODE_WAL_INVALID_VER TAOS_DEF_ERROR_CODE(0, 0x1003)
// #define TSDB_CODE_WAL_OUT_OF_MEMORY TAOS_DEF_ERROR_CODE(0, 0x1004) // 2.x
#define TSDB_CODE_WAL_LOG_NOT_EXIST TAOS_DEF_ERROR_CODE(0, 0x1005)
@@ -712,15 +717,13 @@ int32_t* taosGetErrno();
#define TSDB_CODE_UDF_STOPPING TAOS_DEF_ERROR_CODE(0, 0x2901)
#define TSDB_CODE_UDF_PIPE_READ_ERR TAOS_DEF_ERROR_CODE(0, 0x2902)
#define TSDB_CODE_UDF_PIPE_CONNECT_ERR TAOS_DEF_ERROR_CODE(0, 0x2903)
-#define TSDB_CODE_UDF_PIPE_NO_PIPE TAOS_DEF_ERROR_CODE(0, 0x2904)
+#define TSDB_CODE_UDF_PIPE_NOT_EXIST TAOS_DEF_ERROR_CODE(0, 0x2904)
#define TSDB_CODE_UDF_LOAD_UDF_FAILURE TAOS_DEF_ERROR_CODE(0, 0x2905)
-#define TSDB_CODE_UDF_INVALID_STATE TAOS_DEF_ERROR_CODE(0, 0x2906)
-#define TSDB_CODE_UDF_INVALID_INPUT TAOS_DEF_ERROR_CODE(0, 0x2907)
-#define TSDB_CODE_UDF_NO_FUNC_HANDLE TAOS_DEF_ERROR_CODE(0, 0x2908)
-#define TSDB_CODE_UDF_INVALID_BUFSIZE TAOS_DEF_ERROR_CODE(0, 0x2909)
-#define TSDB_CODE_UDF_INVALID_OUTPUT_TYPE TAOS_DEF_ERROR_CODE(0, 0x290A)
-#define TSDB_CODE_UDF_SCRIPT_NOT_SUPPORTED TAOS_DEF_ERROR_CODE(0, 0x290B)
-#define TSDB_CODE_UDF_FUNC_EXEC_FAILURE TAOS_DEF_ERROR_CODE(0, 0x290C)
+#define TSDB_CODE_UDF_INVALID_INPUT TAOS_DEF_ERROR_CODE(0, 0x2906)
+#define TSDB_CODE_UDF_INVALID_BUFSIZE TAOS_DEF_ERROR_CODE(0, 0x2907)
+#define TSDB_CODE_UDF_INVALID_OUTPUT_TYPE TAOS_DEF_ERROR_CODE(0, 0x2908)
+#define TSDB_CODE_UDF_SCRIPT_NOT_SUPPORTED TAOS_DEF_ERROR_CODE(0, 0x2909)
+#define TSDB_CODE_UDF_FUNC_EXEC_FAILURE TAOS_DEF_ERROR_CODE(0, 0x290A)
// sml
#define TSDB_CODE_SML_INVALID_PROTOCOL_TYPE TAOS_DEF_ERROR_CODE(0, 0x3000)
diff --git a/include/util/tlog.h b/include/util/tlog.h
index 0071b3d32c..d267d5876a 100644
--- a/include/util/tlog.h
+++ b/include/util/tlog.h
@@ -83,6 +83,12 @@ void taosPrintLongString(const char *flags, ELogLevel level, int32_t dflag, cons
#endif
;
+void taosPrintSlowLog(const char *format, ...)
+#ifdef __GNUC__
+ __attribute__((format(printf, 1, 2)))
+#endif
+ ;
+
bool taosAssertDebug(bool condition, const char *file, int32_t line, const char *format, ...);
bool taosAssertRelease(bool condition);
diff --git a/source/client/inc/clientInt.h b/source/client/inc/clientInt.h
index 41f87379a9..8e20d7d275 100644
--- a/source/client/inc/clientInt.h
+++ b/source/client/inc/clientInt.h
@@ -63,6 +63,7 @@ typedef struct {
// statistics
int32_t reportCnt;
int32_t connKeyCnt;
+ int32_t passKeyCnt; // with passVer call back
int64_t reportBytes; // not implemented
int64_t startTime;
// ctl
@@ -125,6 +126,12 @@ typedef struct SAppInfo {
TdThreadMutex mutex;
} SAppInfo;
+typedef struct {
+ int32_t ver;
+ void* param;
+ __taos_notify_fn_t fp;
+} SPassInfo;
+
typedef struct STscObj {
char user[TSDB_USER_LEN];
char pass[TSDB_PASSWORD_LEN];
@@ -140,6 +147,7 @@ typedef struct STscObj {
int32_t numOfReqs; // number of sqlObj bound to this connection
SAppInstInfo* pAppInfo;
SHashObj* pRequests;
+ SPassInfo passInfo;
} STscObj;
typedef struct STscDbg {
@@ -353,7 +361,7 @@ void stopAllRequests(SHashObj* pRequests);
// conn level
int hbRegisterConn(SAppHbMgr* pAppHbMgr, int64_t tscRefId, int64_t clusterId, int8_t connType);
-void hbDeregisterConn(SAppHbMgr* pAppHbMgr, SClientHbKey connKey);
+void hbDeregisterConn(SAppHbMgr* pAppHbMgr, SClientHbKey connKey, void* param);
typedef struct SSqlCallbackWrapper {
SParseContext* pParseCtx;
diff --git a/source/client/src/clientEnv.c b/source/client/src/clientEnv.c
index 418103f2a6..07ca3d8909 100644
--- a/source/client/src/clientEnv.c
+++ b/source/client/src/clientEnv.c
@@ -42,7 +42,7 @@ SAppInfo appInfo;
int64_t lastClusterId = 0;
int32_t clientReqRefPool = -1;
int32_t clientConnRefPool = -1;
-int32_t clientStop = 0;
+int32_t clientStop = -1;
int32_t timestampDeltaLimit = 900; // s
@@ -69,7 +69,6 @@ static int32_t registerRequest(SRequestObj *pRequest, STscObj *pTscObj) {
}
static void deregisterRequest(SRequestObj *pRequest) {
- const static int64_t SLOW_QUERY_INTERVAL = 3000000L; // todo configurable
if (pRequest == NULL) {
tscError("pRequest == NULL");
return;
@@ -80,6 +79,7 @@ static void deregisterRequest(SRequestObj *pRequest) {
int32_t currentInst = atomic_sub_fetch_64((int64_t *)&pActivity->currentRequests, 1);
int32_t num = atomic_sub_fetch_32(&pTscObj->numOfReqs, 1);
+ int32_t reqType = SLOW_LOG_TYPE_OTHERS;
int64_t duration = taosGetTimestampUs() - pRequest->metric.start;
tscDebug("0x%" PRIx64 " free Request from connObj: 0x%" PRIx64 ", reqId:0x%" PRIx64
@@ -95,6 +95,7 @@ static void deregisterRequest(SRequestObj *pRequest) {
duration, pRequest->metric.parseCostUs, pRequest->metric.ctgCostUs, pRequest->metric.analyseCostUs,
pRequest->metric.planCostUs, pRequest->metric.execCostUs);
atomic_add_fetch_64((int64_t *)&pActivity->insertElapsedTime, duration);
+ reqType = SLOW_LOG_TYPE_INSERT;
} else if (QUERY_NODE_SELECT_STMT == pRequest->stmtType) {
tscDebug("query duration %" PRId64 "us: parseCost:%" PRId64 "us, ctgCost:%" PRId64 "us, analyseCost:%" PRId64
"us, planCost:%" PRId64 "us, exec:%" PRId64 "us",
@@ -102,12 +103,16 @@ static void deregisterRequest(SRequestObj *pRequest) {
pRequest->metric.planCostUs, pRequest->metric.execCostUs);
atomic_add_fetch_64((int64_t *)&pActivity->queryElapsedTime, duration);
+ reqType = SLOW_LOG_TYPE_QUERY;
}
}
- if (duration >= SLOW_QUERY_INTERVAL) {
+ if (duration >= (tsSlowLogThreshold * 1000000UL)) {
atomic_add_fetch_64((int64_t *)&pActivity->numOfSlowQueries, 1);
- tscWarnL("slow query: %s, duration:%" PRId64, pRequest->sqlstr, duration);
+ if (tsSlowLogScope & reqType) {
+ taosPrintSlowLog("PID:%d, Conn:%u, QID:0x%" PRIx64 ", Start:%" PRId64 ", Duration:%" PRId64 "us, SQL:%s",
+ taosGetPId(), pTscObj->connId, pRequest->requestId, pRequest->metric.start, duration, pRequest->sqlstr);
+ }
}
releaseTscObj(pTscObj->id);
@@ -239,7 +244,7 @@ void destroyTscObj(void *pObj) {
tscTrace("begin to destroy tscObj %" PRIx64 " p:%p", tscId, pTscObj);
SClientHbKey connKey = {.tscRid = pTscObj->id, .connType = pTscObj->connType};
- hbDeregisterConn(pTscObj->pAppInfo->pAppHbMgr, connKey);
+ hbDeregisterConn(pTscObj->pAppInfo->pAppHbMgr, connKey, pTscObj->passInfo.fp);
destroyAllRequests(pTscObj->pRequests);
taosHashCleanup(pTscObj->pRequests);
@@ -427,8 +432,12 @@ static void *tscCrashReportThreadFp(void *param) {
}
#endif
+ if (-1 != atomic_val_compare_exchange_32(&clientStop, -1, 0)) {
+ return NULL;
+ }
+
while (1) {
- if (clientStop) break;
+ if (clientStop > 0) break;
if (loopTimes++ < reportPeriodNum) {
taosMsleep(sleepTime);
continue;
@@ -466,7 +475,7 @@ static void *tscCrashReportThreadFp(void *param) {
loopTimes = 0;
}
- clientStop = -1;
+ clientStop = -2;
return NULL;
}
diff --git a/source/client/src/clientHb.c b/source/client/src/clientHb.c
index c9c2e7a5f8..79435da89f 100644
--- a/source/client/src/clientHb.c
+++ b/source/client/src/clientHb.c
@@ -19,6 +19,15 @@
#include "scheduler.h"
#include "trpc.h"
+typedef struct {
+ union {
+ struct {
+ int64_t clusterId;
+ int32_t passKeyCnt;
+ };
+ };
+} SHbParam;
+
static SClientHbMgr clientHbMgr = {0};
static int32_t hbCreateThread();
@@ -49,6 +58,52 @@ static int32_t hbProcessUserAuthInfoRsp(void *value, int32_t valueLen, struct SC
return TSDB_CODE_SUCCESS;
}
+static int32_t hbProcessUserPassInfoRsp(void *value, int32_t valueLen, SClientHbKey *connKey, SAppHbMgr *pAppHbMgr) {
+ int32_t code = 0;
+ int32_t numOfBatchs = 0;
+ SUserPassBatchRsp batchRsp = {0};
+ if (tDeserializeSUserPassBatchRsp(value, valueLen, &batchRsp) != 0) {
+ code = TSDB_CODE_INVALID_MSG;
+ return code;
+ }
+
+ numOfBatchs = taosArrayGetSize(batchRsp.pArray);
+
+ SClientHbReq *pReq = NULL;
+ while ((pReq = taosHashIterate(pAppHbMgr->activeInfo, pReq))) {
+ STscObj *pTscObj = (STscObj *)acquireTscObj(pReq->connKey.tscRid);
+ if (!pTscObj) {
+ continue;
+ }
+ SPassInfo *passInfo = &pTscObj->passInfo;
+ if (!passInfo->fp) {
+ releaseTscObj(pReq->connKey.tscRid);
+ continue;
+ }
+
+ for (int32_t i = 0; i < numOfBatchs; ++i) {
+ SGetUserPassRsp *rsp = taosArrayGet(batchRsp.pArray, i);
+ if (0 == strncmp(rsp->user, pTscObj->user, TSDB_USER_LEN)) {
+ int32_t oldVer = atomic_load_32(&passInfo->ver);
+ if (oldVer < rsp->version) {
+ atomic_store_32(&passInfo->ver, rsp->version);
+ if (passInfo->fp) {
+ (*passInfo->fp)(passInfo->param, &passInfo->ver, TAOS_NOTIFY_PASSVER);
+ }
+ tscDebug("update passVer of user %s from %d to %d, tscRid:%" PRIi64, rsp->user, oldVer,
+ atomic_load_32(&passInfo->ver), pTscObj->id);
+ }
+ break;
+ }
+ }
+ releaseTscObj(pReq->connKey.tscRid);
+ }
+
+ taosArrayDestroy(batchRsp.pArray);
+
+ return code;
+}
+
static int32_t hbGenerateVgInfoFromRsp(SDBVgInfo **pInfo, SUseDbRsp *rsp) {
int32_t code = 0;
SDBVgInfo *vgInfo = taosMemoryCalloc(1, sizeof(SDBVgInfo));
@@ -291,6 +346,15 @@ static int32_t hbQueryHbRspHandle(SAppHbMgr *pAppHbMgr, SClientHbRsp *pRsp) {
hbProcessStbInfoRsp(kv->value, kv->valueLen, pCatalog);
break;
}
+ case HEARTBEAT_KEY_USER_PASSINFO: {
+ if (kv->valueLen <= 0 || NULL == kv->value) {
+ tscError("invalid hb user pass info, len:%d, value:%p", kv->valueLen, kv->value);
+ break;
+ }
+
+ hbProcessUserPassInfoRsp(kv->value, kv->valueLen, &pRsp->connKey, pAppHbMgr);
+ break;
+ }
default:
tscError("invalid hb key type:%d", kv->key);
break;
@@ -472,6 +536,49 @@ int32_t hbGetQueryBasicInfo(SClientHbKey *connKey, SClientHbReq *req) {
return TSDB_CODE_SUCCESS;
}
+static int32_t hbGetUserBasicInfo(SClientHbKey *connKey, SClientHbReq *req) {
+ STscObj *pTscObj = (STscObj *)acquireTscObj(connKey->tscRid);
+ if (!pTscObj) {
+ tscWarn("tscObj rid %" PRIx64 " not exist", connKey->tscRid);
+ return TSDB_CODE_APP_ERROR;
+ }
+
+ int32_t code = 0;
+ SUserPassVersion *user = taosMemoryMalloc(sizeof(SUserPassVersion));
+ if (!user) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _return;
+ }
+ strncpy(user->user, pTscObj->user, TSDB_USER_LEN);
+ user->version = htonl(pTscObj->passInfo.ver);
+
+ SKv kv = {
+ .key = HEARTBEAT_KEY_USER_PASSINFO,
+ .valueLen = sizeof(SUserPassVersion),
+ .value = user,
+ };
+
+ tscDebug("hb got user basic info, valueLen:%d, user:%s, passVer:%d, tscRid:%" PRIi64, kv.valueLen, user->user,
+ pTscObj->passInfo.ver, connKey->tscRid);
+
+ if (!req->info) {
+ req->info = taosHashInit(64, hbKeyHashFunc, 1, HASH_ENTRY_LOCK);
+ }
+
+ if (taosHashPut(req->info, &kv.key, sizeof(kv.key), &kv, sizeof(kv)) < 0) {
+ code = terrno ? terrno : TSDB_CODE_APP_ERROR;
+ goto _return;
+ }
+
+_return:
+ releaseTscObj(connKey->tscRid);
+ if (code) {
+ tscError("hb got user basic info failed since %s", terrstr(code));
+ }
+
+ return code;
+}
+
int32_t hbGetExpiredUserInfo(SClientHbKey *connKey, struct SCatalog *pCatalog, SClientHbReq *req) {
SUserAuthVersion *users = NULL;
uint32_t userNum = 0;
@@ -607,19 +714,23 @@ int32_t hbGetAppInfo(int64_t clusterId, SClientHbReq *req) {
}
int32_t hbQueryHbReqHandle(SClientHbKey *connKey, void *param, SClientHbReq *req) {
- int64_t *clusterId = (int64_t *)param;
+ SHbParam *hbParam = (SHbParam *)param;
struct SCatalog *pCatalog = NULL;
- int32_t code = catalogGetHandle(*clusterId, &pCatalog);
+ int32_t code = catalogGetHandle(hbParam->clusterId, &pCatalog);
if (code != TSDB_CODE_SUCCESS) {
- tscWarn("catalogGetHandle failed, clusterId:%" PRIx64 ", error:%s", *clusterId, tstrerror(code));
+ tscWarn("catalogGetHandle failed, clusterId:%" PRIx64 ", error:%s", hbParam->clusterId, tstrerror(code));
return code;
}
- hbGetAppInfo(*clusterId, req);
+ hbGetAppInfo(hbParam->clusterId, req);
hbGetQueryBasicInfo(connKey, req);
+ if (hbParam->passKeyCnt > 0) {
+ hbGetUserBasicInfo(connKey, req);
+ }
+
code = hbGetExpiredUserInfo(connKey, pCatalog, req);
if (TSDB_CODE_SUCCESS != code) {
return code;
@@ -673,7 +784,26 @@ SClientHbBatchReq *hbGatherAllInfo(SAppHbMgr *pAppHbMgr) {
while (pIter != NULL) {
pOneReq = taosArrayPush(pBatchReq->reqs, pOneReq);
- code = (*clientHbMgr.reqHandle[pOneReq->connKey.connType])(&pOneReq->connKey, &pOneReq->clusterId, pOneReq);
+ SHbParam param;
+ switch (pOneReq->connKey.connType) {
+ case CONN_TYPE__QUERY: {
+ param.clusterId = pOneReq->clusterId;
+ param.passKeyCnt = atomic_load_32(&pAppHbMgr->passKeyCnt);
+ break;
+ }
+ default:
+ break;
+ }
+ if (clientHbMgr.reqHandle[pOneReq->connKey.connType]) {
+ code = (*clientHbMgr.reqHandle[pOneReq->connKey.connType])(&pOneReq->connKey, ¶m, pOneReq);
+ if (code) {
+ tscWarn("hbGatherAllInfo failed since %s, tscRid:%" PRIi64 ", connType:%" PRIi8, tstrerror(code),
+ pOneReq->connKey.tscRid, pOneReq->connKey.connType);
+ }
+ }
+ break;
+
+#if 0
if (code) {
pIter = taosHashIterate(pAppHbMgr->activeInfo, pIter);
pOneReq = pIter;
@@ -682,6 +812,7 @@ SClientHbBatchReq *hbGatherAllInfo(SAppHbMgr *pAppHbMgr) {
pIter = taosHashIterate(pAppHbMgr->activeInfo, pIter);
pOneReq = pIter;
+#endif
}
releaseTscObj(rid);
@@ -1023,7 +1154,7 @@ int hbRegisterConn(SAppHbMgr *pAppHbMgr, int64_t tscRefId, int64_t clusterId, in
}
}
-void hbDeregisterConn(SAppHbMgr *pAppHbMgr, SClientHbKey connKey) {
+void hbDeregisterConn(SAppHbMgr *pAppHbMgr, SClientHbKey connKey, void *param) {
SClientHbReq *pReq = taosHashAcquire(pAppHbMgr->activeInfo, &connKey, sizeof(SClientHbKey));
if (pReq) {
tFreeClientHbReq(pReq);
@@ -1036,4 +1167,7 @@ void hbDeregisterConn(SAppHbMgr *pAppHbMgr, SClientHbKey connKey) {
}
atomic_sub_fetch_32(&pAppHbMgr->connKeyCnt, 1);
+ if (param) {
+ atomic_sub_fetch_32(&pAppHbMgr->passKeyCnt, 1);
+ }
}
diff --git a/source/client/src/clientImpl.c b/source/client/src/clientImpl.c
index ce174744ef..f8eade1d7c 100644
--- a/source/client/src/clientImpl.c
+++ b/source/client/src/clientImpl.c
@@ -1248,6 +1248,11 @@ STscObj* taosConnectImpl(const char* user, const char* auth, const char* db, __t
return NULL;
}
+ pRequest->sqlstr = taosStrdup("taos_connect");
+ if (pRequest->sqlstr) {
+ pRequest->sqlLen = strlen(pRequest->sqlstr);
+ }
+
SMsgSendInfo* body = buildConnectMsg(pRequest);
int64_t transporterId = 0;
@@ -1257,7 +1262,7 @@ STscObj* taosConnectImpl(const char* user, const char* auth, const char* db, __t
if (pRequest->code != TSDB_CODE_SUCCESS) {
const char* errorMsg =
(pRequest->code == TSDB_CODE_RPC_FQDN_ERROR) ? taos_errstr(pRequest) : tstrerror(pRequest->code);
- fprintf(stderr, "failed to connect to server, reason: %s\n\n", errorMsg);
+ tscError("failed to connect to server, reason: %s", errorMsg);
terrno = pRequest->code;
destroyRequest(pRequest);
diff --git a/source/client/src/clientMain.c b/source/client/src/clientMain.c
index 60c7b44b3d..aed11b4fb1 100644
--- a/source/client/src/clientMain.c
+++ b/source/client/src/clientMain.c
@@ -119,6 +119,39 @@ TAOS *taos_connect(const char *ip, const char *user, const char *pass, const cha
return NULL;
}
+int taos_set_notify_cb(TAOS *taos, __taos_notify_fn_t fp, void *param, int type) {
+ if (taos == NULL) {
+ terrno = TSDB_CODE_INVALID_PARA;
+ return terrno;
+ }
+
+ STscObj *pObj = acquireTscObj(*(int64_t *)taos);
+ if (NULL == pObj) {
+ terrno = TSDB_CODE_TSC_DISCONNECTED;
+ tscError("invalid parameter for %s", __func__);
+ return terrno;
+ }
+
+ switch (type) {
+ case TAOS_NOTIFY_PASSVER: {
+ pObj->passInfo.fp = fp;
+ pObj->passInfo.param = param;
+ if (fp) {
+ atomic_add_fetch_32(&pObj->pAppInfo->pAppHbMgr->passKeyCnt, 1);
+ }
+ break;
+ }
+ default: {
+ terrno = TSDB_CODE_INVALID_PARA;
+ releaseTscObj(*(int64_t *)taos);
+ return terrno;
+ }
+ }
+
+ releaseTscObj(*(int64_t *)taos);
+ return 0;
+}
+
void taos_close_internal(void *taos) {
if (taos == NULL) {
return;
diff --git a/source/client/src/clientMsgHandler.c b/source/client/src/clientMsgHandler.c
index a0146cfa39..52c5fc7940 100644
--- a/source/client/src/clientMsgHandler.c
+++ b/source/client/src/clientMsgHandler.c
@@ -130,6 +130,7 @@ int32_t processConnectRsp(void* param, SDataBuf* pMsg, int32_t code) {
lastClusterId = connectRsp.clusterId;
pTscObj->connType = connectRsp.connType;
+ pTscObj->passInfo.ver = connectRsp.passVer;
hbRegisterConn(pTscObj->pAppInfo->pAppHbMgr, pTscObj->id, connectRsp.clusterId, connectRsp.connType);
diff --git a/source/client/src/clientRawBlockWrite.c b/source/client/src/clientRawBlockWrite.c
index a09780dc15..32f28e4563 100644
--- a/source/client/src/clientRawBlockWrite.c
+++ b/source/client/src/clientRawBlockWrite.c
@@ -1511,7 +1511,7 @@ static int32_t tmqWriteRawDataImpl(TAOS* taos, void* data, int32_t dataLen) {
rspObj.resType = RES_TYPE__TMQ;
tDecoderInit(&decoder, data, dataLen);
- code = tDecodeSMqDataRsp(&decoder, &rspObj.rsp);
+ code = tDecodeMqDataRsp(&decoder, &rspObj.rsp);
if (code != 0) {
uError("WriteRaw:decode smqDataRsp error");
code = TSDB_CODE_INVALID_MSG;
@@ -1615,7 +1615,7 @@ static int32_t tmqWriteRawDataImpl(TAOS* taos, void* data, int32_t dataLen) {
code = pRequest->code;
end:
- tDeleteSMqDataRsp(&rspObj.rsp);
+ tDeleteMqDataRsp(&rspObj.rsp);
tDecoderClear(&decoder);
qDestroyQuery(pQuery);
destroyRequest(pRequest);
@@ -1858,7 +1858,7 @@ int32_t tmq_get_raw(TAOS_RES* res, tmq_raw_data* raw) {
int32_t len = 0;
int32_t code = 0;
- tEncodeSize(tEncodeSMqDataRsp, &rspObj->rsp, len, code);
+ tEncodeSize(tEncodeMqDataRsp, &rspObj->rsp, len, code);
if (code < 0) {
return -1;
}
@@ -1866,7 +1866,7 @@ int32_t tmq_get_raw(TAOS_RES* res, tmq_raw_data* raw) {
void* buf = taosMemoryCalloc(1, len);
SEncoder encoder = {0};
tEncoderInit(&encoder, buf, len);
- tEncodeSMqDataRsp(&encoder, &rspObj->rsp);
+ tEncodeMqDataRsp(&encoder, &rspObj->rsp);
tEncoderClear(&encoder);
raw->raw = buf;
diff --git a/source/client/src/clientSml.c b/source/client/src/clientSml.c
index 17150286e1..011a1b3111 100644
--- a/source/client/src/clientSml.c
+++ b/source/client/src/clientSml.c
@@ -660,6 +660,7 @@ static int32_t smlSendMetaMsg(SSmlHandle *info, SName *pName, SArray *pColumns,
SMCreateStbReq pReq = {0};
int32_t code = TSDB_CODE_SUCCESS;
SCmdMsgInfo pCmdMsg = {0};
+ char *pSql = NULL;
// put front for free
pReq.numOfColumns = taosArrayGetSize(pColumns);
@@ -667,7 +668,27 @@ static int32_t smlSendMetaMsg(SSmlHandle *info, SName *pName, SArray *pColumns,
pReq.numOfTags = taosArrayGetSize(pTags);
pReq.pTags = pTags;
- code = buildRequest(info->taos->id, "", 0, NULL, false, &pRequest, 0);
+ if (action == SCHEMA_ACTION_CREATE_STABLE) {
+ pReq.colVer = 1;
+ pReq.tagVer = 1;
+ pReq.suid = 0;
+ pReq.source = TD_REQ_FROM_APP;
+ pSql = "sml_create_stable";
+ } else if (action == SCHEMA_ACTION_ADD_TAG || action == SCHEMA_ACTION_CHANGE_TAG_SIZE) {
+ pReq.colVer = pTableMeta->sversion;
+ pReq.tagVer = pTableMeta->tversion + 1;
+ pReq.suid = pTableMeta->uid;
+ pReq.source = TD_REQ_FROM_TAOX;
+ pSql = (action == SCHEMA_ACTION_ADD_TAG) ? "sml_add_tag" : "sml_modify_tag_size";
+ } else if (action == SCHEMA_ACTION_ADD_COLUMN || action == SCHEMA_ACTION_CHANGE_COLUMN_SIZE) {
+ pReq.colVer = pTableMeta->sversion + 1;
+ pReq.tagVer = pTableMeta->tversion;
+ pReq.suid = pTableMeta->uid;
+ pReq.source = TD_REQ_FROM_TAOX;
+ pSql = (action == SCHEMA_ACTION_ADD_COLUMN) ? "sml_add_column" : "sml_modify_column_size";
+ }
+
+ code = buildRequest(info->taos->id, pSql, strlen(pSql), NULL, false, &pRequest, 0);
if (code != TSDB_CODE_SUCCESS) {
goto end;
}
@@ -678,23 +699,6 @@ static int32_t smlSendMetaMsg(SSmlHandle *info, SName *pName, SArray *pColumns,
goto end;
}
- if (action == SCHEMA_ACTION_CREATE_STABLE) {
- pReq.colVer = 1;
- pReq.tagVer = 1;
- pReq.suid = 0;
- pReq.source = TD_REQ_FROM_APP;
- } else if (action == SCHEMA_ACTION_ADD_TAG || action == SCHEMA_ACTION_CHANGE_TAG_SIZE) {
- pReq.colVer = pTableMeta->sversion;
- pReq.tagVer = pTableMeta->tversion + 1;
- pReq.suid = pTableMeta->uid;
- pReq.source = TD_REQ_FROM_TAOX;
- } else if (action == SCHEMA_ACTION_ADD_COLUMN || action == SCHEMA_ACTION_CHANGE_COLUMN_SIZE) {
- pReq.colVer = pTableMeta->sversion + 1;
- pReq.tagVer = pTableMeta->tversion;
- pReq.suid = pTableMeta->uid;
- pReq.source = TD_REQ_FROM_TAOX;
- }
-
if (pReq.numOfTags == 0) {
pReq.numOfTags = 1;
SField field = {0};
@@ -1514,6 +1518,44 @@ static int smlProcess(SSmlHandle *info, char *lines[], char *rawLine, char *rawL
return code;
}
+void smlSetReqSQL(SRequestObj *request, char *lines[], char *rawLine, char *rawLineEnd) {
+ if (tsSlowLogScope & SLOW_LOG_TYPE_INSERT) {
+ int32_t len = 0;
+ int32_t rlen = 0;
+ char* p = NULL;
+
+ if (lines && lines[0]) {
+ len = strlen(lines[0]);
+ p = lines[0];
+ } else if (rawLine) {
+ if (rawLineEnd) {
+ len = rawLineEnd - rawLine;
+ } else {
+ len = strlen(rawLine);
+ }
+ p = rawLine;
+ }
+
+ if (NULL == p) {
+ return;
+ }
+
+ rlen = TMIN(len, TSDB_MAX_ALLOWED_SQL_LEN);
+ rlen = TMAX(rlen, 0);
+
+ char *sql = taosMemoryMalloc(rlen + 1);
+ if (NULL == sql) {
+ uError("malloc %d for sml sql failed", rlen + 1);
+ return;
+ }
+ memcpy(sql, p, rlen);
+ sql[rlen] = 0;
+
+ request->sqlstr = sql;
+ request->sqlLen = rlen;
+ }
+}
+
TAOS_RES *taos_schemaless_insert_inner(TAOS *taos, char *lines[], char *rawLine, char *rawLineEnd, int numLines,
int protocol, int precision, int32_t ttl, int64_t reqid) {
int32_t code = TSDB_CODE_SUCCESS;
@@ -1546,6 +1588,8 @@ TAOS_RES *taos_schemaless_insert_inner(TAOS *taos, char *lines[], char *rawLine,
info->msgBuf.len = ERROR_MSG_BUF_DEFAULT_SIZE;
info->lineNum = numLines;
+ smlSetReqSQL(request, lines, rawLine, rawLineEnd);
+
SSmlMsgBuf msg = {ERROR_MSG_BUF_DEFAULT_SIZE, request->msgBuf};
if (request->pDb == NULL) {
request->code = TSDB_CODE_PAR_DB_NOT_SPECIFIED;
diff --git a/source/client/src/clientTmq.c b/source/client/src/clientTmq.c
index ceca06e309..76fd1d84d0 100644
--- a/source/client/src/clientTmq.c
+++ b/source/client/src/clientTmq.c
@@ -133,16 +133,23 @@ enum {
TMQ_DELAYED_TASK__COMMIT,
};
-typedef struct {
- int64_t pollCnt;
- int64_t numOfRows;
+typedef struct SVgOffsetInfo {
STqOffsetVal committedOffset;
STqOffsetVal currentOffset;
- int32_t vgId;
- int32_t vgStatus;
- int32_t vgSkipCnt;
- int64_t emptyBlockReceiveTs; // once empty block is received, idle for ignoreCnt then start to poll data
- SEpSet epSet;
+ int64_t walVerBegin;
+ int64_t walVerEnd;
+} SVgOffsetInfo;
+
+typedef struct {
+ int64_t pollCnt;
+ int64_t numOfRows;
+ SVgOffsetInfo offsetInfo;
+ int32_t vgId;
+ int32_t vgStatus;
+ int32_t vgSkipCnt; // here used to mark the slow vgroups
+ bool receiveInfo;
+ int64_t emptyBlockReceiveTs; // once empty block is received, idle for ignoreCnt then start to poll data
+ SEpSet epSet;
} SMqClientVg;
typedef struct {
@@ -190,6 +197,23 @@ typedef struct {
uint64_t requestId; // request id for debug purpose
} SMqPollCbParam;
+typedef struct SMqVgCommon {
+ tsem_t rsp;
+ int32_t numOfRsp;
+ SArray* pList;
+ TdThreadMutex mutex;
+ int64_t consumerId;
+ char* pTopicName;
+ int32_t code;
+} SMqVgCommon;
+
+typedef struct SMqVgWalInfoParam {
+ int32_t vgId;
+ int32_t epoch;
+ int32_t totalReq;
+ SMqVgCommon* pCommon;
+} SMqVgWalInfoParam;
+
typedef struct {
int64_t refId;
int32_t epoch;
@@ -204,7 +228,7 @@ typedef struct {
typedef struct {
SMqCommitCbParamSet* params;
- STqOffset* pOffset;
+ SMqVgOffset* pOffset;
char topicName[TSDB_TOPIC_FNAME_LEN];
int32_t vgId;
tmq_t* pTmq;
@@ -219,7 +243,7 @@ static int32_t doAskEp(tmq_t* tmq);
static int32_t makeTopicVgroupKey(char* dst, const char* topicName, int32_t vg);
static int32_t tmqCommitDone(SMqCommitCbParamSet* pParamSet);
static int32_t doSendCommitMsg(tmq_t* tmq, SMqClientVg* pVg, const char* pTopicName, SMqCommitCbParamSet* pParamSet,
- int32_t index, int32_t totalVgroups);
+ int32_t index, int32_t totalVgroups, int32_t type);
static void commitRspCountDown(SMqCommitCbParamSet* pParamSet, int64_t consumerId, const char* pTopic, int32_t vgId);
static void asyncAskEp(tmq_t* pTmq, __tmq_askep_fn_t askEpFn, void* param);
static void addToQueueCallbackFn(tmq_t* pTmq, int32_t code, SDataBuf* pDataBuf, void* param);
@@ -441,7 +465,7 @@ static int32_t tmqCommitCb(void* param, SDataBuf* pBuf, int32_t code) {
// if (code1 != TSDB_CODE_SUCCESS) { // retry failed.
// tscError("consumer:0x%" PRIx64 " topic:%s vgId:%d offset:%" PRId64
// " retry failed, ignore this commit. code:%s ordinal:%d/%d",
- // pParam->pTmq->consumerId, pParam->topicName, pVg->vgId, pVg->committedOffset.version,
+ // pParam->pTmq->consumerId, pParam->topicName, pVg->vgId, pVg->offsetInfo.committedOffset.version,
// tstrerror(terrno), index + 1, numOfVgroups);
// }
// }
@@ -467,22 +491,23 @@ static int32_t tmqCommitCb(void* param, SDataBuf* pBuf, int32_t code) {
}
static int32_t doSendCommitMsg(tmq_t* tmq, SMqClientVg* pVg, const char* pTopicName, SMqCommitCbParamSet* pParamSet,
- int32_t index, int32_t totalVgroups) {
- STqOffset* pOffset = taosMemoryCalloc(1, sizeof(STqOffset));
+ int32_t index, int32_t totalVgroups, int32_t type) {
+ SMqVgOffset* pOffset = taosMemoryCalloc(1, sizeof(SMqVgOffset));
if (pOffset == NULL) {
return TSDB_CODE_OUT_OF_MEMORY;
}
- pOffset->val = pVg->currentOffset;
+ pOffset->consumerId = tmq->consumerId;
+ pOffset->offset.val = pVg->offsetInfo.currentOffset;
int32_t groupLen = strlen(tmq->groupId);
- memcpy(pOffset->subKey, tmq->groupId, groupLen);
- pOffset->subKey[groupLen] = TMQ_SEPARATOR;
- strcpy(pOffset->subKey + groupLen + 1, pTopicName);
+ memcpy(pOffset->offset.subKey, tmq->groupId, groupLen);
+ pOffset->offset.subKey[groupLen] = TMQ_SEPARATOR;
+ strcpy(pOffset->offset.subKey + groupLen + 1, pTopicName);
int32_t len = 0;
int32_t code = 0;
- tEncodeSize(tEncodeSTqOffset, pOffset, len, code);
+ tEncodeSize(tEncodeMqVgOffset, pOffset, len, code);
if (code < 0) {
return TSDB_CODE_INVALID_PARA;
}
@@ -499,7 +524,7 @@ static int32_t doSendCommitMsg(tmq_t* tmq, SMqClientVg* pVg, const char* pTopicN
SEncoder encoder;
tEncoderInit(&encoder, abuf, len);
- tEncodeSTqOffset(&encoder, pOffset);
+ tEncodeMqVgOffset(&encoder, pOffset);
tEncoderClear(&encoder);
// build param
@@ -533,19 +558,19 @@ static int32_t doSendCommitMsg(tmq_t* tmq, SMqClientVg* pVg, const char* pTopicN
pMsgSendInfo->param = pParam;
pMsgSendInfo->paramFreeFp = taosMemoryFree;
pMsgSendInfo->fp = tmqCommitCb;
- pMsgSendInfo->msgType = TDMT_VND_TMQ_COMMIT_OFFSET;
+ pMsgSendInfo->msgType = type;
atomic_add_fetch_32(&pParamSet->waitingRspNum, 1);
atomic_add_fetch_32(&pParamSet->totalRspNum, 1);
SEp* pEp = GET_ACTIVE_EP(&pVg->epSet);
char offsetBuf[80] = {0};
- tFormatOffset(offsetBuf, tListLen(offsetBuf), &pOffset->val);
+ tFormatOffset(offsetBuf, tListLen(offsetBuf), &pOffset->offset.val);
char commitBuf[80] = {0};
- tFormatOffset(commitBuf, tListLen(commitBuf), &pVg->committedOffset);
+ tFormatOffset(commitBuf, tListLen(commitBuf), &pVg->offsetInfo.committedOffset);
tscDebug("consumer:0x%" PRIx64 " topic:%s on vgId:%d send offset:%s prev:%s, ep:%s:%d, ordinal:%d/%d, req:0x%" PRIx64,
- tmq->consumerId, pOffset->subKey, pVg->vgId, offsetBuf, commitBuf, pEp->fqdn, pEp->port, index + 1,
+ tmq->consumerId, pOffset->offset.subKey, pVg->vgId, offsetBuf, commitBuf, pEp->fqdn, pEp->port, index + 1,
totalVgroups, pMsgSendInfo->requestId);
int64_t transporterId = 0;
@@ -554,7 +579,22 @@ static int32_t doSendCommitMsg(tmq_t* tmq, SMqClientVg* pVg, const char* pTopicN
return TSDB_CODE_SUCCESS;
}
-static void asyncCommitOffset(tmq_t* tmq, const TAOS_RES* pRes, tmq_commit_cb* pCommitFp, void* userParam) {
+static SMqClientTopic* getTopicByName(tmq_t* tmq, const char* pTopicName) {
+ int32_t numOfTopics = taosArrayGetSize(tmq->clientTopics);
+ for (int32_t i = 0; i < numOfTopics; ++i) {
+ SMqClientTopic* pTopic = taosArrayGet(tmq->clientTopics, i);
+ if (strcmp(pTopic->topicName, pTopicName) != 0) {
+ continue;
+ }
+
+ return pTopic;
+ }
+
+ tscError("consumer:0x%" PRIx64 ", total:%d, failed to find topic:%s", tmq->consumerId, numOfTopics, pTopicName);
+ return NULL;
+}
+
+static void asyncCommitOffset(tmq_t* tmq, const TAOS_RES* pRes, int32_t type, tmq_commit_cb* pCommitFp, void* userParam) {
char* pTopicName = NULL;
int32_t vgId = 0;
int32_t code = 0;
@@ -596,15 +636,8 @@ static void asyncCommitOffset(tmq_t* tmq, const TAOS_RES* pRes, tmq_commit_cb* p
tscDebug("consumer:0x%" PRIx64 " do manual commit offset for %s, vgId:%d", tmq->consumerId, pTopicName, vgId);
- int32_t i = 0;
- for (; i < numOfTopics; i++) {
- SMqClientTopic* pTopic = taosArrayGet(tmq->clientTopics, i);
- if (strcmp(pTopic->topicName, pTopicName) == 0) {
- break;
- }
- }
-
- if (i == numOfTopics) {
+ SMqClientTopic* pTopic = getTopicByName(tmq, pTopicName);
+ if (pTopic == NULL) {
tscWarn("consumer:0x%" PRIx64 " failed to find the specified topic:%s, total topics:%d", tmq->consumerId,
pTopicName, numOfTopics);
taosMemoryFree(pParamSet);
@@ -612,8 +645,6 @@ static void asyncCommitOffset(tmq_t* tmq, const TAOS_RES* pRes, tmq_commit_cb* p
return;
}
- SMqClientTopic* pTopic = taosArrayGet(tmq->clientTopics, i);
-
int32_t j = 0;
int32_t numOfVgroups = taosArrayGetSize(pTopic->vgs);
for (j = 0; j < numOfVgroups; j++) {
@@ -632,8 +663,8 @@ static void asyncCommitOffset(tmq_t* tmq, const TAOS_RES* pRes, tmq_commit_cb* p
}
SMqClientVg* pVg = taosArrayGet(pTopic->vgs, j);
- if (pVg->currentOffset.type > 0 && !tOffsetEqual(&pVg->currentOffset, &pVg->committedOffset)) {
- code = doSendCommitMsg(tmq, pVg, pTopic->topicName, pParamSet, j, numOfVgroups);
+ if (pVg->offsetInfo.currentOffset.type > 0 && !tOffsetEqual(&pVg->offsetInfo.currentOffset, &pVg->offsetInfo.committedOffset)) {
+ code = doSendCommitMsg(tmq, pVg, pTopic->topicName, pParamSet, j, numOfVgroups, type);
// failed to commit, callback user function directly.
if (code != TSDB_CODE_SUCCESS) {
@@ -673,20 +704,20 @@ static void asyncCommitAllOffsets(tmq_t* tmq, tmq_commit_cb* pCommitFp, void* us
for (int32_t j = 0; j < numOfVgroups; j++) {
SMqClientVg* pVg = taosArrayGet(pTopic->vgs, j);
- if (pVg->currentOffset.type > 0 && !tOffsetEqual(&pVg->currentOffset, &pVg->committedOffset)) {
- int32_t code = doSendCommitMsg(tmq, pVg, pTopic->topicName, pParamSet, j, numOfVgroups);
+ if (pVg->offsetInfo.currentOffset.type > 0 && !tOffsetEqual(&pVg->offsetInfo.currentOffset, &pVg->offsetInfo.committedOffset)) {
+ int32_t code = doSendCommitMsg(tmq, pVg, pTopic->topicName, pParamSet, j, numOfVgroups, TDMT_VND_TMQ_COMMIT_OFFSET);
if (code != TSDB_CODE_SUCCESS) {
tscError("consumer:0x%" PRIx64 " topic:%s vgId:%d offset:%" PRId64 " failed, code:%s ordinal:%d/%d",
- tmq->consumerId, pTopic->topicName, pVg->vgId, pVg->committedOffset.version, tstrerror(terrno),
+ tmq->consumerId, pTopic->topicName, pVg->vgId, pVg->offsetInfo.committedOffset.version, tstrerror(terrno),
j + 1, numOfVgroups);
continue;
}
// update the offset value.
- pVg->committedOffset = pVg->currentOffset;
+ pVg->offsetInfo.committedOffset = pVg->offsetInfo.currentOffset;
} else {
tscDebug("consumer:0x%" PRIx64 " topic:%s vgId:%d, no commit, current:%" PRId64 ", ordinal:%d/%d",
- tmq->consumerId, pTopic->topicName, pVg->vgId, pVg->currentOffset.version, j + 1, numOfVgroups);
+ tmq->consumerId, pTopic->topicName, pVg->vgId, pVg->offsetInfo.currentOffset.version, j + 1, numOfVgroups);
}
}
}
@@ -1088,7 +1119,7 @@ _failed:
}
int32_t tmq_subscribe(tmq_t* tmq, const tmq_list_t* topic_list) {
- const int32_t MAX_RETRY_COUNT = 120 * 2; // let's wait for 2 mins at most
+ const int32_t MAX_RETRY_COUNT = 120 * 4; // let's wait for 4 mins at most
const SArray* container = &topic_list->container;
int32_t sz = taosArrayGetSize(container);
void* buf = NULL;
@@ -1141,22 +1172,13 @@ int32_t tmq_subscribe(tmq_t* tmq, const tmq_list_t* topic_list) {
goto FAIL;
}
- SMqSubscribeCbParam param = {
- .rspErr = 0,
- .refId = tmq->refId,
- .epoch = tmq->epoch,
- };
-
+ SMqSubscribeCbParam param = { .rspErr = 0, .refId = tmq->refId, .epoch = tmq->epoch };
if (tsem_init(¶m.rspSem, 0, 0) != 0) {
code = TSDB_CODE_TSC_INTERNAL_ERROR;
goto FAIL;
}
- sendInfo->msgInfo = (SDataBuf){
- .pData = buf,
- .len = tlen,
- .handle = NULL,
- };
+ sendInfo->msgInfo = (SDataBuf){.pData = buf, .len = tlen, .handle = NULL};
sendInfo->requestId = generateRequestId();
sendInfo->requestObjRefId = 0;
@@ -1184,7 +1206,7 @@ int32_t tmq_subscribe(tmq_t* tmq, const tmq_list_t* topic_list) {
int32_t retryCnt = 0;
while (TSDB_CODE_MND_CONSUMER_NOT_READY == doAskEp(tmq)) {
if (retryCnt++ > MAX_RETRY_COUNT) {
- tscError("consumer:0x%" PRIx64 ", mnd not ready for subscribe, retry:%d in 500ms", tmq->consumerId, retryCnt);
+ tscError("consumer:0x%" PRIx64 ", mnd not ready for subscribe, max retry reached:%d", tmq->consumerId, retryCnt);
code = TSDB_CODE_TSC_INTERNAL_ERROR;
goto FAIL;
}
@@ -1220,7 +1242,7 @@ void tmq_conf_set_auto_commit_cb(tmq_conf_t* conf, tmq_commit_cb* cb, void* para
conf->commitCbUserParam = param;
}
-int32_t tmqPollCb(void* param, SDataBuf* pMsg, int32_t code) {
+static int32_t tmqPollCb(void* param, SDataBuf* pMsg, int32_t code) {
SMqPollCbParam* pParam = (SMqPollCbParam*)param;
int64_t refId = pParam->refId;
@@ -1273,12 +1295,12 @@ int32_t tmqPollCb(void* param, SDataBuf* pMsg, int32_t code) {
}
int32_t msgEpoch = ((SMqRspHead*)pMsg->pData)->epoch;
- int32_t tmqEpoch = atomic_load_32(&tmq->epoch);
- if (msgEpoch < tmqEpoch) {
+ int32_t clientEpoch = atomic_load_32(&tmq->epoch);
+ if (msgEpoch < clientEpoch) {
// do not write into queue since updating epoch reset
tscWarn("consumer:0x%" PRIx64
" msg discard from vgId:%d since from earlier epoch, rsp epoch %d, current epoch %d, reqId:0x%" PRIx64,
- tmq->consumerId, vgId, msgEpoch, tmqEpoch, requestId);
+ tmq->consumerId, vgId, msgEpoch, clientEpoch, requestId);
tsem_post(&tmq->rspSem);
taosReleaseRef(tmqMgmt.rsetId, refId);
@@ -1288,9 +1310,9 @@ int32_t tmqPollCb(void* param, SDataBuf* pMsg, int32_t code) {
return 0;
}
- if (msgEpoch != tmqEpoch) {
+ if (msgEpoch != clientEpoch) {
tscWarn("consumer:0x%" PRIx64 " mismatch rsp from vgId:%d, epoch %d, current epoch %d, reqId:0x%" PRIx64,
- tmq->consumerId, vgId, msgEpoch, tmqEpoch, requestId);
+ tmq->consumerId, vgId, msgEpoch, clientEpoch, requestId);
}
// handle meta rsp
@@ -1316,7 +1338,7 @@ int32_t tmqPollCb(void* param, SDataBuf* pMsg, int32_t code) {
if (rspType == TMQ_MSG_TYPE__POLL_RSP) {
SDecoder decoder;
tDecoderInit(&decoder, POINTER_SHIFT(pMsg->pData, sizeof(SMqRspHead)), pMsg->len - sizeof(SMqRspHead));
- tDecodeSMqDataRsp(&decoder, &pRspWrapper->dataRsp);
+ tDecodeMqDataRsp(&decoder, &pRspWrapper->dataRsp);
tDecoderClear(&decoder);
memcpy(&pRspWrapper->dataRsp, pMsg->pData, sizeof(SMqRspHead));
@@ -1327,7 +1349,7 @@ int32_t tmqPollCb(void* param, SDataBuf* pMsg, int32_t code) {
} else if (rspType == TMQ_MSG_TYPE__POLL_META_RSP) {
SDecoder decoder;
tDecoderInit(&decoder, POINTER_SHIFT(pMsg->pData, sizeof(SMqRspHead)), pMsg->len - sizeof(SMqRspHead));
- tDecodeSMqMetaRsp(&decoder, &pRspWrapper->metaRsp);
+ tDecodeMqMetaRsp(&decoder, &pRspWrapper->metaRsp);
tDecoderClear(&decoder);
memcpy(&pRspWrapper->metaRsp, pMsg->pData, sizeof(SMqRspHead));
} else if (rspType == TMQ_MSG_TYPE__TAOSX_RSP) {
@@ -1398,7 +1420,6 @@ static void initClientTopicFromRsp(SMqClientTopic* pTopic, SMqSubTopicEp* pTopic
SMqClientVg clientVg = {
.pollCnt = 0,
- .currentOffset = offsetNew,
.vgId = pVgEp->vgId,
.epSet = pVgEp->epSet,
.vgStatus = TMQ_VG_STATUS__IDLE,
@@ -1407,6 +1428,10 @@ static void initClientTopicFromRsp(SMqClientTopic* pTopic, SMqSubTopicEp* pTopic
.numOfRows = numOfRows,
};
+ clientVg.offsetInfo.currentOffset = offsetNew;
+ clientVg.offsetInfo.committedOffset = offsetNew;
+ clientVg.offsetInfo.walVerBegin = -1;
+ clientVg.offsetInfo.walVerEnd = -1;
taosArrayPush(pTopic->vgs, &clientVg);
}
}
@@ -1456,11 +1481,11 @@ static bool doUpdateLocalEp(tmq_t* tmq, int32_t epoch, const SMqAskEpRsp* pRsp)
makeTopicVgroupKey(vgKey, pTopicCur->topicName, pVgCur->vgId);
char buf[80];
- tFormatOffset(buf, 80, &pVgCur->currentOffset);
+ tFormatOffset(buf, 80, &pVgCur->offsetInfo.currentOffset);
tscDebug("consumer:0x%" PRIx64 ", epoch:%d vgId:%d vgKey:%s, offset:%s", tmq->consumerId, epoch, pVgCur->vgId,
vgKey, buf);
- SVgroupSaveInfo info = {.offset = pVgCur->currentOffset, .numOfRows = pVgCur->numOfRows};
+ SVgroupSaveInfo info = {.offset = pVgCur->offsetInfo.currentOffset, .numOfRows = pVgCur->numOfRows};
taosHashPut(pVgOffsetHashMap, vgKey, strlen(vgKey), &info, sizeof(SVgroupSaveInfo));
}
}
@@ -1536,8 +1561,8 @@ int32_t askEpCallbackFn(void* param, SDataBuf* pMsg, int32_t code) {
tscDebug("consumer:0x%" PRIx64 ", recv ep, msg epoch %d, current epoch %d, update local ep", tmq->consumerId,
head->epoch, epoch);
}
- pParam->pUserFn(tmq, code, pMsg, pParam->pParam);
+ pParam->pUserFn(tmq, code, pMsg, pParam->pParam);
taosReleaseRef(tmqMgmt.rsetId, pParam->refId);
taosMemoryFree(pMsg->pEpSet);
@@ -1556,8 +1581,7 @@ void tmqBuildConsumeReqImpl(SMqPollReq* pReq, tmq_t* tmq, int64_t timeout, SMqCl
pReq->consumerId = tmq->consumerId;
pReq->timeout = timeout;
pReq->epoch = tmq->epoch;
- /*pReq->currentOffset = reqOffset;*/
- pReq->reqOffset = pVg->currentOffset;
+ pReq->reqOffset = pVg->offsetInfo.currentOffset;
pReq->head.vgId = pVg->vgId;
pReq->useSnapshot = tmq->useSnapshot;
pReq->reqId = generateRequestId();
@@ -1655,7 +1679,7 @@ static int32_t doTmqPollImpl(tmq_t* pTmq, SMqClientTopic* pTopic, SMqClientVg* p
pParam->refId = pTmq->refId;
pParam->epoch = pTmq->epoch;
- pParam->pVg = pVg; // pVg may be released,fix it
+ pParam->pVg = pVg;
pParam->pTopic = pTopic;
pParam->vgId = pVg->vgId;
pParam->requestId = req.reqId;
@@ -1667,12 +1691,7 @@ static int32_t doTmqPollImpl(tmq_t* pTmq, SMqClientTopic* pTopic, SMqClientVg* p
return handleErrorBeforePoll(pVg, pTmq);
}
- sendInfo->msgInfo = (SDataBuf){
- .pData = msg,
- .len = msgSize,
- .handle = NULL,
- };
-
+ sendInfo->msgInfo = (SDataBuf){.pData = msg, .len = msgSize, .handle = NULL};
sendInfo->requestId = req.reqId;
sendInfo->requestObjRefId = 0;
sendInfo->param = pParam;
@@ -1681,7 +1700,7 @@ static int32_t doTmqPollImpl(tmq_t* pTmq, SMqClientTopic* pTopic, SMqClientVg* p
int64_t transporterId = 0;
char offsetFormatBuf[80];
- tFormatOffset(offsetFormatBuf, tListLen(offsetFormatBuf), &pVg->currentOffset);
+ tFormatOffset(offsetFormatBuf, tListLen(offsetFormatBuf), &pVg->offsetInfo.currentOffset);
tscDebug("consumer:0x%" PRIx64 " send poll to %s vgId:%d, epoch %d, req:%s, reqId:0x%" PRIx64, pTmq->consumerId,
pTopic->topicName, pVg->vgId, pTmq->epoch, offsetFormatBuf, req.reqId);
@@ -1716,13 +1735,6 @@ static int32_t tmqPollImpl(tmq_t* tmq, int64_t timeout) {
tscTrace("consumer:0x%" PRIx64 " epoch %d wait poll-rsp, skip vgId:%d skip cnt %d", tmq->consumerId, tmq->epoch,
pVg->vgId, vgSkipCnt);
continue;
-#if 0
- if (skipCnt < 30000) {
- continue;
- } else {
- tscDebug("consumer:0x%" PRIx64 ",skip vgId:%d skip too much reset", tmq->consumerId, pVg->vgId);
- }
-#endif
}
atomic_store_32(&pVg->vgSkipCnt, 0);
@@ -1798,9 +1810,16 @@ static void* tmqHandleAllRsp(tmq_t* tmq, int64_t timeout, bool pollIfReset) {
}
// update the local offset value only for the returned values.
- pVg->currentOffset = pDataRsp->rspOffset;
+ pVg->offsetInfo.currentOffset = pDataRsp->rspOffset;
+
+ // update the status
atomic_store_32(&pVg->vgStatus, TMQ_VG_STATUS__IDLE);
+ // update the valid wal version range
+ pVg->offsetInfo.walVerBegin = pDataRsp->head.walsver;
+ pVg->offsetInfo.walVerEnd = pDataRsp->head.walever;
+ pVg->receiveInfo = true;
+
char buf[80];
tFormatOffset(buf, 80, &pDataRsp->rspOffset);
if (pDataRsp->blockNum == 0) {
@@ -1828,6 +1847,7 @@ static void* tmqHandleAllRsp(tmq_t* tmq, int64_t timeout, bool pollIfReset) {
taosFreeQitem(pollRspWrapper);
}
} else if (pRspWrapper->tmqRspType == TMQ_MSG_TYPE__POLL_META_RSP) {
+ // todo handle the wal range and epset for each vgroup
SMqPollRspWrapper* pollRspWrapper = (SMqPollRspWrapper*)pRspWrapper;
int32_t consumerEpoch = atomic_load_32(&tmq->epoch);
@@ -1835,7 +1855,7 @@ static void* tmqHandleAllRsp(tmq_t* tmq, int64_t timeout, bool pollIfReset) {
if (pollRspWrapper->metaRsp.head.epoch == consumerEpoch) {
SMqClientVg* pVg = pollRspWrapper->vgHandle;
- pVg->currentOffset = pollRspWrapper->metaRsp.rspOffset;
+ pVg->offsetInfo.currentOffset = pollRspWrapper->metaRsp.rspOffset;
atomic_store_32(&pVg->vgStatus, TMQ_VG_STATUS__IDLE);
// build rsp
SMqMetaRspObj* pRsp = tmqBuildMetaRspFromWrapper(pollRspWrapper);
@@ -1853,7 +1873,7 @@ static void* tmqHandleAllRsp(tmq_t* tmq, int64_t timeout, bool pollIfReset) {
if (pollRspWrapper->taosxRsp.head.epoch == consumerEpoch) {
SMqClientVg* pVg = pollRspWrapper->vgHandle;
- pVg->currentOffset = pollRspWrapper->taosxRsp.rspOffset;
+ pVg->offsetInfo.currentOffset = pollRspWrapper->taosxRsp.rspOffset;
atomic_store_32(&pVg->vgStatus, TMQ_VG_STATUS__IDLE);
if (pollRspWrapper->taosxRsp.blockNum == 0) {
@@ -1879,7 +1899,7 @@ static void* tmqHandleAllRsp(tmq_t* tmq, int64_t timeout, bool pollIfReset) {
tmq->totalRows += numOfRows;
char buf[80];
- tFormatOffset(buf, 80, &pVg->currentOffset);
+ tFormatOffset(buf, 80, &pVg->offsetInfo.currentOffset);
tscDebug("consumer:0x%" PRIx64 " process taosx poll rsp, vgId:%d, offset:%s, blocks:%d, rows:%" PRId64
", vg total:%" PRId64 " total:%" PRId64 " reqId:0x%" PRIx64,
tmq->consumerId, pVg->vgId, buf, pollRspWrapper->dataRsp.blockNum, numOfRows, pVg->numOfRows,
@@ -1915,15 +1935,6 @@ TAOS_RES* tmq_consumer_poll(tmq_t* tmq, int64_t timeout) {
tscDebug("consumer:0x%" PRIx64 " start to poll at %" PRId64 ", timeout:%" PRId64, tmq->consumerId, startTime,
timeout);
-#if 0
- tmqHandleAllDelayedTask(tmq);
- tmqPollImpl(tmq, timeout);
- rspObj = tmqHandleAllRsp(tmq, timeout, false);
- if (rspObj) {
- return (TAOS_RES*)rspObj;
- }
-#endif
-
// in no topic status, delayed task also need to be processed
if (atomic_load_8(&tmq->status) == TMQ_CONSUMER_STATUS__INIT) {
tscDebug("consumer:0x%" PRIx64 " poll return since consumer is init", tmq->consumerId);
@@ -2119,11 +2130,11 @@ void tmq_commit_async(tmq_t* tmq, const TAOS_RES* pRes, tmq_commit_cb* cb, void*
if (pRes == NULL) { // here needs to commit all offsets.
asyncCommitAllOffsets(tmq, cb, param);
} else { // only commit one offset
- asyncCommitOffset(tmq, pRes, cb, param);
+ asyncCommitOffset(tmq, pRes, TDMT_VND_TMQ_COMMIT_OFFSET, cb, param);
}
}
-static void commitCallBackFn(tmq_t *pTmq, int32_t code, void* param) {
+static void commitCallBackFn(tmq_t *UNUSED_PARAM(tmq), int32_t code, void* param) {
SSyncCommitInfo* pInfo = (SSyncCommitInfo*) param;
pInfo->code = code;
tsem_post(&pInfo->sem);
@@ -2139,7 +2150,7 @@ int32_t tmq_commit_sync(tmq_t* tmq, const TAOS_RES* pRes) {
if (pRes == NULL) {
asyncCommitAllOffsets(tmq, commitCallBackFn, pInfo);
} else {
- asyncCommitOffset(tmq, pRes, commitCallBackFn, pInfo);
+ asyncCommitOffset(tmq, pRes, TDMT_VND_TMQ_COMMIT_OFFSET, commitCallBackFn, pInfo);
}
tsem_wait(&pInfo->sem);
@@ -2323,4 +2334,272 @@ SReqResultInfo* tmqGetNextResInfo(TAOS_RES* res, bool convertUcs4) {
}
return NULL;
+}
+
+static int32_t tmqGetWalInfoCb(void* param, SDataBuf* pMsg, int32_t code) {
+ SMqVgWalInfoParam* pParam = param;
+ SMqVgCommon* pCommon = pParam->pCommon;
+
+ int32_t total = atomic_add_fetch_32(&pCommon->numOfRsp, 1);
+ if (code != TSDB_CODE_SUCCESS) {
+ tscError("consumer:0x%" PRIx64 " failed to get the wal info from vgId:%d for topic:%s", pCommon->consumerId,
+ pParam->vgId, pCommon->pTopicName);
+ pCommon->code = code;
+ } else {
+ SMqDataRsp rsp;
+ SDecoder decoder;
+ tDecoderInit(&decoder, POINTER_SHIFT(pMsg->pData, sizeof(SMqRspHead)), pMsg->len - sizeof(SMqRspHead));
+ tDecodeMqDataRsp(&decoder, &rsp);
+ tDecoderClear(&decoder);
+
+ SMqRspHead* pHead = pMsg->pData;
+
+ tmq_topic_assignment assignment = {.begin = pHead->walsver,
+ .end = pHead->walever,
+ .currentOffset = rsp.rspOffset.version,
+ .vgId = pParam->vgId};
+
+ taosThreadMutexLock(&pCommon->mutex);
+ taosArrayPush(pCommon->pList, &assignment);
+ taosThreadMutexUnlock(&pCommon->mutex);
+ }
+
+ if (total == pParam->totalReq) {
+ tsem_post(&pCommon->rsp);
+ }
+
+ taosMemoryFree(pParam);
+ return 0;
+}
+
+static void destroyCommonInfo(SMqVgCommon* pCommon) {
+ taosArrayDestroy(pCommon->pList);
+ tsem_destroy(&pCommon->rsp);
+ taosThreadMutexDestroy(&pCommon->mutex);
+ taosMemoryFree(pCommon->pTopicName);
+ taosMemoryFree(pCommon);
+}
+
+int32_t tmq_get_topic_assignment(tmq_t* tmq, const char* pTopicName, tmq_topic_assignment** assignment,
+ int32_t* numOfAssignment) {
+ *numOfAssignment = 0;
+ *assignment = NULL;
+
+ int32_t accId = tmq->pTscObj->acctId;
+ char tname[128] = {0};
+ sprintf(tname, "%d.%s", accId, pTopicName);
+
+ SMqClientTopic* pTopic = getTopicByName(tmq, tname);
+ if (pTopic == NULL) {
+ return TSDB_CODE_INVALID_PARA;
+ }
+
+ // in case of snapshot is opened, no valid offset will return
+ *numOfAssignment = taosArrayGetSize(pTopic->vgs);
+
+ *assignment = taosMemoryCalloc(*numOfAssignment, sizeof(tmq_topic_assignment));
+ if (*assignment == NULL) {
+ tscError("consumer:0x%" PRIx64 " failed to malloc buffer, size:%" PRIzu, tmq->consumerId,
+ (*numOfAssignment) * sizeof(tmq_topic_assignment));
+ return TSDB_CODE_OUT_OF_MEMORY;
+ }
+
+ bool needFetch = false;
+
+ for (int32_t j = 0; j < (*numOfAssignment); ++j) {
+ SMqClientVg* pClientVg = taosArrayGet(pTopic->vgs, j);
+ if (!pClientVg->receiveInfo) {
+ needFetch = true;
+ break;
+ }
+
+ tmq_topic_assignment* pAssignment = &(*assignment)[j];
+ if (pClientVg->offsetInfo.currentOffset.type == TMQ_OFFSET__LOG) {
+ pAssignment->currentOffset = pClientVg->offsetInfo.currentOffset.version;
+ } else {
+ pAssignment->currentOffset = 0;
+ }
+
+ pAssignment->begin = pClientVg->offsetInfo.walVerBegin;
+ pAssignment->end = pClientVg->offsetInfo.walVerEnd;
+ pAssignment->vgId = pClientVg->vgId;
+ }
+
+ if (needFetch) {
+ SMqVgCommon* pCommon = taosMemoryCalloc(1, sizeof(SMqVgCommon));
+ if (pCommon == NULL) {
+ terrno = TSDB_CODE_OUT_OF_MEMORY;
+ return terrno;
+ }
+
+ pCommon->pList= taosArrayInit(4, sizeof(tmq_topic_assignment));
+ tsem_init(&pCommon->rsp, 0, 0);
+ taosThreadMutexInit(&pCommon->mutex, 0);
+ pCommon->pTopicName = taosStrdup(pTopic->topicName);
+ pCommon->consumerId = tmq->consumerId;
+
+ terrno = TSDB_CODE_OUT_OF_MEMORY;
+ for (int32_t i = 0; i < (*numOfAssignment); ++i) {
+ SMqClientVg* pClientVg = taosArrayGet(pTopic->vgs, i);
+
+ SMqVgWalInfoParam* pParam = taosMemoryMalloc(sizeof(SMqVgWalInfoParam));
+ if (pParam == NULL) {
+ destroyCommonInfo(pCommon);
+ return terrno;
+ }
+
+ pParam->epoch = tmq->epoch;
+ pParam->vgId = pClientVg->vgId;
+ pParam->totalReq = *numOfAssignment;
+ pParam->pCommon = pCommon;
+
+ SMqPollReq req = {0};
+ tmqBuildConsumeReqImpl(&req, tmq, 10, pTopic, pClientVg);
+
+ int32_t msgSize = tSerializeSMqPollReq(NULL, 0, &req);
+ if (msgSize < 0) {
+ taosMemoryFree(pParam);
+ destroyCommonInfo(pCommon);
+ return terrno;
+ }
+
+ char* msg = taosMemoryCalloc(1, msgSize);
+ if (NULL == msg) {
+ taosMemoryFree(pParam);
+ destroyCommonInfo(pCommon);
+ return terrno;
+ }
+
+ if (tSerializeSMqPollReq(msg, msgSize, &req) < 0) {
+ taosMemoryFree(msg);
+ taosMemoryFree(pParam);
+ destroyCommonInfo(pCommon);
+ return terrno;
+ }
+
+ SMsgSendInfo* sendInfo = taosMemoryCalloc(1, sizeof(SMsgSendInfo));
+ if (sendInfo == NULL) {
+ taosMemoryFree(pParam);
+ taosMemoryFree(msg);
+ destroyCommonInfo(pCommon);
+ return terrno;
+ }
+
+ sendInfo->msgInfo = (SDataBuf){.pData = msg, .len = msgSize, .handle = NULL};
+ sendInfo->requestId = req.reqId;
+ sendInfo->requestObjRefId = 0;
+ sendInfo->param = pParam;
+ sendInfo->fp = tmqGetWalInfoCb;
+ sendInfo->msgType = TDMT_VND_TMQ_VG_WALINFO;
+
+ int64_t transporterId = 0;
+ char offsetFormatBuf[80];
+ tFormatOffset(offsetFormatBuf, tListLen(offsetFormatBuf), &pClientVg->offsetInfo.currentOffset);
+
+ tscDebug("consumer:0x%" PRIx64 " %s retrieve wal info vgId:%d, epoch %d, req:%s, reqId:0x%" PRIx64,
+ tmq->consumerId, pTopic->topicName, pClientVg->vgId, tmq->epoch, offsetFormatBuf, req.reqId);
+ asyncSendMsgToServer(tmq->pTscObj->pAppInfo->pTransporter, &pClientVg->epSet, &transporterId, sendInfo);
+ }
+
+ tsem_wait(&pCommon->rsp);
+ int32_t code = pCommon->code;
+
+ terrno = code;
+ if (code != TSDB_CODE_SUCCESS) {
+ taosMemoryFree(*assignment);
+ *assignment = NULL;
+ *numOfAssignment = 0;
+ } else {
+ int32_t num = taosArrayGetSize(pCommon->pList);
+ for(int32_t i = 0; i < num; ++i) {
+ (*assignment)[i] = *(tmq_topic_assignment*)taosArrayGet(pCommon->pList, i);
+ }
+ *numOfAssignment = num;
+ }
+
+ destroyCommonInfo(pCommon);
+ return code;
+ } else {
+ return TSDB_CODE_SUCCESS;
+ }
+}
+
+int32_t tmq_offset_seek(tmq_t* tmq, const char* pTopicName, int32_t vgId, int64_t offset) {
+ if (tmq == NULL) {
+ tscError("invalid tmq handle, null");
+ return TSDB_CODE_INVALID_PARA;
+ }
+
+ int32_t accId = tmq->pTscObj->acctId;
+ char tname[128] = {0};
+ sprintf(tname, "%d.%s", accId, pTopicName);
+
+ SMqClientTopic* pTopic = getTopicByName(tmq, tname);
+ if (pTopic == NULL) {
+ tscError("consumer:0x%" PRIx64 " invalid topic name:%s", tmq->consumerId, pTopicName);
+ return TSDB_CODE_INVALID_PARA;
+ }
+
+ SMqClientVg* pVg = NULL;
+ int32_t numOfVgs = taosArrayGetSize(pTopic->vgs);
+ for (int32_t i = 0; i < numOfVgs; ++i) {
+ SMqClientVg* pClientVg = taosArrayGet(pTopic->vgs, i);
+ if (pClientVg->vgId == vgId) {
+ pVg = pClientVg;
+ break;
+ }
+ }
+
+ if (pVg == NULL) {
+ tscError("consumer:0x%" PRIx64 " invalid vgroup id:%d", tmq->consumerId, vgId);
+ return TSDB_CODE_INVALID_PARA;
+ }
+
+ SVgOffsetInfo* pOffsetInfo = &pVg->offsetInfo;
+
+ int32_t type = pOffsetInfo->currentOffset.type;
+ if (type != TMQ_OFFSET__LOG) {
+ tscError("consumer:0x%" PRIx64 " offset type:%d not wal version, seek not allowed", tmq->consumerId, type);
+ return TSDB_CODE_INVALID_PARA;
+ }
+
+ if (offset < pOffsetInfo->walVerBegin || offset > pOffsetInfo->walVerEnd) {
+ tscError("consumer:0x%" PRIx64 " invalid seek params, offset:%" PRId64, tmq->consumerId, offset);
+ return TSDB_CODE_INVALID_PARA;
+ }
+
+ // update the offset, and then commit to vnode
+ if (pOffsetInfo->currentOffset.type == TMQ_OFFSET__LOG) {
+ pOffsetInfo->currentOffset.version = offset;
+ pOffsetInfo->committedOffset.version = INT64_MIN;
+ }
+
+ SMqRspObj rspObj = {.resType = RES_TYPE__TMQ, .vgId = pVg->vgId};
+ tstrncpy(rspObj.topic, tname, tListLen(rspObj.topic));
+
+ tscDebug("consumer:0x%" PRIx64 " seek to %" PRId64 " on vgId:%d", tmq->consumerId, offset, pVg->vgId);
+
+ SSyncCommitInfo* pInfo = taosMemoryMalloc(sizeof(SSyncCommitInfo));
+ if (pInfo == NULL) {
+ tscError("consumer:0x%"PRIx64" failed to prepare seek operation", tmq->consumerId);
+ return TSDB_CODE_OUT_OF_MEMORY;
+ }
+
+ tsem_init(&pInfo->sem, 0, 0);
+ pInfo->code = 0;
+
+ asyncCommitOffset(tmq, &rspObj, TDMT_VND_TMQ_SEEK_TO_OFFSET, commitCallBackFn, pInfo);
+
+ tsem_wait(&pInfo->sem);
+ int32_t code = pInfo->code;
+
+ tsem_destroy(&pInfo->sem);
+ taosMemoryFree(pInfo);
+
+ if (code != TSDB_CODE_SUCCESS) {
+ tscError("consumer:0x%" PRIx64 " failed to send seek to vgId:%d, code:%s", tmq->consumerId, pVg->vgId,
+ tstrerror(code));
+ }
+
+ return code;
}
\ No newline at end of file
diff --git a/source/client/test/clientTests.cpp b/source/client/test/clientTests.cpp
index 055ac450dc..f15a93cb2c 100644
--- a/source/client/test/clientTests.cpp
+++ b/source/client/test/clientTests.cpp
@@ -30,6 +30,27 @@
#include "taos.h"
namespace {
+
+void printSubResults(void* pRes, int32_t* totalRows) {
+ char buf[1024];
+
+ while (1) {
+ TAOS_ROW row = taos_fetch_row(pRes);
+ if (row == NULL) {
+ break;
+ }
+
+ TAOS_FIELD* fields = taos_fetch_fields(pRes);
+ int32_t numOfFields = taos_field_count(pRes);
+ int32_t precision = taos_result_precision(pRes);
+ taos_print_row(buf, row, fields, numOfFields);
+ *totalRows += 1;
+ printf("precision: %d, row content: %s\n", precision, buf);
+ }
+
+// taos_free_result(pRes);
+}
+
void showDB(TAOS* pConn) {
TAOS_RES* pRes = taos_query(pConn, "show databases");
TAOS_ROW pRow = NULL;
@@ -112,7 +133,7 @@ void createNewTable(TAOS* pConn, int32_t index) {
}
taos_free_result(pRes);
- for (int32_t i = 0; i < 100; i += 20) {
+ for (int32_t i = 0; i < 10000; i += 20) {
char sql[1024] = {0};
sprintf(sql,
"insert into tu%d values(now+%da, %d)(now+%da, %d)(now+%da, %d)(now+%da, %d)"
@@ -803,7 +824,7 @@ TEST(clientCase, projection_query_tables) {
}
taos_free_result(pRes);
- for (int32_t i = 0; i < 10000; ++i) {
+ for (int32_t i = 0; i < 1; ++i) {
printf("create table :%d\n", i);
createNewTable(pConn, i);
}
@@ -990,7 +1011,7 @@ TEST(clientCase, sub_db_test) {
tmq_conf_set(conf, "td.connect.user", "root");
tmq_conf_set(conf, "td.connect.pass", "taosdata");
tmq_conf_set(conf, "auto.offset.reset", "earliest");
- tmq_conf_set(conf, "experimental.snapshot.enable", "true");
+ tmq_conf_set(conf, "experimental.snapshot.enable", "false");
tmq_conf_set(conf, "msg.with.table.name", "true");
tmq_conf_set_auto_commit_cb(conf, tmq_commit_cb_print, NULL);
@@ -1000,7 +1021,7 @@ TEST(clientCase, sub_db_test) {
// 创建订阅 topics 列表
tmq_list_t* topicList = tmq_list_new();
tmq_list_append(topicList, "topic_t1");
- tmq_list_append(topicList, "topic_s2");
+// tmq_list_append(topicList, "topic_s2");
// 启动订阅
tmq_subscribe(tmq, topicList);
@@ -1059,13 +1080,13 @@ TEST(clientCase, sub_tb_test) {
ASSERT_NE(pConn, nullptr);
tmq_conf_t* conf = tmq_conf_new();
- tmq_conf_set(conf, "enable.auto.commit", "true");
+ tmq_conf_set(conf, "enable.auto.commit", "false");
tmq_conf_set(conf, "auto.commit.interval.ms", "1000");
- tmq_conf_set(conf, "group.id", "cgrpName45");
+ tmq_conf_set(conf, "group.id", "cgrpName1024");
tmq_conf_set(conf, "td.connect.user", "root");
tmq_conf_set(conf, "td.connect.pass", "taosdata");
tmq_conf_set(conf, "auto.offset.reset", "earliest");
- tmq_conf_set(conf, "experimental.snapshot.enable", "true");
+ tmq_conf_set(conf, "experimental.snapshot.enable", "false");
tmq_conf_set(conf, "msg.with.table.name", "true");
tmq_conf_set_auto_commit_cb(conf, tmq_commit_cb_print, NULL);
@@ -1074,11 +1095,10 @@ TEST(clientCase, sub_tb_test) {
// 创建订阅 topics 列表
tmq_list_t* topicList = tmq_list_new();
- tmq_list_append(topicList, "topic_t2");
+ tmq_list_append(topicList, "topic_t1");
// 启动订阅
tmq_subscribe(tmq, topicList);
-
tmq_list_destroy(topicList);
TAOS_FIELD* fields = NULL;
@@ -1090,11 +1110,21 @@ TEST(clientCase, sub_tb_test) {
int32_t count = 0;
+ tmq_topic_assignment* pAssign = NULL;
+ int32_t numOfAssign = 0;
+
+ int32_t code = tmq_get_topic_assignment(tmq, "topic_t1", &pAssign, &numOfAssign);
+ if (code != 0) {
+ printf("error occurs:%s\n", tmq_err2str(code));
+ tmq_consumer_close(tmq);
+ taos_close(pConn);
+ fprintf(stderr, "%d msg consumed, include %d rows\n", msgCnt, totalRows);
+ return;
+ }
+
while (1) {
TAOS_RES* pRes = tmq_consumer_poll(tmq, timeout);
- if (pRes) {
- char buf[1024];
-
+ if (pRes != NULL) {
const char* topicName = tmq_get_topic_name(pRes);
const char* dbName = tmq_get_db_name(pRes);
int32_t vgroupId = tmq_get_vgroup_id(pRes);
@@ -1103,27 +1133,18 @@ TEST(clientCase, sub_tb_test) {
printf("db: %s\n", dbName);
printf("vgroup id: %d\n", vgroupId);
- while (1) {
- TAOS_ROW row = taos_fetch_row(pRes);
- if (row == NULL) {
- break;
- }
-
- fields = taos_fetch_fields(pRes);
- numOfFields = taos_field_count(pRes);
- precision = taos_result_precision(pRes);
- taos_print_row(buf, row, fields, numOfFields);
- totalRows += 1;
- printf("precision: %d, row content: %s\n", precision, buf);
- }
-
- taos_free_result(pRes);
- // if ((++count) > 1) {
- // break;
- // }
+ printSubResults(pRes, &totalRows);
} else {
- break;
+// tmq_offset_seek(tmq, "topic_t1", pAssign[0].vgroupHandle, pAssign[0].begin);
+// break;
}
+
+ tmq_commit_sync(tmq, pRes);
+ if (pRes != NULL) {
+ taos_free_result(pRes);
+ }
+
+ tmq_offset_seek(tmq, "topic_t1", pAssign[0].vgId, pAssign[0].begin);
}
tmq_consumer_close(tmq);
diff --git a/source/common/src/tdataformat.c b/source/common/src/tdataformat.c
index d6ab974c6c..796c5cf8ff 100644
--- a/source/common/src/tdataformat.c
+++ b/source/common/src/tdataformat.c
@@ -500,7 +500,7 @@ int32_t tRowGet(SRow *pRow, STSchema *pTSchema, int32_t iCol, SColVal *pColVal)
break;
default:
ASSERTS(0, "invalid row format");
- return TSDB_CODE_IVLD_DATA_FMT;
+ return TSDB_CODE_INVALID_DATA_FMT;
}
if (bv == BIT_FLG_NONE) {
@@ -938,7 +938,7 @@ static int32_t tRowTupleUpsertColData(SRow *pRow, STSchema *pTSchema, SColData *
break;
default:
ASSERTS(0, "Invalid row flag");
- return TSDB_CODE_IVLD_DATA_FMT;
+ return TSDB_CODE_INVALID_DATA_FMT;
}
while (pColData) {
@@ -963,7 +963,7 @@ static int32_t tRowTupleUpsertColData(SRow *pRow, STSchema *pTSchema, SColData *
break;
default:
ASSERTS(0, "Invalid row flag");
- return TSDB_CODE_IVLD_DATA_FMT;
+ return TSDB_CODE_INVALID_DATA_FMT;
}
if (bv == BIT_FLG_NONE) {
@@ -1054,7 +1054,7 @@ static int32_t tRowKVUpsertColData(SRow *pRow, STSchema *pTSchema, SColData *aCo
pData = pv + ((uint32_t *)pKVIdx->idx)[iCol];
} else {
ASSERTS(0, "Invalid KV row format");
- return TSDB_CODE_IVLD_DATA_FMT;
+ return TSDB_CODE_INVALID_DATA_FMT;
}
int16_t cid;
@@ -2503,9 +2503,11 @@ _exit:
int32_t tColDataAddValueByBind(SColData *pColData, TAOS_MULTI_BIND *pBind) {
int32_t code = 0;
- ASSERT(pColData->type == pBind->buffer_type);
-
- if (IS_VAR_DATA_TYPE(pBind->buffer_type)) { // var-length data type
+ if (!(pBind->num == 1 && pBind->is_null && *pBind->is_null)) {
+ ASSERT(pColData->type == pBind->buffer_type);
+ }
+
+ if (IS_VAR_DATA_TYPE(pColData->type)) { // var-length data type
for (int32_t i = 0; i < pBind->num; ++i) {
if (pBind->is_null && pBind->is_null[i]) {
code = tColDataAppendValueImpl[pColData->flag][CV_FLAG_NULL](pColData, NULL, 0);
diff --git a/source/common/src/tglobal.c b/source/common/src/tglobal.c
index da4a912238..0a29a415f0 100644
--- a/source/common/src/tglobal.c
+++ b/source/common/src/tglobal.c
@@ -117,6 +117,10 @@ int32_t tsRedirectFactor = 2;
int32_t tsRedirectMaxPeriod = 1000;
int32_t tsMaxRetryWaitTime = 10000;
bool tsUseAdapter = false;
+int32_t tsSlowLogThreshold = 3; // seconds
+int32_t tsSlowLogScope = SLOW_LOG_TYPE_ALL;
+
+
/*
@@ -345,6 +349,8 @@ static int32_t taosAddClientCfg(SConfig *pCfg) {
if (cfgAddBool(pCfg, "useAdapter", tsUseAdapter, true) != 0) return -1;
if (cfgAddBool(pCfg, "crashReporting", tsEnableCrashReport, true) != 0) return -1;
if (cfgAddInt64(pCfg, "queryMaxConcurrentTables", tsQueryMaxConcurrentTables, INT64_MIN, INT64_MAX, 1) != 0) return -1;
+ if (cfgAddInt32(pCfg, "slowLogThreshold", tsSlowLogThreshold, 0, INT32_MAX, true) != 0) return -1;
+ if (cfgAddString(pCfg, "slowLogScope", "", true) != 0) return -1;
tsNumOfRpcThreads = tsNumOfCores / 2;
tsNumOfRpcThreads = TRANGE(tsNumOfRpcThreads, 2, TSDB_MAX_RPC_THREADS);
@@ -692,6 +698,42 @@ static void taosSetServerLogCfg(SConfig *pCfg) {
metaDebugFlag = cfgGetItem(pCfg, "metaDebugFlag")->i32;
}
+static int32_t taosSetSlowLogScope(char *pScope) {
+ if (NULL == pScope || 0 == strlen(pScope)) {
+ tsSlowLogScope = SLOW_LOG_TYPE_ALL;
+ return 0;
+ }
+
+ if (0 == strcasecmp(pScope, "all")) {
+ tsSlowLogScope = SLOW_LOG_TYPE_ALL;
+ return 0;
+ }
+
+ if (0 == strcasecmp(pScope, "query")) {
+ tsSlowLogScope = SLOW_LOG_TYPE_QUERY;
+ return 0;
+ }
+
+ if (0 == strcasecmp(pScope, "insert")) {
+ tsSlowLogScope = SLOW_LOG_TYPE_INSERT;
+ return 0;
+ }
+
+ if (0 == strcasecmp(pScope, "others")) {
+ tsSlowLogScope = SLOW_LOG_TYPE_OTHERS;
+ return 0;
+ }
+
+ if (0 == strcasecmp(pScope, "none")) {
+ tsSlowLogScope = 0;
+ return 0;
+ }
+
+ uError("Invalid slowLog scope value:%s", pScope);
+ terrno = TSDB_CODE_INVALID_CFG_VALUE;
+ return -1;
+}
+
static int32_t taosSetClientCfg(SConfig *pCfg) {
tstrncpy(tsLocalFqdn, cfgGetItem(pCfg, "fqdn")->str, TSDB_FQDN_LEN);
tsServerPort = (uint16_t)cfgGetItem(pCfg, "serverPort")->i32;
@@ -742,6 +784,10 @@ static int32_t taosSetClientCfg(SConfig *pCfg) {
tsUseAdapter = cfgGetItem(pCfg, "useAdapter")->bval;
tsEnableCrashReport = cfgGetItem(pCfg, "crashReporting")->bval;
tsQueryMaxConcurrentTables = cfgGetItem(pCfg, "queryMaxConcurrentTables")->i64;
+ tsSlowLogThreshold = cfgGetItem(pCfg, "slowLogThreshold")->i32;
+ if (taosSetSlowLogScope(cfgGetItem(pCfg, "slowLogScope")->str)) {
+ return -1;
+ }
tsMaxRetryWaitTime = cfgGetItem(pCfg, "maxRetryWaitTime")->i32;
@@ -1156,6 +1202,12 @@ int32_t taosSetCfg(SConfig *pCfg, char *name) {
sDebugFlag = cfgGetItem(pCfg, "sDebugFlag")->i32;
} else if (strcasecmp("smaDebugFlag", name) == 0) {
smaDebugFlag = cfgGetItem(pCfg, "smaDebugFlag")->i32;
+ } else if (strcasecmp("slowLogThreshold", name) == 0) {
+ tsSlowLogThreshold = cfgGetItem(pCfg, "slowLogThreshold")->i32;
+ } else if (strcasecmp("slowLogScope", name) == 0) {
+ if (taosSetSlowLogScope(cfgGetItem(pCfg, "slowLogScope")->str)) {
+ return -1;
+ }
}
break;
}
diff --git a/source/common/src/tmsg.c b/source/common/src/tmsg.c
index 85c150066d..4139d6c7d4 100644
--- a/source/common/src/tmsg.c
+++ b/source/common/src/tmsg.c
@@ -2936,6 +2936,59 @@ void tFreeSUserAuthBatchRsp(SUserAuthBatchRsp *pRsp) {
taosArrayDestroy(pRsp->pArray);
}
+int32_t tSerializeSUserPassBatchRsp(void *buf, int32_t bufLen, SUserPassBatchRsp *pRsp) {
+ SEncoder encoder = {0};
+ tEncoderInit(&encoder, buf, bufLen);
+
+ if (tStartEncode(&encoder) < 0) return -1;
+
+ int32_t numOfBatch = taosArrayGetSize(pRsp->pArray);
+ if (tEncodeI32(&encoder, numOfBatch) < 0) return -1;
+ for (int32_t i = 0; i < numOfBatch; ++i) {
+ SGetUserPassRsp *pUserPassRsp = taosArrayGet(pRsp->pArray, i);
+ if (tEncodeCStr(&encoder, pUserPassRsp->user) < 0) return -1;
+ if (tEncodeI32(&encoder, pUserPassRsp->version) < 0) return -1;
+ }
+ tEndEncode(&encoder);
+
+ int32_t tlen = encoder.pos;
+ tEncoderClear(&encoder);
+ return tlen;
+}
+
+int32_t tDeserializeSUserPassBatchRsp(void *buf, int32_t bufLen, SUserPassBatchRsp *pRsp) {
+ SDecoder decoder = {0};
+ tDecoderInit(&decoder, buf, bufLen);
+
+ if (tStartDecode(&decoder) < 0) return -1;
+
+ int32_t numOfBatch = taosArrayGetSize(pRsp->pArray);
+ if (tDecodeI32(&decoder, &numOfBatch) < 0) return -1;
+
+ pRsp->pArray = taosArrayInit(numOfBatch, sizeof(SGetUserPassRsp));
+ if (pRsp->pArray == NULL) {
+ terrno = TSDB_CODE_OUT_OF_MEMORY;
+ return -1;
+ }
+
+ for (int32_t i = 0; i < numOfBatch; ++i) {
+ SGetUserPassRsp rsp = {0};
+ if (tDecodeCStrTo(&decoder, rsp.user) < 0) return -1;
+ if (tDecodeI32(&decoder, &rsp.version) < 0) return -1;
+ taosArrayPush(pRsp->pArray, &rsp);
+ }
+ tEndDecode(&decoder);
+
+ tDecoderClear(&decoder);
+ return 0;
+}
+
+void tFreeSUserPassBatchRsp(SUserPassBatchRsp *pRsp) {
+ if(pRsp) {
+ taosArrayDestroy(pRsp->pArray);
+ }
+}
+
int32_t tSerializeSDbCfgReq(void *buf, int32_t bufLen, SDbCfgReq *pReq) {
SEncoder encoder = {0};
tEncoderInit(&encoder, buf, bufLen);
@@ -3976,6 +4029,7 @@ int32_t tSerializeSConnectRsp(void *buf, int32_t bufLen, SConnectRsp *pRsp) {
if (tEncodeI32(&encoder, pRsp->svrTimestamp) < 0) return -1;
if (tEncodeCStr(&encoder, pRsp->sVer) < 0) return -1;
if (tEncodeCStr(&encoder, pRsp->sDetailVer) < 0) return -1;
+ if (tEncodeI32(&encoder, pRsp->passVer) < 0) return -1;
tEndEncode(&encoder);
int32_t tlen = encoder.pos;
@@ -3999,6 +4053,13 @@ int32_t tDeserializeSConnectRsp(void *buf, int32_t bufLen, SConnectRsp *pRsp) {
if (tDecodeI32(&decoder, &pRsp->svrTimestamp) < 0) return -1;
if (tDecodeCStrTo(&decoder, pRsp->sVer) < 0) return -1;
if (tDecodeCStrTo(&decoder, pRsp->sDetailVer) < 0) return -1;
+
+ if (!tDecodeIsEnd(&decoder)) {
+ if (tDecodeI32(&decoder, &pRsp->passVer) < 0) return -1;
+ } else {
+ pRsp->passVer = 0;
+ }
+
tEndDecode(&decoder);
tDecoderClear(&decoder);
@@ -6951,6 +7012,18 @@ int32_t tDecodeSTqOffset(SDecoder *pDecoder, STqOffset *pOffset) {
return 0;
}
+int32_t tEncodeMqVgOffset(SEncoder* pEncoder, const SMqVgOffset* pOffset) {
+ if (tEncodeSTqOffset(pEncoder, &pOffset->offset) < 0) return -1;
+ if (tEncodeI64(pEncoder, pOffset->consumerId) < 0) return -1;
+ return 0;
+}
+
+int32_t tDecodeMqVgOffset(SDecoder* pDecoder, SMqVgOffset* pOffset) {
+ if (tDecodeSTqOffset(pDecoder, &pOffset->offset) < 0) return -1;
+ if (tDecodeI64(pDecoder, &pOffset->consumerId) < 0) return -1;
+ return 0;
+}
+
int32_t tEncodeSTqCheckInfo(SEncoder *pEncoder, const STqCheckInfo *pInfo) {
if (tEncodeCStr(pEncoder, pInfo->topic) < 0) return -1;
if (tEncodeI64(pEncoder, pInfo->ntbUid) < 0) return -1;
@@ -7015,21 +7088,21 @@ int32_t tDecodeDeleteRes(SDecoder *pCoder, SDeleteRes *pRes) {
return 0;
}
-int32_t tEncodeSMqMetaRsp(SEncoder *pEncoder, const SMqMetaRsp *pRsp) {
+int32_t tEncodeMqMetaRsp(SEncoder *pEncoder, const SMqMetaRsp *pRsp) {
if (tEncodeSTqOffsetVal(pEncoder, &pRsp->rspOffset) < 0) return -1;
if (tEncodeI16(pEncoder, pRsp->resMsgType)) return -1;
if (tEncodeBinary(pEncoder, pRsp->metaRsp, pRsp->metaRspLen)) return -1;
return 0;
}
-int32_t tDecodeSMqMetaRsp(SDecoder *pDecoder, SMqMetaRsp *pRsp) {
+int32_t tDecodeMqMetaRsp(SDecoder *pDecoder, SMqMetaRsp *pRsp) {
if (tDecodeSTqOffsetVal(pDecoder, &pRsp->rspOffset) < 0) return -1;
if (tDecodeI16(pDecoder, &pRsp->resMsgType) < 0) return -1;
if (tDecodeBinaryAlloc(pDecoder, &pRsp->metaRsp, (uint64_t *)&pRsp->metaRspLen) < 0) return -1;
return 0;
}
-int32_t tEncodeSMqDataRsp(SEncoder *pEncoder, const SMqDataRsp *pRsp) {
+int32_t tEncodeMqDataRsp(SEncoder *pEncoder, const SMqDataRsp *pRsp) {
if (tEncodeSTqOffsetVal(pEncoder, &pRsp->reqOffset) < 0) return -1;
if (tEncodeSTqOffsetVal(pEncoder, &pRsp->rspOffset) < 0) return -1;
if (tEncodeI32(pEncoder, pRsp->blockNum) < 0) return -1;
@@ -7054,7 +7127,7 @@ int32_t tEncodeSMqDataRsp(SEncoder *pEncoder, const SMqDataRsp *pRsp) {
return 0;
}
-int32_t tDecodeSMqDataRsp(SDecoder *pDecoder, SMqDataRsp *pRsp) {
+int32_t tDecodeMqDataRsp(SDecoder *pDecoder, SMqDataRsp *pRsp) {
if (tDecodeSTqOffsetVal(pDecoder, &pRsp->reqOffset) < 0) return -1;
if (tDecodeSTqOffsetVal(pDecoder, &pRsp->rspOffset) < 0) return -1;
if (tDecodeI32(pDecoder, &pRsp->blockNum) < 0) return -1;
@@ -7099,7 +7172,7 @@ int32_t tDecodeSMqDataRsp(SDecoder *pDecoder, SMqDataRsp *pRsp) {
return 0;
}
-void tDeleteSMqDataRsp(SMqDataRsp *pRsp) {
+void tDeleteMqDataRsp(SMqDataRsp *pRsp) {
pRsp->blockDataLen = taosArrayDestroy(pRsp->blockDataLen);
taosArrayDestroyP(pRsp->blockData, (FDelete)taosMemoryFree);
pRsp->blockData = NULL;
@@ -7200,8 +7273,7 @@ int32_t tDecodeSTaosxRsp(SDecoder *pDecoder, STaosxRsp *pRsp) {
}
void tDeleteSTaosxRsp(STaosxRsp *pRsp) {
- taosArrayDestroy(pRsp->blockDataLen);
- pRsp->blockDataLen = NULL;
+ pRsp->blockDataLen = taosArrayDestroy(pRsp->blockDataLen);
taosArrayDestroyP(pRsp->blockData, (FDelete)taosMemoryFree);
pRsp->blockData = NULL;
taosArrayDestroyP(pRsp->blockSchema, (FDelete)tDeleteSSchemaWrapper);
@@ -7209,8 +7281,7 @@ void tDeleteSTaosxRsp(STaosxRsp *pRsp) {
taosArrayDestroyP(pRsp->blockTbName, (FDelete)taosMemoryFree);
pRsp->blockTbName = NULL;
- taosArrayDestroy(pRsp->createTableLen);
- pRsp->createTableLen = NULL;
+ pRsp->createTableLen = taosArrayDestroy(pRsp->createTableLen);
taosArrayDestroyP(pRsp->createTableReq, (FDelete)taosMemoryFree);
pRsp->createTableReq = NULL;
}
@@ -7583,3 +7654,41 @@ void tDestroySSubmitRsp2(SSubmitRsp2 *pRsp, int32_t flag) {
}
}
}
+
+int32_t tEncodeMqSubTopicEp(void **buf, const SMqSubTopicEp *pTopicEp) {
+ int32_t tlen = 0;
+ tlen += taosEncodeString(buf, pTopicEp->topic);
+ tlen += taosEncodeString(buf, pTopicEp->db);
+ int32_t sz = taosArrayGetSize(pTopicEp->vgs);
+ tlen += taosEncodeFixedI32(buf, sz);
+ for (int32_t i = 0; i < sz; i++) {
+ SMqSubVgEp *pVgEp = (SMqSubVgEp *)taosArrayGet(pTopicEp->vgs, i);
+ tlen += tEncodeSMqSubVgEp(buf, pVgEp);
+ }
+ tlen += taosEncodeSSchemaWrapper(buf, &pTopicEp->schema);
+ return tlen;
+}
+
+void *tDecodeMqSubTopicEp(void *buf, SMqSubTopicEp *pTopicEp) {
+ buf = taosDecodeStringTo(buf, pTopicEp->topic);
+ buf = taosDecodeStringTo(buf, pTopicEp->db);
+ int32_t sz;
+ buf = taosDecodeFixedI32(buf, &sz);
+ pTopicEp->vgs = taosArrayInit(sz, sizeof(SMqSubVgEp));
+ if (pTopicEp->vgs == NULL) {
+ return NULL;
+ }
+ for (int32_t i = 0; i < sz; i++) {
+ SMqSubVgEp vgEp;
+ buf = tDecodeSMqSubVgEp(buf, &vgEp);
+ taosArrayPush(pTopicEp->vgs, &vgEp);
+ }
+ buf = taosDecodeSSchemaWrapper(buf, &pTopicEp->schema);
+ return buf;
+}
+
+void tDeleteMqSubTopicEp(SMqSubTopicEp *pSubTopicEp) {
+ taosMemoryFreeClear(pSubTopicEp->schema.pSchema);
+ pSubTopicEp->schema.nCols = 0;
+ taosArrayDestroy(pSubTopicEp->vgs);
+}
\ No newline at end of file
diff --git a/source/dnode/mgmt/mgmt_mnode/src/mmInt.c b/source/dnode/mgmt/mgmt_mnode/src/mmInt.c
index 05b59b9865..7840528db9 100644
--- a/source/dnode/mgmt/mgmt_mnode/src/mmInt.c
+++ b/source/dnode/mgmt/mgmt_mnode/src/mmInt.c
@@ -159,6 +159,10 @@ static int32_t mmSyncIsCatchUp(SMnodeMgmt *pMgmt) {
return mndIsCatchUp(pMgmt->pMnode);
}
+static ESyncRole mmSyncGetRole(SMnodeMgmt *pMgmt) {
+ return mndGetRole(pMgmt->pMnode);
+}
+
SMgmtFunc mmGetMgmtFunc() {
SMgmtFunc mgmtFunc = {0};
mgmtFunc.openFp = mmOpen;
@@ -170,6 +174,7 @@ SMgmtFunc mmGetMgmtFunc() {
mgmtFunc.requiredFp = mmRequire;
mgmtFunc.getHandlesFp = mmGetMsgHandles;
mgmtFunc.isCatchUpFp = (NodeIsCatchUpFp)mmSyncIsCatchUp;
+ mgmtFunc.nodeRoleFp = (NodeRole)mmSyncGetRole;
return mgmtFunc;
}
diff --git a/source/dnode/mgmt/mgmt_vnode/src/vmHandle.c b/source/dnode/mgmt/mgmt_vnode/src/vmHandle.c
index d7197832e5..9dbc12cf62 100644
--- a/source/dnode/mgmt/mgmt_vnode/src/vmHandle.c
+++ b/source/dnode/mgmt/mgmt_vnode/src/vmHandle.c
@@ -336,13 +336,23 @@ int32_t vmProcessAlterVnodeTypeReq(SVnodeMgmt *pMgmt, SRpcMsg *pMsg) {
SVnodeObj *pVnode = vmAcquireVnode(pMgmt, req.vgId);
if (pVnode == NULL) {
- dError("vgId:%d, failed to alter hashrange since %s", req.vgId, terrstr());
+ dError("vgId:%d, failed to alter vnode type since %s", req.vgId, terrstr());
terrno = TSDB_CODE_VND_NOT_EXIST;
return -1;
}
+ ESyncRole role = vnodeGetRole(pVnode->pImpl);
+ dInfo("vgId:%d, checking node role:%d", req.vgId, role);
+ if(role == TAOS_SYNC_ROLE_VOTER){
+ terrno = TSDB_CODE_VND_ALREADY_IS_VOTER;
+ vmReleaseVnode(pMgmt, pVnode);
+ return -1;
+ }
+
dInfo("vgId:%d, checking node catch up", req.vgId);
- if(vnodeIsCatchUp(pVnode->pImpl) != 0){
+ if(vnodeIsCatchUp(pVnode->pImpl) != 1){
+ terrno = TSDB_CODE_VND_NOT_CATCH_UP;
+ vmReleaseVnode(pMgmt, pVnode);
return -1;
}
@@ -365,6 +375,7 @@ int32_t vmProcessAlterVnodeTypeReq(SVnodeMgmt *pMgmt, SRpcMsg *pMsg) {
req.selfIndex >= req.replica || req.learnerSelfIndex >= req.learnerReplica) {
terrno = TSDB_CODE_INVALID_MSG;
dError("vgId:%d, failed to alter replica since invalid msg", vgId);
+ vmReleaseVnode(pMgmt, pVnode);
return -1;
}
@@ -381,6 +392,7 @@ int32_t vmProcessAlterVnodeTypeReq(SVnodeMgmt *pMgmt, SRpcMsg *pMsg) {
terrno = TSDB_CODE_INVALID_MSG;
dError("vgId:%d, dnodeId:%d ep:%s:%u not matched with local dnode", vgId, pReplica->id, pReplica->fqdn,
pReplica->port);
+ vmReleaseVnode(pMgmt, pVnode);
return -1;
}
@@ -680,9 +692,11 @@ SArray *vmGetMsgHandles() {
if (dmSetMgmtHandle(pArray, TDMT_VND_TMQ_SUBSCRIBE, vmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_VND_TMQ_DELETE_SUB, vmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_VND_TMQ_COMMIT_OFFSET, vmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
+ if (dmSetMgmtHandle(pArray, TDMT_VND_TMQ_SEEK_TO_OFFSET, vmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_VND_TMQ_ADD_CHECKINFO, vmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_VND_TMQ_DEL_CHECKINFO, vmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_VND_TMQ_CONSUME, vmPutMsgToFetchQueue, 0) == NULL) goto _OVER;
+ if (dmSetMgmtHandle(pArray, TDMT_VND_TMQ_VG_WALINFO, vmPutMsgToFetchQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_VND_DELETE, vmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_VND_BATCH_DEL, vmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
if (dmSetMgmtHandle(pArray, TDMT_VND_COMMIT, vmPutMsgToWriteQueue, 0) == NULL) goto _OVER;
diff --git a/source/dnode/mgmt/node_mgmt/src/dmEnv.c b/source/dnode/mgmt/node_mgmt/src/dmEnv.c
index c53c21cd30..3459af1a3a 100644
--- a/source/dnode/mgmt/node_mgmt/src/dmEnv.c
+++ b/source/dnode/mgmt/node_mgmt/src/dmEnv.c
@@ -214,9 +214,19 @@ static int32_t dmProcessAlterNodeTypeReq(EDndNodeType ntype, SRpcMsg *pMsg) {
pWrapper = &pDnode->wrappers[ntype];
+ if(pWrapper->func.nodeRoleFp != NULL){
+ ESyncRole role = (*pWrapper->func.nodeRoleFp)(pWrapper->pMgmt);
+ dInfo("node:%s, checking node role:%d", pWrapper->name, role);
+ if(role == TAOS_SYNC_ROLE_VOTER){
+ terrno = TSDB_CODE_MNODE_ALREADY_IS_VOTER;
+ return -1;
+ }
+ }
+
if(pWrapper->func.isCatchUpFp != NULL){
dInfo("node:%s, checking node catch up", pWrapper->name);
- if(!(*pWrapper->func.isCatchUpFp)(pWrapper->pMgmt) == 0){
+ if((*pWrapper->func.isCatchUpFp)(pWrapper->pMgmt) != 1){
+ terrno = TSDB_CODE_MNODE_NOT_CATCH_UP;
return -1;
}
}
diff --git a/source/dnode/mgmt/node_util/inc/dmUtil.h b/source/dnode/mgmt/node_util/inc/dmUtil.h
index 000ce81207..98ef8cd95b 100644
--- a/source/dnode/mgmt/node_util/inc/dmUtil.h
+++ b/source/dnode/mgmt/node_util/inc/dmUtil.h
@@ -135,6 +135,7 @@ typedef int32_t (*NodeDropFp)(const SMgmtInputOpt *pInput, SRpcMsg *pMsg);
typedef int32_t (*NodeRequireFp)(const SMgmtInputOpt *pInput, bool *required);
typedef SArray *(*NodeGetHandlesFp)(); // array of SMgmtHandle
typedef bool (*NodeIsCatchUpFp)(void *pMgmt);
+typedef bool (*NodeRole)(void *pMgmt);
typedef struct {
NodeOpenFp openFp;
@@ -146,6 +147,7 @@ typedef struct {
NodeRequireFp requiredFp;
NodeGetHandlesFp getHandlesFp;
NodeIsCatchUpFp isCatchUpFp;
+ NodeRole nodeRoleFp;
} SMgmtFunc;
typedef struct {
diff --git a/source/dnode/mnode/impl/inc/mndDef.h b/source/dnode/mnode/impl/inc/mndDef.h
index cc295f0d24..f547ce025d 100644
--- a/source/dnode/mnode/impl/inc/mndDef.h
+++ b/source/dnode/mnode/impl/inc/mndDef.h
@@ -280,6 +280,7 @@ typedef struct {
int8_t reserve;
int32_t acctId;
int32_t authVersion;
+ int32_t passVersion;
SHashObj* readDbs;
SHashObj* writeDbs;
SHashObj* topics;
diff --git a/source/dnode/mnode/impl/inc/mndUser.h b/source/dnode/mnode/impl/inc/mndUser.h
index 95d15f6e5a..aa7f97f087 100644
--- a/source/dnode/mnode/impl/inc/mndUser.h
+++ b/source/dnode/mnode/impl/inc/mndUser.h
@@ -35,6 +35,8 @@ SHashObj *mndDupTableHash(SHashObj *pOld);
SHashObj *mndDupTopicHash(SHashObj *pOld);
int32_t mndValidateUserAuthInfo(SMnode *pMnode, SUserAuthVersion *pUsers, int32_t numOfUses, void **ppRsp,
int32_t *pRspLen);
+int32_t mndValidateUserPassInfo(SMnode *pMnode, SUserPassVersion *pUsers, int32_t numOfUses, void **ppRsp,
+ int32_t *pRspLen);
int32_t mndUserRemoveDb(SMnode *pMnode, STrans *pTrans, char *db);
int32_t mndUserRemoveTopic(SMnode *pMnode, STrans *pTrans, char *topic);
diff --git a/source/dnode/mnode/impl/src/mndConsumer.c b/source/dnode/mnode/impl/src/mndConsumer.c
index 1b146506a2..0d75b5fd68 100644
--- a/source/dnode/mnode/impl/src/mndConsumer.c
+++ b/source/dnode/mnode/impl/src/mndConsumer.c
@@ -556,9 +556,14 @@ static int32_t mndProcessAskEpReq(SRpcMsg *pMsg) {
return -1;
}
- ((SMqRspHead *)buf)->mqMsgType = TMQ_MSG_TYPE__EP_RSP;
- ((SMqRspHead *)buf)->epoch = serverEpoch;
- ((SMqRspHead *)buf)->consumerId = pConsumer->consumerId;
+ SMqRspHead* pHead = buf;
+
+ pHead->mqMsgType = TMQ_MSG_TYPE__EP_RSP;
+ pHead->epoch = serverEpoch;
+ pHead->consumerId = pConsumer->consumerId;
+ pHead->walsver = 0;
+ pHead->walever = 0;
+
void *abuf = POINTER_SHIFT(buf, sizeof(SMqRspHead));
tEncodeSMqAskEpRsp(&abuf, &rsp);
diff --git a/source/dnode/mnode/impl/src/mndDump.c b/source/dnode/mnode/impl/src/mndDump.c
index 44a7d49fff..a991bddda8 100644
--- a/source/dnode/mnode/impl/src/mndDump.c
+++ b/source/dnode/mnode/impl/src/mndDump.c
@@ -421,6 +421,7 @@ void dumpUser(SSdb *pSdb, SJson *json) {
tjsonAddStringToObject(item, "updateTime", i642str(pObj->updateTime));
tjsonAddStringToObject(item, "superUser", i642str(pObj->superUser));
tjsonAddStringToObject(item, "authVersion", i642str(pObj->authVersion));
+ tjsonAddStringToObject(item, "passVersion", i642str(pObj->passVersion));
tjsonAddStringToObject(item, "numOfReadDbs", i642str(taosHashGetSize(pObj->readDbs)));
tjsonAddStringToObject(item, "numOfWriteDbs", i642str(taosHashGetSize(pObj->writeDbs)));
sdbRelease(pSdb, pObj);
diff --git a/source/dnode/mnode/impl/src/mndMain.c b/source/dnode/mnode/impl/src/mndMain.c
index 13ae4a11d5..a9f52128a6 100644
--- a/source/dnode/mnode/impl/src/mndMain.c
+++ b/source/dnode/mnode/impl/src/mndMain.c
@@ -590,6 +590,11 @@ int32_t mndIsCatchUp(SMnode *pMnode) {
return syncIsCatchUp(rid);
}
+ESyncRole mndGetRole(SMnode *pMnode){
+ int64_t rid = pMnode->syncMgmt.sync;
+ return syncGetRole(rid);
+}
+
void mndStop(SMnode *pMnode) {
mndSetStop(pMnode);
mndSyncStop(pMnode);
diff --git a/source/dnode/mnode/impl/src/mndMnode.c b/source/dnode/mnode/impl/src/mndMnode.c
index 53baf843de..5e3476859a 100644
--- a/source/dnode/mnode/impl/src/mndMnode.c
+++ b/source/dnode/mnode/impl/src/mndMnode.c
@@ -322,7 +322,8 @@ static int32_t mndBuildAlterMnodeTypeRedoAction(STrans *pTrans,
.pCont = pReq,
.contLen = contLen,
.msgType = TDMT_DND_ALTER_MNODE_TYPE,
- .acceptableCode = TSDB_CODE_MNODE_ALREADY_DEPLOYED,
+ .retryCode = TSDB_CODE_MNODE_NOT_CATCH_UP,
+ .acceptableCode = TSDB_CODE_MNODE_ALREADY_IS_VOTER,
};
if (mndTransAppendRedoAction(pTrans, &action) != 0) {
diff --git a/source/dnode/mnode/impl/src/mndProfile.c b/source/dnode/mnode/impl/src/mndProfile.c
index 50e502f4ab..2ebb5aeb99 100644
--- a/source/dnode/mnode/impl/src/mndProfile.c
+++ b/source/dnode/mnode/impl/src/mndProfile.c
@@ -283,6 +283,7 @@ static int32_t mndProcessConnectReq(SRpcMsg *pReq) {
connectRsp.connType = connReq.connType;
connectRsp.dnodeNum = mndGetDnodeSize(pMnode);
connectRsp.svrTimestamp = taosGetTimestampSec();
+ connectRsp.passVer = pUser->passVersion;
strcpy(connectRsp.sVer, version);
snprintf(connectRsp.sDetailVer, sizeof(connectRsp.sDetailVer), "ver:%s\nbuild:%s\ngitinfo:%s", version, buildinfo,
@@ -547,6 +548,16 @@ static int32_t mndProcessQueryHeartBeat(SMnode *pMnode, SRpcMsg *pMsg, SClientHb
}
break;
}
+ case HEARTBEAT_KEY_USER_PASSINFO: {
+ void *rspMsg = NULL;
+ int32_t rspLen = 0;
+ mndValidateUserPassInfo(pMnode, kv->value, kv->valueLen / sizeof(SUserPassVersion), &rspMsg, &rspLen);
+ if (rspMsg && rspLen > 0) {
+ SKv kv1 = {.key = HEARTBEAT_KEY_USER_PASSINFO, .valueLen = rspLen, .value = rspMsg};
+ taosArrayPush(hbRsp.info, &kv1);
+ }
+ break;
+ }
default:
mError("invalid kv key:%d", kv->key);
hbRsp.status = TSDB_CODE_APP_ERROR;
diff --git a/source/dnode/mnode/impl/src/mndUser.c b/source/dnode/mnode/impl/src/mndUser.c
index d08227927a..f6e5895cda 100644
--- a/source/dnode/mnode/impl/src/mndUser.c
+++ b/source/dnode/mnode/impl/src/mndUser.c
@@ -23,7 +23,7 @@
#include "mndTrans.h"
#include "tbase64.h"
-#define USER_VER_NUMBER 3
+#define USER_VER_NUMBER 4
#define USER_RESERVE_SIZE 64
static int32_t mndCreateDefaultUsers(SMnode *pMnode);
@@ -174,6 +174,7 @@ SSdbRaw *mndUserActionEncode(SUserObj *pUser) {
SDB_SET_INT8(pRaw, dataPos, pUser->enable, _OVER)
SDB_SET_INT8(pRaw, dataPos, pUser->reserve, _OVER)
SDB_SET_INT32(pRaw, dataPos, pUser->authVersion, _OVER)
+ SDB_SET_INT32(pRaw, dataPos, pUser->passVersion, _OVER)
SDB_SET_INT32(pRaw, dataPos, numOfReadDbs, _OVER)
SDB_SET_INT32(pRaw, dataPos, numOfWriteDbs, _OVER)
SDB_SET_INT32(pRaw, dataPos, numOfTopics, _OVER)
@@ -263,7 +264,7 @@ static SSdbRow *mndUserActionDecode(SSdbRaw *pRaw) {
int8_t sver = 0;
if (sdbGetRawSoftVer(pRaw, &sver) != 0) goto _OVER;
- if (sver != 1 && sver != 2 && sver != 3) {
+ if (sver < 1 || sver > USER_VER_NUMBER) {
terrno = TSDB_CODE_SDB_INVALID_DATA_VER;
goto _OVER;
}
@@ -285,6 +286,9 @@ static SSdbRow *mndUserActionDecode(SSdbRaw *pRaw) {
SDB_GET_INT8(pRaw, dataPos, &pUser->enable, _OVER)
SDB_GET_INT8(pRaw, dataPos, &pUser->reserve, _OVER)
SDB_GET_INT32(pRaw, dataPos, &pUser->authVersion, _OVER)
+ if (sver >= 4) {
+ SDB_GET_INT32(pRaw, dataPos, &pUser->passVersion, _OVER)
+ }
int32_t numOfReadDbs = 0;
int32_t numOfWriteDbs = 0;
@@ -529,6 +533,7 @@ static int32_t mndUserActionUpdate(SSdb *pSdb, SUserObj *pOld, SUserObj *pNew) {
taosWLockLatch(&pOld->lock);
pOld->updateTime = pNew->updateTime;
pOld->authVersion = pNew->authVersion;
+ pOld->passVersion = pNew->passVersion;
pOld->sysInfo = pNew->sysInfo;
pOld->enable = pNew->enable;
memcpy(pOld->pass, pNew->pass, TSDB_PASSWORD_LEN);
@@ -818,10 +823,14 @@ static int32_t mndProcessAlterUserReq(SRpcMsg *pReq) {
if (mndUserDupObj(pUser, &newUser) != 0) goto _OVER;
+ newUser.passVersion = pUser->passVersion;
if (alterReq.alterType == TSDB_ALTER_USER_PASSWD) {
char pass[TSDB_PASSWORD_LEN + 1] = {0};
taosEncryptPass_c((uint8_t *)alterReq.pass, strlen(alterReq.pass), pass);
memcpy(newUser.pass, pass, TSDB_PASSWORD_LEN);
+ if (0 != strncmp(pUser->pass, pass, TSDB_PASSWORD_LEN)) {
+ ++newUser.passVersion;
+ }
}
if (alterReq.alterType == TSDB_ALTER_USER_SUPERUSER) {
@@ -1420,6 +1429,69 @@ _OVER:
return code;
}
+int32_t mndValidateUserPassInfo(SMnode *pMnode, SUserPassVersion *pUsers, int32_t numOfUses, void **ppRsp,
+ int32_t *pRspLen) {
+ int32_t code = 0;
+ SUserPassBatchRsp batchRsp = {0};
+
+ for (int32_t i = 0; i < numOfUses; ++i) {
+ SUserObj *pUser = mndAcquireUser(pMnode, pUsers[i].user);
+ if (pUser == NULL) {
+ mError("user:%s, failed to validate user pass since %s", pUsers[i].user, terrstr());
+ continue;
+ }
+
+ pUsers[i].version = ntohl(pUsers[i].version);
+ if (pUser->passVersion <= pUsers[i].version) {
+ mTrace("user:%s, not update since mnd passVer %d <= client passVer %d", pUsers[i].user, pUser->passVersion,
+ pUsers[i].version);
+ mndReleaseUser(pMnode, pUser);
+ continue;
+ }
+
+ SGetUserPassRsp rsp = {0};
+ memcpy(rsp.user, pUser->user, TSDB_USER_LEN);
+ rsp.version = pUser->passVersion;
+
+ if (!batchRsp.pArray && !(batchRsp.pArray = taosArrayInit(numOfUses, sizeof(SGetUserPassRsp)))) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ mndReleaseUser(pMnode, pUser);
+ goto _OVER;
+ }
+
+ taosArrayPush(batchRsp.pArray, &rsp);
+ mndReleaseUser(pMnode, pUser);
+ }
+
+ if (taosArrayGetSize(batchRsp.pArray) <= 0) {
+ goto _OVER;
+ }
+
+ int32_t rspLen = tSerializeSUserPassBatchRsp(NULL, 0, &batchRsp);
+ if (rspLen < 0) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _OVER;
+ }
+ void *pRsp = taosMemoryMalloc(rspLen);
+ if (pRsp == NULL) {
+ code = TSDB_CODE_OUT_OF_MEMORY;
+ goto _OVER;
+ }
+ tSerializeSUserPassBatchRsp(pRsp, rspLen, &batchRsp);
+
+ *ppRsp = pRsp;
+ *pRspLen = rspLen;
+
+_OVER:
+ if (code) {
+ *ppRsp = NULL;
+ *pRspLen = 0;
+ }
+
+ tFreeSUserPassBatchRsp(&batchRsp);
+ return code;
+}
+
int32_t mndUserRemoveDb(SMnode *pMnode, STrans *pTrans, char *db) {
int32_t code = 0;
SSdb *pSdb = pMnode->pSdb;
diff --git a/source/dnode/mnode/impl/src/mndVgroup.c b/source/dnode/mnode/impl/src/mndVgroup.c
index d674db5b4b..f0bece6e5e 100644
--- a/source/dnode/mnode/impl/src/mndVgroup.c
+++ b/source/dnode/mnode/impl/src/mndVgroup.c
@@ -1263,6 +1263,8 @@ int32_t mndAddAlterVnodeTypeAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb,
action.pCont = pReq;
action.contLen = contLen;
action.msgType = TDMT_DND_ALTER_VNODE_TYPE;
+ action.acceptableCode = TSDB_CODE_VND_ALREADY_IS_VOTER;
+ action.retryCode = TSDB_CODE_VND_NOT_CATCH_UP;
if (mndTransAppendRedoAction(pTrans, &action) != 0) {
taosMemoryFree(pReq);
diff --git a/source/dnode/vnode/inc/vnode.h b/source/dnode/vnode/inc/vnode.h
index 7dfaf1508d..828a173108 100644
--- a/source/dnode/vnode/inc/vnode.h
+++ b/source/dnode/vnode/inc/vnode.h
@@ -69,6 +69,7 @@ void vnodeGetInfo(SVnode *pVnode, const char **dbname, int32_t *vgId);
int32_t vnodeProcessCreateTSma(SVnode *pVnode, void *pCont, uint32_t contLen);
int32_t vnodeGetAllTableList(SVnode *pVnode, uint64_t uid, SArray *list);
int32_t vnodeIsCatchUp(SVnode *pVnode);
+ESyncRole vnodeGetRole(SVnode *pVnode);
int32_t vnodeGetCtbIdList(SVnode *pVnode, int64_t suid, SArray *list);
int32_t vnodeGetCtbIdListByFilter(SVnode *pVnode, int64_t suid, SArray *list, bool (*filter)(void *arg), void *arg);
diff --git a/source/dnode/vnode/src/inc/tq.h b/source/dnode/vnode/src/inc/tq.h
index c007f84790..142a1f6fb3 100644
--- a/source/dnode/vnode/src/inc/tq.h
+++ b/source/dnode/vnode/src/inc/tq.h
@@ -106,6 +106,7 @@ typedef struct {
SMqDataRsp* pDataRsp;
char subKey[TSDB_SUBSCRIBE_KEY_LEN];
SRpcHandleInfo info;
+ STqHandle* pHandle;
} STqPushEntry;
struct STQ {
@@ -145,8 +146,9 @@ int32_t tqFetchLog(STQ* pTq, STqHandle* pHandle, int64_t* fetchOffset, SWalCkHea
// tqExec
int32_t tqTaosxScanLog(STQ* pTq, STqHandle* pHandle, SPackedData submit, STaosxRsp* pRsp, int32_t* totalRows);
int32_t tqAddBlockDataToRsp(const SSDataBlock* pBlock, SMqDataRsp* pRsp, int32_t numOfCols, int8_t precision);
-int32_t tqSendDataRsp(STQ* pTq, const SRpcMsg* pMsg, const SMqPollReq* pReq, const SMqDataRsp* pRsp, int32_t type);
-int32_t tqPushDataRsp(STQ* pTq, STqPushEntry* pPushEntry);
+int32_t tqSendDataRsp(STqHandle* pHandle, const SRpcMsg* pMsg, const SMqPollReq* pReq, const SMqDataRsp* pRsp,
+ int32_t type, int32_t vgId);
+int32_t tqPushDataRsp(STqPushEntry* pPushEntry, int32_t vgId);
// tqMeta
int32_t tqMetaOpen(STQ* pTq);
@@ -179,15 +181,17 @@ int32_t tqExpandTask(STQ* pTq, SStreamTask* pTask, int64_t ver);
int32_t tqStreamTasksScanWal(STQ* pTq);
// tq util
+char* createStreamTaskIdStr(int64_t streamId, int32_t taskId);
void createStreamTaskOffsetKey(char* dst, uint64_t streamId, uint32_t taskId);
int32_t tqAddInputBlockNLaunchTask(SStreamTask* pTask, SStreamQueueItem* pQueueItem, int64_t ver);
-int32_t launchTaskForWalBlock(SStreamTask* pTask, SFetchRet* pRet, STqOffset* pOffset);
int32_t tqExtractDataForMq(STQ* pTq, STqHandle* pHandle, const SMqPollReq* pRequest, SRpcMsg* pMsg);
+int32_t tqDoSendDataRsp(const SRpcHandleInfo* pRpcHandleInfo, const SMqDataRsp* pRsp, int32_t epoch, int64_t consumerId,
+ int32_t type, int64_t sver, int64_t ever);
+int32_t tqInitDataRsp(SMqDataRsp* pRsp, const SMqPollReq* pReq);
void doSaveTaskOffset(STqOffsetStore* pOffsetStore, const char* pKey, int64_t ver);
void saveOffsetForAllTasks(STQ* pTq, int64_t ver);
void initOffsetForAllRestoreTasks(STQ* pTq);
-int32_t transferToWalReadTask(SStreamMeta* pStreamMeta, SArray* pTaskList);
#ifdef __cplusplus
}
diff --git a/source/dnode/vnode/src/inc/vnodeInt.h b/source/dnode/vnode/src/inc/vnodeInt.h
index 2576fce998..70b997aba2 100644
--- a/source/dnode/vnode/src/inc/vnodeInt.h
+++ b/source/dnode/vnode/src/inc/vnodeInt.h
@@ -206,7 +206,10 @@ int32_t tqProcessDelCheckInfoReq(STQ* pTq, int64_t version, char* msg, int32_t m
int32_t tqProcessSubscribeReq(STQ* pTq, int64_t version, char* msg, int32_t msgLen);
int32_t tqProcessDeleteSubReq(STQ* pTq, int64_t version, char* msg, int32_t msgLen);
int32_t tqProcessOffsetCommitReq(STQ* pTq, int64_t version, char* msg, int32_t msgLen);
+int32_t tqProcessSeekReq(STQ* pTq, int64_t sversion, char* msg, int32_t msgLen);
int32_t tqProcessPollReq(STQ* pTq, SRpcMsg* pMsg);
+int32_t tqProcessVgWalInfoReq(STQ* pTq, SRpcMsg* pMsg);
+
// tq-stream
int32_t tqProcessTaskDeployReq(STQ* pTq, int64_t version, char* msg, int32_t msgLen);
int32_t tqProcessTaskDropReq(STQ* pTq, int64_t version, char* msg, int32_t msgLen);
diff --git a/source/dnode/vnode/src/tq/tq.c b/source/dnode/vnode/src/tq/tq.c
index 1230a352d9..4a9bf07429 100644
--- a/source/dnode/vnode/src/tq/tq.c
+++ b/source/dnode/vnode/src/tq/tq.c
@@ -20,6 +20,8 @@
// 2: wait to be inited or cleaup
#define WAL_READ_TASKS_ID (-1)
+static int32_t tqInitialize(STQ* pTq);
+
int32_t tqInit() {
int8_t old;
while (1) {
@@ -74,7 +76,7 @@ static void destroyTqHandle(void* data) {
static void tqPushEntryFree(void* data) {
STqPushEntry* p = *(void**)data;
if (p->pDataRsp->head.mqMsgType == TMQ_MSG_TYPE__POLL_RSP) {
- tDeleteSMqDataRsp(p->pDataRsp);
+ tDeleteMqDataRsp(p->pDataRsp);
} else if (p->pDataRsp->head.mqMsgType == TMQ_MSG_TYPE__TAOSX_RSP) {
tDeleteSTaosxRsp((STaosxRsp*)p->pDataRsp);
}
@@ -109,25 +111,32 @@ STQ* tqOpen(const char* path, SVnode* pVnode) {
pTq->pCheckInfo = taosHashInit(64, MurmurHash3_32, true, HASH_ENTRY_LOCK);
taosHashSetFreeFp(pTq->pCheckInfo, (FDelete)tDeleteSTqCheckInfo);
+ tqInitialize(pTq);
+ return pTq;
+}
+
+int32_t tqInitialize(STQ* pTq) {
if (tqMetaOpen(pTq) < 0) {
- return NULL;
+ return -1;
}
pTq->pOffsetStore = tqOffsetOpen(pTq);
if (pTq->pOffsetStore == NULL) {
- return NULL;
+ return -1;
}
- pTq->pStreamMeta = streamMetaOpen(path, pTq, (FTaskExpand*)tqExpandTask, pTq->pVnode->config.vgId);
+ pTq->pStreamMeta = streamMetaOpen(pTq->path, pTq, (FTaskExpand*)tqExpandTask, pTq->pVnode->config.vgId);
if (pTq->pStreamMeta == NULL) {
- return NULL;
+ return -1;
}
- if (streamLoadTasks(pTq->pStreamMeta, walGetCommittedVer(pVnode->pWal)) < 0) {
- return NULL;
+ // the version is kept in task's meta data
+ // todo check if this version is required or not
+ if (streamLoadTasks(pTq->pStreamMeta, walGetCommittedVer(pTq->pVnode->pWal)) < 0) {
+ return -1;
}
- return pTq;
+ return 0;
}
void tqClose(STQ* pTq) {
@@ -145,71 +154,30 @@ void tqClose(STQ* pTq) {
taosMemoryFree(pTq);
}
-static int32_t doSendDataRsp(const SRpcHandleInfo* pRpcHandleInfo, const SMqDataRsp* pRsp, int32_t epoch,
- int64_t consumerId, int32_t type) {
- int32_t len = 0;
- int32_t code = 0;
-
- if (type == TMQ_MSG_TYPE__POLL_RSP) {
- tEncodeSize(tEncodeSMqDataRsp, pRsp, len, code);
- } else if (type == TMQ_MSG_TYPE__TAOSX_RSP) {
- tEncodeSize(tEncodeSTaosxRsp, (STaosxRsp*)pRsp, len, code);
- }
-
- if (code < 0) {
- return -1;
- }
-
- int32_t tlen = sizeof(SMqRspHead) + len;
- void* buf = rpcMallocCont(tlen);
- if (buf == NULL) {
- return -1;
- }
-
- ((SMqRspHead*)buf)->mqMsgType = type;
- ((SMqRspHead*)buf)->epoch = epoch;
- ((SMqRspHead*)buf)->consumerId = consumerId;
-
- void* abuf = POINTER_SHIFT(buf, sizeof(SMqRspHead));
-
- SEncoder encoder = {0};
- tEncoderInit(&encoder, abuf, len);
-
- if (type == TMQ_MSG_TYPE__POLL_RSP) {
- tEncodeSMqDataRsp(&encoder, pRsp);
- } else if (type == TMQ_MSG_TYPE__TAOSX_RSP) {
- tEncodeSTaosxRsp(&encoder, (STaosxRsp*)pRsp);
- }
-
- tEncoderClear(&encoder);
-
- SRpcMsg rsp = {
- .info = *pRpcHandleInfo,
- .pCont = buf,
- .contLen = tlen,
- .code = 0,
- };
-
- tmsgSendRsp(&rsp);
- return 0;
-}
-
-int32_t tqPushDataRsp(STQ* pTq, STqPushEntry* pPushEntry) {
+int32_t tqPushDataRsp(STqPushEntry* pPushEntry, int32_t vgId) {
SMqDataRsp* pRsp = pPushEntry->pDataRsp;
SMqRspHead* pHeader = &pPushEntry->pDataRsp->head;
- doSendDataRsp(&pPushEntry->info, pRsp, pHeader->epoch, pHeader->consumerId, pHeader->mqMsgType);
+
+ int64_t sver = 0, ever = 0;
+ walReaderValidVersionRange(pPushEntry->pHandle->execHandle.pTqReader->pWalReader, &sver, &ever);
+
+ tqDoSendDataRsp(&pPushEntry->info, pRsp, pHeader->epoch, pHeader->consumerId, pHeader->mqMsgType, sver, ever);
char buf1[80] = {0};
char buf2[80] = {0};
tFormatOffset(buf1, tListLen(buf1), &pRsp->reqOffset);
tFormatOffset(buf2, tListLen(buf2), &pRsp->rspOffset);
tqDebug("vgId:%d, from consumer:0x%" PRIx64 " (epoch %d) push rsp, block num: %d, req:%s, rsp:%s",
- TD_VID(pTq->pVnode), pRsp->head.consumerId, pRsp->head.epoch, pRsp->blockNum, buf1, buf2);
+ vgId, pRsp->head.consumerId, pRsp->head.epoch, pRsp->blockNum, buf1, buf2);
return 0;
}
-int32_t tqSendDataRsp(STQ* pTq, const SRpcMsg* pMsg, const SMqPollReq* pReq, const SMqDataRsp* pRsp, int32_t type) {
- doSendDataRsp(&pMsg->info, pRsp, pReq->epoch, pReq->consumerId, type);
+int32_t tqSendDataRsp(STqHandle* pHandle, const SRpcMsg* pMsg, const SMqPollReq* pReq, const SMqDataRsp* pRsp,
+ int32_t type, int32_t vgId) {
+ int64_t sver = 0, ever = 0;
+ walReaderValidVersionRange(pHandle->execHandle.pTqReader->pWalReader, &sver, &ever);
+
+ tqDoSendDataRsp(&pMsg->info, pRsp, pReq->epoch, pReq->consumerId, type, sver, ever);
char buf1[80] = {0};
char buf2[80] = {0};
@@ -217,50 +185,54 @@ int32_t tqSendDataRsp(STQ* pTq, const SRpcMsg* pMsg, const SMqPollReq* pReq, con
tFormatOffset(buf2, 80, &pRsp->rspOffset);
tqDebug("vgId:%d consumer:0x%" PRIx64 " (epoch %d) send rsp, block num:%d, req:%s, rsp:%s, reqId:0x%" PRIx64,
- TD_VID(pTq->pVnode), pReq->consumerId, pReq->epoch, pRsp->blockNum, buf1, buf2, pReq->reqId);
+ vgId, pReq->consumerId, pReq->epoch, pRsp->blockNum, buf1, buf2, pReq->reqId);
return 0;
}
int32_t tqProcessOffsetCommitReq(STQ* pTq, int64_t sversion, char* msg, int32_t msgLen) {
- STqOffset offset = {0};
- int32_t vgId = TD_VID(pTq->pVnode);
+ SMqVgOffset vgOffset = {0};
+ int32_t vgId = TD_VID(pTq->pVnode);
SDecoder decoder;
tDecoderInit(&decoder, (uint8_t*)msg, msgLen);
- if (tDecodeSTqOffset(&decoder, &offset) < 0) {
+ if (tDecodeMqVgOffset(&decoder, &vgOffset) < 0) {
return -1;
}
tDecoderClear(&decoder);
- if (offset.val.type == TMQ_OFFSET__SNAPSHOT_DATA || offset.val.type == TMQ_OFFSET__SNAPSHOT_META) {
+ STqOffset* pOffset = &vgOffset.offset;
+
+ if (pOffset->val.type == TMQ_OFFSET__SNAPSHOT_DATA || pOffset->val.type == TMQ_OFFSET__SNAPSHOT_META) {
tqDebug("receive offset commit msg to %s on vgId:%d, offset(type:snapshot) uid:%" PRId64 ", ts:%" PRId64,
- offset.subKey, vgId, offset.val.uid, offset.val.ts);
- } else if (offset.val.type == TMQ_OFFSET__LOG) {
- tqDebug("receive offset commit msg to %s on vgId:%d, offset(type:log) version:%" PRId64, offset.subKey, vgId,
- offset.val.version);
- if (offset.val.version + 1 == sversion) {
- offset.val.version += 1;
+ pOffset->subKey, vgId, pOffset->val.uid, pOffset->val.ts);
+ } else if (pOffset->val.type == TMQ_OFFSET__LOG) {
+ tqDebug("receive offset commit msg to %s on vgId:%d, offset(type:log) version:%" PRId64, pOffset->subKey, vgId,
+ pOffset->val.version);
+ if (pOffset->val.version + 1 == sversion) {
+ pOffset->val.version += 1;
}
} else {
- tqError("invalid commit offset type:%d", offset.val.type);
+ tqError("invalid commit offset type:%d", pOffset->val.type);
return -1;
}
- STqOffset* pSavedOffset = tqOffsetRead(pTq->pOffsetStore, offset.subKey);
- if (pSavedOffset != NULL && tqOffsetLessOrEqual(&offset, pSavedOffset)) {
+ STqOffset* pSavedOffset = tqOffsetRead(pTq->pOffsetStore, pOffset->subKey);
+ if (pSavedOffset != NULL && tqOffsetLessOrEqual(pOffset, pSavedOffset)) {
+ tqDebug("not update the offset, vgId:%d sub:%s since committed:%" PRId64 " less than/equal to existed:%" PRId64,
+ vgId, pOffset->subKey, pOffset->val.version, pSavedOffset->val.version);
return 0; // no need to update the offset value
}
// save the new offset value
- if (tqOffsetWrite(pTq->pOffsetStore, &offset) < 0) {
+ if (tqOffsetWrite(pTq->pOffsetStore, pOffset) < 0) {
return -1;
}
- if (offset.val.type == TMQ_OFFSET__LOG) {
- STqHandle* pHandle = taosHashGet(pTq->pHandle, offset.subKey, strlen(offset.subKey));
- if (pHandle && (walRefVer(pHandle->pRef, offset.val.version) < 0)) {
+ if (pOffset->val.type == TMQ_OFFSET__LOG) {
+ STqHandle* pHandle = taosHashGet(pTq->pHandle, pOffset->subKey, strlen(pOffset->subKey));
+ if (pHandle && (walRefVer(pHandle->pRef, pOffset->val.version) < 0)) {
return -1;
}
}
@@ -268,6 +240,78 @@ int32_t tqProcessOffsetCommitReq(STQ* pTq, int64_t sversion, char* msg, int32_t
return 0;
}
+int32_t tqProcessSeekReq(STQ* pTq, int64_t sversion, char* msg, int32_t msgLen) {
+ SMqVgOffset vgOffset = {0};
+ int32_t vgId = TD_VID(pTq->pVnode);
+
+ SDecoder decoder;
+ tDecoderInit(&decoder, (uint8_t*)msg, msgLen);
+ if (tDecodeMqVgOffset(&decoder, &vgOffset) < 0) {
+ return -1;
+ }
+
+ tDecoderClear(&decoder);
+
+ STqOffset* pOffset = &vgOffset.offset;
+ if (pOffset->val.type != TMQ_OFFSET__LOG) {
+ tqError("vgId:%d, subKey:%s invalid seek offset type:%d", vgId, pOffset->subKey, pOffset->val.type);
+ return -1;
+ }
+
+ STqHandle* pHandle = taosHashGet(pTq->pHandle, pOffset->subKey, strlen(pOffset->subKey));
+ if (pHandle == NULL) {
+ tqError("tmq seek: consumer:0x%" PRIx64 " vgId:%d subkey %s not found", vgOffset.consumerId, vgId,
+ pOffset->subKey);
+ terrno = TSDB_CODE_INVALID_MSG;
+ return -1;
+ }
+
+ // 2. check consumer-vg assignment status
+ taosRLockLatch(&pTq->lock);
+ if (pHandle->consumerId != vgOffset.consumerId) {
+ tqDebug("ERROR tmq seek: consumer:0x%" PRIx64 " vgId:%d, subkey %s, mismatch for saved handle consumer:0x%" PRIx64,
+ vgOffset.consumerId, vgId, pOffset->subKey, pHandle->consumerId);
+ terrno = TSDB_CODE_TMQ_CONSUMER_MISMATCH;
+ taosRUnLockLatch(&pTq->lock);
+ return -1;
+ }
+ taosRUnLockLatch(&pTq->lock);
+
+ //3. check the offset info
+ STqOffset* pSavedOffset = tqOffsetRead(pTq->pOffsetStore, pOffset->subKey);
+ if (pSavedOffset != NULL) {
+ if (pSavedOffset->val.type != TMQ_OFFSET__LOG) {
+ tqError("invalid saved offset type, vgId:%d sub:%s", vgId, pOffset->subKey);
+ return 0; // no need to update the offset value
+ }
+
+ if (pSavedOffset->val.version == pOffset->val.version) {
+ tqDebug("vgId:%d subKey:%s no need to seek to %" PRId64 " prev offset:%" PRId64, vgId, pOffset->subKey,
+ pOffset->val.version, pSavedOffset->val.version);
+ return 0;
+ }
+ }
+
+ int64_t sver = 0, ever = 0;
+ walReaderValidVersionRange(pHandle->execHandle.pTqReader->pWalReader, &sver, &ever);
+ if (pOffset->val.version < sver) {
+ pOffset->val.version = sver;
+ } else if (pOffset->val.version > ever) {
+ pOffset->val.version = ever;
+ }
+
+ // save the new offset value
+ tqDebug("vgId:%d sub:%s seek to %" PRId64 " prev offset:%" PRId64, vgId, pOffset->subKey, pOffset->val.version,
+ pSavedOffset->val.version);
+
+ if (tqOffsetWrite(pTq->pOffsetStore, pOffset) < 0) {
+ tqError("failed to save offset, vgId:%d sub:%s seek to %" PRId64, vgId, pOffset->subKey, pOffset->val.version);
+ return -1;
+ }
+
+ return 0;
+}
+
int32_t tqCheckColModifiable(STQ* pTq, int64_t tbUid, int32_t colId) {
void* pIter = NULL;
@@ -344,6 +388,81 @@ int32_t tqProcessPollReq(STQ* pTq, SRpcMsg* pMsg) {
return tqExtractDataForMq(pTq, pHandle, &req, pMsg);
}
+int32_t tqProcessVgWalInfoReq(STQ* pTq, SRpcMsg* pMsg) {
+ SMqPollReq req = {0};
+ if (tDeserializeSMqPollReq(pMsg->pCont, pMsg->contLen, &req) < 0) {
+ tqError("tDeserializeSMqPollReq %d failed", pMsg->contLen);
+ terrno = TSDB_CODE_INVALID_MSG;
+ return -1;
+ }
+
+ int64_t consumerId = req.consumerId;
+ STqOffsetVal reqOffset = req.reqOffset;
+ int32_t vgId = TD_VID(pTq->pVnode);
+
+ // 1. find handle
+ STqHandle* pHandle = taosHashGet(pTq->pHandle, req.subKey, strlen(req.subKey));
+ if (pHandle == NULL) {
+ tqError("consumer:0x%" PRIx64 " vgId:%d subkey:%s not found", consumerId, vgId, req.subKey);
+ terrno = TSDB_CODE_INVALID_MSG;
+ return -1;
+ }
+
+ // 2. check re-balance status
+ taosRLockLatch(&pTq->lock);
+ if (pHandle->consumerId != consumerId) {
+ tqDebug("ERROR consumer:0x%" PRIx64 " vgId:%d, subkey %s, mismatch for saved handle consumer:0x%" PRIx64,
+ consumerId, vgId, req.subKey, pHandle->consumerId);
+ terrno = TSDB_CODE_TMQ_CONSUMER_MISMATCH;
+ taosRUnLockLatch(&pTq->lock);
+ return -1;
+ }
+ taosRUnLockLatch(&pTq->lock);
+
+ int64_t sver = 0, ever = 0;
+ walReaderValidVersionRange(pHandle->execHandle.pTqReader->pWalReader, &sver, &ever);
+
+ SMqDataRsp dataRsp = {0};
+ tqInitDataRsp(&dataRsp, &req);
+
+ STqOffset* pOffset = tqOffsetRead(pTq->pOffsetStore, req.subKey);
+ if (pOffset != NULL) {
+ if (pOffset->val.type != TMQ_OFFSET__LOG) {
+ tqError("consumer:0x%" PRIx64 " vgId:%d subkey:%s use snapshot, no valid wal info", consumerId, vgId, req.subKey);
+ terrno = TSDB_CODE_INVALID_PARA;
+ tDeleteMqDataRsp(&dataRsp);
+ return -1;
+ }
+
+ dataRsp.rspOffset.type = TMQ_OFFSET__LOG;
+ dataRsp.rspOffset.version = pOffset->val.version;
+ } else {
+ if (req.useSnapshot == true) {
+ tqError("consumer:0x%" PRIx64 " vgId:%d subkey:%s snapshot not support wal info", consumerId, vgId, req.subKey);
+ terrno = TSDB_CODE_INVALID_PARA;
+ tDeleteMqDataRsp(&dataRsp);
+ return -1;
+ }
+
+ dataRsp.rspOffset.type = TMQ_OFFSET__LOG;
+
+ if (reqOffset.type == TMQ_OFFSET__RESET_EARLIEAST) {
+ dataRsp.rspOffset.version = sver;
+ } else if (reqOffset.type == TMQ_OFFSET__RESET_LATEST) {
+ dataRsp.rspOffset.version = ever;
+ } else {
+ tqError("consumer:0x%" PRIx64 " vgId:%d subkey:%s invalid offset type:%d", consumerId, vgId, req.subKey,
+ reqOffset.type);
+ terrno = TSDB_CODE_INVALID_PARA;
+ tDeleteMqDataRsp(&dataRsp);
+ return -1;
+ }
+ }
+
+ tqDoSendDataRsp(&pMsg->info, &dataRsp, req.epoch, req.consumerId, TMQ_MSG_TYPE__WALINFO_RSP, sver, ever);
+ return 0;
+}
+
int32_t tqProcessDeleteSubReq(STQ* pTq, int64_t sversion, char* msg, int32_t msgLen) {
SMqVDeleteReq* pReq = (SMqVDeleteReq*)msg;
@@ -548,12 +667,8 @@ int32_t tqProcessSubscribeReq(STQ* pTq, int64_t sversion, char* msg, int32_t msg
}
int32_t tqExpandTask(STQ* pTq, SStreamTask* pTask, int64_t ver) {
- // todo extract method
- char buf[128] = {0};
- sprintf(buf, "0x%"PRIx64"-%d", pTask->id.streamId, pTask->id.taskId);
-
int32_t vgId = TD_VID(pTq->pVnode);
- pTask->id.idStr = taosStrdup(buf);
+ pTask->id.idStr = createStreamTaskIdStr(pTask->id.streamId, pTask->id.taskId);
pTask->refCnt = 1;
pTask->status.schedStatus = TASK_SCHED_STATUS__INACTIVE;
pTask->inputQueue = streamQueueOpen();
@@ -633,8 +748,11 @@ int32_t tqExpandTask(STQ* pTq, SStreamTask* pTask, int64_t ver) {
}
streamSetupTrigger(pTask);
- tqInfo("vgId:%d expand stream task, s-task:%s, ver:%" PRId64 " child id:%d, level:%d", vgId, pTask->id.idStr,
+ tqInfo("vgId:%d expand stream task, s-task:%s, checkpoint ver:%" PRId64 " child id:%d, level:%d", vgId, pTask->id.idStr,
pTask->chkInfo.version, pTask->selfChildId, pTask->taskLevel);
+
+ // next valid version will add one
+ pTask->chkInfo.version += 1;
return 0;
}
@@ -750,7 +868,7 @@ int32_t tqProcessTaskDeployReq(STQ* pTq, int64_t sversion, char* msg, int32_t ms
tDecoderClear(&decoder);
- // 2.save task
+ // 2.save task, use the newest commit version as the initial start version of stream task.
code = streamMetaAddDeployedTask(pTq->pStreamMeta, sversion, pTask);
if (code < 0) {
tqError("vgId:%d failed to add s-task:%s, total:%d", TD_VID(pTq->pVnode), pTask->id.idStr,
@@ -1276,6 +1394,13 @@ int32_t tqStartStreamTasks(STQ* pTq) {
SStreamMeta* pMeta = pTq->pStreamMeta;
taosWLockLatch(&pMeta->lock);
+ int32_t numOfTasks = taosHashGetSize(pTq->pStreamMeta->pTasks);
+ if (numOfTasks == 0) {
+ tqInfo("vgId:%d no stream tasks exists", vgId);
+ taosWUnLockLatch(&pTq->pStreamMeta->lock);
+ return 0;
+ }
+
pMeta->walScan += 1;
if (pMeta->walScan > 1) {
@@ -1292,8 +1417,6 @@ int32_t tqStartStreamTasks(STQ* pTq) {
return -1;
}
- int32_t numOfTasks = taosHashGetSize(pTq->pStreamMeta->pTasks);
-
tqInfo("vgId:%d start wal scan stream tasks, tasks:%d", vgId, numOfTasks);
initOffsetForAllRestoreTasks(pTq);
diff --git a/source/dnode/vnode/src/tq/tqPush.c b/source/dnode/vnode/src/tq/tqPush.c
index 7a1a6b7454..43463f67b7 100644
--- a/source/dnode/vnode/src/tq/tqPush.c
+++ b/source/dnode/vnode/src/tq/tqPush.c
@@ -263,7 +263,7 @@ static void doPushDataForEntry(void* pIter, STqExecHandle* pExec, STQ* pTq, int6
if (pRsp->blockNum > 0) {
tqOffsetResetToLog(&pRsp->rspOffset, ver);
- tqPushDataRsp(pTq, pPushEntry);
+ tqPushDataRsp(pPushEntry, vgId);
recordPushedEntry(pCachedKey, pIter);
}
}
@@ -376,6 +376,7 @@ int32_t tqRegisterPushHandle(STQ* pTq, void* pHandle, const SMqPollReq* pRequest
return -1;
}
+ pPushEntry->pHandle = pHandle;
pPushEntry->info = pRpcMsg->info;
memcpy(pPushEntry->subKey, pTqHandle->subKey, TSDB_SUBSCRIBE_KEY_LEN);
@@ -388,6 +389,7 @@ int32_t tqRegisterPushHandle(STQ* pTq, void* pHandle, const SMqPollReq* pRequest
}
SMqRspHead* pHead = &pPushEntry->pDataRsp->head;
+
pHead->consumerId = consumerId;
pHead->epoch = pRequest->epoch;
pHead->mqMsgType = type;
@@ -411,7 +413,7 @@ int32_t tqUnregisterPushHandle(STQ* pTq, const char* pKey, int32_t keyLen, uint6
(*pEntry)->subKey, vgId, taosHashGetSize(pTq->pPushMgr) - 1);
if (rspConsumer) { // rsp the old consumer with empty block.
- tqPushDataRsp(pTq, *pEntry);
+ tqPushDataRsp(*pEntry, vgId);
}
taosHashRemove(pTq->pPushMgr, pKey, keyLen);
diff --git a/source/dnode/vnode/src/tq/tqRestore.c b/source/dnode/vnode/src/tq/tqRestore.c
index 6ed74ddcc3..54fcc04b62 100644
--- a/source/dnode/vnode/src/tq/tqRestore.c
+++ b/source/dnode/vnode/src/tq/tqRestore.c
@@ -52,33 +52,9 @@ int tqStreamTasksScanWal(STQ* pTq) {
double el = (taosGetTimestampMs() - st) / 1000.0;
tqInfo("vgId:%d scan wal for stream tasks completed, elapsed time:%.2f sec", vgId, el);
-
- // restore wal scan flag
-// atomic_store_8(&pTq->pStreamMeta->walScan, 0);
return 0;
}
-//int32_t transferToNormalTask(SStreamMeta* pStreamMeta, SArray* pTaskList) {
-// int32_t numOfTask = taosArrayGetSize(pTaskList);
-// if (numOfTask <= 0) {
-// return TSDB_CODE_SUCCESS;
-// }
-//
-// // todo: add lock
-// for (int32_t i = 0; i < numOfTask; ++i) {
-// SStreamTask* pTask = taosArrayGetP(pTaskList, i);
-// tqDebug("vgId:%d transfer s-task:%s state restore -> ready, checkpoint:%" PRId64 " checkpoint id:%" PRId64,
-// pStreamMeta->vgId, pTask->id.idStr, pTask->chkInfo.version, pTask->chkInfo.id);
-// taosHashRemove(pStreamMeta->pWalReadTasks, &pTask->id.taskId, sizeof(pTask->id.taskId));
-//
-// // NOTE: do not change the following order
-// atomic_store_8(&pTask->status.taskStatus, TASK_STATUS__NORMAL);
-// taosHashPut(pStreamMeta->pTasks, &pTask->id.taskId, sizeof(pTask->id.taskId), &pTask, POINTER_BYTES);
-// }
-//
-// return TSDB_CODE_SUCCESS;
-//}
-
int32_t streamTaskReplayWal(SStreamMeta* pStreamMeta, STqOffsetStore* pOffsetStore, bool* pScanIdle) {
void* pIter = NULL;
int32_t vgId = pStreamMeta->vgId;
@@ -99,8 +75,8 @@ int32_t streamTaskReplayWal(SStreamMeta* pStreamMeta, STqOffsetStore* pOffsetSto
continue;
}
- if (pTask->status.taskStatus == TASK_STATUS__RECOVER_PREPARE ||
- pTask->status.taskStatus == TASK_STATUS__WAIT_DOWNSTREAM) {
+ int8_t status = pTask->status.taskStatus;
+ if (status == TASK_STATUS__RECOVER_PREPARE || status == TASK_STATUS__WAIT_DOWNSTREAM) {
tqDebug("s-task:%s skip push data, not ready for processing, status %d", pTask->id.idStr,
pTask->status.taskStatus);
continue;
diff --git a/source/dnode/vnode/src/tq/tqUtil.c b/source/dnode/vnode/src/tq/tqUtil.c
index 4c37e1052f..c09a8a030e 100644
--- a/source/dnode/vnode/src/tq/tqUtil.c
+++ b/source/dnode/vnode/src/tq/tqUtil.c
@@ -17,7 +17,13 @@
#define IS_OFFSET_RESET_TYPE(_t) ((_t) < 0)
-static int32_t tqSendMetaPollRsp(STQ* pTq, const SRpcMsg* pMsg, const SMqPollReq* pReq, const SMqMetaRsp* pRsp);
+static int32_t tqSendMetaPollRsp(STqHandle* pHandle, const SRpcMsg* pMsg, const SMqPollReq* pReq, const SMqMetaRsp* pRsp, int32_t vgId);
+
+char* createStreamTaskIdStr(int64_t streamId, int32_t taskId) {
+ char buf[128] = {0};
+ sprintf(buf, "0x%" PRIx64 "-%d", streamId, taskId);
+ return taosStrdup(buf);
+}
// stream_task:stream_id:task_id
void createStreamTaskOffsetKey(char* dst, uint64_t streamId, uint32_t taskId) {
@@ -118,7 +124,7 @@ void doSaveTaskOffset(STqOffsetStore* pOffsetStore, const char* pKey, int64_t ve
tqOffsetWrite(pOffsetStore, &offset);
}
-static int32_t tqInitDataRsp(SMqDataRsp* pRsp, const SMqPollReq* pReq, int8_t subType) {
+int32_t tqInitDataRsp(SMqDataRsp* pRsp, const SMqPollReq* pReq) {
pRsp->reqOffset = pReq->reqOffset;
pRsp->blockData = taosArrayInit(0, sizeof(void*));
@@ -144,6 +150,21 @@ static int32_t tqInitTaosxRsp(STaosxRsp* pRsp, const SMqPollReq* pReq) {
pRsp->blockSchema = taosArrayInit(0, sizeof(void*));
if (pRsp->blockData == NULL || pRsp->blockDataLen == NULL || pRsp->blockTbName == NULL || pRsp->blockSchema == NULL) {
+ if (pRsp->blockData != NULL) {
+ pRsp->blockData = taosArrayDestroy(pRsp->blockData);
+ }
+
+ if (pRsp->blockDataLen != NULL) {
+ pRsp->blockDataLen = taosArrayDestroy(pRsp->blockDataLen);
+ }
+
+ if (pRsp->blockTbName != NULL) {
+ pRsp->blockTbName = taosArrayDestroy(pRsp->blockTbName);
+ }
+
+ if (pRsp->blockSchema != NULL) {
+ pRsp->blockSchema = taosArrayDestroy(pRsp->blockSchema);
+ }
return -1;
}
@@ -193,13 +214,13 @@ static int32_t extractResetOffsetVal(STqOffsetVal* pOffsetVal, STQ* pTq, STqHand
} else if (reqOffset.type == TMQ_OFFSET__RESET_LATEST) {
if (pHandle->execHandle.subType == TOPIC_SUB_TYPE__COLUMN) {
SMqDataRsp dataRsp = {0};
- tqInitDataRsp(&dataRsp, pRequest, pHandle->execHandle.subType);
+ tqInitDataRsp(&dataRsp, pRequest);
tqOffsetResetToLog(&dataRsp.rspOffset, walGetLastVer(pTq->pVnode->pWal));
tqDebug("tmq poll: consumer:0x%" PRIx64 ", subkey %s, vgId:%d, (latest) offset reset to %" PRId64, consumerId,
pHandle->subKey, vgId, dataRsp.rspOffset.version);
- int32_t code = tqSendDataRsp(pTq, pMsg, pRequest, &dataRsp, TMQ_MSG_TYPE__POLL_RSP);
- tDeleteSMqDataRsp(&dataRsp);
+ int32_t code = tqSendDataRsp(pHandle, pMsg, pRequest, &dataRsp, TMQ_MSG_TYPE__POLL_RSP, vgId);
+ tDeleteMqDataRsp(&dataRsp);
*pBlockReturned = true;
return code;
@@ -207,7 +228,7 @@ static int32_t extractResetOffsetVal(STqOffsetVal* pOffsetVal, STQ* pTq, STqHand
STaosxRsp taosxRsp = {0};
tqInitTaosxRsp(&taosxRsp, pRequest);
tqOffsetResetToLog(&taosxRsp.rspOffset, walGetLastVer(pTq->pVnode->pWal));
- int32_t code = tqSendDataRsp(pTq, pMsg, pRequest, (SMqDataRsp*)&taosxRsp, TMQ_MSG_TYPE__TAOSX_RSP);
+ int32_t code = tqSendDataRsp(pHandle, pMsg, pRequest, (SMqDataRsp*)&taosxRsp, TMQ_MSG_TYPE__TAOSX_RSP, vgId);
tDeleteSTaosxRsp(&taosxRsp);
*pBlockReturned = true;
@@ -226,47 +247,43 @@ static int32_t extractResetOffsetVal(STqOffsetVal* pOffsetVal, STQ* pTq, STqHand
static int32_t extractDataAndRspForNormalSubscribe(STQ* pTq, STqHandle* pHandle, const SMqPollReq* pRequest,
SRpcMsg* pMsg, STqOffsetVal* pOffset) {
+ char buf[80] = {0};
uint64_t consumerId = pRequest->consumerId;
int32_t vgId = TD_VID(pTq->pVnode);
SMqDataRsp dataRsp = {0};
- tqInitDataRsp(&dataRsp, pRequest, pHandle->execHandle.subType);
+ tqInitDataRsp(&dataRsp, pRequest);
// lock
taosWLockLatch(&pTq->lock);
qSetTaskId(pHandle->execHandle.task, consumerId, pRequest->reqId);
+
int code = tqScanData(pTq, pHandle, &dataRsp, pOffset);
- if(code != 0) {
- goto end;
+ if (code == 0) {
+
+ // till now, all data has been transferred to consumer, new data needs to push client once arrived.
+ if (dataRsp.blockNum == 0 && dataRsp.reqOffset.type == TMQ_OFFSET__LOG &&
+ dataRsp.reqOffset.version == dataRsp.rspOffset.version && pHandle->consumerId == pRequest->consumerId) {
+ code = tqRegisterPushHandle(pTq, pHandle, pRequest, pMsg, &dataRsp, TMQ_MSG_TYPE__POLL_RSP);
+ taosWUnLockLatch(&pTq->lock);
+ return code;
+ }
+
+ // NOTE: this pHandle->consumerId may have been changed already.
+ code = tqSendDataRsp(pHandle, pMsg, pRequest, (SMqDataRsp*)&dataRsp, TMQ_MSG_TYPE__POLL_RSP, vgId);
}
- // till now, all data has been transferred to consumer, new data needs to push client once arrived.
- if (dataRsp.blockNum == 0 && dataRsp.reqOffset.type == TMQ_OFFSET__LOG &&
- dataRsp.reqOffset.version == dataRsp.rspOffset.version && pHandle->consumerId == pRequest->consumerId) {
- code = tqRegisterPushHandle(pTq, pHandle, pRequest, pMsg, &dataRsp, TMQ_MSG_TYPE__POLL_RSP);
- taosWUnLockLatch(&pTq->lock);
- return code;
- }
+ tFormatOffset(buf, 80, &dataRsp.rspOffset);
+ tqDebug("tmq poll: consumer:0x%" PRIx64 ", subkey %s, vgId:%d, rsp block:%d, rsp offset type:%s, reqId:0x%" PRIx64
+ " code:%d",
+ consumerId, pHandle->subKey, vgId, dataRsp.blockNum, buf, pRequest->reqId, code);
+ taosWUnLockLatch(&pTq->lock);
+ tDeleteMqDataRsp(&dataRsp);
-
- code = tqSendDataRsp(pTq, pMsg, pRequest, (SMqDataRsp*)&dataRsp, TMQ_MSG_TYPE__POLL_RSP);
-
- // NOTE: this pHandle->consumerId may have been changed already.
-
- end:
- {
- char buf[80] = {0};
- tFormatOffset(buf, 80, &dataRsp.rspOffset);
- tqDebug("tmq poll: consumer:0x%" PRIx64 ", subkey %s, vgId:%d, rsp block:%d, rsp offset type:%s, reqId:0x%" PRIx64 " code:%d",
- consumerId, pHandle->subKey, vgId, dataRsp.blockNum, buf, pRequest->reqId, code);
- taosWUnLockLatch(&pTq->lock);
- tDeleteSMqDataRsp(&dataRsp);
- }
return code;
}
-
static int32_t extractDataAndRspForDbStbSubscribe(STQ* pTq, STqHandle* pHandle, const SMqPollReq* pRequest, SRpcMsg* pMsg, STqOffsetVal *offset) {
int code = 0;
int32_t vgId = TD_VID(pTq->pVnode);
@@ -277,11 +294,12 @@ static int32_t extractDataAndRspForDbStbSubscribe(STQ* pTq, STqHandle* pHandle,
if (offset->type != TMQ_OFFSET__LOG) {
if (tqScanTaosx(pTq, pHandle, &taosxRsp, &metaRsp, offset) < 0) {
+ tDeleteSTaosxRsp(&taosxRsp);
return -1;
}
if (metaRsp.metaRspLen > 0) {
- code = tqSendMetaPollRsp(pTq, pMsg, pRequest, &metaRsp);
+ code = tqSendMetaPollRsp(pHandle, pMsg, pRequest, &metaRsp, vgId);
tqDebug("tmq poll: consumer:0x%" PRIx64 " subkey:%s vgId:%d, send meta offset type:%d,uid:%" PRId64 ",ts:%" PRId64,
pRequest->consumerId, pHandle->subKey, vgId, metaRsp.rspOffset.type, metaRsp.rspOffset.uid, metaRsp.rspOffset.ts);
taosMemoryFree(metaRsp.metaRsp);
@@ -292,7 +310,7 @@ static int32_t extractDataAndRspForDbStbSubscribe(STQ* pTq, STqHandle* pHandle,
tqDebug("taosx poll: consumer:0x%" PRIx64 " subkey:%s vgId:%d, send data blockNum:%d, offset type:%d,uid:%" PRId64
",ts:%" PRId64,pRequest->consumerId, pHandle->subKey, vgId, taosxRsp.blockNum, taosxRsp.rspOffset.type, taosxRsp.rspOffset.uid,taosxRsp.rspOffset.ts);
if (taosxRsp.blockNum > 0) {
- code = tqSendDataRsp(pTq, pMsg, pRequest, (SMqDataRsp*)&taosxRsp, TMQ_MSG_TYPE__TAOSX_RSP);
+ code = tqSendDataRsp(pHandle, pMsg, pRequest, (SMqDataRsp*)&taosxRsp, TMQ_MSG_TYPE__TAOSX_RSP, vgId);
tDeleteSTaosxRsp(&taosxRsp);
return code;
}else {
@@ -300,7 +318,6 @@ static int32_t extractDataAndRspForDbStbSubscribe(STQ* pTq, STqHandle* pHandle,
}
}
-
if (offset->type == TMQ_OFFSET__LOG) {
int64_t fetchVer = offset->version + 1;
pCkHead = taosMemoryMalloc(sizeof(SWalCkHead) + 2048);
@@ -315,13 +332,14 @@ static int32_t extractDataAndRspForDbStbSubscribe(STQ* pTq, STqHandle* pHandle,
int32_t savedEpoch = atomic_load_32(&pHandle->epoch);
if (savedEpoch > pRequest->epoch) {
tqWarn("tmq poll: consumer:0x%" PRIx64 " (epoch %d), subkey:%s vgId:%d offset %" PRId64
- ", found new consumer epoch %d, discard req epoch %d", pRequest->consumerId, pRequest->epoch, pHandle->subKey, vgId, fetchVer, savedEpoch, pRequest->epoch);
+ ", found new consumer epoch %d, discard req epoch %d",
+ pRequest->consumerId, pRequest->epoch, pHandle->subKey, vgId, fetchVer, savedEpoch, pRequest->epoch);
break;
}
if (tqFetchLog(pTq, pHandle, &fetchVer, &pCkHead, pRequest->reqId) < 0) {
tqOffsetResetToLog(&taosxRsp.rspOffset, fetchVer);
- code = tqSendDataRsp(pTq, pMsg, pRequest, (SMqDataRsp*)&taosxRsp, TMQ_MSG_TYPE__TAOSX_RSP);
+ code = tqSendDataRsp(pHandle, pMsg, pRequest, (SMqDataRsp*)&taosxRsp, TMQ_MSG_TYPE__TAOSX_RSP, vgId);
tDeleteSTaosxRsp(&taosxRsp);
taosMemoryFreeClear(pCkHead);
return code;
@@ -335,7 +353,7 @@ static int32_t extractDataAndRspForDbStbSubscribe(STQ* pTq, STqHandle* pHandle,
if (pHead->msgType != TDMT_VND_SUBMIT) {
if(totalRows > 0) {
tqOffsetResetToLog(&taosxRsp.rspOffset, fetchVer - 1);
- code = tqSendDataRsp(pTq, pMsg, pRequest, (SMqDataRsp*)&taosxRsp, TMQ_MSG_TYPE__TAOSX_RSP);
+ code = tqSendDataRsp(pHandle, pMsg, pRequest, (SMqDataRsp*)&taosxRsp, TMQ_MSG_TYPE__TAOSX_RSP, vgId);
tDeleteSTaosxRsp(&taosxRsp);
taosMemoryFreeClear(pCkHead);
return code;
@@ -346,12 +364,13 @@ static int32_t extractDataAndRspForDbStbSubscribe(STQ* pTq, STqHandle* pHandle,
metaRsp.resMsgType = pHead->msgType;
metaRsp.metaRspLen = pHead->bodyLen;
metaRsp.metaRsp = pHead->body;
- if (tqSendMetaPollRsp(pTq, pMsg, pRequest, &metaRsp) < 0) {
+ if (tqSendMetaPollRsp(pHandle, pMsg, pRequest, &metaRsp, vgId) < 0) {
code = -1;
taosMemoryFreeClear(pCkHead);
tDeleteSTaosxRsp(&taosxRsp);
return code;
}
+
code = 0;
taosMemoryFreeClear(pCkHead);
tDeleteSTaosxRsp(&taosxRsp);
@@ -375,7 +394,7 @@ static int32_t extractDataAndRspForDbStbSubscribe(STQ* pTq, STqHandle* pHandle,
if (totalRows >= 4096 || taosxRsp.createTableNum > 0) {
tqOffsetResetToLog(&taosxRsp.rspOffset, fetchVer);
- code = tqSendDataRsp(pTq, pMsg, pRequest, (SMqDataRsp*)&taosxRsp, TMQ_MSG_TYPE__TAOSX_RSP);
+ code = tqSendDataRsp(pHandle, pMsg, pRequest, (SMqDataRsp*)&taosxRsp, TMQ_MSG_TYPE__TAOSX_RSP, vgId);
tDeleteSTaosxRsp(&taosxRsp);
taosMemoryFreeClear(pCkHead);
return code;
@@ -423,10 +442,19 @@ int32_t tqExtractDataForMq(STQ* pTq, STqHandle* pHandle, const SMqPollReq* pRequ
return extractDataAndRspForDbStbSubscribe(pTq, pHandle, pRequest, pMsg, &offset);
}
-int32_t tqSendMetaPollRsp(STQ* pTq, const SRpcMsg* pMsg, const SMqPollReq* pReq, const SMqMetaRsp* pRsp) {
+static void initMqRspHead(SMqRspHead* pMsgHead, int32_t type, int32_t epoch, int64_t consumerId, int64_t sver,
+ int64_t ever) {
+ pMsgHead->consumerId = consumerId;
+ pMsgHead->epoch = epoch;
+ pMsgHead->mqMsgType = type;
+ pMsgHead->walsver = sver;
+ pMsgHead->walever = ever;
+}
+
+int32_t tqSendMetaPollRsp(STqHandle* pHandle, const SRpcMsg* pMsg, const SMqPollReq* pReq, const SMqMetaRsp* pRsp, int32_t vgId) {
int32_t len = 0;
int32_t code = 0;
- tEncodeSize(tEncodeSMqMetaRsp, pRsp, len, code);
+ tEncodeSize(tEncodeMqMetaRsp, pRsp, len, code);
if (code < 0) {
return -1;
}
@@ -436,27 +464,64 @@ int32_t tqSendMetaPollRsp(STQ* pTq, const SRpcMsg* pMsg, const SMqPollReq* pReq,
return -1;
}
- ((SMqRspHead*)buf)->mqMsgType = TMQ_MSG_TYPE__POLL_META_RSP;
- ((SMqRspHead*)buf)->epoch = pReq->epoch;
- ((SMqRspHead*)buf)->consumerId = pReq->consumerId;
+ int64_t sver = 0, ever = 0;
+ walReaderValidVersionRange(pHandle->execHandle.pTqReader->pWalReader, &sver, &ever);
+ initMqRspHead(buf, TMQ_MSG_TYPE__POLL_META_RSP, pReq->epoch, pReq->consumerId, sver, ever);
void* abuf = POINTER_SHIFT(buf, sizeof(SMqRspHead));
SEncoder encoder = {0};
tEncoderInit(&encoder, abuf, len);
- tEncodeSMqMetaRsp(&encoder, pRsp);
+ tEncodeMqMetaRsp(&encoder, pRsp);
tEncoderClear(&encoder);
- SRpcMsg resp = {
- .info = pMsg->info,
- .pCont = buf,
- .contLen = tlen,
- .code = 0,
- };
- tmsgSendRsp(&resp);
+ SRpcMsg resp = { .info = pMsg->info, .pCont = buf, .contLen = tlen, .code = 0 };
- tqDebug("vgId:%d, from consumer:0x%" PRIx64 " (epoch %d) send rsp, res msg type %d, offset type:%d",
- TD_VID(pTq->pVnode), pReq->consumerId, pReq->epoch, pRsp->resMsgType, pRsp->rspOffset.type);
+ tmsgSendRsp(&resp);
+ tqDebug("vgId:%d, from consumer:0x%" PRIx64 " (epoch %d) send rsp, res msg type %d, offset type:%d", vgId,
+ pReq->consumerId, pReq->epoch, pRsp->resMsgType, pRsp->rspOffset.type);
return 0;
}
+
+int32_t tqDoSendDataRsp(const SRpcHandleInfo* pRpcHandleInfo, const SMqDataRsp* pRsp, int32_t epoch, int64_t consumerId,
+ int32_t type, int64_t sver, int64_t ever) {
+ int32_t len = 0;
+ int32_t code = 0;
+
+ if (type == TMQ_MSG_TYPE__POLL_RSP || type == TMQ_MSG_TYPE__WALINFO_RSP) {
+ tEncodeSize(tEncodeMqDataRsp, pRsp, len, code);
+ } else if (type == TMQ_MSG_TYPE__TAOSX_RSP) {
+ tEncodeSize(tEncodeSTaosxRsp, (STaosxRsp*)pRsp, len, code);
+ }
+
+ if (code < 0) {
+ return -1;
+ }
+
+ int32_t tlen = sizeof(SMqRspHead) + len;
+ void* buf = rpcMallocCont(tlen);
+ if (buf == NULL) {
+ return -1;
+ }
+
+ SMqRspHead* pHead = (SMqRspHead*)buf;
+ initMqRspHead(pHead, type, epoch, consumerId, sver, ever);
+
+ void* abuf = POINTER_SHIFT(buf, sizeof(SMqRspHead));
+
+ SEncoder encoder = {0};
+ tEncoderInit(&encoder, abuf, len);
+
+ if (type == TMQ_MSG_TYPE__POLL_RSP || type == TMQ_MSG_TYPE__WALINFO_RSP) {
+ tEncodeMqDataRsp(&encoder, pRsp);
+ } else if (type == TMQ_MSG_TYPE__TAOSX_RSP) {
+ tEncodeSTaosxRsp(&encoder, (STaosxRsp*)pRsp);
+ }
+
+ tEncoderClear(&encoder);
+ SRpcMsg rsp = { .info = *pRpcHandleInfo, .pCont = buf, .contLen = tlen, .code = 0 };
+
+ tmsgSendRsp(&rsp);
+ return 0;
+}
\ No newline at end of file
diff --git a/source/dnode/vnode/src/tsdb/tsdbRead.c b/source/dnode/vnode/src/tsdb/tsdbRead.c
index 89686c3d33..362dc51ad5 100644
--- a/source/dnode/vnode/src/tsdb/tsdbRead.c
+++ b/source/dnode/vnode/src/tsdb/tsdbRead.c
@@ -1881,8 +1881,8 @@ static FORCE_INLINE STSchema* getLatestTableSchema(STsdbReader* pReader, uint64_
return pReader->pSchema;
}
- pReader->pSchema = metaGetTbTSchema(pReader->pTsdb->pVnode->pMeta, uid, -1, 1);
- if (pReader->pSchema == NULL) {
+ int32_t code = metaGetTbTSchemaEx(pReader->pTsdb->pVnode->pMeta, pReader->suid, uid, -1, &pReader->pSchema);
+ if (code != TSDB_CODE_SUCCESS || pReader->pSchema == NULL) {
tsdbError("failed to get table schema, uid:%" PRIu64 ", it may have been dropped, ver:-1, %s", uid, pReader->idStr);
}
@@ -1890,9 +1890,15 @@ static FORCE_INLINE STSchema* getLatestTableSchema(STsdbReader* pReader, uint64_
}
static FORCE_INLINE STSchema* doGetSchemaForTSRow(int32_t sversion, STsdbReader* pReader, uint64_t uid) {
+ int32_t code = 0;
+
// always set the newest schema version in pReader->pSchema
if (pReader->pSchema == NULL) {
- pReader->pSchema = metaGetTbTSchema(pReader->pTsdb->pVnode->pMeta, uid, -1, 1);
+ code = metaGetTbTSchemaEx(pReader->pTsdb->pVnode->pMeta, pReader->suid, uid, -1, &pReader->pSchema);
+ if (code != TSDB_CODE_SUCCESS) {
+ terrno = code;
+ return NULL;
+ }
}
if (pReader->pSchema && sversion == pReader->pSchema->version) {
@@ -1905,7 +1911,7 @@ static FORCE_INLINE STSchema* doGetSchemaForTSRow(int32_t sversion, STsdbReader*
}
STSchema* ptr = NULL;
- int32_t code = metaGetTbTSchemaEx(pReader->pTsdb->pVnode->pMeta, pReader->suid, uid, sversion, &ptr);
+ code = metaGetTbTSchemaEx(pReader->pTsdb->pVnode->pMeta, pReader->suid, uid, sversion, &ptr);
if (code != TSDB_CODE_SUCCESS) {
terrno = code;
return NULL;
@@ -1969,7 +1975,7 @@ static int32_t doMergeBufAndFileRows(STsdbReader* pReader, STableBlockScanInfo*
// DESC: mem -----> imem -----> last block -----> file block
if (pReader->order == TSDB_ORDER_ASC) {
if (minKey == key) {
- init = true;
+ init = true; // todo check if pReader->pSchema is null or not
int32_t code = tsdbRowMergerInit(&merge, NULL, &fRow, pReader->pSchema);
if (code != TSDB_CODE_SUCCESS) {
return code;
@@ -2014,6 +2020,10 @@ static int32_t doMergeBufAndFileRows(STsdbReader* pReader, STableBlockScanInfo*
if (minKey == k.ts) {
init = true;
STSchema* pSchema = doGetSchemaForTSRow(TSDBROW_SVERSION(pRow), pReader, pBlockScanInfo->uid);
+ if (pSchema == NULL) {
+ return terrno;
+ }
+
int32_t code = tsdbRowMergerInit(&merge, NULL, pRow, pSchema);
if (code != TSDB_CODE_SUCCESS) {
return code;
@@ -2222,6 +2232,7 @@ static int32_t doMergeMultiLevelRows(STsdbReader* pReader, STableBlockScanInfo*
if (pSchema == NULL) {
return code;
}
+
STSchema* piSchema = doGetSchemaForTSRow(TSDBROW_SVERSION(piRow), pReader, pBlockScanInfo->uid);
if (piSchema == NULL) {
return code;
@@ -3843,11 +3854,8 @@ int32_t doMergeMemTableMultiRows(TSDBROW* pRow, uint64_t uid, SIterInfo* pIter,
return terrno;
}
- if (pReader->pSchema == NULL) {
- pReader->pSchema = pTSchema;
- }
-
- code = tsdbRowMergerInit(&merge, pReader->pSchema, ¤t, pTSchema);
+ STSchema* ps = (pReader->pSchema != NULL)? pReader->pSchema:pTSchema;
+ code = tsdbRowMergerInit(&merge, ps, ¤t, pTSchema);
if (code != TSDB_CODE_SUCCESS) {
return code;
}
@@ -3891,7 +3899,14 @@ int32_t doMergeMemIMemRows(TSDBROW* pRow, TSDBROW* piRow, STableBlockScanInfo* p
TSDBKEY k = TSDBROW_KEY(pRow);
TSDBKEY ik = TSDBROW_KEY(piRow);
STSchema* pSchema = doGetSchemaForTSRow(TSDBROW_SVERSION(pRow), pReader, pBlockScanInfo->uid);
+ if (pSchema == NULL) {
+ return terrno;
+ }
+
STSchema* piSchema = doGetSchemaForTSRow(TSDBROW_SVERSION(piRow), pReader, pBlockScanInfo->uid);
+ if (piSchema == NULL) {
+ return terrno;
+ }
if (ASCENDING_TRAVERSE(pReader->order)) { // ascending order imem --> mem
int32_t code = tsdbRowMergerInit(&merge, pSchema, piRow, piSchema);
@@ -4000,10 +4015,11 @@ int32_t doAppendRowFromTSRow(SSDataBlock* pBlock, STsdbReader* pReader, SRow* pT
int64_t uid = pScanInfo->uid;
int32_t code = TSDB_CODE_SUCCESS;
- int32_t numOfCols = (int32_t)taosArrayGetSize(pBlock->pDataBlock);
-
SBlockLoadSuppInfo* pSupInfo = &pReader->suppInfo;
STSchema* pSchema = doGetSchemaForTSRow(pTSRow->sver, pReader, uid);
+ if (pSchema == NULL) {
+ return terrno;
+ }
SColVal colVal = {0};
int32_t i = 0, j = 0;
@@ -5187,8 +5203,6 @@ int64_t tsdbGetNumOfRowsInMemTable(STsdbReader* pReader) {
}
int32_t tsdbGetTableSchema(SVnode* pVnode, int64_t uid, STSchema** pSchema, int64_t* suid) {
- int32_t sversion = 1;
-
SMetaReader mr = {0};
metaReaderInit(&mr, pVnode->pMeta, 0);
int32_t code = metaGetTableEntryByUidCache(&mr, uid);
@@ -5200,6 +5214,7 @@ int32_t tsdbGetTableSchema(SVnode* pVnode, int64_t uid, STSchema** pSchema, int6
*suid = 0;
+ // only child table and ordinary table is allowed, super table is not allowed.
if (mr.me.type == TSDB_CHILD_TABLE) {
tDecoderClear(&mr.coder);
*suid = mr.me.ctbEntry.suid;
@@ -5209,9 +5224,7 @@ int32_t tsdbGetTableSchema(SVnode* pVnode, int64_t uid, STSchema** pSchema, int6
metaReaderClear(&mr);
return terrno;
}
- sversion = mr.me.stbEntry.schemaRow.version;
- } else if (mr.me.type == TSDB_NORMAL_TABLE) {
- sversion = mr.me.ntbEntry.schemaRow.version;
+ } else if (mr.me.type == TSDB_NORMAL_TABLE) { // do nothing
} else {
terrno = TSDB_CODE_INVALID_PARA;
metaReaderClear(&mr);
@@ -5219,9 +5232,10 @@ int32_t tsdbGetTableSchema(SVnode* pVnode, int64_t uid, STSchema** pSchema, int6
}
metaReaderClear(&mr);
- *pSchema = metaGetTbTSchema(pVnode->pMeta, uid, sversion, 1);
- return TSDB_CODE_SUCCESS;
+ // get the newest table schema version
+ code = metaGetTbTSchemaEx(pVnode->pMeta, *suid, uid, -1, pSchema);
+ return code;
}
int32_t tsdbTakeReadSnap(STsdbReader* pReader, _query_reseek_func_t reseek, STsdbReadSnap** ppSnap) {
diff --git a/source/dnode/vnode/src/vnd/vnodeCfg.c b/source/dnode/vnode/src/vnd/vnodeCfg.c
index 65f32b0a85..511ba9cc24 100644
--- a/source/dnode/vnode/src/vnd/vnodeCfg.c
+++ b/source/dnode/vnode/src/vnd/vnodeCfg.c
@@ -60,19 +60,19 @@ int vnodeCheckCfg(const SVnodeCfg *pCfg) {
const char* vnodeRoleToStr(ESyncRole role) {
switch (role) {
case TAOS_SYNC_ROLE_VOTER:
- return "voter";
+ return "true";
case TAOS_SYNC_ROLE_LEARNER:
- return "learner";
+ return "false";
default:
return "unknown";
}
}
const ESyncRole vnodeStrToRole(char* str) {
- if(strcmp(str, "voter") == 0){
+ if(strcmp(str, "true") == 0){
return TAOS_SYNC_ROLE_VOTER;
}
- if(strcmp(str, "learner") == 0){
+ if(strcmp(str, "false") == 0){
return TAOS_SYNC_ROLE_LEARNER;
}
@@ -139,7 +139,6 @@ int vnodeEncodeConfig(const void *pObj, SJson *pJson) {
if (tjsonAddIntegerToObject(pJson, "hashSuffix", pCfg->hashSuffix) < 0) return -1;
if (tjsonAddIntegerToObject(pJson, "syncCfg.replicaNum", pCfg->syncCfg.replicaNum) < 0) return -1;
- if (tjsonAddIntegerToObject(pJson, "syncCfg.totalReplicaNum", pCfg->syncCfg.totalReplicaNum) < 0) return -1;
if (tjsonAddIntegerToObject(pJson, "syncCfg.myIndex", pCfg->syncCfg.myIndex) < 0) return -1;
if (tjsonAddIntegerToObject(pJson, "vndStats.stables", pCfg->vndStats.numOfSTables) < 0) return -1;
@@ -161,7 +160,7 @@ int vnodeEncodeConfig(const void *pObj, SJson *pJson) {
if (tjsonAddStringToObject(info, "nodeFqdn", pNode->nodeFqdn) < 0) return -1;
if (tjsonAddIntegerToObject(info, "nodeId", pNode->nodeId) < 0) return -1;
if (tjsonAddIntegerToObject(info, "clusterId", pNode->clusterId) < 0) return -1;
- if (tjsonAddStringToObject(info, "nodeRole", vnodeRoleToStr(pNode->nodeRole)) < 0) return -1;
+ if (tjsonAddStringToObject(info, "isReplica", vnodeRoleToStr(pNode->nodeRole)) < 0) return -1;
if (tjsonAddItemToArray(nodeInfo, info) < 0) return -1;
vDebug("vgId:%d, encode config, replica:%d ep:%s:%u dnode:%d", pCfg->vgId, i, pNode->nodeFqdn, pNode->nodePort,
pNode->nodeId);
@@ -259,8 +258,6 @@ int vnodeDecodeConfig(const SJson *pJson, void *pObj) {
tjsonGetNumberValue(pJson, "syncCfg.replicaNum", pCfg->syncCfg.replicaNum, code);
if (code < 0) return -1;
- tjsonGetNumberValue(pJson, "syncCfg.totalReplicaNum", pCfg->syncCfg.totalReplicaNum, code);
- if (code < 0) return -1;
tjsonGetNumberValue(pJson, "syncCfg.myIndex", pCfg->syncCfg.myIndex, code);
if (code < 0) return -1;
@@ -277,10 +274,7 @@ int vnodeDecodeConfig(const SJson *pJson, void *pObj) {
SJson *nodeInfo = tjsonGetObjectItem(pJson, "syncCfg.nodeInfo");
int arraySize = tjsonGetArraySize(nodeInfo);
- if(pCfg->syncCfg.totalReplicaNum == 0 && pCfg->syncCfg.replicaNum > 0){
- pCfg->syncCfg.totalReplicaNum = pCfg->syncCfg.replicaNum;
- }
- if (arraySize != pCfg->syncCfg.totalReplicaNum) return -1;
+ pCfg->syncCfg.totalReplicaNum = arraySize;
vDebug("vgId:%d, decode config, replicas:%d totalReplicas:%d selfIndex:%d", pCfg->vgId, pCfg->syncCfg.replicaNum,
pCfg->syncCfg.totalReplicaNum, pCfg->syncCfg.myIndex);
@@ -296,7 +290,7 @@ int vnodeDecodeConfig(const SJson *pJson, void *pObj) {
tjsonGetNumberValue(info, "clusterId", pNode->clusterId, code);
if (code < 0) return -1;
char role[10] = {0};
- code = tjsonGetStringValue(info, "nodeRole", role);
+ code = tjsonGetStringValue(info, "isReplica", role);
if (code < 0) return -1;
if(strlen(role) != 0){
pNode->nodeRole = vnodeStrToRole(role);
diff --git a/source/dnode/vnode/src/vnd/vnodeOpen.c b/source/dnode/vnode/src/vnd/vnodeOpen.c
index deeb0af42a..7d41edfdd9 100644
--- a/source/dnode/vnode/src/vnd/vnodeOpen.c
+++ b/source/dnode/vnode/src/vnd/vnodeOpen.c
@@ -431,6 +431,10 @@ int32_t vnodeIsCatchUp(SVnode *pVnode){
return syncIsCatchUp(pVnode->sync);
}
+ESyncRole vnodeGetRole(SVnode *pVnode){
+ return syncGetRole(pVnode->sync);
+}
+
void vnodeStop(SVnode *pVnode) {}
int64_t vnodeGetSyncHandle(SVnode *pVnode) { return pVnode->sync; }
diff --git a/source/dnode/vnode/src/vnd/vnodeSvr.c b/source/dnode/vnode/src/vnd/vnodeSvr.c
index 1adb75ac88..dd576392f0 100644
--- a/source/dnode/vnode/src/vnd/vnodeSvr.c
+++ b/source/dnode/vnode/src/vnd/vnodeSvr.c
@@ -389,6 +389,11 @@ int32_t vnodeProcessWriteMsg(SVnode *pVnode, SRpcMsg *pMsg, int64_t version, SRp
goto _err;
}
break;
+ case TDMT_VND_TMQ_SEEK_TO_OFFSET:
+ if (tqProcessSeekReq(pVnode->pTq, version, pReq, pMsg->contLen - sizeof(SMsgHead)) < 0) {
+ goto _err;
+ }
+ break;
case TDMT_VND_TMQ_ADD_CHECKINFO:
if (tqProcessAddCheckInfoReq(pVnode->pTq, version, pReq, len) < 0) {
goto _err;
@@ -539,6 +544,8 @@ int32_t vnodeProcessFetchMsg(SVnode *pVnode, SRpcMsg *pMsg, SQueueInfo *pInfo) {
return vnodeGetBatchMeta(pVnode, pMsg);
case TDMT_VND_TMQ_CONSUME:
return tqProcessPollReq(pVnode->pTq, pMsg);
+ case TDMT_VND_TMQ_VG_WALINFO:
+ return tqProcessVgWalInfoReq(pVnode->pTq, pMsg);
case TDMT_STREAM_TASK_RUN:
return tqProcessTaskRunReq(pVnode->pTq, pMsg);
case TDMT_STREAM_TASK_DISPATCH:
diff --git a/source/dnode/vnode/src/vnd/vnodeSync.c b/source/dnode/vnode/src/vnd/vnodeSync.c
index fccac5c625..ba73c5fd4c 100644
--- a/source/dnode/vnode/src/vnd/vnodeSync.c
+++ b/source/dnode/vnode/src/vnd/vnodeSync.c
@@ -547,7 +547,7 @@ static void vnodeRestoreFinish(const SSyncFSM *pFsm, const SyncIndex commitIdx)
walApplyVer(pVnode->pWal, commitIdx);
pVnode->restored = true;
- vInfo("vgId:%d, sync restore finished", pVnode->config.vgId);
+ vInfo("vgId:%d, sync restore finished, start to restore stream tasks by replay wal", pVnode->config.vgId);
// start to restore all stream tasks
tqStartStreamTasks(pVnode->pTq);
diff --git a/source/libs/executor/inc/executil.h b/source/libs/executor/inc/executil.h
index 9b8f034e44..2e92f9e396 100644
--- a/source/libs/executor/inc/executil.h
+++ b/source/libs/executor/inc/executil.h
@@ -108,6 +108,7 @@ uint64_t tableListGetSize(const STableListInfo* pTableList);
uint64_t tableListGetSuid(const STableListInfo* pTableList);
STableKeyInfo* tableListGetInfo(const STableListInfo* pTableList, int32_t index);
int32_t tableListFind(const STableListInfo* pTableList, uint64_t uid, int32_t startIndex);
+void tableListGetSourceTableInfo(const STableListInfo* pTableList, uint64_t* psuid, uint64_t* uid, int32_t* type);
size_t getResultRowSize(struct SqlFunctionCtx* pCtx, int32_t numOfOutput);
void initResultRowInfo(SResultRowInfo* pResultRowInfo);
diff --git a/source/libs/executor/inc/executorimpl.h b/source/libs/executor/inc/executorimpl.h
index 2cb6626b03..43ee54f65d 100644
--- a/source/libs/executor/inc/executorimpl.h
+++ b/source/libs/executor/inc/executorimpl.h
@@ -366,6 +366,7 @@ typedef struct STagScanInfo {
int32_t curPos;
SReadHandle readHandle;
STableListInfo* pTableListInfo;
+ SLimitNode* pSlimit;
} STagScanInfo;
typedef enum EStreamScanMode {
@@ -427,7 +428,6 @@ typedef struct STimeWindowAggSupp {
} STimeWindowAggSupp;
typedef struct SStreamScanInfo {
- uint64_t tableUid; // queried super table uid
SExprInfo* pPseudoExpr;
int32_t numOfPseudoExpr;
SExprSupp tbnameCalSup;
diff --git a/source/libs/executor/src/dataDeleter.c b/source/libs/executor/src/dataDeleter.c
index dc3bf83a91..d693faf7f1 100644
--- a/source/libs/executor/src/dataDeleter.c
+++ b/source/libs/executor/src/dataDeleter.c
@@ -240,6 +240,7 @@ int32_t createDataDeleter(SDataSinkManager* pManager, const SDataSinkNode* pData
SDataDeleterHandle* deleter = taosMemoryCalloc(1, sizeof(SDataDeleterHandle));
if (NULL == deleter) {
+ taosMemoryFree(pParam);
code = TSDB_CODE_OUT_OF_MEMORY;
goto _end;
}
diff --git a/source/libs/executor/src/dataInserter.c b/source/libs/executor/src/dataInserter.c
index e9c46843c0..90d740bebd 100644
--- a/source/libs/executor/src/dataInserter.c
+++ b/source/libs/executor/src/dataInserter.c
@@ -408,6 +408,7 @@ int32_t createDataInserter(SDataSinkManager* pManager, const SDataSinkNode* pDat
void* pParam) {
SDataInserterHandle* inserter = taosMemoryCalloc(1, sizeof(SDataInserterHandle));
if (NULL == inserter) {
+ taosMemoryFree(pParam);
terrno = TSDB_CODE_OUT_OF_MEMORY;
return TSDB_CODE_OUT_OF_MEMORY;
}
diff --git a/source/libs/executor/src/executil.c b/source/libs/executor/src/executil.c
index 7d318786ba..f61fd1ae01 100644
--- a/source/libs/executor/src/executil.c
+++ b/source/libs/executor/src/executil.c
@@ -27,15 +27,21 @@
#include "executorimpl.h"
#include "tcompression.h"
+typedef struct STableListIdInfo {
+ uint64_t suid;
+ uint64_t uid;
+ int32_t tableType;
+} STableListIdInfo;
+
// If the numOfOutputGroups is 1, the data blocks that belongs to different groups will be provided randomly
// The numOfOutputGroups is specified by physical plan. and will not be affect by numOfGroups
struct STableListInfo {
- bool oneTableForEachGroup;
- int32_t numOfOuputGroups; // the data block will be generated one by one
- int32_t* groupOffset; // keep the offset value for each group in the tableList
- SArray* pTableList;
- SHashObj* map; // speedup acquire the tableQueryInfo by table uid
- uint64_t suid;
+ bool oneTableForEachGroup;
+ int32_t numOfOuputGroups; // the data block will be generated one by one
+ int32_t* groupOffset; // keep the offset value for each group in the tableList
+ SArray* pTableList;
+ SHashObj* map; // speedup acquire the tableQueryInfo by table uid
+ STableListIdInfo idInfo; // this maybe the super table or ordinary table
};
typedef struct tagFilterAssist {
@@ -470,7 +476,7 @@ int32_t getColInfoResultForGroupby(void* metaHandle, SNodeList* group, STableLis
}
// int64_t stt = taosGetTimestampUs();
- code = metaGetTableTags(metaHandle, pTableListInfo->suid, pUidTagList);
+ code = metaGetTableTags(metaHandle, pTableListInfo->idInfo.suid, pUidTagList);
if (code != TSDB_CODE_SUCCESS) {
goto end;
}
@@ -953,7 +959,7 @@ static int32_t doFilterByTagCond(STableListInfo* pListInfo, SArray* pUidList, SN
FilterCondType condType = checkTagCond(pTagCond);
- int32_t filter = optimizeTbnameInCond(metaHandle, pListInfo->suid, pUidTagList, pTagCond);
+ int32_t filter = optimizeTbnameInCond(metaHandle, pListInfo->idInfo.suid, pUidTagList, pTagCond);
if (filter == 0) { // tbname in filter is activated, do nothing and return
taosArrayClear(pUidList);
@@ -966,12 +972,12 @@ static int32_t doFilterByTagCond(STableListInfo* pListInfo, SArray* pUidList, SN
terrno = 0;
} else {
if ((condType == FILTER_NO_LOGIC || condType == FILTER_AND) && status != SFLT_NOT_INDEX) {
- code = metaGetTableTagsByUids(metaHandle, pListInfo->suid, pUidTagList);
+ code = metaGetTableTagsByUids(metaHandle, pListInfo->idInfo.suid, pUidTagList);
} else {
- code = metaGetTableTags(metaHandle, pListInfo->suid, pUidTagList);
+ code = metaGetTableTags(metaHandle, pListInfo->idInfo.suid, pUidTagList);
}
if (code != TSDB_CODE_SUCCESS) {
- qError("failed to get table tags from meta, reason:%s, suid:%" PRIu64, tstrerror(code), pListInfo->suid);
+ qError("failed to get table tags from meta, reason:%s, suid:%" PRIu64, tstrerror(code), pListInfo->idInfo.suid);
terrno = code;
goto end;
}
@@ -1025,15 +1031,17 @@ int32_t getTableList(void* metaHandle, void* pVnode, SScanPhysiNode* pScanNode,
int32_t code = TSDB_CODE_SUCCESS;
size_t numOfTables = 0;
- pListInfo->suid = pScanNode->suid;
+ pListInfo->idInfo.suid = pScanNode->suid;
+ pListInfo->idInfo.tableType = pScanNode->tableType;
+
SArray* pUidList = taosArrayInit(8, sizeof(uint64_t));
SIdxFltStatus status = SFLT_NOT_INDEX;
if (pScanNode->tableType != TSDB_SUPER_TABLE) {
+ pListInfo->idInfo.uid = pScanNode->uid;
if (metaIsTableExist(metaHandle, pScanNode->uid)) {
taosArrayPush(pUidList, &pScanNode->uid);
}
-
code = doFilterByTagCond(pListInfo, pUidList, pTagCond, metaHandle, status);
if (code != TSDB_CODE_SUCCESS) {
goto _end;
@@ -1794,7 +1802,9 @@ uint64_t tableListGetSize(const STableListInfo* pTableList) {
return taosArrayGetSize(pTableList->pTableList);
}
-uint64_t tableListGetSuid(const STableListInfo* pTableList) { return pTableList->suid; }
+uint64_t tableListGetSuid(const STableListInfo* pTableList) {
+ return pTableList->idInfo.suid;
+}
STableKeyInfo* tableListGetInfo(const STableListInfo* pTableList, int32_t index) {
if (taosArrayGetSize(pTableList->pTableList) == 0) {
@@ -1819,6 +1829,12 @@ int32_t tableListFind(const STableListInfo* pTableList, uint64_t uid, int32_t st
return -1;
}
+void tableListGetSourceTableInfo(const STableListInfo* pTableList, uint64_t* psuid, uint64_t* uid, int32_t* type) {
+ *psuid = pTableList->idInfo.suid;
+ *uid = pTableList->idInfo.uid;
+ *type = pTableList->idInfo.tableType;
+}
+
uint64_t getTableGroupId(const STableListInfo* pTableList, uint64_t tableUid) {
int32_t* slot = taosHashGet(pTableList->map, &tableUid, sizeof(tableUid));
ASSERT(pTableList->map != NULL && slot != NULL);
diff --git a/source/libs/executor/src/executor.c b/source/libs/executor/src/executor.c
index 6e3a7d8725..1732ec04a7 100644
--- a/source/libs/executor/src/executor.c
+++ b/source/libs/executor/src/executor.c
@@ -14,6 +14,7 @@
*/
#include "executor.h"
+#include
#include "executorimpl.h"
#include "planner.h"
#include "tdatablock.h"
@@ -327,6 +328,13 @@ static SArray* filterUnqualifiedTables(const SStreamScanInfo* pScanInfo, const S
return qa;
}
+ STableScanInfo* pTableScanInfo = pScanInfo->pTableScanOp->info;
+
+ uint64_t suid = 0;
+ uint64_t uid = 0;
+ int32_t type = 0;
+ tableListGetSourceTableInfo(pTableScanInfo->base.pTableListInfo, &suid, &uid, &type);
+
// let's discard the tables those are not created according to the queried super table.
SMetaReader mr = {0};
metaReaderInit(&mr, pScanInfo->readHandle.meta, 0);
@@ -341,9 +349,21 @@ static SArray* filterUnqualifiedTables(const SStreamScanInfo* pScanInfo, const S
tDecoderClear(&mr.coder);
- // TODO handle ntb case
- if (mr.me.type != TSDB_CHILD_TABLE || mr.me.ctbEntry.suid != pScanInfo->tableUid) {
+ if (mr.me.type == TSDB_SUPER_TABLE) {
continue;
+ } else {
+ if (type == TSDB_SUPER_TABLE) {
+ // this new created child table does not belong to the scanned super table.
+ if (mr.me.type != TSDB_CHILD_TABLE || mr.me.ctbEntry.suid != suid) {
+ continue;
+ }
+ } else { // ordinary table
+ // In case that the scanned target table is an ordinary table. When replay the WAL during restore the vnode, we
+ // should check all newly created ordinary table to make sure that this table isn't the destination table.
+ if (mr.me.uid != uid) {
+ continue;
+ }
+ }
}
if (pScanInfo->pTagCond != NULL) {
@@ -382,7 +402,7 @@ int32_t qUpdateTableListForStreamScanner(qTaskInfo_t tinfo, const SArray* tableI
SStreamScanInfo* pScanInfo = pInfo->info;
if (isAdd) { // add new table id
- SArray* qa = filterUnqualifiedTables(pScanInfo, tableIdList, GET_TASKID(pTaskInfo));
+ SArray* qa = filterUnqualifiedTables(pScanInfo, tableIdList, id);
int32_t numOfQualifiedTables = taosArrayGetSize(qa);
qDebug("%d qualified child tables added into stream scanner, %s", numOfQualifiedTables, id);
code = tqReaderAddTbUidList(pScanInfo->tqReader, qa);
@@ -497,10 +517,8 @@ int32_t qCreateExecTask(SReadHandle* readHandle, int32_t vgId, uint64_t taskId,
goto _error;
}
+ // pSinkParam has been freed during create sinker.
code = dsCreateDataSinker(pSubplan->pDataSink, handle, pSinkParam, (*pTask)->id.str);
- if (code != TSDB_CODE_SUCCESS) {
- taosMemoryFreeClear(pSinkParam);
- }
}
qDebug("subplan task create completed, TID:0x%" PRIx64 " QID:0x%" PRIx64, taskId, pSubplan->id.queryId);
diff --git a/source/libs/executor/src/groupoperator.c b/source/libs/executor/src/groupoperator.c
index 3d9bacf39f..612ecb4684 100644
--- a/source/libs/executor/src/groupoperator.c
+++ b/source/libs/executor/src/groupoperator.c
@@ -871,9 +871,9 @@ SOperatorInfo* createPartitionOperatorInfo(SOperatorInfo* downstream, SPartition
getBufferPgSize(pInfo->binfo.pRes->info.rowSize, &defaultPgsz, &defaultBufsz);
if (!osTempSpaceAvailable()) {
- terrno = TSDB_CODE_NO_AVAIL_DISK;
+ terrno = TSDB_CODE_NO_DISKSPACE;
pTaskInfo->code = terrno;
- qError("Create partition operator info failed since %s", terrstr(terrno));
+ qError("Create partition operator info failed since %s, tempDir:%s", terrstr(), tsTempDir);
goto _error;
}
diff --git a/source/libs/executor/src/scanoperator.c b/source/libs/executor/src/scanoperator.c
index ae396a4c68..6d62d55024 100644
--- a/source/libs/executor/src/scanoperator.c
+++ b/source/libs/executor/src/scanoperator.c
@@ -690,7 +690,7 @@ static SSDataBlock* doTableScanImpl(SOperatorInfo* pOperator) {
}
uint32_t status = 0;
- int32_t code = loadDataBlock(pOperator, &pTableScanInfo->base, pBlock, &status);
+ code = loadDataBlock(pOperator, &pTableScanInfo->base, pBlock, &status);
if (code != TSDB_CODE_SUCCESS) {
T_LONG_JMP(pTaskInfo->env, code);
}
@@ -2441,7 +2441,6 @@ SOperatorInfo* createStreamScanOperatorInfo(SReadHandle* pHandle, STableScanPhys
}
pInfo->readHandle = *pHandle;
- pInfo->tableUid = pScanPhyNode->uid;
pTaskInfo->streamInfo.snapshotVer = pHandle->version;
pInfo->pCreateTbRes = buildCreateTableBlock(&pInfo->tbnameCalSup, &pInfo->tagCalSup);
blockDataEnsureCapacity(pInfo->pCreateTbRes, 8);
@@ -2513,6 +2512,51 @@ _error:
return NULL;
}
+static void doTagScanOneTable(SOperatorInfo* pOperator, const SSDataBlock* pRes, int32_t count, SMetaReader* mr) {
+ SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo;
+ STagScanInfo* pInfo = pOperator->info;
+ SExprInfo* pExprInfo = &pOperator->exprSupp.pExprInfo[0];
+
+ STableKeyInfo* item = tableListGetInfo(pInfo->pTableListInfo, pInfo->curPos);
+ int32_t code = metaGetTableEntryByUid(mr, item->uid);
+ tDecoderClear(&(*mr).coder);
+ if (code != TSDB_CODE_SUCCESS) {
+ qError("failed to get table meta, uid:0x%" PRIx64 ", code:%s, %s", item->uid, tstrerror(terrno),
+ GET_TASKID(pTaskInfo));
+ metaReaderClear(mr);
+ T_LONG_JMP(pTaskInfo->env, terrno);
+ }
+
+ char str[512];
+ for (int32_t j = 0; j < pOperator->exprSupp.numOfExprs; ++j) {
+ SColumnInfoData* pDst = taosArrayGet(pRes->pDataBlock, pExprInfo[j].base.resSchema.slotId);
+
+ // refactor later
+ if (fmIsScanPseudoColumnFunc(pExprInfo[j].pExpr->_function.functionId)) {
+ STR_TO_VARSTR(str, (*mr).me.name);
+ colDataSetVal(pDst, (count), str, false);
+ } else { // it is a tag value
+ STagVal val = {0};
+ val.cid = pExprInfo[j].base.pParam[0].pCol->colId;
+ const char* p = metaGetTableTagVal((*mr).me.ctbEntry.pTags, pDst->info.type, &val);
+
+ char* data = NULL;
+ if (pDst->info.type != TSDB_DATA_TYPE_JSON && p != NULL) {
+ data = tTagValToData((const STagVal*)p, false);
+ } else {
+ data = (char*)p;
+ }
+ colDataSetVal(pDst, (count), data,
+ (data == NULL) || (pDst->info.type == TSDB_DATA_TYPE_JSON && tTagIsJsonNull(data)));
+
+ if (pDst->info.type != TSDB_DATA_TYPE_JSON && p != NULL && IS_VAR_DATA_TYPE(((const STagVal*)p)->type) &&
+ data != NULL) {
+ taosMemoryFree(data);
+ }
+ }
+ }
+}
+
static SSDataBlock* doTagScan(SOperatorInfo* pOperator) {
if (pOperator->status == OP_EXEC_DONE) {
return NULL;
@@ -2537,48 +2581,22 @@ static SSDataBlock* doTagScan(SOperatorInfo* pOperator) {
metaReaderInit(&mr, pInfo->readHandle.meta, 0);
while (pInfo->curPos < size && count < pOperator->resultInfo.capacity) {
- STableKeyInfo* item = tableListGetInfo(pInfo->pTableListInfo, pInfo->curPos);
- int32_t code = metaGetTableEntryByUid(&mr, item->uid);
- tDecoderClear(&mr.coder);
- if (code != TSDB_CODE_SUCCESS) {
- qError("failed to get table meta, uid:0x%" PRIx64 ", code:%s, %s", item->uid, tstrerror(terrno),
- GET_TASKID(pTaskInfo));
- metaReaderClear(&mr);
- T_LONG_JMP(pTaskInfo->env, terrno);
- }
-
- for (int32_t j = 0; j < pOperator->exprSupp.numOfExprs; ++j) {
- SColumnInfoData* pDst = taosArrayGet(pRes->pDataBlock, pExprInfo[j].base.resSchema.slotId);
-
- // refactor later
- if (fmIsScanPseudoColumnFunc(pExprInfo[j].pExpr->_function.functionId)) {
- STR_TO_VARSTR(str, mr.me.name);
- colDataSetVal(pDst, count, str, false);
- } else { // it is a tag value
- STagVal val = {0};
- val.cid = pExprInfo[j].base.pParam[0].pCol->colId;
- const char* p = metaGetTableTagVal(mr.me.ctbEntry.pTags, pDst->info.type, &val);
-
- char* data = NULL;
- if (pDst->info.type != TSDB_DATA_TYPE_JSON && p != NULL) {
- data = tTagValToData((const STagVal*)p, false);
- } else {
- data = (char*)p;
- }
- colDataSetVal(pDst, count, data,
- (data == NULL) || (pDst->info.type == TSDB_DATA_TYPE_JSON && tTagIsJsonNull(data)));
-
- if (pDst->info.type != TSDB_DATA_TYPE_JSON && p != NULL && IS_VAR_DATA_TYPE(((const STagVal*)p)->type) &&
- data != NULL) {
- taosMemoryFree(data);
- }
- }
- }
-
- count += 1;
+ doTagScanOneTable(pOperator, pRes, count, &mr);
+ ++count;
if (++pInfo->curPos >= size) {
setOperatorCompleted(pOperator);
}
+ // each table with tbname is a group, hence its own block, but only group when slimit exists for performance reason.
+ if (pInfo->pSlimit != NULL) {
+ if (pInfo->curPos < pInfo->pSlimit->offset) {
+ continue;
+ }
+ pInfo->pRes->info.id.groupId = calcGroupId(mr.me.name, strlen(mr.me.name));
+ if (pInfo->curPos >= (pInfo->pSlimit->offset + pInfo->pSlimit->limit) - 1) {
+ setOperatorCompleted(pOperator);
+ }
+ break;
+ }
}
metaReaderClear(&mr);
@@ -2629,6 +2647,7 @@ SOperatorInfo* createTagScanOperatorInfo(SReadHandle* pReadHandle, STagScanPhysi
pInfo->pRes = createDataBlockFromDescNode(pDescNode);
pInfo->readHandle = *pReadHandle;
pInfo->curPos = 0;
+ pInfo->pSlimit = (SLimitNode*)pPhyNode->node.pSlimit; //TODO: slimit now only indicate group
setOperatorInfo(pOperator, "TagScanOperator", QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN, false, OP_NOT_OPENED, pInfo,
pTaskInfo);
diff --git a/source/libs/executor/src/timewindowoperator.c b/source/libs/executor/src/timewindowoperator.c
index 007a6f63d1..7afda3f597 100644
--- a/source/libs/executor/src/timewindowoperator.c
+++ b/source/libs/executor/src/timewindowoperator.c
@@ -2911,8 +2911,8 @@ int32_t initStreamAggSupporter(SStreamAggSupporter* pSup, SqlFunctionCtx* pCtx,
bufSize = pageSize * 4;
}
if (!osTempSpaceAvailable()) {
- terrno = TSDB_CODE_NO_AVAIL_DISK;
- qError("Init stream agg supporter failed since %s", terrstr(terrno));
+ terrno = TSDB_CODE_NO_DISKSPACE;
+ qError("Init stream agg supporter failed since %s, tempDir:%s", terrstr(), tsTempDir);
return terrno;
}
int32_t code = createDiskbasedBuf(&pSup->pResultBuf, pageSize, bufSize, "function", tsTempDir);
diff --git a/source/libs/executor/src/tlinearhash.c b/source/libs/executor/src/tlinearhash.c
index 2cba3855c7..023583fcde 100644
--- a/source/libs/executor/src/tlinearhash.c
+++ b/source/libs/executor/src/tlinearhash.c
@@ -248,8 +248,8 @@ SLHashObj* tHashInit(int32_t inMemPages, int32_t pageSize, _hash_fn_t fn, int32_
}
if (!osTempSpaceAvailable()) {
- terrno = TSDB_CODE_NO_AVAIL_DISK;
- printf("tHash Init failed since %s", terrstr(terrno));
+ terrno = TSDB_CODE_NO_DISKSPACE;
+ printf("tHash Init failed since %s, tempDir:%s", terrstr(), tsTempDir);
taosMemoryFree(pHashObj);
return NULL;
}
diff --git a/source/libs/executor/src/tsort.c b/source/libs/executor/src/tsort.c
index 6c8e581b3f..da5f65fdf2 100644
--- a/source/libs/executor/src/tsort.c
+++ b/source/libs/executor/src/tsort.c
@@ -195,8 +195,8 @@ static int32_t doAddToBuf(SSDataBlock* pDataBlock, SSortHandle* pHandle) {
if (pHandle->pBuf == NULL) {
if (!osTempSpaceAvailable()) {
- terrno = TSDB_CODE_NO_AVAIL_DISK;
- qError("Add to buf failed since %s", terrstr(terrno));
+ terrno = TSDB_CODE_NO_DISKSPACE;
+ qError("Add to buf failed since %s, tempDir:%s", terrstr(), tsTempDir);
return terrno;
}
@@ -261,9 +261,8 @@ static int32_t sortComparInit(SMsortComparParam* pParam, SArray* pSources, int32
// multi-pass internal merge sort is required
if (pHandle->pBuf == NULL) {
if (!osTempSpaceAvailable()) {
- code = TSDB_CODE_NO_AVAIL_DISK;
- terrno = code;
- qError("Sort compare init failed since %s, %s", tstrerror(code), pHandle->idStr);
+ code = terrno = TSDB_CODE_NO_DISKSPACE;
+ qError("Sort compare init failed since %s, tempDir:%s, idStr:%s", terrstr(), tsTempDir, pHandle->idStr);
return code;
}
diff --git a/source/libs/function/src/builtinsimpl.c b/source/libs/function/src/builtinsimpl.c
index a8ecd9b0a2..ead53aade6 100644
--- a/source/libs/function/src/builtinsimpl.c
+++ b/source/libs/function/src/builtinsimpl.c
@@ -855,7 +855,9 @@ int32_t setSelectivityValue(SqlFunctionCtx* pCtx, SSDataBlock* pBlock, const STu
int32_t numOfCols = pCtx->subsidiaries.num;
const char* p = loadTupleData(pCtx, pTuplePos);
if (p == NULL) {
- terrno = TSDB_CODE_NO_AVAIL_DISK;
+ terrno = TSDB_CODE_NOT_FOUND;
+ qError("Load tuple data failed since %s, groupId:%" PRIu64 ", ts:%" PRId64, terrstr(),
+ pTuplePos->streamTupleKey.groupId, pTuplePos->streamTupleKey.ts);
return terrno;
}
@@ -5098,7 +5100,9 @@ int32_t modeFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
if (maxCount != 0) {
const char* pData = loadTupleData(pCtx, &resDataPos);
if (pData == NULL) {
- code = TSDB_CODE_NO_AVAIL_DISK;
+ code = terrno = TSDB_CODE_NOT_FOUND;
+ qError("Load tuple data failed since %s, groupId:%" PRIu64 ", ts:%" PRId64, terrstr(),
+ resDataPos.streamTupleKey.groupId, resDataPos.streamTupleKey.ts);
modeFunctionCleanup(pInfo);
return code;
}
diff --git a/source/libs/function/src/tpercentile.c b/source/libs/function/src/tpercentile.c
index de381fadbd..2edfb33e81 100644
--- a/source/libs/function/src/tpercentile.c
+++ b/source/libs/function/src/tpercentile.c
@@ -277,7 +277,7 @@ tMemBucket *tMemBucketCreate(int16_t nElemSize, int16_t dataType, double minval,
resetSlotInfo(pBucket);
if (!osTempSpaceAvailable()) {
- terrno = TSDB_CODE_NO_AVAIL_DISK;
+ terrno = TSDB_CODE_NO_DISKSPACE;
// qError("MemBucket create disk based Buf failed since %s", terrstr(terrno));
tMemBucketDestroy(pBucket);
return NULL;
diff --git a/source/libs/function/src/tudf.c b/source/libs/function/src/tudf.c
index 8c8b99a6f8..6b70422ac8 100644
--- a/source/libs/function/src/tudf.c
+++ b/source/libs/function/src/tudf.c
@@ -1580,7 +1580,7 @@ int32_t udfcStartUvTask(SClientUvTaskNode *uvTask) {
case UV_TASK_REQ_RSP: {
uv_pipe_t *pipe = uvTask->pipe;
if (pipe == NULL) {
- code = TSDB_CODE_UDF_PIPE_NO_PIPE;
+ code = TSDB_CODE_UDF_PIPE_NOT_EXIST;
} else {
uv_write_t *write = taosMemoryMalloc(sizeof(uv_write_t));
write->data = pipe->data;
@@ -1598,7 +1598,7 @@ int32_t udfcStartUvTask(SClientUvTaskNode *uvTask) {
case UV_TASK_DISCONNECT: {
uv_pipe_t *pipe = uvTask->pipe;
if (pipe == NULL) {
- code = TSDB_CODE_UDF_PIPE_NO_PIPE;
+ code = TSDB_CODE_UDF_PIPE_NOT_EXIST;
} else {
SClientUvConn *conn = pipe->data;
QUEUE_INSERT_TAIL(&conn->taskQueue, &uvTask->connTaskQueue);
@@ -1759,9 +1759,6 @@ int32_t udfcRunUdfUvTask(SClientUdfTask *task, int8_t uvTaskType) {
}
int32_t doSetupUdf(char udfName[], UdfcFuncHandle *funcHandle) {
- if (gUdfcProxy.udfcState != UDFC_STATE_READY) {
- return TSDB_CODE_UDF_INVALID_STATE;
- }
SClientUdfTask *task = taosMemoryCalloc(1, sizeof(SClientUdfTask));
task->errCode = 0;
task->session = taosMemoryCalloc(1, sizeof(SUdfcUvSession));
@@ -1804,7 +1801,7 @@ int32_t callUdf(UdfcFuncHandle handle, int8_t callType, SSDataBlock *input, SUdf
SUdfcUvSession *session = (SUdfcUvSession *)handle;
if (session->udfUvPipe == NULL) {
fnError("No pipe to udfd");
- return TSDB_CODE_UDF_PIPE_NO_PIPE;
+ return TSDB_CODE_UDF_PIPE_NOT_EXIST;
}
SClientUdfTask *task = taosMemoryCalloc(1, sizeof(SClientUdfTask));
task->errCode = 0;
@@ -1928,7 +1925,7 @@ int32_t doTeardownUdf(UdfcFuncHandle handle) {
if (session->udfUvPipe == NULL) {
fnError("tear down udf. pipe to udfd does not exist. udf name: %s", session->udfName);
taosMemoryFree(session);
- return TSDB_CODE_UDF_PIPE_NO_PIPE;
+ return TSDB_CODE_UDF_PIPE_NOT_EXIST;
}
SClientUdfTask *task = taosMemoryCalloc(1, sizeof(SClientUdfTask));
diff --git a/source/libs/function/src/udfd.c b/source/libs/function/src/udfd.c
index 5034af2f82..d2553ba96d 100644
--- a/source/libs/function/src/udfd.c
+++ b/source/libs/function/src/udfd.c
@@ -844,7 +844,7 @@ void udfdGetFuncBodyPath(const SUdf *udf, char *path) {
int32_t udfdSaveFuncBodyToFile(SFuncInfo *pFuncInfo, SUdf *udf) {
if (!osDataSpaceAvailable()) {
- terrno = TSDB_CODE_NO_AVAIL_DISK;
+ terrno = TSDB_CODE_NO_DISKSPACE;
fnError("udfd create shared library failed since %s", terrstr(terrno));
return terrno;
}
diff --git a/source/libs/parser/src/parInsertStmt.c b/source/libs/parser/src/parInsertStmt.c
index 01a635e4b2..922a0f45ff 100644
--- a/source/libs/parser/src/parInsertStmt.c
+++ b/source/libs/parser/src/parInsertStmt.c
@@ -251,7 +251,7 @@ int32_t qBindStmtColsValue(void* pBlock, TAOS_MULTI_BIND* bind, char* msgBuf, in
goto _return;
}
- if (bind[c].buffer_type != pColSchema->type) {
+ if ((!(rowNum == 1 && bind[c].is_null && *bind[c].is_null)) && bind[c].buffer_type != pColSchema->type) { // for rowNum ==1 , connector may not set buffer_type
code = buildInvalidOperationMsg(&pBuf, "column type mis-match with buffer type");
goto _return;
}
diff --git a/source/libs/planner/src/planOptimizer.c b/source/libs/planner/src/planOptimizer.c
index 07ea110d7e..4f8b57de5f 100644
--- a/source/libs/planner/src/planOptimizer.c
+++ b/source/libs/planner/src/planOptimizer.c
@@ -2418,6 +2418,36 @@ static bool tagScanOptShouldBeOptimized(SLogicNode* pNode) {
return true;
}
+static SLogicNode* tagScanOptFindAncestorWithSlimit(SLogicNode* pTableScanNode) {
+ SLogicNode* pNode = pTableScanNode->pParent;
+ while (NULL != pNode) {
+ if (QUERY_NODE_LOGIC_PLAN_PARTITION == nodeType(pNode) || QUERY_NODE_LOGIC_PLAN_AGG == nodeType(pNode) ||
+ QUERY_NODE_LOGIC_PLAN_WINDOW == nodeType(pNode) || QUERY_NODE_LOGIC_PLAN_SORT == nodeType(pNode)) {
+ return NULL;
+ }
+ if (NULL != pNode->pSlimit) {
+ return pNode;
+ }
+ pNode = pNode->pParent;
+ }
+ return NULL;
+}
+
+static void tagScanOptCloneAncestorSlimit(SLogicNode* pTableScanNode) {
+ if (NULL != pTableScanNode->pSlimit) {
+ return;
+ }
+
+ SLogicNode* pNode = tagScanOptFindAncestorWithSlimit(pTableScanNode);
+ if (NULL != pNode) {
+ //TODO: only set the slimit now. push down slimit later
+ pTableScanNode->pSlimit = nodesCloneNode(pNode->pSlimit);
+ ((SLimitNode*)pTableScanNode->pSlimit)->limit += ((SLimitNode*)pTableScanNode->pSlimit)->offset;
+ ((SLimitNode*)pTableScanNode->pSlimit)->offset = 0;
+ }
+ return;
+}
+
static int32_t tagScanOptimize(SOptimizeContext* pCxt, SLogicSubplan* pLogicSubplan) {
SScanLogicNode* pScanNode = (SScanLogicNode*)optFindPossibleNode(pLogicSubplan->pNode, tagScanOptShouldBeOptimized);
if (NULL == pScanNode) {
@@ -2458,6 +2488,7 @@ static int32_t tagScanOptimize(SOptimizeContext* pCxt, SLogicSubplan* pLogicSubp
NODES_CLEAR_LIST(pAgg->pChildren);
}
nodesDestroyNode((SNode*)pAgg);
+ tagScanOptCloneAncestorSlimit((SLogicNode*)pScanNode);
pCxt->optimized = true;
return TSDB_CODE_SUCCESS;
}
diff --git a/source/libs/stream/src/stream.c b/source/libs/stream/src/stream.c
index 7171b52912..0f000f1f50 100644
--- a/source/libs/stream/src/stream.c
+++ b/source/libs/stream/src/stream.c
@@ -16,7 +16,7 @@
#include "streamInc.h"
#include "ttimer.h"
-#define STREAM_TASK_INPUT_QUEUEU_CAPACITY 2000
+#define STREAM_TASK_INPUT_QUEUEU_CAPACITY 100000
int32_t streamInit() {
int8_t old;
@@ -352,4 +352,8 @@ void* streamQueueNextItem(SStreamQueue* queue) {
}
return streamQueueCurItem(queue);
}
+}
+
+void streamTaskInputFail(SStreamTask* pTask) {
+ atomic_store_8(&pTask->inputStatus, TASK_INPUT_STATUS__FAILED);
}
\ No newline at end of file
diff --git a/source/libs/stream/src/streamDispatch.c b/source/libs/stream/src/streamDispatch.c
index a9f6d29bf5..549374ed94 100644
--- a/source/libs/stream/src/streamDispatch.c
+++ b/source/libs/stream/src/streamDispatch.c
@@ -230,23 +230,21 @@ int32_t streamDispatchOneCheckReq(SStreamTask* pTask, const SStreamTaskCheckReq*
SEncoder encoder;
tEncoderInit(&encoder, abuf, tlen);
if ((code = tEncodeSStreamTaskCheckReq(&encoder, pReq)) < 0) {
- goto FAIL;
+ rpcFreeCont(buf);
+ return code;
}
+
tEncoderClear(&encoder);
msg.contLen = tlen + sizeof(SMsgHead);
msg.pCont = buf;
msg.msgType = TDMT_STREAM_TASK_CHECK;
- qDebug("dispatch from s-task:%s to downstream s-task:%"PRIx64":%d node %d: check msg", pTask->id.idStr,
- pReq->streamId, pReq->downstreamTaskId, nodeId);
+ qDebug("dispatch from s-task:%s to downstream s-task:%" PRIx64 ":%d node %d: check msg", pTask->id.idStr,
+ pReq->streamId, pReq->downstreamTaskId, nodeId);
tmsgSendReq(pEpSet, &msg);
-
return 0;
-FAIL:
- if (buf) rpcFreeCont(buf);
- return code;
}
int32_t streamDispatchOneRecoverFinishReq(SStreamTask* pTask, const SStreamRecoverFinishReq* pReq, int32_t vgId,
diff --git a/source/libs/stream/src/streamExec.c b/source/libs/stream/src/streamExec.c
index 3d896c08ac..9a6ff302ef 100644
--- a/source/libs/stream/src/streamExec.c
+++ b/source/libs/stream/src/streamExec.c
@@ -189,7 +189,10 @@ int32_t streamScanExec(SStreamTask* pTask, int32_t batchSz) {
qDebug("task %d scan exec dispatch block num %d", pTask->id.taskId, batchCnt);
streamDispatch(pTask);
}
- if (finished) break;
+
+ if (finished) {
+ break;
+ }
}
return 0;
}
diff --git a/source/libs/stream/src/streamMeta.c b/source/libs/stream/src/streamMeta.c
index 51cc315780..860514bb44 100644
--- a/source/libs/stream/src/streamMeta.c
+++ b/source/libs/stream/src/streamMeta.c
@@ -296,8 +296,7 @@ int32_t streamLoadTasks(SStreamMeta* pMeta, int64_t ver) {
tDecodeStreamTask(&decoder, pTask);
tDecoderClear(&decoder);
- // todo set correct initial version.
- if (pMeta->expandFunc(pMeta->ahandle, pTask, 0) < 0) {
+ if (pMeta->expandFunc(pMeta->ahandle, pTask, pTask->chkInfo.version) < 0) {
tdbFree(pKey);
tdbFree(pVal);
tdbTbcClose(pCur);
diff --git a/source/libs/stream/src/streamRecover.c b/source/libs/stream/src/streamRecover.c
index 03afc0692d..55c745e417 100644
--- a/source/libs/stream/src/streamRecover.c
+++ b/source/libs/stream/src/streamRecover.c
@@ -102,8 +102,10 @@ int32_t streamRecheckOneDownstream(SStreamTask* pTask, const SStreamTaskCheckRsp
.downstreamNodeId = pRsp->downstreamNodeId,
.childId = pRsp->childId,
};
- qDebug("task %d at node %d check downstream task %d at node %d (recheck)", pTask->id.taskId, pTask->nodeId,
+
+ qDebug("s-task:%s at node %d check downstream task %d at node %d (recheck)", pTask->id.idStr, pTask->nodeId,
req.downstreamTaskId, req.downstreamNodeId);
+
if (pTask->outputType == TASK_OUTPUT__FIXED_DISPATCH) {
streamDispatchOneCheckReq(pTask, &req, pRsp->downstreamNodeId, &pTask->fixedEpDispatcher.epSet);
} else if (pTask->outputType == TASK_OUTPUT__SHUFFLE_DISPATCH) {
@@ -116,6 +118,7 @@ int32_t streamRecheckOneDownstream(SStreamTask* pTask, const SStreamTaskCheckRsp
}
}
}
+
return 0;
}
@@ -158,9 +161,10 @@ int32_t streamProcessTaskCheckRsp(SStreamTask* pTask, const SStreamTaskCheckRsp*
} else {
ASSERT(0);
}
- } else {
+ } else { // not ready, it should wait for at least 100ms and then retry
streamRecheckOneDownstream(pTask, pRsp);
}
+
return 0;
}
diff --git a/source/libs/sync/src/syncCommit.c b/source/libs/sync/src/syncCommit.c
index 2501b4df8b..d3397f8e88 100644
--- a/source/libs/sync/src/syncCommit.c
+++ b/source/libs/sync/src/syncCommit.c
@@ -75,10 +75,12 @@ bool syncNodeAgreedUpon(SSyncNode* pNode, SyncIndex index) {
SSyncIndexMgr* pMatches = pNode->pMatchIndex;
ASSERT(pNode->replicaNum == pMatches->replicaNum);
- for (int i = 0; i < pNode->replicaNum; i++) {
- SyncIndex matchIndex = pMatches->index[i];
- if (matchIndex >= index) {
- count++;
+ for (int i = 0; i < pNode->totalReplicaNum; i++) {
+ if(pNode->raftCfg.cfg.nodeInfo[i].nodeRole == TAOS_SYNC_ROLE_VOTER){
+ SyncIndex matchIndex = pMatches->index[i];
+ if (matchIndex >= index) {
+ count++;
+ }
}
}
diff --git a/source/libs/sync/src/syncMain.c b/source/libs/sync/src/syncMain.c
index c4e7833245..499df4a98b 100644
--- a/source/libs/sync/src/syncMain.c
+++ b/source/libs/sync/src/syncMain.c
@@ -463,8 +463,7 @@ bool syncSnapshotRecving(int64_t rid) {
int32_t syncNodeLeaderTransfer(SSyncNode* pSyncNode) {
if (pSyncNode->peersNum == 0) {
sDebug("vgId:%d, only one replica, cannot leader transfer", pSyncNode->vgId);
- terrno = TSDB_CODE_SYN_ONE_REPLICA;
- return -1;
+ return 0;
}
int32_t ret = 0;
@@ -486,7 +485,6 @@ int32_t syncNodeLeaderTransfer(SSyncNode* pSyncNode) {
int32_t syncNodeLeaderTransferTo(SSyncNode* pSyncNode, SNodeInfo newLeader) {
if (pSyncNode->replicaNum == 1) {
sDebug("vgId:%d, only one replica, cannot leader transfer", pSyncNode->vgId);
- terrno = TSDB_CODE_SYN_ONE_REPLICA;
return -1;
}
@@ -580,25 +578,37 @@ int32_t syncIsCatchUp(int64_t rid) {
return -1;
}
- while(1){
- if(pSyncNode->pLogBuf->totalIndex < 0 || pSyncNode->pLogBuf->commitIndex < 0 ||
- pSyncNode->pLogBuf->totalIndex < pSyncNode->pLogBuf->commitIndex ||
- pSyncNode->pLogBuf->totalIndex - pSyncNode->pLogBuf->commitIndex > SYNC_LEARNER_CATCHUP){
- sInfo("vgId:%d, Not catch up, wait one second, totalIndex:%" PRId64 " commitIndex:%" PRId64 " matchIndex:%" PRId64,
- pSyncNode->vgId, pSyncNode->pLogBuf->totalIndex, pSyncNode->pLogBuf->commitIndex,
- pSyncNode->pLogBuf->matchIndex);
- taosSsleep(1);
- }
- else{
- sInfo("vgId:%d, Catch up, totalIndex:%" PRId64 " commitIndex:%" PRId64 " matchIndex:%" PRId64,
- pSyncNode->vgId, pSyncNode->pLogBuf->totalIndex, pSyncNode->pLogBuf->commitIndex,
- pSyncNode->pLogBuf->matchIndex);
- break;
- }
+ int32_t isCatchUp = 0;
+ if(pSyncNode->pLogBuf->totalIndex < 0 || pSyncNode->pLogBuf->commitIndex < 0 ||
+ pSyncNode->pLogBuf->totalIndex < pSyncNode->pLogBuf->commitIndex ||
+ pSyncNode->pLogBuf->totalIndex - pSyncNode->pLogBuf->commitIndex > SYNC_LEARNER_CATCHUP){
+ sInfo("vgId:%d, Not catch up, wait one second, totalIndex:%" PRId64 " commitIndex:%" PRId64 " matchIndex:%" PRId64,
+ pSyncNode->vgId, pSyncNode->pLogBuf->totalIndex, pSyncNode->pLogBuf->commitIndex,
+ pSyncNode->pLogBuf->matchIndex);
+ isCatchUp = 0;
+ }
+ else{
+ sInfo("vgId:%d, Catch up, totalIndex:%" PRId64 " commitIndex:%" PRId64 " matchIndex:%" PRId64,
+ pSyncNode->vgId, pSyncNode->pLogBuf->totalIndex, pSyncNode->pLogBuf->commitIndex,
+ pSyncNode->pLogBuf->matchIndex);
+ isCatchUp = 1;
}
syncNodeRelease(pSyncNode);
- return 0;
+ return isCatchUp;
+}
+
+ESyncRole syncGetRole(int64_t rid) {
+ SSyncNode* pSyncNode = syncNodeAcquire(rid);
+ if (pSyncNode == NULL) {
+ sError("sync Node Acquire error since %d", errno);
+ return -1;
+ }
+
+ ESyncRole role = pSyncNode->raftCfg.cfg.nodeInfo[pSyncNode->raftCfg.cfg.myIndex].nodeRole;
+
+ syncNodeRelease(pSyncNode);
+ return role;
}
int32_t syncNodePropose(SSyncNode* pSyncNode, SRpcMsg* pMsg, bool isWeak, int64_t* seq) {
@@ -2144,7 +2154,7 @@ static void syncNodeEqPeerHeartbeatTimer(void* param, void* tmrId) {
SSyncHbTimerData* pData = syncHbTimerDataAcquire(hbDataRid);
if (pData == NULL) {
- sError("hb timer get pData NULL, rid:%" PRId64 " addr:%" PRId64, hbDataRid, pData->destId.addr);
+ sError("hb timer get pData NULL, %" PRId64, hbDataRid);
return;
}
@@ -2414,18 +2424,19 @@ int32_t syncNodeOnHeartbeat(SSyncNode* ths, const SRpcMsg* pRpcMsg) {
(void)syncBuildLocalCmd(&rpcMsgLocalCmd, ths->vgId);
SyncLocalCmd* pSyncMsg = rpcMsgLocalCmd.pCont;
- pSyncMsg->cmd = SYNC_LOCAL_CMD_FOLLOWER_CMT;
+ pSyncMsg->cmd =
+ (ths->state == TAOS_SYNC_STATE_LEARNER) ? SYNC_LOCAL_CMD_LEARNER_CMT : SYNC_LOCAL_CMD_FOLLOWER_CMT;
pSyncMsg->commitIndex = pMsg->commitIndex;
pSyncMsg->currentTerm = pMsg->term;
- SyncIndex fcIndex = pSyncMsg->commitIndex;
if (ths->syncEqMsg != NULL && ths->msgcb != NULL) {
int32_t code = ths->syncEqMsg(ths->msgcb, &rpcMsgLocalCmd);
if (code != 0) {
- sError("vgId:%d, sync enqueue fc-commit msg error, code:%d", ths->vgId, code);
+ sError("vgId:%d, failed to enqueue commit msg from heartbeat since %s, code:%d", ths->vgId, terrstr(), code);
rpcFreeCont(rpcMsgLocalCmd.pCont);
} else {
- sTrace("vgId:%d, sync enqueue fc-commit msg, fc-index:%" PRId64, ths->vgId, fcIndex);
+ sTrace("vgId:%d, enqueue commit msg from heartbeat, commit-index:%" PRId64 ", term:%" PRId64, ths->vgId,
+ pMsg->commitIndex, pMsg->term);
}
}
}
@@ -2446,27 +2457,7 @@ int32_t syncNodeOnHeartbeat(SSyncNode* ths, const SRpcMsg* pRpcMsg) {
sError("vgId:%d, sync enqueue step-down msg error, code:%d", ths->vgId, code);
rpcFreeCont(rpcMsgLocalCmd.pCont);
} else {
- sTrace("vgId:%d, sync enqueue step-down msg, new-term:%" PRId64, ths->vgId, pSyncMsg->currentTerm);
- }
- }
- }
-
- if (pMsg->term >= currentTerm && ths->state == TAOS_SYNC_STATE_LEARNER) {
- SRpcMsg rpcMsgLocalCmd = {0};
- (void)syncBuildLocalCmd(&rpcMsgLocalCmd, ths->vgId);
-
- SyncLocalCmd* pSyncMsg = rpcMsgLocalCmd.pCont;
- pSyncMsg->cmd = SYNC_LOCAL_CMD_LEARNER_CMT;
- pSyncMsg->currentTerm = pMsg->term;
- pSyncMsg->commitIndex = pMsg->commitIndex;
-
- if (ths->syncEqMsg != NULL && ths->msgcb != NULL) {
- int32_t code = ths->syncEqMsg(ths->msgcb, &rpcMsgLocalCmd);
- if (code != 0) {
- sError("vgId:%d, sync enqueue step-down msg error, code:%d", ths->vgId, code);
- rpcFreeCont(rpcMsgLocalCmd.pCont);
- } else {
- sTrace("vgId:%d, sync enqueue step-down msg, new-term:%" PRId64, ths->vgId, pSyncMsg->currentTerm);
+ sTrace("vgId:%d, sync enqueue step-down msg, new-term:%" PRId64, ths->vgId, pMsg->term);
}
}
}
@@ -2521,7 +2512,7 @@ int32_t syncNodeOnLocalCmd(SSyncNode* ths, const SRpcMsg* pRpcMsg) {
if (pMsg->cmd == SYNC_LOCAL_CMD_STEP_DOWN) {
syncNodeStepDown(ths, pMsg->currentTerm);
- } else if (pMsg->cmd == SYNC_LOCAL_CMD_FOLLOWER_CMT) {
+ } else if (pMsg->cmd == SYNC_LOCAL_CMD_FOLLOWER_CMT || pMsg->cmd == SYNC_LOCAL_CMD_LEARNER_CMT) {
if (syncLogBufferIsEmpty(ths->pLogBuf)) {
sError("vgId:%d, sync log buffer is empty.", ths->vgId);
return 0;
@@ -2534,20 +2525,7 @@ int32_t syncNodeOnLocalCmd(SSyncNode* ths, const SRpcMsg* pRpcMsg) {
sError("vgId:%d, failed to commit raft log since %s. commit index:%" PRId64 "", ths->vgId, terrstr(),
ths->commitIndex);
}
- } else if (pMsg->cmd == SYNC_LOCAL_CMD_LEARNER_CMT){
- if (syncLogBufferIsEmpty(ths->pLogBuf)) {
- sError("vgId:%d, sync log buffer is empty.", ths->vgId);
- return 0;
- }
- raftStoreSetTerm(ths, pMsg->currentTerm);
- (void)syncNodeUpdateCommitIndex(ths, pMsg->commitIndex);
- sTrace("vgId:%d, start to commit raft log in heartbeat. commit index:%" PRId64 "", ths->vgId, ths->commitIndex);
- if (syncLogBufferCommit(ths->pLogBuf, ths, ths->commitIndex) < 0) {
- sError("vgId:%d, failed to commit raft log since %s. commit index:%" PRId64 "", ths->vgId, terrstr(),
- ths->commitIndex);
- }
- }
- else {
+ } else {
sError("error local cmd");
}
diff --git a/source/libs/sync/src/syncPipeline.c b/source/libs/sync/src/syncPipeline.c
index 85c18220a6..8bb72de518 100644
--- a/source/libs/sync/src/syncPipeline.c
+++ b/source/libs/sync/src/syncPipeline.c
@@ -54,7 +54,7 @@ int32_t syncLogBufferAppend(SSyncLogBuffer* pBuf, SSyncNode* pNode, SSyncRaftEnt
}
if (pNode->restoreFinish && index - pBuf->commitIndex >= TSDB_SYNC_NEGOTIATION_WIN) {
- terrno = TSDB_CODE_SYN_NEGO_WIN_EXCEEDED;
+ terrno = TSDB_CODE_SYN_NEGOTIATION_WIN_FULL;
sError("vgId:%d, failed to append since %s, index:%" PRId64 ", commit-index:%" PRId64, pNode->vgId, terrstr(),
index, pBuf->commitIndex);
goto _err;
diff --git a/source/libs/sync/src/syncRaftCfg.c b/source/libs/sync/src/syncRaftCfg.c
index 576b9d62f5..480ed4b2af 100644
--- a/source/libs/sync/src/syncRaftCfg.c
+++ b/source/libs/sync/src/syncRaftCfg.c
@@ -21,19 +21,19 @@
const char* syncRoleToStr(ESyncRole role) {
switch (role) {
case TAOS_SYNC_ROLE_VOTER:
- return "voter";
+ return "true";
case TAOS_SYNC_ROLE_LEARNER:
- return "learner";
+ return "false";
default:
return "unknown";
}
}
const ESyncRole syncStrToRole(char* str) {
- if(strcmp(str, "voter") == 0){
+ if(strcmp(str, "true") == 0){
return TAOS_SYNC_ROLE_VOTER;
}
- if(strcmp(str, "learner") == 0){
+ if(strcmp(str, "false") == 0){
return TAOS_SYNC_ROLE_LEARNER;
}
@@ -42,7 +42,6 @@ const ESyncRole syncStrToRole(char* str) {
static int32_t syncEncodeSyncCfg(const void *pObj, SJson *pJson) {
SSyncCfg *pCfg = (SSyncCfg *)pObj;
- if (tjsonAddDoubleToObject(pJson, "totalReplicaNum", pCfg->totalReplicaNum) < 0) return -1;
if (tjsonAddDoubleToObject(pJson, "replicaNum", pCfg->replicaNum) < 0) return -1;
if (tjsonAddDoubleToObject(pJson, "myIndex", pCfg->myIndex) < 0) return -1;
@@ -56,7 +55,7 @@ static int32_t syncEncodeSyncCfg(const void *pObj, SJson *pJson) {
if (tjsonAddStringToObject(info, "nodeFqdn", pCfg->nodeInfo[i].nodeFqdn) < 0) return -1;
if (tjsonAddIntegerToObject(info, "nodeId", pCfg->nodeInfo[i].nodeId) < 0) return -1;
if (tjsonAddIntegerToObject(info, "clusterId", pCfg->nodeInfo[i].clusterId) < 0) return -1;
- if (tjsonAddStringToObject(info, "nodeRole", syncRoleToStr(pCfg->nodeInfo[i].nodeRole)) < 0) return -1;
+ if (tjsonAddStringToObject(info, "isReplica", syncRoleToStr(pCfg->nodeInfo[i].nodeRole)) < 0) return -1;
if (tjsonAddItemToArray(nodeInfo, info) < 0) return -1;
}
@@ -133,7 +132,6 @@ static int32_t syncDecodeSyncCfg(const SJson *pJson, void *pObj) {
SSyncCfg *pCfg = (SSyncCfg *)pObj;
int32_t code = 0;
- tjsonGetInt32ValueFromDouble(pJson, "totalReplicaNum", pCfg->totalReplicaNum, code);
tjsonGetInt32ValueFromDouble(pJson, "replicaNum", pCfg->replicaNum, code);
if (code < 0) return -1;
tjsonGetInt32ValueFromDouble(pJson, "myIndex", pCfg->myIndex, code);
@@ -153,7 +151,7 @@ static int32_t syncDecodeSyncCfg(const SJson *pJson, void *pObj) {
tjsonGetNumberValue(info, "nodeId", pCfg->nodeInfo[i].nodeId, code);
tjsonGetNumberValue(info, "clusterId", pCfg->nodeInfo[i].clusterId, code);
char role[10] = {0};
- code = tjsonGetStringValue(info, "nodeRole", role);
+ code = tjsonGetStringValue(info, "isReplica", role);
if(code < 0) return -1;
if(strlen(role) != 0){
pCfg->nodeInfo[i].nodeRole = syncStrToRole(role);
diff --git a/source/libs/wal/src/walRead.c b/source/libs/wal/src/walRead.c
index dc3ff3e6de..19694a6126 100644
--- a/source/libs/wal/src/walRead.c
+++ b/source/libs/wal/src/walRead.c
@@ -102,6 +102,13 @@ int32_t walNextValidMsg(SWalReader *pReader) {
int64_t walReaderGetCurrentVer(const SWalReader *pReader) { return pReader->curVersion; }
+void walReaderValidVersionRange(SWalReader *pReader, int64_t *sver, int64_t *ever) {
+ *sver = walGetFirstVer(pReader->pWal);
+ int64_t lastVer = walGetLastVer(pReader->pWal);
+ int64_t committedVer = walGetCommittedVer(pReader->pWal);
+ *ever = pReader->cond.scanUncommited ? lastVer : committedVer;
+}
+
static int64_t walReadSeekFilePos(SWalReader *pReader, int64_t fileFirstVer, int64_t ver) {
int64_t ret = 0;
diff --git a/source/util/src/terror.c b/source/util/src/terror.c
index 34b09761c8..6fc16ad4a9 100644
--- a/source/util/src/terror.c
+++ b/source/util/src/terror.c
@@ -98,7 +98,8 @@ TAOS_DEFINE_ERROR(TSDB_CODE_NO_ENOUGH_DISKSPACE, "No enough disk space"
TAOS_DEFINE_ERROR(TSDB_CODE_APP_IS_STARTING, "Database is starting up")
TAOS_DEFINE_ERROR(TSDB_CODE_APP_IS_STOPPING, "Database is closing down")
-TAOS_DEFINE_ERROR(TSDB_CODE_IVLD_DATA_FMT, "Invalid data format")
+TAOS_DEFINE_ERROR(TSDB_CODE_INVALID_DATA_FMT, "Invalid data format")
+TAOS_DEFINE_ERROR(TSDB_CODE_INVALID_CFG_VALUE, "Invalid configuration value")
//client
TAOS_DEFINE_ERROR(TSDB_CODE_TSC_INVALID_OPERATION, "Invalid operation")
@@ -413,20 +414,14 @@ TAOS_DEFINE_ERROR(TSDB_CODE_GRANT_TABLE_LIMITED, "Table creation limite
// sync
TAOS_DEFINE_ERROR(TSDB_CODE_SYN_TIMEOUT, "Sync timeout")
-TAOS_DEFINE_ERROR(TSDB_CODE_SYN_IS_LEADER, "Sync is leader")
TAOS_DEFINE_ERROR(TSDB_CODE_SYN_NOT_LEADER, "Sync leader is unreachable")
-TAOS_DEFINE_ERROR(TSDB_CODE_SYN_ONE_REPLICA, "Sync one replica")
-TAOS_DEFINE_ERROR(TSDB_CODE_SYN_NOT_IN_NEW_CONFIG, "Sync not in new config")
TAOS_DEFINE_ERROR(TSDB_CODE_SYN_NEW_CONFIG_ERROR, "Sync new config error")
-TAOS_DEFINE_ERROR(TSDB_CODE_SYN_RECONFIG_NOT_READY, "Sync not ready for reconfig")
-TAOS_DEFINE_ERROR(TSDB_CODE_SYN_PROPOSE_NOT_READY, "Sync not ready for propose")
-TAOS_DEFINE_ERROR(TSDB_CODE_SYN_STANDBY_NOT_READY, "Sync not ready for standby")
-TAOS_DEFINE_ERROR(TSDB_CODE_SYN_BATCH_ERROR, "Sync batch error")
+TAOS_DEFINE_ERROR(TSDB_CODE_SYN_PROPOSE_NOT_READY, "Sync not ready to propose")
TAOS_DEFINE_ERROR(TSDB_CODE_SYN_RESTORING, "Sync leader is restoring")
TAOS_DEFINE_ERROR(TSDB_CODE_SYN_INVALID_SNAPSHOT_MSG, "Sync invalid snapshot msg")
TAOS_DEFINE_ERROR(TSDB_CODE_SYN_BUFFER_FULL, "Sync buffer is full")
TAOS_DEFINE_ERROR(TSDB_CODE_SYN_WRITE_STALL, "Sync write stall")
-TAOS_DEFINE_ERROR(TSDB_CODE_SYN_NEGO_WIN_EXCEEDED, "Sync negotiation win exceeded")
+TAOS_DEFINE_ERROR(TSDB_CODE_SYN_NEGOTIATION_WIN_FULL, "Sync negotiation win is full")
TAOS_DEFINE_ERROR(TSDB_CODE_SYN_INTERNAL_ERROR, "Sync internal error")
//tq
@@ -444,8 +439,7 @@ TAOS_DEFINE_ERROR(TSDB_CODE_TQ_NO_COMMITTED_OFFSET, "TQ no committed offse
// wal
TAOS_DEFINE_ERROR(TSDB_CODE_WAL_FILE_CORRUPTED, "WAL file is corrupted")
-TAOS_DEFINE_ERROR(TSDB_CODE_WAL_SIZE_LIMIT, "WAL size exceeds limit")
-TAOS_DEFINE_ERROR(TSDB_CODE_WAL_INVALID_VER, "WAL use invalid version")
+TAOS_DEFINE_ERROR(TSDB_CODE_WAL_INVALID_VER, "WAL invalid version")
TAOS_DEFINE_ERROR(TSDB_CODE_WAL_LOG_NOT_EXIST, "WAL log not exist")
TAOS_DEFINE_ERROR(TSDB_CODE_WAL_CHKSUM_MISMATCH, "WAL checksum mismatch")
TAOS_DEFINE_ERROR(TSDB_CODE_WAL_LOG_INCOMPLETE, "WAL log incomplete")
@@ -581,11 +575,9 @@ TAOS_DEFINE_ERROR(TSDB_CODE_FUNC_DUP_TIMESTAMP, "Duplicate timestamps
TAOS_DEFINE_ERROR(TSDB_CODE_UDF_STOPPING, "udf is stopping")
TAOS_DEFINE_ERROR(TSDB_CODE_UDF_PIPE_READ_ERR, "udf pipe read error")
TAOS_DEFINE_ERROR(TSDB_CODE_UDF_PIPE_CONNECT_ERR, "udf pipe connect error")
-TAOS_DEFINE_ERROR(TSDB_CODE_UDF_PIPE_NO_PIPE, "udf no pipe")
+TAOS_DEFINE_ERROR(TSDB_CODE_UDF_PIPE_NOT_EXIST, "udf pipe not exist")
TAOS_DEFINE_ERROR(TSDB_CODE_UDF_LOAD_UDF_FAILURE, "udf load failure")
-TAOS_DEFINE_ERROR(TSDB_CODE_UDF_INVALID_STATE, "udf invalid state")
TAOS_DEFINE_ERROR(TSDB_CODE_UDF_INVALID_INPUT, "udf invalid function input")
-TAOS_DEFINE_ERROR(TSDB_CODE_UDF_NO_FUNC_HANDLE, "udf no function handle")
TAOS_DEFINE_ERROR(TSDB_CODE_UDF_INVALID_BUFSIZE, "udf invalid bufsize")
TAOS_DEFINE_ERROR(TSDB_CODE_UDF_INVALID_OUTPUT_TYPE, "udf invalid output type")
TAOS_DEFINE_ERROR(TSDB_CODE_UDF_SCRIPT_NOT_SUPPORTED, "udf program language not supported")
diff --git a/source/util/src/tlog.c b/source/util/src/tlog.c
index a3d3c399ab..baf6a9f319 100644
--- a/source/util/src/tlog.c
+++ b/source/util/src/tlog.c
@@ -24,10 +24,11 @@
#define LOG_MAX_LINE_SIZE (10024)
#define LOG_MAX_LINE_BUFFER_SIZE (LOG_MAX_LINE_SIZE + 3)
#define LOG_MAX_LINE_DUMP_SIZE (1024 * 1024)
-#define LOG_MAX_LINE_DUMP_BUFFER_SIZE (LOG_MAX_LINE_DUMP_SIZE + 3)
+#define LOG_MAX_LINE_DUMP_BUFFER_SIZE (LOG_MAX_LINE_DUMP_SIZE + 128)
#define LOG_FILE_NAME_LEN 300
#define LOG_DEFAULT_BUF_SIZE (20 * 1024 * 1024) // 20MB
+#define LOG_SLOW_BUF_SIZE (10 * 1024 * 1024) // 10MB
#define LOG_DEFAULT_INTERVAL 25
#define LOG_INTERVAL_STEP 5
@@ -51,6 +52,8 @@ typedef struct {
int32_t stop;
TdThread asyncThread;
TdThreadMutex buffMutex;
+ int32_t writeInterval;
+ int32_t lastDuration;
} SLogBuff;
typedef struct {
@@ -62,6 +65,7 @@ typedef struct {
pid_t pid;
char logName[LOG_FILE_NAME_LEN];
SLogBuff *logHandle;
+ SLogBuff *slowHandle;
TdThreadMutex logMutex;
} SLogObj;
@@ -69,7 +73,6 @@ extern SConfig *tsCfg;
static int8_t tsLogInited = 0;
static SLogObj tsLogObj = {.fileNum = 1};
static int64_t tsAsyncLogLostLines = 0;
-static int32_t tsWriteInterval = LOG_DEFAULT_INTERVAL;
static int32_t tsDaylightActive; /* Currently in daylight saving time. */
bool tsLogEmbedded = 0;
@@ -82,6 +85,7 @@ int64_t tsNumOfErrorLogs = 0;
int64_t tsNumOfInfoLogs = 0;
int64_t tsNumOfDebugLogs = 0;
int64_t tsNumOfTraceLogs = 0;
+int64_t tsNumOfSlowLogs = 0;
// log
int32_t dDebugFlag = 131;
@@ -136,6 +140,34 @@ static int32_t taosStartLog() {
return 0;
}
+int32_t taosInitSlowLog() {
+ char fullName[PATH_MAX] = {0};
+ char logFileName[64] = {0};
+#ifdef CUS_PROMPT
+ snprintf(logFileName, 64, "%sSlowLog", CUS_PROMPT);
+#else
+ snprintf(logFileName, 64, "taosSlowLog");
+#endif
+
+ if (strlen(tsLogDir) != 0) {
+ snprintf(fullName, PATH_MAX, "%s" TD_DIRSEP "%s", tsLogDir, logFileName);
+ } else {
+ snprintf(fullName, PATH_MAX, "%s", logFileName);
+ }
+
+ tsLogObj.slowHandle = taosLogBuffNew(LOG_SLOW_BUF_SIZE);
+ if (tsLogObj.slowHandle == NULL) return -1;
+
+ taosUmaskFile(0);
+ tsLogObj.slowHandle->pFile = taosOpenFile(fullName, TD_FILE_CREATE | TD_FILE_WRITE | TD_FILE_APPEND);
+ if (tsLogObj.slowHandle->pFile == NULL) {
+ printf("\nfailed to open slow log file:%s, reason:%s\n", fullName, strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
int32_t taosInitLog(const char *logName, int32_t maxFiles) {
if (atomic_val_compare_exchange_8(&tsLogInited, 0, 1) != 0) return 0;
osUpdate();
@@ -151,6 +183,8 @@ int32_t taosInitLog(const char *logName, int32_t maxFiles) {
tsLogObj.logHandle = taosLogBuffNew(LOG_DEFAULT_BUF_SIZE);
if (tsLogObj.logHandle == NULL) return -1;
if (taosOpenLogFile(fullName, tsNumOfLogLines, maxFiles) < 0) return -1;
+
+ if (taosInitSlowLog() < 0) return -1;
if (taosStartLog() < 0) return -1;
return 0;
}
@@ -159,25 +193,34 @@ static void taosStopLog() {
if (tsLogObj.logHandle) {
tsLogObj.logHandle->stop = 1;
}
+ if (tsLogObj.slowHandle) {
+ tsLogObj.slowHandle->stop = 1;
+ }
}
void taosCloseLog() {
+ taosStopLog();
+
+ if (tsLogObj.logHandle != NULL && taosCheckPthreadValid(tsLogObj.logHandle->asyncThread)) {
+ taosThreadJoin(tsLogObj.logHandle->asyncThread, NULL);
+ taosThreadClear(&tsLogObj.logHandle->asyncThread);
+ }
+
+ if (tsLogObj.slowHandle != NULL) {
+ taosThreadMutexDestroy(&tsLogObj.slowHandle->buffMutex);
+ taosCloseFile(&tsLogObj.slowHandle->pFile);
+ taosMemoryFreeClear(tsLogObj.slowHandle->buffer);
+ taosMemoryFreeClear(tsLogObj.slowHandle);
+ }
+
if (tsLogObj.logHandle != NULL) {
- taosStopLog();
- if (tsLogObj.logHandle != NULL && taosCheckPthreadValid(tsLogObj.logHandle->asyncThread)) {
- taosThreadJoin(tsLogObj.logHandle->asyncThread, NULL);
- taosThreadClear(&tsLogObj.logHandle->asyncThread);
- }
tsLogInited = 0;
taosThreadMutexDestroy(&tsLogObj.logHandle->buffMutex);
taosCloseFile(&tsLogObj.logHandle->pFile);
taosMemoryFreeClear(tsLogObj.logHandle->buffer);
- memset(&tsLogObj.logHandle->buffer, 0, sizeof(tsLogObj.logHandle->buffer));
taosThreadMutexDestroy(&tsLogObj.logMutex);
taosMemoryFreeClear(tsLogObj.logHandle);
- memset(&tsLogObj.logHandle, 0, sizeof(tsLogObj.logHandle));
- tsLogObj.logHandle = NULL;
}
}
@@ -513,10 +556,9 @@ void taosPrintLongString(const char *flags, ELogLevel level, int32_t dflag, cons
va_list argpointer;
va_start(argpointer, format);
- len += vsnprintf(buffer + len, LOG_MAX_LINE_DUMP_BUFFER_SIZE - len, format, argpointer);
+ len += vsnprintf(buffer + len, LOG_MAX_LINE_DUMP_BUFFER_SIZE - 2 - len, format, argpointer);
va_end(argpointer);
- if (len > LOG_MAX_LINE_DUMP_SIZE) len = LOG_MAX_LINE_DUMP_SIZE;
buffer[len++] = '\n';
buffer[len] = 0;
@@ -524,6 +566,31 @@ void taosPrintLongString(const char *flags, ELogLevel level, int32_t dflag, cons
taosMemoryFree(buffer);
}
+void taosPrintSlowLog(const char *format, ...) {
+ if (!osLogSpaceAvailable()) return;
+
+ char *buffer = taosMemoryMalloc(LOG_MAX_LINE_DUMP_BUFFER_SIZE);
+ int32_t len = taosBuildLogHead(buffer, "");
+
+ va_list argpointer;
+ va_start(argpointer, format);
+ len += vsnprintf(buffer + len, LOG_MAX_LINE_DUMP_BUFFER_SIZE - 2 - len, format, argpointer);
+ va_end(argpointer);
+
+ buffer[len++] = '\n';
+ buffer[len] = 0;
+
+ atomic_add_fetch_64(&tsNumOfSlowLogs, 1);
+
+ if (tsAsyncLog) {
+ taosPushLogBuffer(tsLogObj.slowHandle, buffer, len);
+ } else {
+ taosWriteFile(tsLogObj.slowHandle->pFile, buffer, len);
+ }
+
+ taosMemoryFree(buffer);
+}
+
void taosDumpData(unsigned char *msg, int32_t len) {
if (!osLogSpaceAvailable()) return;
taosUpdateLogNums(DEBUG_DUMP);
@@ -568,6 +635,7 @@ static SLogBuff *taosLogBuffNew(int32_t bufSize) {
LOG_BUF_SIZE(pLogBuf) = bufSize;
pLogBuf->minBuffSize = bufSize / 10;
pLogBuf->stop = 0;
+ pLogBuf->writeInterval = LOG_DEFAULT_INTERVAL;
if (taosThreadMutexInit(&LOG_BUF_MUTEX(pLogBuf), NULL) < 0) goto _err;
// tsem_init(&(pLogBuf->buffNotEmpty), 0, 0);
@@ -651,83 +719,78 @@ static int32_t taosGetLogRemainSize(SLogBuff *pLogBuf, int32_t start, int32_t en
}
static void taosWriteLog(SLogBuff *pLogBuf) {
- static int32_t lastDuration = 0;
- int32_t remainChecked = 0;
- int32_t start, end, pollSize;
+ int32_t start = LOG_BUF_START(pLogBuf);
+ int32_t end = LOG_BUF_END(pLogBuf);
- do {
- if (remainChecked == 0) {
- start = LOG_BUF_START(pLogBuf);
- end = LOG_BUF_END(pLogBuf);
+ if (start == end) {
+ dbgEmptyW++;
+ pLogBuf->writeInterval = LOG_MAX_INTERVAL;
+ return;
+ }
- if (start == end) {
- dbgEmptyW++;
- tsWriteInterval = LOG_MAX_INTERVAL;
- return;
- }
-
- pollSize = taosGetLogRemainSize(pLogBuf, start, end);
- if (pollSize < pLogBuf->minBuffSize) {
- lastDuration += tsWriteInterval;
- if (lastDuration < LOG_MAX_WAIT_MSEC) {
- break;
- }
- }
-
- lastDuration = 0;
+ int32_t pollSize = taosGetLogRemainSize(pLogBuf, start, end);
+ if (pollSize < pLogBuf->minBuffSize) {
+ pLogBuf->lastDuration += pLogBuf->writeInterval;
+ if (pLogBuf->lastDuration < LOG_MAX_WAIT_MSEC) {
+ return;
}
+ }
- if (start < end) {
- taosWriteFile(pLogBuf->pFile, LOG_BUF_BUFFER(pLogBuf) + start, pollSize);
- } else {
- int32_t tsize = LOG_BUF_SIZE(pLogBuf) - start;
- taosWriteFile(pLogBuf->pFile, LOG_BUF_BUFFER(pLogBuf) + start, tsize);
+ pLogBuf->lastDuration = 0;
- taosWriteFile(pLogBuf->pFile, LOG_BUF_BUFFER(pLogBuf), end);
+ if (start < end) {
+ taosWriteFile(pLogBuf->pFile, LOG_BUF_BUFFER(pLogBuf) + start, pollSize);
+ } else {
+ int32_t tsize = LOG_BUF_SIZE(pLogBuf) - start;
+ taosWriteFile(pLogBuf->pFile, LOG_BUF_BUFFER(pLogBuf) + start, tsize);
+
+ taosWriteFile(pLogBuf->pFile, LOG_BUF_BUFFER(pLogBuf), end);
+ }
+
+ dbgWN++;
+ dbgWSize += pollSize;
+
+ if (pollSize < pLogBuf->minBuffSize) {
+ dbgSmallWN++;
+ if (pLogBuf->writeInterval < LOG_MAX_INTERVAL) {
+ pLogBuf->writeInterval += LOG_INTERVAL_STEP;
}
-
- dbgWN++;
- dbgWSize += pollSize;
-
- if (pollSize < pLogBuf->minBuffSize) {
- dbgSmallWN++;
- if (tsWriteInterval < LOG_MAX_INTERVAL) {
- tsWriteInterval += LOG_INTERVAL_STEP;
- }
- } else if (pollSize > LOG_BUF_SIZE(pLogBuf) / 3) {
- dbgBigWN++;
- tsWriteInterval = LOG_MIN_INTERVAL;
- } else if (pollSize > LOG_BUF_SIZE(pLogBuf) / 4) {
- if (tsWriteInterval > LOG_MIN_INTERVAL) {
- tsWriteInterval -= LOG_INTERVAL_STEP;
- }
+ } else if (pollSize > LOG_BUF_SIZE(pLogBuf) / 3) {
+ dbgBigWN++;
+ pLogBuf->writeInterval = LOG_MIN_INTERVAL;
+ } else if (pollSize > LOG_BUF_SIZE(pLogBuf) / 4) {
+ if (pLogBuf->writeInterval > LOG_MIN_INTERVAL) {
+ pLogBuf->writeInterval -= LOG_INTERVAL_STEP;
}
+ }
- LOG_BUF_START(pLogBuf) = (LOG_BUF_START(pLogBuf) + pollSize) % LOG_BUF_SIZE(pLogBuf);
+ LOG_BUF_START(pLogBuf) = (LOG_BUF_START(pLogBuf) + pollSize) % LOG_BUF_SIZE(pLogBuf);
- start = LOG_BUF_START(pLogBuf);
- end = LOG_BUF_END(pLogBuf);
+ start = LOG_BUF_START(pLogBuf);
+ end = LOG_BUF_END(pLogBuf);
- pollSize = taosGetLogRemainSize(pLogBuf, start, end);
- if (pollSize < pLogBuf->minBuffSize) {
- break;
- }
+ pollSize = taosGetLogRemainSize(pLogBuf, start, end);
+ if (pollSize < pLogBuf->minBuffSize) {
+ return;
+ }
- tsWriteInterval = LOG_MIN_INTERVAL;
-
- remainChecked = 1;
- } while (1);
+ pLogBuf->writeInterval = 0;
}
static void *taosAsyncOutputLog(void *param) {
- SLogBuff *pLogBuf = (SLogBuff *)param;
+ SLogBuff *pLogBuf = (SLogBuff *)tsLogObj.logHandle;
+ SLogBuff *pSlowBuf = (SLogBuff *)tsLogObj.slowHandle;
+
setThreadName("log");
int32_t count = 0;
int32_t updateCron = 0;
+ int32_t writeInterval = 0;
+
while (1) {
- count += tsWriteInterval;
+ writeInterval = TMIN(pLogBuf->writeInterval, pSlowBuf->writeInterval);
+ count += writeInterval;
updateCron++;
- taosMsleep(tsWriteInterval);
+ taosMsleep(writeInterval);
if (count > 1000) {
osUpdate();
count = 0;
@@ -735,13 +798,14 @@ static void *taosAsyncOutputLog(void *param) {
// Polling the buffer
taosWriteLog(pLogBuf);
+ taosWriteLog(pSlowBuf);
if (updateCron >= 3600 * 24 * 40 / 2) {
taosUpdateDaylight();
updateCron = 0;
}
- if (pLogBuf->stop) break;
+ if (pLogBuf->stop || pSlowBuf->stop) break;
}
return NULL;
diff --git a/source/util/src/tworker.c b/source/util/src/tworker.c
index a49ff0cd5b..6edee27c05 100644
--- a/source/util/src/tworker.c
+++ b/source/util/src/tworker.c
@@ -217,8 +217,8 @@ STaosQueue *tAutoQWorkerAllocQueue(SAutoQWorkerPool *pool, void *ahandle, FItem
int32_t queueNum = taosGetQueueNumber(pool->qset);
int32_t curWorkerNum = taosArrayGetSize(pool->workers);
- int32_t dstWorkerNum = ceil(queueNum * pool->ratio);
- if (dstWorkerNum < 2) dstWorkerNum = 2;
+ int32_t dstWorkerNum = ceilf(queueNum * pool->ratio);
+ if (dstWorkerNum < 1) dstWorkerNum = 1;
// spawn a thread to process queue
while (curWorkerNum < dstWorkerNum) {
diff --git a/tests/parallel_test/cases.task b/tests/parallel_test/cases.task
index dda4ec3e84..9f9679ae35 100644
--- a/tests/parallel_test/cases.task
+++ b/tests/parallel_test/cases.task
@@ -887,6 +887,7 @@
,,y,script,./test.sh -f tsim/query/emptyTsRange.sim
,,y,script,./test.sh -f tsim/query/partitionby.sim
,,y,script,./test.sh -f tsim/query/tableCount.sim
+,,y,script,./test.sh -f tsim/query/tag_scan.sim
,,y,script,./test.sh -f tsim/query/nullColSma.sim
,,y,script,./test.sh -f tsim/qnode/basic1.sim
,,y,script,./test.sh -f tsim/snode/basic1.sim
diff --git a/tests/pytest/util/sql.py b/tests/pytest/util/sql.py
index 783ee476cb..c041282bfc 100644
--- a/tests/pytest/util/sql.py
+++ b/tests/pytest/util/sql.py
@@ -431,7 +431,7 @@ class TDSql:
time.sleep(1)
continue
- def execute(self, sql,queryTimes=10):
+ def execute(self, sql,queryTimes=30):
self.sql = sql
i=1
while i <= queryTimes:
diff --git a/tests/script/api/makefile b/tests/script/api/makefile
index 6739794cc8..6d55d8a75f 100644
--- a/tests/script/api/makefile
+++ b/tests/script/api/makefile
@@ -15,8 +15,11 @@ exe:
gcc $(CFLAGS) ./stopquery.c -o $(ROOT)stopquery $(LFLAGS)
gcc $(CFLAGS) ./dbTableRoute.c -o $(ROOT)dbTableRoute $(LFLAGS)
gcc $(CFLAGS) ./insertSameTs.c -o $(ROOT)insertSameTs $(LFLAGS)
+ gcc $(CFLAGS) ./passwdTest.c -o $(ROOT)passwdTest $(LFLAGS)
clean:
rm $(ROOT)batchprepare
rm $(ROOT)stopquery
rm $(ROOT)dbTableRoute
+ rm $(ROOT)insertSameTs
+ rm $(ROOT)passwdTest
diff --git a/tests/script/api/passwdTest.c b/tests/script/api/passwdTest.c
new file mode 100644
index 0000000000..8a2b0a0390
--- /dev/null
+++ b/tests/script/api/passwdTest.c
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2019 TAOS Data, Inc.
+ *
+ * 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 .
+ */
+
+// TAOS standard API example. The same syntax as MySQL, but only a subset
+// to compile: gcc -o demo demo.c -ltaos
+
+/**
+ * passwdTest.c
+ * - Run the test case in clear TDengine environment with default root passwd 'taosdata'
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include "taos.h" // TAOS header file
+
+#define nDup 1
+#define nRoot 10
+#define nUser 10
+#define USER_LEN 24
+
+void Test(TAOS *taos, char *qstr);
+void createUers(TAOS *taos, const char *host, char *qstr);
+void passVerTestMulti(const char *host, char *qstr);
+
+int nPassVerNotified = 0;
+TAOS *taosu[nRoot] = {0};
+char users[nUser][USER_LEN] = {0};
+
+void __taos_notify_cb(void *param, void *ext, int type) {
+ switch (type) {
+ case TAOS_NOTIFY_PASSVER: {
+ ++nPassVerNotified;
+ printf("%s:%d type:%d user:%s ver:%d\n", __func__, __LINE__, type, param ? (char *)param : "NULL", *(int *)ext);
+ break;
+ }
+ default:
+ printf("%s:%d unknown type:%d\n", __func__, __LINE__, type);
+ break;
+ }
+}
+
+static void queryDB(TAOS *taos, char *command) {
+ int i;
+ TAOS_RES *pSql = NULL;
+ int32_t code = -1;
+
+ for (i = 0; i < nDup; ++i) {
+ if (NULL != pSql) {
+ taos_free_result(pSql);
+ pSql = NULL;
+ }
+
+ pSql = taos_query(taos, command);
+ code = taos_errno(pSql);
+ if (0 == code) {
+ break;
+ }
+ }
+
+ if (code != 0) {
+ fprintf(stderr, "failed to run: %s, reason: %s\n", command, taos_errstr(pSql));
+ taos_free_result(pSql);
+ taos_close(taos);
+ exit(EXIT_FAILURE);
+ } else {
+ fprintf(stderr, "success to run: %s\n", command);
+ }
+
+ taos_free_result(pSql);
+}
+
+int main(int argc, char *argv[]) {
+ char qstr[1024];
+
+ // connect to server
+ if (argc < 2) {
+ printf("please input server-ip \n");
+ return 0;
+ }
+
+ TAOS *taos = taos_connect(argv[1], "root", "taosdata", NULL, 0);
+ if (taos == NULL) {
+ printf("failed to connect to server, reason:%s\n", "null taos" /*taos_errstr(taos)*/);
+ exit(1);
+ }
+ createUers(taos, argv[1], qstr);
+ passVerTestMulti(argv[1], qstr);
+
+ taos_close(taos);
+ taos_cleanup();
+}
+
+void createUers(TAOS *taos, const char *host, char *qstr) {
+ // users
+ for (int i = 0; i < nUser; ++i) {
+ sprintf(users[i], "user%d", i);
+ sprintf(qstr, "CREATE USER %s PASS 'taosdata'", users[i]);
+ queryDB(taos, qstr);
+
+ taosu[i] = taos_connect(host, users[i], "taosdata", NULL, 0);
+ if (taosu[i] == NULL) {
+ printf("failed to connect to server, user:%s, reason:%s\n", users[i], "null taos" /*taos_errstr(taos)*/);
+ exit(1);
+ }
+
+ int code = taos_set_notify_cb(taosu[i], __taos_notify_cb, users[i], TAOS_NOTIFY_PASSVER);
+
+ if (code != 0) {
+ fprintf(stderr, "failed to run: taos_set_notify_cb for user:%s since %d\n", users[i], code);
+ } else {
+ fprintf(stderr, "success to run: taos_set_notify_cb for user:%s\n", users[i]);
+ }
+
+ // alter pass for users
+ sprintf(qstr, "alter user %s pass 'taos'", users[i]);
+ queryDB(taos, qstr);
+ }
+}
+
+void passVerTestMulti(const char *host, char *qstr) {
+ // root
+ TAOS *taos[nRoot] = {0};
+ char userName[USER_LEN] = "root";
+
+ for (int i = 0; i < nRoot; ++i) {
+ taos[i] = taos_connect(host, "root", "taosdata", NULL, 0);
+ if (taos[i] == NULL) {
+ printf("failed to connect to server, reason:%s\n", "null taos" /*taos_errstr(taos)*/);
+ exit(1);
+ }
+
+ int code = taos_set_notify_cb(taos[i], __taos_notify_cb, userName, TAOS_NOTIFY_PASSVER);
+
+ if (code != 0) {
+ fprintf(stderr, "failed to run: taos_set_notify_cb since %d\n", code);
+ } else {
+ fprintf(stderr, "success to run: taos_set_notify_cb\n");
+ }
+ }
+
+ queryDB(taos[0], "create database if not exists demo1 vgroups 1 minrows 10");
+ queryDB(taos[0], "create database if not exists demo2 vgroups 1 minrows 10");
+ queryDB(taos[0], "create database if not exists demo3 vgroups 1 minrows 10");
+
+ queryDB(taos[0], "create table demo1.stb (ts timestamp, c1 int) tags(t1 int)");
+ queryDB(taos[0], "create table demo2.stb (ts timestamp, c1 int) tags(t1 int)");
+ queryDB(taos[0], "create table demo3.stb (ts timestamp, c1 int) tags(t1 int)");
+
+ strcpy(qstr, "alter user root pass 'taos'");
+ queryDB(taos[0], qstr);
+
+ // calculate the nPassVerNotified for root and users
+ int nConn = nRoot + nUser;
+
+ for (int i = 0; i < 15; ++i) {
+ if (nPassVerNotified >= nConn) break;
+ sleep(1);
+ }
+
+ // close the taos_conn
+ for (int i = 0; i < nRoot; ++i) {
+ taos_close(taos[i]);
+ printf("%s:%d close taos[%d]\n", __func__, __LINE__, i);
+ sleep(1);
+ }
+
+ for (int i = 0; i < nUser; ++i) {
+ taos_close(taosu[i]);
+ printf("%s:%d close taosu[%d]\n", __func__, __LINE__, i);
+ sleep(1);
+ }
+
+ if (nPassVerNotified >= nConn) {
+ fprintf(stderr, "succeed to get passVer notification since nNotify %d >= nConn %d\n", nPassVerNotified, nConn);
+ } else {
+ fprintf(stderr, "failed to get passVer notification since nNotify %d < nConn %d\n", nPassVerNotified, nConn);
+ }
+ // sleep(300);
+}
\ No newline at end of file
diff --git a/tests/script/tsim/query/tag_scan.sim b/tests/script/tsim/query/tag_scan.sim
new file mode 100644
index 0000000000..03e3a20632
--- /dev/null
+++ b/tests/script/tsim/query/tag_scan.sim
@@ -0,0 +1,48 @@
+system sh/stop_dnodes.sh
+system sh/deploy.sh -n dnode1 -i 1
+system sh/exec.sh -n dnode1 -s start
+sql connect
+sql drop database if exists test
+sql create database test;
+sql use test;
+
+sql create table st(ts timestamp, f int) tags (t int);
+sql insert into ct1 using st tags(1) values(now, 1);
+sql insert into ct2 using st tags(2) values(now, 2);
+sql insert into ct3 using st tags(3) values(now, 3);
+sql insert into ct4 using st tags(4) values(now, 4);
+
+sql create table st2(ts timestamp, f int) tags (t int);
+sql insert into ct21 using st2 tags(1) values(now, 1);
+sql insert into ct22 using st2 tags(2) values(now, 2);
+sql insert into ct23 using st2 tags(3) values(now, 3);
+sql insert into ct24 using st2 tags(4) values(now, 4);
+
+sql select tbname, 1 from st group by tbname order by tbname;
+print $rows $data00 $data10 $data20
+if $rows != 4 then
+ return -1
+endi
+if $data00 != @ct1@ then
+ return -1
+endi
+if $data10 != @ct2@ then
+ return -1
+endi
+sql select tbname, 1 from st group by tbname slimit 0, 1;
+print $rows
+if $rows != 1 then
+ return -1
+endi
+sql select tbname, 1 from st group by tbname slimit 2, 2;
+print $rows $data00 $data10
+if $rows != 2 then
+ return -1
+endi
+sql select tbname, 1 from st group by tbname order by tbname slimit 0, 1;
+print $rows $data00 $data10 $data20
+if $rows != 4 then
+ return -1
+endi
+
+system sh/exec.sh -n dnode1 -s stop -x SIGINT
diff --git a/tests/system-test/1-insert/delete_childtable.py b/tests/system-test/1-insert/delete_childtable.py
index e3144edb45..a12f884981 100644
--- a/tests/system-test/1-insert/delete_childtable.py
+++ b/tests/system-test/1-insert/delete_childtable.py
@@ -27,7 +27,7 @@ class TDTestCase:
def init(self, conn, logSql, replicaVar=1):
self.replicaVar = int(replicaVar)
tdLog.debug("start to execute %s" % __file__)
- tdSql.init(conn.cursor())
+ tdSql.init(conn.cursor(), True)
self.dbname = 'db_test'
self.setsql = TDSetSql()
self.stbname = 'stb'
diff --git a/tools/shell/src/shellEngine.c b/tools/shell/src/shellEngine.c
index 910b067d4e..478801d3e7 100644
--- a/tools/shell/src/shellEngine.c
+++ b/tools/shell/src/shellEngine.c
@@ -1115,6 +1115,7 @@ int32_t shellExecute() {
}
if (shell.conn == NULL) {
+ printf("failed to connect to server, reason: %s\n", taos_errstr(NULL));
fflush(stdout);
return -1;
}