Merge branch '3.0' of https://github.com/taosdata/TDengine into fix/TD-31297

This commit is contained in:
54liuyao 2024-08-08 08:40:07 +08:00
commit c91595c2cc
93 changed files with 758 additions and 468 deletions

View File

@ -63,7 +63,7 @@ toc_max_heading_level: 4
1. 数据库Database数据库提供时序数据的高效存储和读取能力。在工业、物联网场景由设备所产生的时序数据量是十分惊人的。从存储数据的角度来说数据库需要把这些数据持久化到硬盘上并最大程度地压缩从而降低存储成本。从读取数据的角度来说数据库需要保证实时查询以及历史数据的查询效率。比较传统的存储方案是使用 MySql、Oracle 等关系型数据库,也有 Hadoop 体系的 HBase专用的时序数据库则有 InfluxDB、OpenTSDB、Prometheus 等。
2. 数据订阅Data Subscription很多时序数据应用都需要在第一时间订阅到业务所需的实时数据从而及时了解被监测对对象的最新状态用 AI 或其他工具做实时的数据分析。同时,由于数据的隐私以及安全,你只能许应用订阅他有权限访问的数据。因此,一个时序数据处理平台一定需要具备数据订阅的能力,帮助应用实时获取最新数据。
2. 数据订阅Data Subscription很多时序数据应用都需要在第一时间订阅到业务所需的实时数据从而及时了解被监测对对象的最新状态用 AI 或其他工具做实时的数据分析。同时,由于数据的隐私以及安全,你只能许应用订阅他有权限访问的数据。因此,一个时序数据处理平台一定需要具备数据订阅的能力,帮助应用实时获取最新数据。
3. ETLExtract Transform Load在实际的物联网、工业场景中时序数据的采集需要特定的 ETL 工具进行数据的提取、清洗和转换操作,才能把数据写入数据库中,以保证数据的质量。因为不同数据采集系统往往使用不同的标准,比如采集的温度的物理单位不一致,有的用摄氏度,有的用华氏度;系统之间所在的时区不一致,要进行转换;时间分辨率也可能不统一,因此这些从不同系统汇聚来的数据需要进行转换才能写入数据库。
@ -109,7 +109,7 @@ toc_max_heading_level: 4
5. 必须拥有高效的缓存功能:绝大部分场景,都需要能快速获取设备当前状态或其他信息,用以报警、大屏展示或其他。系统需要提供一高效机制,让用户可以获取全部、或符合过滤条件的部分设备的最新状态。
6. 必须拥有实时流式计算:各种实时预警或预测已经不是简单的基于某一个阈值进行,而是需要通过将一个或多个设备产生的数据流进行实时聚合计算,不只是基于一个时间点、而是基于一个时间窗口进行计算。不仅如此,计算的需求也相当复杂,因场景而异,应许用户自定义函数进行计算。
6. 必须拥有实时流式计算:各种实时预警或预测已经不是简单的基于某一个阈值进行,而是需要通过将一个或多个设备产生的数据流进行实时聚合计算,不只是基于一个时间点、而是基于一个时间窗口进行计算。不仅如此,计算的需求也相当复杂,因场景而异,应许用户自定义函数进行计算。
7. 必须支持数据订阅:与通用大数据平台比较一致,同一组数据往往有很多应用都需要,因此系统应该提供订阅功能,只要有新的数据更新,就应该实时提醒应用。由于数据隐私和安全,而且这个订阅也应该是个性化的,只能订阅有权查看的数据,比如仅仅能订阅每小时的平均功率,而不能订阅原始的电流、电压值。
@ -119,7 +119,7 @@ toc_max_heading_level: 4
10. 必须支持灵活的多维度分析:对于联网设备产生的数据,需要进行各种维度的统计分析,比如从设备所处的地域进行分析,从设备的型号、供应商进行分析,从设备所使用的人员进行分析等等。而且这些维度的分析是无法事先想好的,是在实际运营过程中,根据业务发展的需求定下来的。因此时序大数据系统需要一个灵活的机制增加某个维度的分析。
11. 需要支持即席分析和查询。为提高大数据分析师的工作效率,系统应该提供一命令行工具或许用户通过其他工具,执行 SQL 查询,而不是非要通过编程接口。查询分析的结果可以很方便的导出,再制作成各种图表。
11. 需要支持即席分析和查询。为提高大数据分析师的工作效率,系统应该提供一命令行工具或许用户通过其他工具,执行 SQL 查询,而不是非要通过编程接口。查询分析的结果可以很方便的导出,再制作成各种图表。
12. 必须支持数据降频、插值、特殊函数计算等操作。原始数据的采集频次可能很高,但具体分析往往不需要对原始数据执行,而是数据降频之后。系统需要提供高效的数据降频操作。设备是很难同步的,不同设备采集数据的时间点是很难对齐的,因此分析一个特定时间点的值,往往需要插值才能解决,系统需要提供线性插值、设置固定值等多种插值策略才行。工业互联网里,除通用的统计操作之外,往往还需要支持一些特殊函数,比如时间加权平均、累计求和、差值等。

View File

@ -6,7 +6,7 @@ toc_max_heading_level: 4
TDengine 是一个高性能、分布式的时序数据库。通过集成的缓存、数据订阅、流计算和数据清洗与转换等功能TDengine 已经发展成为一个专为物联网、工业互联网、金融和 IT 运维等关键行业量身定制的时序大数据平台。该平台能够高效地汇聚、存储、分析、计算和分发来自海量数据采集点的大规模数据流,每日处理能力可达 TB 乃至 PB 级别。借助 TDengine企业可以实现实时的业务监控和预警进而发掘出有价值的商业洞察。
自 2019 年 7 月 以 来, 涛 思 数 据 陆 续 将 TDengine 的 不 同 版 本 开 源, 包 括 单 机版2019 年 7 月、集群版2020 年 8 月以及云原生版2022 年 8 月。开源之后TDengine 迅速获得了全球开发者的关注,多次在 GitHub 网站全球趋势排行榜上位居榜首。截至编写本书时TDengine 在 GitHub 网站上已积累近 2.3 万颗星安装实例超过53 万个,覆盖 60 多个国家和地区,广泛应用于电力、石油、化工、新能源、智能制造、汽车、环境监测等行业或领域,赢得了全球开发者的广泛认可
自 2019 年 7 月 以 来, 涛 思 数 据 陆 续 将 TDengine 的 不 同 版 本 开 源, 包 括 单 机版2019 年 7 月、集群版2020 年 8 月以及云原生版2022 年 8 月。开源之后TDengine 迅速获得了全球开发者的关注,多次在 GitHub 网站全球趋势排行榜上位居榜首,最新的关注热度见[涛思数据首页](https://www.taosdata.com/)。
## TDengine 产品
@ -22,7 +22,7 @@ TDengine OSS 是一个开源的高性能时序数据库,与其他时序数据
TDengine 经过特别优化,以适应时间序列数据的独特需求,引入了“一个数据采集点一张表”和“超级表”的创新数据组织策略。这些策略背后的支撑是一个革命性的存储引擎,它极大地提升了数据处理的速度和效率,无论是在数据的写入、查询还是存储方面。接下来,逐一探索 TDengine 的众多功能,帮助您全面了解这个为高效处理时间序列数据而生的大数据平台。
1. 写入数据TDengine 支持多种数据写入方式。首先,它完全兼容 SQL允许用户使用标准的 SQL 语法进行数据写入。而且 TDengine 还支持无模式Schemaless写入包括流行的 InfluxDB Line 协议、OpenTSDB 的 Telnet 和 JSON 协议这些协议的加入使得数据的导入变得更加灵活和高效。更进一步TDengine 与众多第三方工具实现了无缝集成,例如 Telegraf、Prometheus、EMQX、StatsD、collectd 和 HiveMQ 等。对于 TDengine Enterprise TDengine 还提供了 MQTT、OPC-UA、OPC-DA、PI、Wonderware Kafka 等连接器。这些工具通过简单的配置,无需一行代码,就可以将来自各种数据源的数据源源不断的写入数据库,极大地简化了数据收集和存储的过程。
1. 写入数据TDengine 支持多种数据写入方式。首先,它完全兼容 SQL允许用户使用标准的 SQL 语法进行数据写入。而且 TDengine 还支持无模式Schemaless写入包括流行的 InfluxDB Line 协议、OpenTSDB 的 Telnet 和 JSON 协议这些协议的加入使得数据的导入变得更加灵活和高效。更进一步TDengine 与众多第三方工具实现了无缝集成,例如 Telegraf、Prometheus、EMQX、StatsD、collectd 和 HiveMQ 等。在 TDengine Enterprise 中, 还提供了 MQTT、OPC-UA、OPC-DA、PI、Wonderware、Kafka、InfluxDB、OpenTSDB、MySQL、Oracle 和 SQL Server 等连接器。这些工具通过简单的配置,无需一行代码,就可以将来自各种数据源的数据源源不断的写入数据库,极大地简化了数据收集和存储的过程。
2. 查询数据TDengine 提供标准的 SQL 查询语法并针对时序数据和业务的特点优化和新增了许多语法和功能例如降采样、插值、累计求和、时间加权平均、状态窗口、时间窗口、会话窗口、滑动窗口等。TDengine 还支持用户自定义函数UDF
@ -38,13 +38,11 @@ TDengine 经过特别优化,以适应时间序列数据的独特需求,引
8. 数据迁移TDengine 提供了多种便捷的数据导入导出功能包括脚本文件导入导出、数据文件导入导出、taosdump 工具导入导出等。企业版还支持边云协同、数据同步等场景,兼容多种数据源,如 AVEVA PI System 等。
9. 编程连接器TDengine 提供不同语言的连接器,包括 C/C++、Java、Go、Node.js、Rust、Python、C#、R、PHP 等。而且 TDengine 支持 REST 接口,应用可以直接通过 HTTP POST 请求 BODY 中包含的 SQL 语句来操作数据库。
9. 编程连接器TDengine 提供不同语言的连接器,包括 C/C++、Java、Go、Node.js、Rust、Python、C#、R、PHP 等。这些连接器大多都支持原生连接和 WebSocket 两种连接方式。TDengine 也提供 REST 接口,任何语言的应用程序可以直接通过 HTTP 请求访问数据库。
10. 数据安全TDengine 提供了丰富的用户管理和权限管理功能以控制不同用户对数据库和表的访问权限,提供了 IP 白名单功能以控制不同帐号只能从特定的服务器接入集群。TDengine 支持系统管理员对不同数据库按需加密,数据加密后对读写完全透明且对性能的影响很小。还提供了审计日志功能以记录系统中的敏感操作。
11. 编程连接器TDengine 提供了丰富的编程语言连接器,包括 C/C++、Java、Go、Node.js、Rust、Python、C#、R、PHP 等,并支持 REST ful 接口方便应用通过HTTP POST 请求操作数据库。
12. 常用工具TDengine 还提供了交互式命令行程序CLI便于管理集群、检查系统状态、做即时查询。压力测试工具 taosBenchmark用于测试 TDengine 的性能。TDengine 还提供了图形化管理界面,简化了操作和管理过程。
11. 常用工具TDengine 还提供了交互式命令行程序CLI便于管理集群、检查系统状态、做即时查询。压力测试工具 taosBenchmark用于测试 TDengine 的性能。TDengine 还提供了图形化管理界面,简化了操作和管理过程。
## TDengine 与典型时序数据库的区别

View File

@ -71,4 +71,54 @@ taos>
## 快速体验
想要快速体验 TDengine 的写入和查询能力,请参考[快速体验](../use)
### 体验写入
taosBenchmark 是一个专为测试 TDengine 性能而设计的工具它能够全面评估TDengine 在写入、查询和订阅等方面的功能表现。该工具能够模拟大量设备产生的数据,并允许用户灵活控制数据库、超级表、标签列的数量和类型、数据列的数量和类型、子表数量、每张子表的数据量、写入数据的时间间隔、工作线程数量以及是否写入乱序数据等策略。
启动 TDengine 的服务,在终端中执行如下命令
```shell
taosBenchmark -y
```
系统将自动在数据库 test 下创建一张名为 meters的超级表。这张超级表将包含 10 000 张子表,表名从 d0 到 d9999每张表包含 10,000条记录。每条记录包含 ts时间戳、current电流、voltage电压和 phase相位4个字段。时间戳范围从“2017-07-14 10:40:00 000”到“2017-07-14 10:40:09 999”。每张表还带有 location 和 groupId 两个标签其中groupId 设置为 1 到 10而 location 则设置为 California.Campbell、California.Cupertino 等城市信息。
执行该命令后,系统将迅速完成 1 亿条记录的写入过程。实际所需时间取决于硬件性能,但即便在普通 PC 服务器上,这个过程通常也只需要十几秒。
taosBenchmark 提供了丰富的选项,允许用户自定义测试参数,如表的数目、记录条数等。要查看详细的参数列表,请在终端中输入如下命令
```shell
taosBenchmark --help
```
有关taosBenchmark 的详细使用方法,请参考[taosBenchmark 参考手册](../../reference/components/taosbenchmark)
### 体验查询
使用上述 taosBenchmark 插入数据后,可以在 TDengine CLItaos输入查询命令体验查询速度。
1. 查询超级表 meters 下的记录总条数
```shell
SELECT COUNT(*) FROM test.meters;
```
2. 查询 1 亿条记录的平均值、最大值、最小值
```shell
SELECT AVG(current), MAX(voltage), MIN(phase) FROM test.meters;
```
3. 查询 location = "California.SanFrancisco" 的记录总条数
```shell
SELECT COUNT(*) FROM test.meters WHERE location = "California.SanFrancisco";
```
4. 查询 groupId = 10 的所有记录的平均值、最大值、最小值
```shell
SELECT AVG(current), MAX(voltage), MIN(phase) FROM test.meters WHERE groupId = 10;
```
5. 对表 d1001 按每 10 秒进行平均值、最大值和最小值聚合统计
```shell
SELECT _wstart, AVG(current), MAX(voltage), MIN(phase) FROM test.d1001 INTERVAL(10s);
```
在上面的查询中使用系统提供的伪列_wstart 来给出每个窗口的开始时间。

View File

@ -267,4 +267,54 @@ Query OK, 2 row(s) in set (0.003128s)
## 快速体验
想要快速体验 TDengine 的写入和查询能力,请参考[快速体验](../use)
### 体验写入
taosBenchmark 是一个专为测试 TDengine 性能而设计的工具它能够全面评估TDengine 在写入、查询和订阅等方面的功能表现。该工具能够模拟大量设备产生的数据,并允许用户灵活控制数据库、超级表、标签列的数量和类型、数据列的数量和类型、子表数量、每张子表的数据量、写入数据的时间间隔、工作线程数量以及是否写入乱序数据等策略。
启动 TDengine 的服务,在终端中执行如下命令
```shell
taosBenchmark -y
```
系统将自动在数据库 test 下创建一张名为 meters的超级表。这张超级表将包含 10 000 张子表,表名从 d0 到 d9999每张表包含 10,000条记录。每条记录包含 ts时间戳、current电流、voltage电压和 phase相位4个字段。时间戳范围从“2017-07-14 10:40:00 000”到“2017-07-14 10:40:09 999”。每张表还带有 location 和 groupId 两个标签其中groupId 设置为 1 到 10而 location 则设置为 California.Campbell、California.Cupertino 等城市信息。
执行该命令后,系统将迅速完成 1 亿条记录的写入过程。实际所需时间取决于硬件性能,但即便在普通 PC 服务器上,这个过程通常也只需要十几秒。
taosBenchmark 提供了丰富的选项,允许用户自定义测试参数,如表的数目、记录条数等。要查看详细的参数列表,请在终端中输入如下命令
```shell
taosBenchmark --help
```
有关taosBenchmark 的详细使用方法,请参考[taosBenchmark 参考手册](../../reference/components/taosbenchmark)
### 体验查询
使用上述 taosBenchmark 插入数据后,可以在 TDengine CLItaos输入查询命令体验查询速度。
1. 查询超级表 meters 下的记录总条数
```shell
SELECT COUNT(*) FROM test.meters;
```
2. 查询 1 亿条记录的平均值、最大值、最小值
```shell
SELECT AVG(current), MAX(voltage), MIN(phase) FROM test.meters;
```
3. 查询 location = "California.SanFrancisco" 的记录总条数
```shell
SELECT COUNT(*) FROM test.meters WHERE location = "California.SanFrancisco";
```
4. 查询 groupId = 10 的所有记录的平均值、最大值、最小值
```shell
SELECT AVG(current), MAX(voltage), MIN(phase) FROM test.meters WHERE groupId = 10;
```
5. 对表 d1001 按每 10 秒进行平均值、最大值和最小值聚合统计
```shell
SELECT _wstart, AVG(current), MAX(voltage), MIN(phase) FROM test.d1001 INTERVAL(10s);
```
在上面的查询中使用系统提供的伪列_wstart 来给出每个窗口的开始时间。

View File

@ -8,9 +8,13 @@ sidebar_label: 集群维护
本节介绍 TDengine Enterprise 中提供的高阶集群维护手段,能够使 TDengine 集群长期运行得更健壮和高效。
## 节点管理
如何管理集群节点请参考[节点管理](../../reference/taos-sql/node)
## 数据重整
TDengine 面向多种写入场景而很多写入场景下TDengine 的存储会导致数据存储的放大或数据文件的空洞等。这一方面影响数据的存储效率另一方面也会影响查询效率。为了解决上述问题TDengine 企业版提供了对数据的重整功能,即 DATA COMPACT 功能,将存储的数据文件重新整理,删除文件空洞和无效数据,提高数据的组织度,从而提高存储和查询的效率。
TDengine 面向多种写入场景而很多写入场景下TDengine 的存储会导致数据存储的放大或数据文件的空洞等。这一方面影响数据的存储效率另一方面也会影响查询效率。为了解决上述问题TDengine 企业版提供了对数据的重整功能,即 DATA COMPACT 功能,将存储的数据文件重新整理,删除文件空洞和无效数据,提高数据的组织度,从而提高存储和查询的效率。数据重整功能在 3.0.3.0 版本第一次发布,此后又经过了多次迭代优化,建议使用最新版本。
### 语法
@ -39,7 +43,7 @@ KILL COMPACT compact_id
## Vgroup Leader 再平衡
当多副本集群中的一个或多个节点因为升级或其它原因而重启后,有可能出现集群中各个 dnode 负载不均衡的现象,极端情况下会出现所有 vgroup 的 leader 都位于同一个 dnode 的情况。为了解决这个问题,可以使用下面的命令
当多副本集群中的一个或多个节点因为升级或其它原因而重启后,有可能出现集群中各个 dnode 负载不均衡的现象,极端情况下会出现所有 vgroup 的 leader 都位于同一个 dnode 的情况。为了解决这个问题,可以使用下面的命令,该命令在 3.0.4.0 版本中首次发布,建议尽可能使用最新版本。
```SQL
balance vgroup leader; # 再平衡所有 vgroup 的 leader
@ -73,7 +77,7 @@ restore qnode on dnode <dnode_id># 恢复dnode上的qnode
## 分裂虚拟组
当一个 vgroup 因为子表数过多而导致 CPU 或 Disk 资源使用量负载过高时,增加 dnode 节点后可通过split vgroup命令把该vgroup分裂为两个虚拟组。分裂完成后新产生的两个 vgroup 承担原来由一个 vgroup 提供的读写服务。
当一个 vgroup 因为子表数过多而导致 CPU 或 Disk 资源使用量负载过高时,增加 dnode 节点后可通过split vgroup命令把该vgroup分裂为两个虚拟组。分裂完成后新产生的两个 vgroup 承担原来由一个 vgroup 提供的读写服务。该命令在 3.0.6.0 版本第一次发布,建议尽可能使用最新版本。
```sql
split vgroup <vgroup_id>
@ -97,7 +101,7 @@ split vgroup <vgroup_id>
## 双副本
双副本是一种特殊的数据库高可用配置,本节对它的使用和维护操作进行特别说明。
双副本是一种特殊的数据库高可用配置,本节对它的使用和维护操作进行特别说明。该功能在 3.3.0.0 版本中第一次发布,建议尽可能使用最新版本。
### 查看 Vgroups 的状态

View File

@ -4,14 +4,13 @@ title: 多级存储与对象存储
toc_max_heading_level: 4
---
TDengine 特有的多级存储功能,其作用是将较近的热度较高的数据存储在高速介质上,而时间久远热度很低的数据存储在低成本介质上,达成了以下目标:
本节介绍 TDengine Enterprise 特有的多级存储功能,其作用是将较近的热度较高的数据存储在高速介质上,而时间久远热度很低的数据存储在低成本介质上,达成了以下目标:
- 降低存储成本 -- 将数据分级存储后,海量极冷数据存入廉价存储介质带来显著经济性
- 提升写入性能 -- 得益于每级存储可支持多个挂载点WAL 预写日志也支持 0 级的多挂载点并行写入,极大提升写入性能(实际场景测得支持持续写入每秒 3 亿测点以上),在机械硬盘上可获得极高磁盘 IO 吞吐(实测可达 2GB/s
- 方便维护 -- 配置好各级存储挂载点后,系统数据迁移等工作,无需人工干预;存储扩容更灵活、方便
- 对 SQL 透明 -- 无论查询的数据是否跨级,一条 SQL 可返回所有数据,简单高效
多级存储所涉及的各层存储介质都是本地存储设备。除了本地存储设备之外TDengine 还支持使用对象存储(S3),将最冷的一批数据保存在最廉价的介质上,以进一步降低存储成本,并在必要时仍然可以进行查询,且数据存储在哪里也对 SQL 透明。
多级存储所涉及的各层存储介质都是本地存储设备。除了本地存储设备之外TDengine Enterprise 还支持使用对象存储(S3),将最冷的一批数据保存在最廉价的介质上,以进一步降低存储成本,并在必要时仍然可以进行查询,且数据存储在哪里也对 SQL 透明。支持对象存储在 3.3.0.0 版本中首次发布,建议使用最新版本。
## 多级存储

View File

@ -4,7 +4,7 @@ title: 用户和权限管理
toc_max_heading_level: 4
---
TDengine 默认仅配置了一个 root 用户该用户拥有最高权限。TDengine 支持对系统资源、库、表、视图和主题的访问权限控制。root 用户可以为每个用户针对不同的资源设置不同的访问权限。本节介绍 TDengine 中的用户和权限管理。
TDengine 默认仅配置了一个 root 用户该用户拥有最高权限。TDengine 支持对系统资源、库、表、视图和主题的访问权限控制。root 用户可以为每个用户针对不同的资源设置不同的访问权限。本节介绍 TDengine 中的用户和权限管理。用户和权限管理是 TDengine Enterprise 特有功能。
## 用户管理

View File

@ -4,7 +4,7 @@ title: 更多安全策略
toc_max_heading_level: 4
---
除了传统的用户和权限管理之外TDengine 还有其他的安全策略,例如 IP 白名单、审计日志、数据加密等。
除了传统的用户和权限管理之外TDengine 还有其他的安全策略,例如 IP 白名单、审计日志、数据加密等,这些都是 TDengine Enterprise 特有功能,其中白名单功能在 3.2.0.0 版本首次发布,审计日志在 3.1.1.0 版本中首次发布,数据库加密在 3.3.0.0 中首次发布,建议使用最新版本
## IP 白名单

View File

@ -6,7 +6,7 @@ toc_max_heading_level: 4
## 简介
1. 部分用户因为部署环境的特殊性只能部署两台服务器,同时希望实现一定的服务高可用和数据高可靠。本文主要描述基于数据复制和客户端 Failover 两项关键技术的 TDengine 双活系统的产品行为包括双活系统的架构、配置、运维等。TDengine 双活既可以用于前面所述资源受限的环境,也可用于在两套 TDengine 集群(不限资源)之间的灾备场景。
1. 部分用户因为部署环境的特殊性只能部署两台服务器,同时希望实现一定的服务高可用和数据高可靠。本文主要描述基于数据复制和客户端 Failover 两项关键技术的 TDengine 双活系统的产品行为包括双活系统的架构、配置、运维等。TDengine 双活既可以用于前面所述资源受限的环境,也可用于在两套 TDengine 集群(不限资源)之间的灾备场景。双活是 TDengine Enterprise 特有功能,在 3.3.0.0 版本中第一次发布,建议使用最新版本。
2. 双活系统的定义是:业务系统中有且仅有两台服务器,其上分别部署一套服务,在业务层看来这两台机器和两套服务是一个完整的系统,对其中的细节业务层不需要感知。双活中的两个节点通常被称为 Master-Slave意为”主从“或”主备“本文档中可能会出现混用的情况。

View File

@ -41,7 +41,7 @@ TDengine 提供了丰富的应用程序开发接口,为了便于用户快速
3. 使用 Websocket 连接,用户也无需安装客户端驱动程序 taosc。
4. 连接云服务实例,必须使用 REST 连接 或 Websocket 连接。
一般我们建议使用 **Websocket 连接**
**推荐使用 WebSocket 连接**
## 安装客户端驱动 taosc

View File

@ -11,7 +11,9 @@ import TabItem from "@theme/TabItem";
- 减少解析时间通过参数绑定SQL 语句的结构在第一次执行时就已经确定,后续的执行只需要替换参数值,这样可以避免每次执行时都进行语法解析,从而减少解析时间。
- 预编译当使用参数绑定时SQL 语句可以被预编译并缓存,后续使用不同的参数值执行时,可以直接使用预编译的版本,提高执行效率。
- 减少网络开销:参数绑定还可以减少发送到数据库的数据量,因为只需要发送参数值而不是完整的 SQL 语句,特别是在执行大量相似的插入或更新操作时,这种差异尤为明显。
- 减少网络开销:参数绑定还可以减少发送到数据库的数据量,因为只需要发送参数值而不是完整的 SQL 语句,特别是在执行大量相似的插入或更新操作时,这种差异尤为明显。
**Tips: 数据写入推荐使用参数绑定方式**
下面我们继续以智能电表为例,展示各语言连接器使用参数绑定高效写入的功能:
1. 准备一个参数化的 SQL 插入语句,用于向超级表 `meters` 中插入数据。这个语句允许动态地指定子表名、标签和列值。

View File

@ -3,7 +3,7 @@ title: taosX 参考手册
sidebar_label: taosX
---
taosX 是 TDengine 中的一个核心组件提供零代码数据接入的能力taosX 支持两种运行模式:服务模式和命令行模式。本节讲述如何以这两种方式使用 taosX。要想使用 taosX 需要先安装 TDengine Enterprise 安装包。
taosX 是 TDengine Enterprise 中的一个核心组件提供零代码数据接入的能力taosX 支持两种运行模式:服务模式和命令行模式。本节讲述如何以这两种方式使用 taosX。要想使用 taosX 需要先安装 TDengine Enterprise 安装包。
## 命令行模式

View File

@ -3,7 +3,7 @@ title: taosX-Agent 参考手册
sidebar_label: taosX-Agent
---
本节讲述如何部署 `Agent` (for `taosX`)。使用之前需要安装 TDengine Enterprise 安装包之后。
本节讲述如何部署 `Agent` (for `taosX`)。使用之前需要安装 TDengine Enterprise 安装包之后taosX-Agent 用于在部分数据接入场景,如 Pi, OPC UA, OPC DA 等对访问数据源有一定限制或者网络环境特殊的场景下,可以将 taosX-Agent 部署在靠近数据源的环境中甚至与数据源在相同的服务器上,由 taosX-Agent 负责从数据源读取数据并发送给 taosX
## 配置

View File

@ -4,27 +4,27 @@ sidebar_label: taosExplorer
toc_max_heading_level: 4
---
taos-explorer 是一个为用户提供 TDengine 实例的可视化管理交互工具的 web 服务。本节主要讲述其安装和部署。它的各项功能都是基于简单易上手的图形界面,可以直接尝试,如果有需要也可以考高级功能和运维指南中的相关内容。
taosExplorer 是一个为用户提供 TDengine 实例的可视化管理交互工具的 web 服务。本节主要讲述其安装和部署。它的各项功能都是基于简单易上手的图形界面,可以直接尝试,如果有需要也可以考高级功能和运维指南中的相关内容。
## 安装
taos-explorer 无需单独安装,从 TDengine 3.3.0.0 版本开始,它随着 TDengine Enterprise Server 安装包一起发布,安装完成后,就可以看到 `taos-explorer` 服务。
taosEexplorer 无需单独安装,从 TDengine 3.3.0.0 版本开始,它随着 TDengine Enterprise Server 安装包一起发布,安装完成后,就可以看到 `taos-explorer` 服务。
## 配置
在启动 Explorer 之前,请确保配置文件中的内容正确。
在启动 taosExplorer 之前,请确保配置文件中的内容正确。
```TOML
# Explorer listen port
# listen port
port = 6060
# Explorer listen address for IPv4
# listen address for IPv4
addr = "0.0.0.0"
# Explorer listen address for IPv4
# listen address for IPv4
#ipv6 = "::1"
# Explorer log level. Possible: error,warn,info,debug,trace
# log level. Possible: error,warn,info,debug,trace
log_level = "info"
# taosAdapter address.
@ -49,9 +49,9 @@ cors = false
说明:
- `port`Explorer 服务绑定的端口。
- `addr`Explorer 服务绑定的 IPv4 地址,默认为 `0.0.0.0`。如需修改,请配置为 `localhost` 之外的地址以对外提供服务。
- `ipv6`Explorer 服务绑定的 IPv6 地址,默认不绑定 IPv6 地址。
- `port`taosExplorer 服务绑定的端口。
- `addr`taosExplorer 服务绑定的 IPv4 地址,默认为 `0.0.0.0`。如需修改,请配置为 `localhost` 之外的地址以对外提供服务。
- `ipv6`taosExplorer 服务绑定的 IPv6 地址,默认不绑定 IPv6 地址。
- `log_level`:日志级别,可选值为 "error", "warn", "info", "debug", "trace"。
- `cluster`TDengine 集群的 taosAdapter 地址。
- `x_api`taosX 的 gRPC 地址。
@ -62,7 +62,7 @@ cors = false
## 启动停止
然后启动 Explorer可以直接在命令行执行 taos-explorer 或者使用 systemctl 命令:
然后启动 taosExplorer可以直接在命令行执行 taos-explorer 或者使用 systemctl 命令:
```bash
systemctl start taos-explorer # Linux
@ -78,7 +78,7 @@ sc.exe stop taos-explorer # Windows
## 问题排查
1. 当通过浏览器打开 Explorer 站点遇到“无法访问此网站”的错误信息时,请通过命令行登录 taosExplorer 所在机器,并使用命令 `systemctl status taos-explorer` 检查服务的状态,如果返回的状态是 `inactive`,请使用命令`systemctl start taos-explorer` 启动服务。
2. 如果需要获取 Explorer 的详细日志,可通过命令 `journalctl -u taos-explorer`
2. 如果需要获取 taosExplorer 的详细日志,可通过命令 `journalctl -u taos-explorer`
3. 当使用 Nginx 或其他工具进行转发时,注意进行 CORS 设置或在配置文件中使用 `cors = true`
这是一个 Nginx 配置文件 CORS 设置的例子:

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

After

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

After

Width:  |  Height:  |  Size: 70 KiB

View File

@ -7,80 +7,47 @@ toc_max_heading_level: 4
import Tabs from '@theme/Tabs'
import TabItem from '@theme/TabItem'
TDinsight 是使用监控数据库和 [Grafana] 对 TDengine 进行监控的解决方案。
TDinsight 是使用 [Grafana] 对 TDengine 进行监控的解决方案。
TDengine 通过 taosKeeper 将服务器的 CPU、内存、硬盘空间、带宽、请求数、磁盘读写速度、慢查询等信息定时写入指定数据库,并对重要的系统操作(比如登录、创建、删除数据库等)以及各种错误报警信息进行记录。通过 [Grafana][TDengine 数据源插件](https://github.com/taosdata/grafanaplugin/releases)TDinsight 将集群状态、节点信息、插入及查询请求、资源使用情况等进行可视化展示,同时还支持 vnode、dnode、mnode 节点状态异常告警,为开发者实时监控 TDengine 集群运行状态提供了便利。本文将指导用户安装 Grafana 服务器并通过 `TDinsight.sh` 安装脚本自动安装 TDengine 数据源插件及部署 TDinsight 可视化面板。
TDengine 通过 taosKeeper 将服务器的 CPU、内存、硬盘空间、带宽、请求数、磁盘读写速度、慢查询等信息定时写入指定数据库。通过 Grafana 和 TDengine 数据源插件TDinsight 将集群状态、节点信息、插入及查询请求、资源使用情况等进行可视化展示,为开发者实时监控 TDengine 集群运行状态提供了便利。本文将指导用户安装 TDengine 数据源插件及部署 TDinsight 可视化面板。
## 系统要求
## 前置条件
- 单节点的 TDengine 服务器或多节点的 [TDengine] 集群,以及一个[Grafana]服务器。此仪表盘需要 TDengine 3.0.0.0 及以上,并开启监控服务,具体配置请参考:[TDengine 监控配置](../../../operation/monitor)。
首先检查下面服务:
- TDengine 已经安装并正常运行,此仪表盘需要 TDengine 3.0.0.0 及以上,并开启监控上报配置,具体配置请参考:[TDengine 监控配置](../taosd/#监控相关)。
- taosAdapter 已经安装并正常运行。具体细节请参考:[taosAdapter 使用手册](../taosadapter)
- taosKeeper 已安装并正常运行。注意需要 taos.cfg 文件中打开 monitor 相关配置项,具体细节请参考:[taosKeeper 使用手册](../taoskeeper)
- taosKeeper 已安装并正常运行。具体细节请参考:[taosKeeper 使用手册](../taoskeeper)
记录以下信息:
然后记录以下信息:
- taosAdapter 集群 REST API 地址,如:`http://tdengine.local:6041`。
- taosAdapter 集群 REST API 地址,如:`http://localhost:6041`。
- taosAdapter 集群认证信息,可使用用户名及密码。
- taosKeeper 记录监控指标的数据库名称。
## 安装 Grafana
## 安装和启动 Grafana
我们建议在此处使用最新的[Grafana] 8 或 9 版本。您可以在任何[支持的操作系统](https://grafana.com/docs/grafana/latest/installation/requirements/#supported-operating-systems)中,按照 [Grafana 官方文档安装说明](https://grafana.com/docs/grafana/latest/installation/) 安装 [Grafana]。
我们建议您使用最新的 Grafana 版本TDInsight 支持 Grafana 7.5 及以上版本。您可以在任何[支持的操作系统](https://grafana.com/docs/grafana/latest/installation/requirements/#supported-operating-systems)中,按照 [Grafana 官方文档安装说明](https://grafana.com/docs/grafana/latest/installation/) 安装 Grafana。
安装后请参考 [启动 Grafana](https://grafana.com/docs/grafana/latest/setup-grafana/start-restart-grafana/) 启动 Grafana 服务。
<Tabs defaultValue="debian" groupId="install">
<TabItem value="debian" label="基于 Debian 或 Ubuntu 系统">
安装完成后就可以在 Web 浏览器中打开 Grafana 网址,默认是:`http://localhost:3000`。 默认用户名/密码都是 `admin`。Grafana 会要求在首次登录后更改密码。
对于 Debian 或 Ubuntu 操作系统,建议使用 Grafana 镜像仓库。使用如下命令从零开始安装:
:::info
```bash
sudo apt-get install -y apt-transport-https
sudo apt-get install -y software-properties-common wget
wget -q -O - https://packages.grafana.com/gpg.key |\
sudo apt-key add -
echo "deb https://packages.grafana.com/oss/deb stable main" |\
sudo tee -a /etc/apt/sources.list.d/grafana.list
sudo apt-get update
sudo apt-get install grafana
```
下文介绍中,都以 Grafana v11.0.0 版本为例,其他版本功能可能有差异,请参考 [Grafana 官网](https://grafana.com/docs/grafana/latest/)。
</TabItem>
<TabItem value="redhat" label="基于 CentOS / RHEL 系统">
:::
您可以从官方 YUM 镜像仓库安装。
## 安装 TDengine 数据源插件
```bash
sudo tee /etc/yum.repos.d/grafana.repo << EOF
[grafana]
name=grafana
baseurl=https://packages.grafana.com/oss/rpm
repo_gpgcheck=1
enabled=1
gpgcheck=1
gpgkey=https://packages.grafana.com/gpg.key
sslverify=1
sslcacert=/etc/pki/tls/certs/ca-bundle.crt
EOF
sudo yum install grafana
```
或者用 RPM 安装:
```bash
wget https://dl.grafana.com/oss/release/grafana-7.5.11-1.x86_64.rpm
sudo yum install grafana-7.5.11-1.x86_64.rpm
# or
sudo yum install \
https://dl.grafana.com/oss/release/grafana-7.5.11-1.x86_64.rpm
```
</TabItem>
</Tabs>
### 安装 TDengine 数据源插件
TDInsight 支持图形界面安装、手动安装和脚本安装三种安装方式,一般建议图形界面安装。对于 Grafana 8.5 以下版本可以使用手动安装和脚本安装方式。
<Tabs defaultValue="manual" groupId="deploy">
<TabItem value="manual" label="手动设置 TDinsight">
<TabItem value="gui" label="图形界面安装">
使用 Grafana 最新版本8.5+),您可以在 Grafana 中[浏览和管理插件](https://grafana.com/docs/grafana/next/administration/plugin-management/#plugin-catalog)。在 Grafana 管理界面中的 **Configurations > Plugins** 页面直接搜索 `TDengine` 并按照提示安装。
</TabItem>
<TabItem value="manual" label="手动安装">
从 GitHub 安装 TDengine 最新版数据源插件。
@ -108,9 +75,9 @@ allow_loading_unsigned_plugins = tdengine-datasource
</TabItem>
<TabItem value="auto" label="自动部署 TDinsight">
<TabItem value="auto" label="脚本安装">
我们提供了一个自动化安装脚本 [`TDinsight.sh`](https://github.com/taosdata/grafanaplugin/releases/latest/download/TDinsight.sh) 脚本以便用户快速进行安装配置。
我们提供了一个自动化安装脚本 [TDinsight.sh](https://github.com/taosdata/grafanaplugin/releases/latest/download/TDinsight.sh) 脚本以便用户快速进行安装配置。
您可以通过 `wget` 或其他工具下载该脚本:
@ -122,9 +89,154 @@ chmod +x TDinsight.sh
这个脚本会自动下载最新的[Grafana TDengine 数据源插件](https://github.com/taosdata/grafanaplugin/releases/latest) 和 [TDinsight 仪表盘](https://github.com/taosdata/grafanaplugin/blob/master/dashboards/TDinsightV3.json) ,将命令行选项中的可配置参数转为 [Grafana Provisioning](https://grafana.com/docs/grafana/latest/administration/provisioning/) 配置文件,以进行自动化部署及更新等操作。
假设您在同一台主机上使用 TDengine 和 Grafana 的默认服务。运行 `./TDinsight.sh` 并打开 Grafana 浏览器窗口就可以看到 TDinsight 仪表盘了。
1. 假设您在同一台主机上使用 TDengine 和 Grafana 服务。 运行 `./TDinsight.sh` 并打开 Grafana 页面就可以看到 TDinsight 仪表盘了。
2. 假设您在主机 `tdengine` 上启动 TDengine 数据库taosAdapter 的 HTTP 监听端口为 `6041`,用户为 `root1`,密码为 `pass5ord`。执行脚本:`./TDinsight.sh -a http://tdengine:6041 -u root1 -p pass5ord`
下面是 TDinsight.sh 的用法说明:
详细的使用方法请参考 [TDinsight.sh 详细说明](./#附录)
</TabItem>
</Tabs>
## 添加 TDengine 数据源
安装完毕后, 点击 “Connections” -> “Data sources“ 然后选择 ”tdengine-datasource“输入 TDengine 相关配置:
- Host TDengine 集群中提供 REST 服务的 IP 地址与端口号,默认 `http://localhost:6041`
- UserTDengine 用户名。
- PasswordTDengine 用户密码。
点击 `Save & Test` 进行测试,成功会提示:`TDengine Data source is working`。
## 导入 TDengine V3 仪表盘
在配置 TDengine 数据源界面,点击 “Dashboards” tab再点击 ”import” 导入 ”TDengine for 3.x” 仪表盘。
导入成功后可以进入这个 dashboard在左上角 ”Log from“ 选项中选择 taosKeeper 中设置的记录监控指标的数据库就可以看到监控结果。
## TDengine V3 仪表盘详情
TDinsight 仪表盘旨在提供 TDengine 相关资源的使用情况和状态,比如 dnodes、 mnodes、 vnodes 和数据库等。
主要分为集群状态、DNodes 概述、MNode 概述、请求、数据库、DNode 资源使用情况和 taosAdapter 监控信息。下面我们分别详细介绍。
### 集群状态
这部分指标包括集群当前信息和状态。
![TDengine Database TDinsight mnodes overview](./assets/TDinsight-1-cluster-status.webp)
指标详情(从上到下,从左到右):
- **First EP**:当前 TDengine 集群中的`firstEp`设置。
- **Version**TDengine 服务器版本master mnode
- **Expire Time** - 企业版过期时间。
- **Used Measuring Points** - 企业版已使用的测点数。
- **Databases** - 数据库个数。
- **Connections** - 当前连接个数。
- **DNodes/MNodes/VGroups/VNodes**:每种资源的总数和存活数。
- **DNodes/MNodes/VGroups/VNodes Alive Percent**:每种资源的存活数/总数的比例启用告警规则并在资源存活率1 分钟内平均健康资源比例)不足 100%时触发。
- **Measuring Points Used**:启用告警规则的测点数用量(社区版无数据,默认情况下是健康的)。
### DNodes 概述
这部分指标包括集群 dnode 基本信息。
![TDengine Database TDinsight mnodes overview](./assets/TDinsight-2-dnodes.webp)
指标详情:
- **DNodes Status**`show dnodes` 的简单表格视图。
- **DNodes Number**DNodes 数量变化。
### MNode 概述
这部分指标包括集群 mnode 基本信息。
![TDengine Database TDinsight mnodes overview](./assets/TDinsight-3-mnodes.webp)
指标详情:
1. **MNodes Status**`show mnodes` 的简单表格视图。
2. **MNodes Number**:类似于`DNodes Number`MNodes 数量变化。
### 请求统计
这部分指标包括集群执行 sql 的统计指标。
![TDengine Database TDinsight requests](./assets/TDinsight-4-requests.webp)
指标详情:
1. **Select Request**select 请求数。
2. **Delete Request**delete 请求数。
3. **Insert Request**insert 请求数。
4. **Inserted Rows**:实际插入行数。
5. **Slow Sql**:慢查询数,可以在顶部分时长段过滤。
### 表统计
这部分指标包括集群中表的统计指标。
![TDengine Database TDinsight database](./assets/TDinsight-5-database.webp)
指标详情:
1. **STables**:超级表数量。
2. **Total Tables**:所有表数量。
3. **Tables**:所有普通表数量随时间变化图。
4. **Tables Number Foreach VGroups**:每个 VGroups 包含的表数量。
### DNode 资源使用情况
这部分指标包括集群所有数据节点资源使用情况展示,每个数据节点为一个 Row 进行展示。。
![TDengine Database TDinsight dnode-usage](./assets/TDinsight-6-dnode-usage.webp)
指标详情(从上到下,从左到右):
1. **Uptime**:从创建 dnode 开始经过的时间。
2. **Has MNodes?**:当前 dnode 是否为 mnode。
3. **CPU Cores**CPU 核数。
4. **VNodes Number**:当前 dnode 的 VNodes 数量。
5. **VNodes Masters**:处于 master 角色的 vnode 数量。
6. **Current CPU Usage of taosd**taosd 进程的 CPU 使用率。
7. **Current Memory Usage of taosd**taosd 进程的内存使用情况。
8. **Max Disk Used**taosd 所有数据目录对应的最大磁盘使用率。
9. **CPU Usage**:进程和系统 CPU 使用率。
10. **RAM Usage**RAM 使用指标时间序列视图。
11. **Disk Used**:多级存储下每个级别使用的磁盘(默认为 level0 级)。
12. **Disk IO**:磁盘 IO 速率。
13. **Net IO**:网络 IO除本机网络之外的总合网络 IO 速率。
### taosAdapter 监控
这部分指标包括 taosAdapter rest 和 websocket 请求统计详情。
![TDengine Database TDinsight monitor taosadapter](./assets/TDinsight-8-taosadapter.webp)
指标详情:
1. **Total**:总请求数
2. **Successful**:总成功数
3. **Failed**:总失败数
4. **Queries**:总查询数
5. **Writes**:总写入数
6. **Other**:总其他请求数
还有上述分类的细分维度折线图。
## 升级
下面三种方式都可以进行升级:
- 用图形界面,若有新版本,可以在 ”TDengine Datasource“ 插件页面点击 update 升级。
- 按照手动安装步骤自行安装新的 Grafana 插件和 Dashboard。
- 通过重新运行 `TDinsight.sh` 脚本升级到最新的 Grafana 插件和 TDinsight Dashboard。
## 卸载
针对不同的安装方式,卸载时:
- 用图形界面,在 ”TDengine Datasource“ 插件页面点击 ”Uninstall“ 卸载。
- 通过 `TDinsight.sh` 脚本安装的 TDinsight可以使用命令行 `TDinsight.sh -R` 清理相关资源。
- 手动安装的 TDinsight要完全卸载需要清理以下内容
1. Grafana 中的 TDinsight Dashboard。
2. Grafana 中的 Data Source 数据源。
3. 从插件安装目录删除 `tdengine-datasource` 插件。
## 附录
### TDinsight.sh 详细说明
下面是 TDinsight.sh 的用法详细说明:
```text
Usage:
@ -189,211 +301,3 @@ sudo ./TDengine.sh -n TDengine-Env1 -a http://another:6041 -u root -p taosdata -
请注意,配置数据源、通知 Channel 和仪表盘在前端是不可更改的。您应该再次通过此脚本更新配置或手动更改 `/etc/grafana/provisioning` 目录(这是 Grafana 的默认目录,根据需要使用`-P`选项更改)中的配置文件。
特别地,当您使用 Grafana Cloud 或其他组织时,`-O` 可用于设置组织 ID。 `-G` 可指定 Grafana 插件安装目录。 `-e` 参数将仪表盘设置为可编辑。
</TabItem>
</Tabs>
### 启动 Grafana 服务
```bash
sudo systemctl start grafana-server
sudo systemctl enable grafana-server
```
### 登录到 Grafana
在 Web 浏览器中打开默认的 Grafana 网址:`http://localhost:3000`。
默认用户名/密码都是 `admin`。Grafana 会要求在首次登录后更改密码。
### 添加 TDengine 数据源
指向 **Configurations** -> **Data Sources** 菜单,然后点击 **Add data source** 按钮。
![TDengine Database TDinsight 添加数据源按钮](./assets/howto-add-datasource-button.webp)
搜索并选择**TDengine**。
![TDengine Database TDinsight 添加数据源](./assets/howto-add-datasource-tdengine.webp)
配置 TDengine 数据源。
![TDengine Database TDinsight 数据源配置](./assets/howto-add-datasource.webp)
保存并测试,正常情况下会报告 'TDengine Data source is working'。
![TDengine Database TDinsight 数据源测试](./assets/howto-add-datasource-test.webp)
### 导入仪表盘
在配置 TDengine 数据源界面,点击 **Dashboards** tab。
![TDengine Database TDinsight 导入仪表盘和配置](./assets/import_dashboard.webp)
选择 `TDengine for 3.x`,并点击 `import`。
导入完成后,在搜索界面已经出现了 **TDinsight for 3.x** dashboard。
![TDengine Database TDinsight 查看导入结果](./assets/import_dashboard_view.webp)
进入 TDinsight for 3.x dashboard 后,选择 taosKeeper 中设置的记录监控指标的数据库。
![TDengine Database TDinsight 选择数据库](./assets/select_dashboard_db.webp)
然后可以看到监控结果。
## TDinsight 仪表盘详细信息
TDinsight 仪表盘旨在提供 TDengine 相关资源的使用情况和状态,比如 dnodes、 mnodes、 vnodes 和数据库等。
指标详情如下:
### 集群状态
![TDengine Database TDinsight mnodes overview](./assets/TDinsight-1-cluster-status.webp)
这部分包括集群当前信息和状态,告警信息也在此处(从左到右,从上到下)。
- **First EP**:当前 TDengine 集群中的`firstEp`设置。
- **Version**TDengine 服务器版本master mnode
- **Master Uptime**: 当前 Master MNode 被选举为 Master 后经过的时间。
- **Expire Time** - 企业版过期时间。
- **Used Measuring Points** - 企业版已使用的测点数。
- **Databases** - 数据库个数。
- **Connections** - 当前连接个数。
- **DNodes/MNodes/VGroups/VNodes**:每种资源的总数和存活数。
- **DNodes/MNodes/VGroups/VNodes Alive Percent**:每种资源的存活数/总数的比例启用告警规则并在资源存活率1 分钟内平均健康资源比例)不足 100%时触发。
- **Measuring Points Used**:启用告警规则的测点数用量(社区版无数据,默认情况下是健康的)。
- **Grants Expire Time**:启用告警规则的企业版过期时间(社区版无数据,默认情况是健康的)。
- **Error Rate**:启用警报的集群总合错误率(每秒平均错误数)。
### DNodes 状态
![TDengine Database TDinsight mnodes overview](./assets/TDinsight-2-dnodes.webp)
- **DNodes Status**`show dnodes` 的简单表格视图。
- **DNodes Lifetime**:从创建 dnode 开始经过的时间。
- **DNodes Number**DNodes 数量变化。
### MNode 概述
![TDengine Database TDinsight mnodes overview](./assets/TDinsight-3-mnodes.webp)
1. **MNodes Status**`show mnodes` 的简单表格视图。
2. **MNodes Number**:类似于`DNodes Number`MNodes 数量变化。
### 请求
![TDengine Database TDinsight requests](./assets/TDinsight-4-requests.webp)
1. **Requests Rate(Inserts per Second)**:平均每秒插入次数。
2. **Requests (Selects)**查询请求数及变化率count of second
### 数据库
![TDengine Database TDinsight database](./assets/TDinsight-5-database.webp)
数据库使用情况,对变量 `$database` 的每个值即每个数据库进行重复多行展示。
1. **STables**:超级表数量。
2. **Total Tables**:所有表数量。
3. **Tables**:所有普通表数量随时间变化图。
4. **Tables Number Foreach VGroups**:每个 VGroups 包含的表数量。
### DNode 资源使用情况
![TDengine Database TDinsight dnode-usage](./assets/TDinsight-6-dnode-usage.webp)
数据节点资源使用情况展示,对变量 `$fqdn` 即每个数据节点进行重复多行展示。包括:
1. **Uptime**:从创建 dnode 开始经过的时间。
2. **Has MNodes?**:当前 dnode 是否为 mnode。
3. **CPU Cores**CPU 核数。
4. **VNodes Number**:当前 dnode 的 VNodes 数量。
5. **VNodes Masters**:处于 master 角色的 vnode 数量。
6. **Current CPU Usage of taosd**taosd 进程的 CPU 使用率。
7. **Current Memory Usage of taosd**taosd 进程的内存使用情况。
8. **Disk Used**taosd 数据目录的总磁盘使用百分比。
9. **CPU Usage**:进程和系统 CPU 使用率。
10. **RAM Usage**RAM 使用指标时间序列视图。
11. **Disk Used**:多级存储下每个级别使用的磁盘(默认为 level0 级)。
12. **Disk Increasing Rate per Minute**:每分钟磁盘用量增加或减少的百分比。
13. **Disk IO**:磁盘 IO 速率。
14. **Net IO**:网络 IO除本机网络之外的总合网络 IO 速率。
### 登录历史
![TDengine Database TDinsight 登录历史](./assets/TDinsight-7-login-history.webp)
目前只报告每分钟登录次数。
### 监控 taosAdapter
![TDengine Database TDinsight monitor taosadapter](./assets/TDinsight-8-taosadapter.webp)
支持监控 taosAdapter 请求统计和状态详情。包括:
1. **Http Request Total**: 请求总数。
2. **Http Request Fail**: 请求总数。
3. **CPU Used**: taosAdapter CPU 使用情况。
4. **Memory Used**: taosAdapter 内存使用情况。
5. **Http Request Inflight**: 即时处理请求数。
6. **Http Status Code**: taosAdapter http 状态码。
## 升级
通过 `TDinsight.sh` 脚本安装的 TDinsight可以通过重新运行该脚本就可以升级到最新的 Grafana 插件和 TDinsight Dashboard。
手动安装的情况下,可按照上述步骤自行安装新的 Grafana 插件和 Dashboard。
## 卸载
通过 `TDinsight.sh` 脚本安装的 TDinsight可以使用命令行 `TDinsight.sh -R` 清理相关资源。
手动安装时,要完全卸载 TDinsight需要清理以下内容
1. Grafana 中的 TDinsight Dashboard。
2. Grafana 中的 Data Source 数据源。
3. 从插件安装目录删除 `tdengine-datasource` 插件。
## 整合的 Docker 示例
```bash
git clone --depth 1 https://github.com/taosdata/grafanaplugin.git
cd grafanaplugin
```
根据需要在 `docker-compose.yml` 文件中修改:
```yaml
version: '3.7'
services:
grafana:
image: grafana/grafana:7.5.10
volumes:
- ./dist:/var/lib/grafana/plugins/tdengine-datasource
- ./grafana/grafana.ini:/etc/grafana/grafana.ini
- ./grafana/provisioning/:/etc/grafana/provisioning/
- grafana-data:/var/lib/grafana
environment:
TDENGINE_API: ${TDENGINE_API}
TDENGINE_USER: ${TDENGINE_USER}
TDENGINE_PASS: ${TDENGINE_PASS}
ports:
- 3000:3000
volumes:
grafana-data:
```
替换`docker-compose.yml`中的环境变量或保存环境变量到`.env`文件,然后用`docker-compose up`启动 Grafana。`docker-compose` 工具的具体用法参见 [Docker Compose Reference](https://docs.docker.com/compose/)
```bash
docker-compose up -d
```
TDinsight 已经通过 Provisioning 部署完毕,请到 http://localhost:3000/d/tdinsight/ 查看仪表盘。
[grafana]: https://grafana.com
[tdengine]: https://www.taosdata.com

View File

@ -1,7 +1,7 @@
---
sidebar_label: 集群管理
title: 集群管理
description: 管理集群的 SQL 命令的详细解析
sidebar_label: 节点管理
title: 节点管理
description: 管理集群节点的 SQL 命令的详细解析
---
组成 TDengine 集群的物理实体是 dnode (data node 的缩写),它是一个运行在操作系统之上的进程。在 dnode 中可以建立负责时序数据存储的 vnode (virtual node),在多节点集群环境下当某个数据库的 replica 为 3 时,该数据库中的每个 vgroup 由 3 个 vnode 组成;当数据库的 replica 为 1 时,该数据库中的每个 vgroup 由 1 个 vnode 组成。如果要想配置某个数据库为多副本,则集群中的 dnode 数量至少为 3。在 dnode 还可以创建 mnode (management node),单个集群中最多可以创建三个 mnode。在 TDengine 3.0.0.0 中为了支持存算分离,引入了一种新的逻辑节点 qnode (query node)qnode 和 vnode 既可以共存在一个 dnode 中,也可以完全分离在不同的 dnode 上。

View File

@ -35,6 +35,7 @@ Websocket 连接支持所有能运行 Rust 的平台。
| Rust 连接器版本 | TDengine 版本 | 主要功能 |
| :----------------: | :--------------: | :--------------------------------------------------: |
| v0.12.3 | 3.3.0.0 or later | 优化了 Websocket 查询和插入性能,支持了 VARBINARY 和 GEOMETRY 类型 |
| v0.12.0 | 3.2.3.0 or later | WS 支持压缩。 |
| v0.11.0 | 3.2.0.0 | TMQ 功能优化。 |
| v0.10.0 | 3.1.0.0 | WS endpoint 变更。 |
@ -44,7 +45,6 @@ Websocket 连接支持所有能运行 Rust 的平台。
| v0.7.6 | 3.0.3.0 | 支持在请求中使用 req_id。 |
| v0.6.0 | 3.0.0.0 | 基础功能。 |
Rust 连接器仍然在快速开发中1.0 之前无法保证其向后兼容。建议使用 3.0 版本以上的 TDengine以避免已知问题。
## 处理错误

View File

@ -41,12 +41,16 @@ Python 连接器的源码托管在 [GitHub](https://github.com/taosdata/taos-con
|Python Connector 版本|主要变化|
|:-------------------:|:----:|
|2.7.15|新增 VARBINARY 和 GEOMETRY 类型支持|
|2.7.14|修复已知问题|
|2.7.13|新增 tmq 同步提交 offset 接口|
|2.7.12|1. 新增 varbinary 类型支持STMT暂不支持 varbinary <br/> 2. query 性能提升(感谢贡献者[hadrianl](https://github.com/taosdata/taos-connector-python/pull/209)|
|2.7.9|数据订阅支持获取消费进度和重置消费进度|
|2.7.8|新增 `execute_many`|
|Python Websocket Connector 版本|主要变化|
|:----------------------------:|:-----:|
|0.3.2|优化 Websocket sql 查询和插入性能,修改 readme 和 文档,修复已知问题|
|0.2.9|已知问题修复|
|0.2.5|1. 数据订阅支持获取消费进度和重置消费进度 <br/> 2. 支持 schemaless <br/> 3. 支持 STMT|
|0.2.4|数据订阅新增取消订阅方法|

View File

@ -28,14 +28,14 @@ TDengine 提供了丰富的应用程序开发接口,为了便于用户快速
TDengine 版本更新往往会增加新的功能特性,列表中的连接器版本为连接器最佳适配版本。
| **TDengine 版本** | **Java** | **Python** | **Go** | **C#** | **Node.js** | **Rust** |
| ---------------------- | ------------- | -------------------------------------- | ------------ | ------------- | --------------- | -------- |
| **3.3.0.0 及以上** | 3.3.2.0及以上 | taospy 2.7.15及以上taos-ws-py 及以上 | 3.5.5及以上 | 3.1.3及以上 | 3.1.0及以上 | 当前版本 |
| **3.0.0.0 及以上** | 3.0.2以上 | 当前版本 | 3.0 分支 | 3.0.0 | 3.1.0 | 当前版本 |
| **2.4.0.14 及以上** | 2.0.38 | 当前版本 | develop 分支 | 1.0.2 - 1.0.6 | 2.0.10 - 2.0.12 | 当前版本 |
| **2.4.0.4 - 2.4.0.13** | 2.0.37 | 当前版本 | develop 分支 | 1.0.2 - 1.0.6 | 2.0.10 - 2.0.12 | 当前版本 |
| **2.2.x.x ** | 2.0.36 | 当前版本 | master 分支 | n/a | 2.0.7 - 2.0.9 | 当前版本 |
| **2.0.x.x ** | 2.0.34 | 当前版本 | master 分支 | n/a | 2.0.1 - 2.0.6 | 当前版本 |
| **TDengine 版本** | **Java** | **Python** | **Go** | **C#** | **Node.js** | **Rust** |
| ---------------------- | ------------- | ------------------------------------------- | ------------ | ------------- | --------------- | -------- |
| **3.3.0.0 及以上** | 3.3.2.0及以上 | taospy 2.7.15及以上taos-ws-py 0.3.2及以上 | 3.5.5及以上 | 3.1.3及以上 | 3.1.0及以上 | 当前版本 |
| **3.0.0.0 及以上** | 3.0.2以上 | 当前版本 | 3.0 分支 | 3.0.0 | 3.1.0 | 当前版本 |
| **2.4.0.14 及以上** | 2.0.38 | 当前版本 | develop 分支 | 1.0.2 - 1.0.6 | 2.0.10 - 2.0.12 | 当前版本 |
| **2.4.0.4 - 2.4.0.13** | 2.0.37 | 当前版本 | develop 分支 | 1.0.2 - 1.0.6 | 2.0.10 - 2.0.12 | 当前版本 |
| **2.2.x.x ** | 2.0.36 | 当前版本 | master 分支 | n/a | 2.0.7 - 2.0.9 | 当前版本 |
| **2.0.x.x ** | 2.0.34 | 当前版本 | master 分支 | n/a | 2.0.1 - 2.0.6 | 当前版本 |
## 功能特性

View File

@ -178,7 +178,7 @@ TDengine 集群可以容纳单个、多个甚至几千个数据节点。应用
TDengine 存储的数据包括采集的时序数据以及库、表相关的元数据、标签数据等,这些数据具体分为三部分:
- 时序数据TDengine 的核心存储对象,存放于 vnode 里,由 data、head 和 last 三个文件组成,数据量大,查询量取决于应用场景。许乱序写入,但暂时不支持删除操作,并且仅在 update 参数设置为 1 时允许更新操作。通过采用一个采集点一张表的模型,一个时间段的数据是连续存储,对单张表的写入是简单的追加操作,一次读,可以读到多条记录,这样保证对单个采集点的插入和查询操作,性能达到最优。
- 时序数据TDengine 的核心存储对象,存放于 vnode 里,由 data、head 和 last 三个文件组成,数据量大,查询量取决于应用场景。许乱序写入,但暂时不支持删除操作,并且仅在 update 参数设置为 1 时允许更新操作。通过采用一个采集点一张表的模型,一个时间段的数据是连续存储,对单张表的写入是简单的追加操作,一次读,可以读到多条记录,这样保证对单个采集点的插入和查询操作,性能达到最优。
- 数据表元数据:包含标签信息和 Table Schema 信息,存放于 vnode 里的 meta 文件,支持增删改查四个标准操作。数据量很大,有 N 张表,就有 N 条记录,因此采用 LRU 存储支持标签数据的索引。TDengine 支持多核多线程并发查询。只要计算内存足够,元数据全内存存储,千万级别规模的标签数据过滤结果能毫秒级返回。在内存资源不足的情况下,仍然可以支持数千万张表的快速查询。
- 数据库元数据:存放于 mnode 里包含系统节点、用户、DB、STable Schema 等信息,支持增删改查四个标准操作。这部分数据的量不大,可以全内存保存,而且由于客户端有缓存,查询量也不大。因此目前的设计虽是集中式存储管理,但不会构成性能瓶颈。

View File

Before

Width:  |  Height:  |  Size: 319 KiB

After

Width:  |  Height:  |  Size: 319 KiB

View File

Before

Width:  |  Height:  |  Size: 179 KiB

After

Width:  |  Height:  |  Size: 179 KiB

View File

Before

Width:  |  Height:  |  Size: 117 KiB

After

Width:  |  Height:  |  Size: 117 KiB

View File

Before

Width:  |  Height:  |  Size: 133 KiB

After

Width:  |  Height:  |  Size: 133 KiB

View File

Before

Width:  |  Height:  |  Size: 476 KiB

After

Width:  |  Height:  |  Size: 476 KiB

View File

Before

Width:  |  Height:  |  Size: 105 KiB

After

Width:  |  Height:  |  Size: 105 KiB

View File

Before

Width:  |  Height:  |  Size: 359 KiB

After

Width:  |  Height:  |  Size: 359 KiB

View File

Before

Width:  |  Height:  |  Size: 118 KiB

After

Width:  |  Height:  |  Size: 118 KiB

View File

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 52 KiB

View File

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

View File

Before

Width:  |  Height:  |  Size: 96 KiB

After

Width:  |  Height:  |  Size: 96 KiB

View File

Before

Width:  |  Height:  |  Size: 133 KiB

After

Width:  |  Height:  |  Size: 133 KiB

View File

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

Before

Width:  |  Height:  |  Size: 163 KiB

After

Width:  |  Height:  |  Size: 163 KiB

View File

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

View File

Before

Width:  |  Height:  |  Size: 192 KiB

After

Width:  |  Height:  |  Size: 192 KiB

View File

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 46 KiB

View File

Before

Width:  |  Height:  |  Size: 232 KiB

After

Width:  |  Height:  |  Size: 232 KiB

View File

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 75 KiB

View File

Before

Width:  |  Height:  |  Size: 72 KiB

After

Width:  |  Height:  |  Size: 72 KiB

View File

Before

Width:  |  Height:  |  Size: 231 KiB

After

Width:  |  Height:  |  Size: 231 KiB

View File

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 40 KiB

View File

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 61 KiB

View File

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 56 KiB

View File

Before

Width:  |  Height:  |  Size: 215 KiB

After

Width:  |  Height:  |  Size: 215 KiB

View File

Before

Width:  |  Height:  |  Size: 194 KiB

After

Width:  |  Height:  |  Size: 194 KiB

View File

Before

Width:  |  Height:  |  Size: 106 KiB

After

Width:  |  Height:  |  Size: 106 KiB

View File

Before

Width:  |  Height:  |  Size: 155 KiB

After

Width:  |  Height:  |  Size: 155 KiB

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View File

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

View File

@ -25,9 +25,9 @@ extern "C" {
#include "tarray.h"
#include "thash.h"
#include "tlog.h"
#include "tsimplehash.h"
#include "tmsg.h"
#include "tmsgcb.h"
#include "tsimplehash.h"
typedef enum {
JOB_TASK_STATUS_NULL = 0,
@ -69,16 +69,16 @@ typedef enum {
#define QUERY_MSG_MASK_SHOW_REWRITE() (1 << 0)
#define QUERY_MSG_MASK_AUDIT() (1 << 1)
#define QUERY_MSG_MASK_VIEW() (1 << 2)
#define TEST_SHOW_REWRITE_MASK(m) (((m) & QUERY_MSG_MASK_SHOW_REWRITE()) != 0)
#define TEST_AUDIT_MASK(m) (((m) & QUERY_MSG_MASK_AUDIT()) != 0)
#define TEST_VIEW_MASK(m) (((m) & QUERY_MSG_MASK_VIEW()) != 0)
#define TEST_SHOW_REWRITE_MASK(m) (((m)&QUERY_MSG_MASK_SHOW_REWRITE()) != 0)
#define TEST_AUDIT_MASK(m) (((m)&QUERY_MSG_MASK_AUDIT()) != 0)
#define TEST_VIEW_MASK(m) (((m)&QUERY_MSG_MASK_VIEW()) != 0)
typedef struct STableComInfo {
uint8_t numOfTags; // the number of tags in schema
uint8_t precision; // the number of precision
col_id_t numOfColumns; // the number of columns
int16_t numOfPKs;
int32_t rowSize; // row size of the schema
int32_t rowSize; // row size of the schema
} STableComInfo;
typedef struct SIndexMeta {
@ -119,8 +119,9 @@ typedef struct STableMeta {
int32_t sversion;
int32_t tversion;
STableComInfo tableInfo;
SSchemaExt* schemaExt; // There is no additional memory allocation, and the pointer is fixed to the next address of the schema content.
SSchema schema[];
SSchemaExt* schemaExt; // There is no additional memory allocation, and the pointer is fixed to the next address of
// the schema content.
SSchema schema[];
} STableMeta;
#pragma pack(pop)
@ -196,9 +197,9 @@ typedef struct SBoundColInfo {
} SBoundColInfo;
typedef struct STableColsData {
char tbName[TSDB_TABLE_NAME_LEN];
SArray* aCol;
bool getFromHash;
char tbName[TSDB_TABLE_NAME_LEN];
SArray* aCol;
bool getFromHash;
} STableColsData;
typedef struct STableVgUid {
@ -207,15 +208,14 @@ typedef struct STableVgUid {
} STableVgUid;
typedef struct STableBufInfo {
void* pCurBuff;
SArray* pBufList;
int64_t buffUnit;
int64_t buffSize;
int64_t buffIdx;
int64_t buffOffset;
void* pCurBuff;
SArray* pBufList;
int64_t buffUnit;
int64_t buffSize;
int64_t buffIdx;
int64_t buffOffset;
} STableBufInfo;
typedef struct STableDataCxt {
STableMeta* pMeta;
STSchema* pSchema;
@ -237,23 +237,22 @@ typedef struct SStbInterlaceInfo {
void* pRequest;
uint64_t requestId;
int64_t requestSelf;
bool tbFromHash;
bool tbFromHash;
SHashObj* pVgroupHash;
SArray* pVgroupList;
SSHashObj* pTableHash;
int64_t tbRemainNum;
STableBufInfo tbBuf;
char firstName[TSDB_TABLE_NAME_LEN];
STSchema *pTSchema;
STableDataCxt *pDataCtx;
void *boundTags;
STSchema* pTSchema;
STableDataCxt* pDataCtx;
void* boundTags;
bool tableColsReady;
SArray *pTableCols;
int32_t pTableColsIdx;
bool tableColsReady;
SArray* pTableCols;
int32_t pTableColsIdx;
} SStbInterlaceInfo;
typedef int32_t (*__async_send_cb_fn_t)(void* param, SDataBuf* pMsg, int32_t code);
typedef int32_t (*__async_exec_fn_t)(void* param);
@ -308,6 +307,8 @@ void destroyAhandle(void* ahandle);
int32_t asyncSendMsgToServerExt(void* pTransporter, SEpSet* epSet, int64_t* pTransporterId, SMsgSendInfo* pInfo,
bool persistHandle, void* ctx);
int32_t asyncFreeConnById(void* pTransporter, int64_t pid);
;
/**
* Asynchronously send message to server, after the response received, the callback will be incured.
*
@ -325,7 +326,7 @@ void initQueryModuleMsgHandle();
const SSchema* tGetTbnameColumnSchema();
bool tIsValidSchema(struct SSchema* pSchema, int32_t numOfCols, int32_t numOfTags);
int32_t getAsofJoinReverseOp(EOperatorType op);
int32_t getAsofJoinReverseOp(EOperatorType op);
int32_t queryCreateCTableMetaFromMsg(STableMetaRsp* msg, SCTableMeta* pMeta);
int32_t queryCreateTableMetaFromMsg(STableMetaRsp* msg, bool isSuperTable, STableMeta** pMeta);
@ -384,7 +385,7 @@ extern int32_t (*queryProcessMsgRsp[TDMT_MAX])(void* output, char* msg, int32_t
#define NEED_CLIENT_RM_TBLMETA_REQ(_type) \
((_type) == TDMT_VND_CREATE_TABLE || (_type) == TDMT_MND_CREATE_STB || (_type) == TDMT_VND_DROP_TABLE || \
(_type) == TDMT_MND_DROP_STB || (_type) == TDMT_MND_CREATE_VIEW || (_type) == TDMT_MND_DROP_VIEW || \
(_type) == TDMT_MND_DROP_STB || (_type) == TDMT_MND_CREATE_VIEW || (_type) == TDMT_MND_DROP_VIEW || \
(_type) == TDMT_MND_CREATE_TSMA || (_type) == TDMT_MND_DROP_TSMA || (_type) == TDMT_MND_DROP_TB_WITH_TSMA)
#define NEED_SCHEDULER_REDIRECT_ERROR(_code) \

View File

@ -125,6 +125,7 @@ typedef struct SRpcInit {
int32_t timeToGetConn;
int8_t supportBatch; // 0: no batch, 1. batch
int32_t batchSize;
int8_t notWaitAvaliableConn; // 1: wait to get, 0: no wait
void *parent;
} SRpcInit;
@ -158,18 +159,21 @@ void *rpcReallocCont(void *ptr, int64_t contLen);
// Because taosd supports multi-process mode
// These functions should not be used on the server side
// Please use tmsg<xx> functions, which are defined in tmsgcb.h
int rpcSendRequest(void *thandle, const SEpSet *pEpSet, SRpcMsg *pMsg, int64_t *rid);
int rpcSendResponse(const SRpcMsg *pMsg);
int rpcRegisterBrokenLinkArg(SRpcMsg *msg);
int rpcReleaseHandle(void *handle, int8_t type); // just release conn to rpc instance, no close sock
int32_t rpcSendRequest(void *thandle, const SEpSet *pEpSet, SRpcMsg *pMsg, int64_t *rid);
int32_t rpcSendResponse(const SRpcMsg *pMsg);
int32_t rpcRegisterBrokenLinkArg(SRpcMsg *msg);
int32_t rpcReleaseHandle(void *handle, int8_t type); // just release conn to rpc instance, no close sock
// These functions will not be called in the child process
int rpcSendRequestWithCtx(void *thandle, const SEpSet *pEpSet, SRpcMsg *pMsg, int64_t *rid, SRpcCtx *ctx);
int rpcSendRecv(void *shandle, SEpSet *pEpSet, SRpcMsg *pReq, SRpcMsg *pRsp);
int rpcSendRecvWithTimeout(void *shandle, SEpSet *pEpSet, SRpcMsg *pMsg, SRpcMsg *pRsp, int8_t *epUpdated,
int32_t rpcSendRequestWithCtx(void *thandle, const SEpSet *pEpSet, SRpcMsg *pMsg, int64_t *rid, SRpcCtx *ctx);
int32_t rpcSendRecv(void *shandle, SEpSet *pEpSet, SRpcMsg *pReq, SRpcMsg *pRsp);
int32_t rpcSendRecvWithTimeout(void *shandle, SEpSet *pEpSet, SRpcMsg *pMsg, SRpcMsg *pRsp, int8_t *epUpdated,
int32_t timeoutMs);
int rpcSetDefaultAddr(void *thandle, const char *ip, const char *fqdn);
void *rpcAllocHandle();
int32_t rpcFreeConnById(void *shandle, int64_t connId);
int32_t rpcSetDefaultAddr(void *thandle, const char *ip, const char *fqdn);
int32_t rpcAllocHandle(int64_t *refId);
int32_t rpcSetIpWhite(void *thandl, void *arg);
int32_t rpcUtilSIpRangeToStr(SIpV4Range *pRange, char *buf);

View File

@ -387,6 +387,7 @@ int32_t dmInitClient(SDnode *pDnode) {
rpcInit.supportBatch = 1;
rpcInit.batchSize = 8 * 1024;
rpcInit.timeToGetConn = tsTimeToGetAvailableConn;
rpcInit.notWaitAvaliableConn = 1;
(void)taosVersionStrToInt(version, &(rpcInit.compatibilityVer));

View File

@ -1372,7 +1372,7 @@ static int32_t buildResult(SSDataBlock *pBlock, int32_t *numOfRows, int64_t cons
OffsetRows *tmp = taosArrayGet(offsetRows, i);
MND_TMQ_NULL_CHECK(tmp);
if (tmp->vgId != pVgEp->vgId) {
mError("mnd show subscriptions: do not find vgId:%d, %d in offsetRows", tmp->vgId, pVgEp->vgId);
mInfo("mnd show subscriptions: do not find vgId:%d, %d in offsetRows", tmp->vgId, pVgEp->vgId);
continue;
}
data = tmp;
@ -1396,7 +1396,7 @@ static int32_t buildResult(SSDataBlock *pBlock, int32_t *numOfRows, int64_t cons
pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
MND_TMQ_NULL_CHECK(pColInfo);
colDataSetNULL(pColInfo, *numOfRows);
mError("mnd show subscriptions: do not find vgId:%d in offsetRows", pVgEp->vgId);
mInfo("mnd show subscriptions: do not find vgId:%d in offsetRows", pVgEp->vgId);
}
(*numOfRows)++;
}

View File

@ -1440,6 +1440,11 @@ int32_t metaGetTableTags(void *pVnode, uint64_t suid, SArray *pUidTagInfo) {
STUidTagInfo info = {.uid = uid, .pTagVal = pCur->pVal};
info.pTagVal = taosMemoryMalloc(pCur->vLen);
if (!info.pTagVal) {
metaCloseCtbCursor(pCur);
taosHashCleanup(pSepecifiedUidMap);
return TSDB_CODE_OUT_OF_MEMORY;
}
memcpy(info.pTagVal, pCur->pVal, pCur->vLen);
if (taosArrayPush(pUidTagInfo, &info) == NULL) {
metaCloseCtbCursor(pCur);
@ -1462,6 +1467,11 @@ int32_t metaGetTableTags(void *pVnode, uint64_t suid, SArray *pUidTagInfo) {
STUidTagInfo *pTagInfo = taosArrayGet(pUidTagInfo, *index);
if (pTagInfo->pTagVal == NULL) {
pTagInfo->pTagVal = taosMemoryMalloc(pCur->vLen);
if (!pTagInfo->pTagVal) {
metaCloseCtbCursor(pCur);
taosHashCleanup(pSepecifiedUidMap);
return TSDB_CODE_OUT_OF_MEMORY;
}
memcpy(pTagInfo->pTagVal, pCur->pVal, pCur->vLen);
}
}

View File

@ -347,6 +347,7 @@ static int32_t extractDataAndRspForDbStbSubscribe(STQ* pTq, STqHandle* pHandle,
code = TAOS_GET_TERRNO(TSDB_CODE_OUT_OF_MEMORY);
goto END;
}
totalMetaRows++;
if ((taosArrayGetSize(btMetaRsp.batchMetaReq) >= tmqRowSize) || (taosGetTimestampMs() - st > 1000)) {
tqOffsetResetToLog(&btMetaRsp.rspOffset, fetchVer);
code = tqSendBatchMetaPollRsp(pHandle, pMsg, pRequest, &btMetaRsp, vgId);

View File

@ -202,6 +202,7 @@ typedef struct SExchangeInfo {
SLimitInfo limitInfo;
int64_t openedTs; // start exec time stamp, todo: move to SLoadRemoteDataInfo
char* pTaskId;
SArray* pFetchRpcHandles;
} SExchangeInfo;
typedef struct SScanInfo {

View File

@ -298,13 +298,13 @@ _end:
pTaskInfo->code = code;
T_LONG_JMP(pTaskInfo->env, code);
}
(*ppRes) = NULL;
(*ppRes) = NULL;
return code;
}
static SSDataBlock* loadRemoteData(SOperatorInfo* pOperator) {
SSDataBlock* pRes = NULL;
int32_t code = loadRemoteDataNext(pOperator, &pRes);
int32_t code = loadRemoteDataNext(pOperator, &pRes);
return pRes;
}
@ -346,6 +346,14 @@ static int32_t initExchangeOperator(SExchangePhysiNode* pExNode, SExchangeInfo*
qError("%s invalid number: %d of sources in exchange operator", id, (int32_t)numOfSources);
return TSDB_CODE_INVALID_PARA;
}
pInfo->pFetchRpcHandles = taosArrayInit(numOfSources, sizeof(int64_t));
if (!pInfo->pFetchRpcHandles) {
return terrno;
}
void* ret = taosArrayReserve(pInfo->pFetchRpcHandles, numOfSources);
if (!ret) {
return terrno;
}
pInfo->pSources = taosArrayInit(numOfSources, sizeof(SDownstreamSourceNode));
if (pInfo->pSources == NULL) {
@ -384,6 +392,7 @@ static int32_t initExchangeOperator(SExchangePhysiNode* pExNode, SExchangeInfo*
initLimitInfo(pExNode->node.pLimit, pExNode->node.pSlimit, &pInfo->limitInfo);
pInfo->self = taosAddRef(exchangeObjRefPool, pInfo);
return initDataSource(numOfSources, pInfo, id);
}
@ -391,7 +400,7 @@ int32_t createExchangeOperatorInfo(void* pTransporter, SExchangePhysiNode* pExNo
SOperatorInfo** pOptrInfo) {
QRY_OPTR_CHECK(pOptrInfo);
int32_t code = 0;
int32_t code = 0;
int32_t lino = 0;
SExchangeInfo* pInfo = taosMemoryCalloc(1, sizeof(SExchangeInfo));
SOperatorInfo* pOperator = taosMemoryCalloc(1, sizeof(SOperatorInfo));
@ -471,6 +480,14 @@ void freeSourceDataInfo(void* p) {
void doDestroyExchangeOperatorInfo(void* param) {
SExchangeInfo* pExInfo = (SExchangeInfo*)param;
for (int32_t i = 0; i < pExInfo->pFetchRpcHandles->size; ++i) {
int64_t* pRpcHandle = taosArrayGet(pExInfo->pFetchRpcHandles, i);
if (*pRpcHandle > 0) {
SDownstreamSourceNode* pSource = taosArrayGet(pExInfo->pSources, i);
(void)asyncFreeConnById(pExInfo->pTransporter, *pRpcHandle);
}
}
taosArrayDestroy(pExInfo->pFetchRpcHandles);
taosArrayDestroy(pExInfo->pSources);
taosArrayDestroyEx(pExInfo->pSourceDataInfo, freeSourceDataInfo);
@ -498,6 +515,8 @@ int32_t loadRemoteDataCallback(void* param, SDataBuf* pMsg, int32_t code) {
}
int32_t index = pWrapper->sourceIndex;
int64_t* pRpcHandle = taosArrayGet(pExchangeInfo->pFetchRpcHandles, index);
*pRpcHandle = -1;
SSourceDataInfo* pSourceDataInfo = taosArrayGet(pExchangeInfo->pSourceDataInfo, index);
if (!pSourceDataInfo) {
return terrno;
@ -671,6 +690,8 @@ int32_t doSendFetchDataRequest(SExchangeInfo* pExchangeInfo, SExecTaskInfo* pTas
int64_t transporterId = 0;
code = asyncSendMsgToServer(pExchangeInfo->pTransporter, &pSource->addr.epSet, &transporterId, pMsgSendInfo);
QUERY_CHECK_CODE(code, lino, _end);
int64_t* pRpcHandle = taosArrayGet(pExchangeInfo->pFetchRpcHandles, sourceIndex);
*pRpcHandle = transporterId;
}
_end:
@ -693,7 +714,7 @@ int32_t extractDataBlockFromFetchRsp(SSDataBlock* pRes, char* pData, SArray* pCo
int32_t lino = 0;
if (pColList == NULL) { // data from other sources
blockDataCleanup(pRes);
code = blockDecode(pRes, pData, (const char**) pNextStart);
code = blockDecode(pRes, pData, (const char**)pNextStart);
if (code) {
return code;
}

View File

@ -88,20 +88,26 @@ static void switchCtxOrder(SqlFunctionCtx* pCtx, int32_t numOfOutput) {
}
}
static bool overlapWithTimeWindow(SInterval* pInterval, SDataBlockInfo* pBlockInfo, int32_t order) {
static int32_t overlapWithTimeWindow(SInterval* pInterval, SDataBlockInfo* pBlockInfo, int32_t order, bool* overlap) {
int32_t code = TSDB_CODE_SUCCESS;
STimeWindow w = {0};
// 0 by default, which means it is not a interval operator of the upstream operator.
if (pInterval->interval == 0) {
return false;
*overlap = false;
return code;
}
if (order == TSDB_ORDER_ASC) {
w = getAlignQueryTimeWindow(pInterval, pBlockInfo->window.skey);
ASSERT(w.ekey >= pBlockInfo->window.skey);
if(w.ekey < pBlockInfo->window.skey) {
qError("w.ekey:%" PRId64 " < pBlockInfo->window.skey:%" PRId64, w.ekey, pBlockInfo->window.skey);
return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
}
if (w.ekey < pBlockInfo->window.ekey) {
return true;
*overlap = true;
return code;
}
while (1) {
@ -110,17 +116,25 @@ static bool overlapWithTimeWindow(SInterval* pInterval, SDataBlockInfo* pBlockIn
break;
}
ASSERT(w.ekey > pBlockInfo->window.ekey);
if(w.ekey <= pBlockInfo->window.ekey) {
qError("w.ekey:%" PRId64 " <= pBlockInfo->window.ekey:%" PRId64, w.ekey, pBlockInfo->window.ekey);
return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
}
if (TMAX(w.skey, pBlockInfo->window.skey) <= pBlockInfo->window.ekey) {
return true;
*overlap = true;
return code;
}
}
} else {
w = getAlignQueryTimeWindow(pInterval, pBlockInfo->window.ekey);
ASSERT(w.skey <= pBlockInfo->window.ekey);
if(w.skey > pBlockInfo->window.ekey) {
qError("w.skey:%" PRId64 " > pBlockInfo->window.skey:%" PRId64, w.skey, pBlockInfo->window.ekey);
return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
}
if (w.skey > pBlockInfo->window.skey) {
return true;
*overlap = true;
return code;
}
while (1) {
@ -129,14 +143,19 @@ static bool overlapWithTimeWindow(SInterval* pInterval, SDataBlockInfo* pBlockIn
break;
}
ASSERT(w.skey < pBlockInfo->window.skey);
if(w.skey >= pBlockInfo->window.skey){
qError("w.skey:%" PRId64 " >= pBlockInfo->window.skey:%" PRId64, w.skey, pBlockInfo->window.skey);
return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
}
if (pBlockInfo->window.skey <= TMIN(w.ekey, pBlockInfo->window.ekey)) {
return true;
*overlap = true;
return code;
}
}
}
return false;
*overlap = false;
return code;
}
// this function is for table scanner to extract temporary results of upstream aggregate results.
@ -319,9 +338,18 @@ static int32_t loadDataBlock(SOperatorInfo* pOperator, STableScanBase* pTableSca
bool loadSMA = false;
*status = pTableScanInfo->dataBlockLoadFlag;
if (pOperator->exprSupp.pFilterInfo != NULL ||
overlapWithTimeWindow(&pTableScanInfo->pdInfo.interval, &pBlock->info, pTableScanInfo->cond.order)) {
if (pOperator->exprSupp.pFilterInfo != NULL) {
(*status) = FUNC_DATA_REQUIRED_DATA_LOAD;
} else {
bool overlap = false;
int ret =
overlapWithTimeWindow(&pTableScanInfo->pdInfo.interval, &pBlock->info, pTableScanInfo->cond.order, &overlap);
if (ret != TSDB_CODE_SUCCESS) {
return ret;
}
if (overlap) {
(*status) = FUNC_DATA_REQUIRED_DATA_LOAD;
}
}
SDataBlockInfo* pBlockInfo = &pBlock->info;
@ -358,7 +386,10 @@ static int32_t loadDataBlock(SOperatorInfo* pOperator, STableScanBase* pTableSca
}
}
ASSERT(*status == FUNC_DATA_REQUIRED_DATA_LOAD);
if(*status != FUNC_DATA_REQUIRED_DATA_LOAD) {
qError("[loadDataBlock] invalid status:%d", *status);
return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
}
// try to filter data block according to sma info
if (pOperator->exprSupp.pFilterInfo != NULL && (!loadSMA)) {
@ -413,7 +444,10 @@ static int32_t loadDataBlock(SOperatorInfo* pOperator, STableScanBase* pTableSca
return code;
}
ASSERT(p == pBlock);
if(p != pBlock) {
qError("[loadDataBlock] p != pBlock");
return TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR;
}
doSetTagColumnData(pTableScanInfo, pBlock, pTaskInfo, pBlock->info.rows);
// restore the previous value

View File

@ -225,6 +225,7 @@ int32_t asyncSendMsgToServerExt(void* pTransporter, SEpSet* epSet, int64_t* pTra
.code = 0
};
TRACE_SET_ROOTID(&rpcMsg.info.traceId, pInfo->requestId);
int code = rpcSendRequestWithCtx(pTransporter, epSet, &rpcMsg, pTransporterId, rpcCtx);
if (code) {
destroySendMsgInfo(pInfo);
@ -235,6 +236,9 @@ int32_t asyncSendMsgToServerExt(void* pTransporter, SEpSet* epSet, int64_t* pTra
int32_t asyncSendMsgToServer(void* pTransporter, SEpSet* epSet, int64_t* pTransporterId, SMsgSendInfo* pInfo) {
return asyncSendMsgToServerExt(pTransporter, epSet, pTransporterId, pInfo, false, NULL);
}
int32_t asyncFreeConnById(void* pTransporter, int64_t pid) {
return rpcFreeConnById(pTransporter, pid);
}
char* jobTaskStatusStr(int32_t status) {
switch (status) {
@ -448,13 +452,13 @@ void parseTagDatatoJson(void* p, char** jsonStr) {
if (value == NULL) {
goto end;
}
if(!cJSON_AddItemToObject(json, tagJsonKey, value)){
if (!cJSON_AddItemToObject(json, tagJsonKey, value)) {
goto end;
}
} else if (type == TSDB_DATA_TYPE_NCHAR) {
cJSON* value = NULL;
if (pTagVal->nData > 0) {
char* tagJsonValue = taosMemoryCalloc(pTagVal->nData, 1);
char* tagJsonValue = taosMemoryCalloc(pTagVal->nData, 1);
if (tagJsonValue == NULL) {
goto end;
}
@ -479,7 +483,7 @@ void parseTagDatatoJson(void* p, char** jsonStr) {
goto end;
}
if(!cJSON_AddItemToObject(json, tagJsonKey, value)){
if (!cJSON_AddItemToObject(json, tagJsonKey, value)) {
goto end;
}
} else if (type == TSDB_DATA_TYPE_DOUBLE) {
@ -488,7 +492,7 @@ void parseTagDatatoJson(void* p, char** jsonStr) {
if (value == NULL) {
goto end;
}
if(!cJSON_AddItemToObject(json, tagJsonKey, value)){
if (!cJSON_AddItemToObject(json, tagJsonKey, value)) {
goto end;
}
} else if (type == TSDB_DATA_TYPE_BOOL) {
@ -497,7 +501,7 @@ void parseTagDatatoJson(void* p, char** jsonStr) {
if (value == NULL) {
goto end;
}
if(!cJSON_AddItemToObject(json, tagJsonKey, value)){
if (!cJSON_AddItemToObject(json, tagJsonKey, value)) {
goto end;
}
} else {

View File

@ -464,7 +464,7 @@ struct SFilterInfo {
(colInfo).type = RANGE_TYPE_UNIT; \
(colInfo).dataType = FILTER_UNIT_DATA_TYPE(u); \
if (taosArrayPush((SArray *)((colInfo).info), &u) == NULL) { \
FLT_ERR_RET(TSDB_CODE_OUT_OF_MEMORY); \
FLT_ERR_RET(terrno); \
} \
} while (0)
#define FILTER_PUSH_VAR_HASH(colInfo, ha) \
@ -481,6 +481,9 @@ struct SFilterInfo {
#define FILTER_COPY_IDX(dst, src, n) \
do { \
*(dst) = taosMemoryMalloc(sizeof(uint32_t) * n); \
if (NULL == *(dst)) { \
FLT_ERR_JRET(terrno); \
} \
(void)memcpy(*(dst), src, sizeof(uint32_t) * n); \
} while (0)

View File

@ -17,11 +17,11 @@
#include "command.h"
#include "query.h"
#include "schInt.h"
#include "tglobal.h"
#include "tmisce.h"
#include "tmsg.h"
#include "tref.h"
#include "trpc.h"
#include "tglobal.h"
#include "tmisce.h"
// clang-format off
int32_t schValidateRspMsgType(SSchJob *pJob, SSchTask *pTask, int32_t msgType) {
@ -975,11 +975,13 @@ int32_t schAsyncSendMsg(SSchJob *pJob, SSchTask *pTask, SSchTrans *trans, SQuery
SCH_ERR_JRET(schUpdateSendTargetInfo(pMsgSendInfo, addr, pTask));
if (isHb && persistHandle && trans->pHandle == 0) {
trans->pHandle = rpcAllocHandle();
if (NULL == trans->pHandle) {
SCH_TASK_ELOG("rpcAllocHandle failed, code:%x", terrno);
SCH_ERR_JRET(terrno);
int64_t refId = 0;
code = rpcAllocHandle(&refId);
if (code != 0) {
SCH_TASK_ELOG("rpcAllocHandle failed, code:%x", code);
SCH_ERR_JRET(code);
}
trans->pHandle = (void *)refId;
}
if (pJob && pTask) {
@ -1200,7 +1202,14 @@ int32_t schBuildAndSendMsg(SSchJob *pJob, SSchTask *pTask, SQueryNodeAddr *addr,
}
persistHandle = true;
SCH_SET_TASK_HANDLE(pTask, rpcAllocHandle());
int64_t refId = 0;
code = rpcAllocHandle(&refId);
if (code != 0) {
SCH_TASK_ELOG("rpcAllocHandle failed, code:%x", code);
SCH_ERR_JRET(code);
}
SCH_SET_TASK_HANDLE(pTask, (void *)refId);
break;
}
case TDMT_SCH_FETCH:

View File

@ -1144,6 +1144,8 @@ int32_t chkpMayDelObsolete(void* arg, int64_t chkpId, char* path) {
int64_t id = *(int64_t*)taosArrayGet(chkpDel, i);
char tbuf[256] = {0};
sprintf(tbuf, "%s%scheckpoint%" PRId64 "", path, TD_DIRSEP, id);
stInfo("backend remove obsolete checkpoint: %s", tbuf);
if (taosIsDir(tbuf)) {
taosRemoveDir(tbuf);
}
@ -2661,6 +2663,7 @@ void taskDbDestroy(void* pDb, bool flush) {
if (wrapper->removeAllFiles) {
char* err = NULL;
stInfo("drop task remove backend dat:%s", wrapper->path);
taosRemoveDir(wrapper->path);
}
taosMemoryFree(wrapper->path);

View File

@ -321,7 +321,7 @@ void streamFreeTaskState(SStreamTask* pTask, int8_t remove) {
stDebug("s-task:0x%x start to free task state", pTask->id.taskId);
streamStateClose(pTask->pState, remove);
taskDbSetClearFileFlag(pTask->pBackend);
if (remove)taskDbSetClearFileFlag(pTask->pBackend);
taskDbRemoveRef(pTask->pBackend);
pTask->pBackend = NULL;
pTask->pState = NULL;

View File

@ -224,7 +224,10 @@ int tdbTbcOpen(TTB *pTb, TBC **ppTbc, TXN *pTxn) {
return -1;
}
(void)tdbBtcOpen(&pTbc->btc, pTb->pBt, pTxn);
if (tdbBtcOpen(&pTbc->btc, pTb->pBt, pTxn)) {
taosMemoryFree(pTbc);
return -1;
}
*ppTbc = pTbc;
return 0;

View File

@ -148,7 +148,6 @@ typedef struct {
STransSyncMsg* pSyncMsg; // for syncchronous with timeout API
int64_t syncMsgRef;
SCvtAddr cvtAddr;
bool setMaxRetry;
int32_t retryMinInterval;
int32_t retryMaxInterval;
@ -207,7 +206,7 @@ typedef struct {
#pragma pack(pop)
typedef enum { Normal, Quit, Release, Register, Update } STransMsgType;
typedef enum { Normal, Quit, Release, Register, Update, FreeById } STransMsgType;
typedef enum { ConnNormal, ConnAcquire, ConnRelease, ConnBroken, ConnInPool } ConnStatus;
#define container_of(ptr, type, member) ((type*)((char*)(ptr)-offsetof(type, member)))
@ -304,10 +303,10 @@ int32_t transClearBuffer(SConnBuffer* buf);
int32_t transDestroyBuffer(SConnBuffer* buf);
int32_t transAllocBuffer(SConnBuffer* connBuf, uv_buf_t* uvBuf);
bool transReadComplete(SConnBuffer* connBuf);
int transResetBuffer(SConnBuffer* connBuf, int8_t resetBuf);
int transDumpFromBuffer(SConnBuffer* connBuf, char** buf, int8_t resetBuf);
int32_t transResetBuffer(SConnBuffer* connBuf, int8_t resetBuf);
int32_t transDumpFromBuffer(SConnBuffer* connBuf, char** buf, int8_t resetBuf);
int transSetConnOption(uv_tcp_t* stream, int keepalive);
int32_t transSetConnOption(uv_tcp_t* stream, int keepalive);
void transRefSrvHandle(void* handle);
void transUnrefSrvHandle(void* handle);
@ -315,21 +314,24 @@ void transUnrefSrvHandle(void* handle);
void transRefCliHandle(void* handle);
void transUnrefCliHandle(void* handle);
int transReleaseCliHandle(void* handle);
int transReleaseSrvHandle(void* handle);
int32_t transReleaseCliHandle(void* handle);
int32_t transReleaseSrvHandle(void* handle);
int transSendRequest(void* shandle, const SEpSet* pEpSet, STransMsg* pMsg, STransCtx* pCtx);
int transSendRecv(void* shandle, const SEpSet* pEpSet, STransMsg* pMsg, STransMsg* pRsp);
int transSendRecvWithTimeout(void* shandle, SEpSet* pEpSet, STransMsg* pMsg, STransMsg* pRsp, int8_t* epUpdated,
int32_t transSendRequest(void* shandle, const SEpSet* pEpSet, STransMsg* pMsg, STransCtx* pCtx);
int32_t transSendRecv(void* shandle, const SEpSet* pEpSet, STransMsg* pMsg, STransMsg* pRsp);
int32_t transSendRecvWithTimeout(void* shandle, SEpSet* pEpSet, STransMsg* pMsg, STransMsg* pRsp, int8_t* epUpdated,
int32_t timeoutMs);
int transSendResponse(const STransMsg* msg);
int transRegisterMsg(const STransMsg* msg);
int transSetDefaultAddr(void* shandle, const char* ip, const char* fqdn);
int32_t transSendRequestWithId(void* shandle, const SEpSet* pEpSet, STransMsg* pReq, int64_t* transpointId);
int32_t transFreeConnById(void* shandle, int64_t transpointId);
int32_t transSendResponse(const STransMsg* msg);
int32_t transRegisterMsg(const STransMsg* msg);
int32_t transSetDefaultAddr(void* shandle, const char* ip, const char* fqdn);
int32_t transSetIpWhiteList(void* shandle, void* arg, FilteFunc* func);
int transSockInfo2Str(struct sockaddr* sockname, char* dst);
int32_t transSockInfo2Str(struct sockaddr* sockname, char* dst);
int64_t transAllocHandle();
int32_t transAllocHandle(int64_t* refId);
void* transInitServer(uint32_t ip, uint32_t port, char* label, int numOfThreads, void* fp, void* shandle);
void* transInitClient(uint32_t ip, uint32_t port, char* label, int numOfThreads, void* fp, void* shandle);

View File

@ -58,6 +58,8 @@ typedef struct {
int32_t failFastThreshold;
int32_t failFastInterval;
int8_t notWaitAvaliableConn; // 1: no delay, 0: delay
void (*cfp)(void* parent, SRpcMsg*, SEpSet*);
bool (*retry)(int32_t code, tmsg_t msgType);
bool (*startTimer)(int32_t code, tmsg_t msgType);

View File

@ -102,6 +102,8 @@ void* rpcOpen(const SRpcInit* pInit) {
if (pRpc->timeToGetConn == 0) {
pRpc->timeToGetConn = 10 * 1000;
}
pRpc->notWaitAvaliableConn = pInit->notWaitAvaliableConn;
pRpc->tcphandle =
(*taosInitHandle[pRpc->connType])(ip, pInit->localPort, pRpc->label, pRpc->numOfThreads, NULL, pRpc);
@ -163,38 +165,48 @@ void* rpcReallocCont(void* ptr, int64_t contLen) {
return st + TRANS_MSG_OVERHEAD;
}
int rpcSendRequest(void* shandle, const SEpSet* pEpSet, SRpcMsg* pMsg, int64_t* pRid) {
int32_t rpcSendRequest(void* shandle, const SEpSet* pEpSet, SRpcMsg* pMsg, int64_t* pRid) {
return transSendRequest(shandle, pEpSet, pMsg, NULL);
}
int rpcSendRequestWithCtx(void* shandle, const SEpSet* pEpSet, SRpcMsg* pMsg, int64_t* pRid, SRpcCtx* pCtx) {
return transSendRequest(shandle, pEpSet, pMsg, pCtx);
}
int rpcSendRecv(void* shandle, SEpSet* pEpSet, SRpcMsg* pMsg, SRpcMsg* pRsp) {
return transSendRecv(shandle, pEpSet, pMsg, pRsp);
}
int rpcSendRecvWithTimeout(void* shandle, SEpSet* pEpSet, SRpcMsg* pMsg, SRpcMsg* pRsp, int8_t* epUpdated,
int32_t timeoutMs) {
return transSendRecvWithTimeout(shandle, pEpSet, pMsg, pRsp, epUpdated, timeoutMs);
int32_t rpcSendRequestWithCtx(void* shandle, const SEpSet* pEpSet, SRpcMsg* pMsg, int64_t* pRid, SRpcCtx* pCtx) {
if (pCtx != NULL || pMsg->info.handle != 0 || pMsg->info.noResp != 0|| pRid == NULL) {
return transSendRequest(shandle, pEpSet, pMsg, pCtx);
} else {
return transSendRequestWithId(shandle, pEpSet, pMsg, pRid);
}
}
int rpcSendResponse(const SRpcMsg* pMsg) { return transSendResponse(pMsg); }
int32_t rpcSendRequestWithId(void* shandle, const SEpSet* pEpSet, STransMsg* pReq, int64_t* transpointId) {
return transSendRequestWithId(shandle, pEpSet, pReq, transpointId);
}
int32_t rpcSendRecv(void* shandle, SEpSet* pEpSet, SRpcMsg* pMsg, SRpcMsg* pRsp) {
return transSendRecv(shandle, pEpSet, pMsg, pRsp);
}
int32_t rpcSendRecvWithTimeout(void* shandle, SEpSet* pEpSet, SRpcMsg* pMsg, SRpcMsg* pRsp, int8_t* epUpdated,
int32_t timeoutMs) {
return transSendRecvWithTimeout(shandle, pEpSet, pMsg, pRsp, epUpdated, timeoutMs);
}
int32_t rpcFreeConnById(void* shandle, int64_t connId) { return transFreeConnById(shandle, connId); }
int32_t rpcSendResponse(const SRpcMsg* pMsg) { return transSendResponse(pMsg); }
void rpcRefHandle(void* handle, int8_t type) { (*taosRefHandle[type])(handle); }
void rpcUnrefHandle(void* handle, int8_t type) { (*taosUnRefHandle[type])(handle); }
int rpcRegisterBrokenLinkArg(SRpcMsg* msg) { return transRegisterMsg(msg); }
int rpcReleaseHandle(void* handle, int8_t type) { return (*transReleaseHandle[type])(handle); }
int32_t rpcRegisterBrokenLinkArg(SRpcMsg* msg) { return transRegisterMsg(msg); }
int32_t rpcReleaseHandle(void* handle, int8_t type) { return (*transReleaseHandle[type])(handle); }
// client only
int rpcSetDefaultAddr(void* thandle, const char* ip, const char* fqdn) {
int32_t rpcSetDefaultAddr(void* thandle, const char* ip, const char* fqdn) {
// later
return transSetDefaultAddr(thandle, ip, fqdn);
}
// server only
int32_t rpcSetIpWhite(void* thandle, void* arg) { return transSetIpWhiteList(thandle, arg, NULL); }
void* rpcAllocHandle() { return (void*)transAllocHandle(); }
int32_t rpcAllocHandle(int64_t* refId) { return transAllocHandle(refId); }
int32_t rpcUtilSIpRangeToStr(SIpV4Range* pRange, char* buf) { return transUtilSIpRangeToStr(pRange, buf); }
int32_t rpcUtilSWhiteListToStr(SIpWhiteList* pWhiteList, char** ppBuf) {

View File

@ -213,8 +213,10 @@ static void cliHandleReq(SCliMsg* pMsg, SCliThrd* pThrd);
static void cliHandleQuit(SCliMsg* pMsg, SCliThrd* pThrd);
static void cliHandleRelease(SCliMsg* pMsg, SCliThrd* pThrd);
static void cliHandleUpdate(SCliMsg* pMsg, SCliThrd* pThrd);
static void (*cliAsyncHandle[])(SCliMsg* pMsg, SCliThrd* pThrd) = {cliHandleReq, cliHandleQuit, cliHandleRelease, NULL,
cliHandleUpdate};
static void cliHandleFreeById(SCliMsg* pMsg, SCliThrd* pThrd);
static void (*cliAsyncHandle[])(SCliMsg* pMsg, SCliThrd* pThrd) = {cliHandleReq, cliHandleQuit, cliHandleRelease,
NULL, cliHandleUpdate, cliHandleFreeById};
/// static void (*cliAsyncHandle[])(SCliMsg* pMsg, SCliThrd* pThrd) = {cliHandleReq, cliHandleQuit, cliHandleRelease,
/// NULL,cliHandleUpdate};
@ -660,7 +662,9 @@ static SCliConn* getConnFromPool(SCliThrd* pThrd, char* key, bool* exceed) {
if (QUEUE_IS_EMPTY(&plist->conns)) {
if (plist->list->numOfConn >= pTranInst->connLimitNum) {
*exceed = true;
return NULL;;
}
plist->list->numOfConn++;
return NULL;
}
@ -704,7 +708,7 @@ static SCliConn* getConnFromPool2(SCliThrd* pThrd, char* key, SCliMsg** pMsg) {
SMsgList* list = plist->list;
if ((list)->numOfConn >= pTransInst->connLimitNum) {
STraceId* trace = &(*pMsg)->msg.info.traceId;
if (pTransInst->noDelayFp != NULL && pTransInst->noDelayFp((*pMsg)->msg.msgType)) {
if (pTransInst->notWaitAvaliableConn || (pTransInst->noDelayFp != NULL && pTransInst->noDelayFp((*pMsg)->msg.msgType))) {
tDebug("%s msg %s not to send, reason: %s", pTransInst->label, TMSG_INFO((*pMsg)->msg.msgType),
tstrerror(TSDB_CODE_RPC_NETWORK_BUSY));
doNotifyApp(*pMsg, pThrd, TSDB_CODE_RPC_NETWORK_BUSY);
@ -899,10 +903,12 @@ static int32_t specifyConnRef(SCliConn* conn, bool update, int64_t handle) {
exh->handle = conn;
exh->pThrd = conn->hostThrd;
taosWUnLockLatch(&exh->latch);
conn->refId = exh->refId;
taosWUnLockLatch(&exh->latch);
tDebug("conn %p specified by %"PRId64"", conn, handle);
(void)transReleaseExHandle(transGetRefMgt(), handle);
return 0;
}
@ -1035,7 +1041,6 @@ static void cliDestroyConn(SCliConn* conn, bool clear) {
list->size--;
}
}
conn->list = NULL;
(void)transReleaseExHandle(transGetRefMgt(), conn->refId);
@ -1075,8 +1080,11 @@ static void cliDestroy(uv_handle_t* handle) {
(void)atomic_sub_fetch_32(&pThrd->connCount, 1);
if (conn->refId > 0) {
(void)transReleaseExHandle(transGetRefMgt(), conn->refId);
(void)transRemoveExHandle(transGetRefMgt(), conn->refId);
}
taosMemoryFree(conn->dstAddr);
taosMemoryFree(conn->stream);
@ -1589,6 +1597,40 @@ static void cliHandleUpdate(SCliMsg* pMsg, SCliThrd* pThrd) {
pThrd->cvtAddr = pCtx->cvtAddr;
destroyCmsg(pMsg);
}
static void cliHandleFreeById(SCliMsg* pMsg, SCliThrd* pThrd) {
int32_t code = 0;
int64_t refId = (int64_t)(pMsg->msg.info.handle);
SExHandle* exh = transAcquireExHandle(transGetRefMgt(), refId);
if (exh == NULL) {
tDebug("id %" PRId64 " already released", refId);
destroyCmsg(pMsg);
return;
}
taosRLockLatch(&exh->latch);
SCliConn* conn = exh->handle;
taosRUnLockLatch(&exh->latch);
if (conn == NULL || conn->refId != refId) {
TAOS_CHECK_GOTO(TSDB_CODE_REF_INVALID_ID, NULL, _exception);
}
tDebug("do free conn %p by id %" PRId64 "", conn, refId);
int32_t size = transQueueSize(&conn->cliMsgs);
if (size == 0) {
// already recv, and notify upper layer
TAOS_CHECK_GOTO(TSDB_CODE_REF_INVALID_ID, NULL, _exception);
return;
} else {
while (T_REF_VAL_GET(conn) >= 1) transUnrefCliHandle(conn);
}
return;
_exception:
tDebug("already free conn %p by id %" PRId64"", conn, refId);
(void)transReleaseExHandle(transGetRefMgt(), refId);
destroyCmsg(pMsg);
}
SCliConn* cliGetConn(SCliMsg** pMsg, SCliThrd* pThrd, bool* ignore, char* addr) {
STransConnCtx* pCtx = (*pMsg)->ctx;
@ -2759,7 +2801,7 @@ SCliThrd* transGetWorkThrd(STrans* trans, int64_t handle) {
SCliThrd* pThrd = transGetWorkThrdFromHandle(trans, handle);
return pThrd;
}
int transReleaseCliHandle(void* handle) {
int32_t transReleaseCliHandle(void* handle) {
int32_t code = 0;
SCliThrd* pThrd = transGetWorkThrdFromHandle(NULL, (int64_t)handle);
if (pThrd == NULL) {
@ -2823,25 +2865,25 @@ static int32_t transInitMsg(void* shandle, const SEpSet* pEpSet, STransMsg* pReq
cliMsg->type = Normal;
cliMsg->refId = (int64_t)shandle;
QUEUE_INIT(&cliMsg->seqq);
*pCliMsg = cliMsg;
return 0;
}
int transSendRequest(void* shandle, const SEpSet* pEpSet, STransMsg* pReq, STransCtx* ctx) {
int32_t transSendRequest(void* shandle, const SEpSet* pEpSet, STransMsg* pReq, STransCtx* ctx) {
STrans* pTransInst = (STrans*)transAcquireExHandle(transGetInstMgt(), (int64_t)shandle);
if (pTransInst == NULL) {
transFreeMsg(pReq->pCont);
return TSDB_CODE_RPC_BROKEN_LINK;
return TSDB_CODE_RPC_MODULE_QUIT;
}
int32_t code = 0;
int64_t handle = (int64_t)pReq->info.handle;
SCliThrd* pThrd = transGetWorkThrd(pTransInst, handle);
if (pThrd == NULL) {
transFreeMsg(pReq->pCont);
(void)transReleaseExHandle(transGetInstMgt(), (int64_t)shandle);
return TSDB_CODE_RPC_BROKEN_LINK;
TAOS_CHECK_GOTO(TSDB_CODE_RPC_BROKEN_LINK, NULL, _exception;);
}
if (handle != 0) {
SExHandle* exh = transAcquireExHandle(transGetRefMgt(), handle);
if (exh != NULL) {
@ -2849,26 +2891,27 @@ int transSendRequest(void* shandle, const SEpSet* pEpSet, STransMsg* pReq, STran
if (exh->handle == NULL && exh->inited != 0) {
SCliMsg* pCliMsg = NULL;
code = transInitMsg(shandle, pEpSet, pReq, ctx, &pCliMsg);
ASSERT(code == 0);
if (code != 0) {
taosWUnLockLatch(&exh->latch);
(void)transReleaseExHandle(transGetRefMgt(), handle);
TAOS_CHECK_GOTO(code, NULL, _exception);
}
QUEUE_PUSH(&exh->q, &pCliMsg->seqq);
taosWUnLockLatch(&exh->latch);
tDebug("msg refId: %" PRId64 "", handle);
(void)transReleaseExHandle(transGetInstMgt(), (int64_t)shandle);
return 0;
} else {
exh->inited = 1;
taosWUnLockLatch(&exh->latch);
(void)transReleaseExHandle(transGetRefMgt(), handle);
}
exh->inited = 1;
taosWUnLockLatch(&exh->latch);
(void)transReleaseExHandle(transGetRefMgt(), handle);
}
}
SCliMsg* pCliMsg = NULL;
code = transInitMsg(shandle, pEpSet, pReq, ctx, &pCliMsg);
if (code != 0) {
(void)transReleaseExHandle(transGetInstMgt(), (int64_t)shandle);
return code;
}
TAOS_CHECK_GOTO(transInitMsg(shandle, pEpSet, pReq, ctx, &pCliMsg), NULL, _exception);
STraceId* trace = &pReq->info.traceId;
tGDebug("%s send request at thread:%08" PRId64 ", dst:%s:%d, app:%p", transLabel(pTransInst), pThrd->pid,
@ -2880,13 +2923,63 @@ int transSendRequest(void* shandle, const SEpSet* pEpSet, STransMsg* pReq, STran
}
(void)transReleaseExHandle(transGetInstMgt(), (int64_t)shandle);
return 0;
_exception:
transFreeMsg(pReq->pCont);
(void)transReleaseExHandle(transGetInstMgt(), (int64_t)shandle);
return code;
}
int32_t transSendRequestWithId(void* shandle, const SEpSet* pEpSet, STransMsg* pReq, int64_t* transpointId) {
if (transpointId == NULL) {
ASSERT(0);
return TSDB_CODE_INVALID_PARA;
}
int32_t code = 0;
STrans* pTransInst = (STrans*)transAcquireExHandle(transGetInstMgt(), (int64_t)shandle);
if (pTransInst == NULL) {
TAOS_CHECK_GOTO(TSDB_CODE_RPC_MODULE_QUIT, NULL, _exception);
}
TAOS_CHECK_GOTO(transAllocHandle(transpointId), NULL, _exception);
SCliThrd* pThrd = transGetWorkThrd(pTransInst, *transpointId);
if (pThrd == NULL) {
TAOS_CHECK_GOTO(TSDB_CODE_RPC_BROKEN_LINK, NULL, _exception);
}
SExHandle* exh = transAcquireExHandle(transGetRefMgt(), *transpointId);
if (exh == NULL) {
TAOS_CHECK_GOTO(TSDB_CODE_RPC_MODULE_QUIT, NULL, _exception);
}
pReq->info.handle = (void*)(*transpointId);
SCliMsg* pCliMsg = NULL;
TAOS_CHECK_GOTO(transInitMsg(shandle, pEpSet, pReq, NULL, &pCliMsg), NULL, _exception);
STraceId* trace = &pReq->info.traceId;
tGDebug("%s send request at thread:%08" PRId64 ", dst:%s:%d, app:%p", transLabel(pTransInst), pThrd->pid,
EPSET_GET_INUSE_IP(pEpSet), EPSET_GET_INUSE_PORT(pEpSet), pReq->info.ahandle);
if ((code = transAsyncSend(pThrd->asyncPool, &(pCliMsg->q))) != 0) {
destroyCmsg(pCliMsg);
(void)transReleaseExHandle(transGetInstMgt(), (int64_t)shandle);
return (code == TSDB_CODE_RPC_ASYNC_MODULE_QUIT ? TSDB_CODE_RPC_MODULE_QUIT : code);
}
(void)transReleaseExHandle(transGetInstMgt(), (int64_t)shandle);
return 0;
_exception:
transFreeMsg(pReq->pCont);
(void)transReleaseExHandle(transGetInstMgt(), (int64_t)shandle);
return code;
}
int transSendRecv(void* shandle, const SEpSet* pEpSet, STransMsg* pReq, STransMsg* pRsp) {
int32_t transSendRecv(void* shandle, const SEpSet* pEpSet, STransMsg* pReq, STransMsg* pRsp) {
STrans* pTransInst = (STrans*)transAcquireExHandle(transGetInstMgt(), (int64_t)shandle);
if (pTransInst == NULL) {
transFreeMsg(pReq->pCont);
return TSDB_CODE_RPC_BROKEN_LINK;
return TSDB_CODE_RPC_MODULE_QUIT;
}
int32_t code = 0;
@ -2908,8 +3001,7 @@ int transSendRecv(void* shandle, const SEpSet* pEpSet, STransMsg* pReq, STransMs
code = tsem_init(sem, 0, 0);
if (code != 0) {
taosMemoryFree(sem);
code = TAOS_SYSTEM_ERROR(errno);
TAOS_CHECK_GOTO(code, NULL, _RETURN1);
TAOS_CHECK_GOTO(TAOS_SYSTEM_ERROR(errno), NULL, _RETURN1);
}
TRACE_SET_MSGID(&pReq->info.traceId, tGenIdPI64());
@ -3003,13 +3095,13 @@ _EXIT:
taosMemoryFree(pSyncMsg);
return code;
}
int transSendRecvWithTimeout(void* shandle, SEpSet* pEpSet, STransMsg* pReq, STransMsg* pRsp, int8_t* epUpdated,
int32_t timeoutMs) {
int32_t transSendRecvWithTimeout(void* shandle, SEpSet* pEpSet, STransMsg* pReq, STransMsg* pRsp, int8_t* epUpdated,
int32_t timeoutMs) {
int32_t code = 0;
STrans* pTransInst = (STrans*)transAcquireExHandle(transGetInstMgt(), (int64_t)shandle);
if (pTransInst == NULL) {
transFreeMsg(pReq->pCont);
return TSDB_CODE_RPC_BROKEN_LINK;
return TSDB_CODE_RPC_MODULE_QUIT;
}
STransMsg* pTransMsg = taosMemoryCalloc(1, sizeof(STransMsg));
@ -3096,22 +3188,21 @@ _RETURN2:
/*
*
**/
int transSetDefaultAddr(void* shandle, const char* ip, const char* fqdn) {
int32_t transSetDefaultAddr(void* shandle, const char* ip, const char* fqdn) {
if (ip == NULL || fqdn == NULL) return TSDB_CODE_INVALID_PARA;
STrans* pTransInst = (STrans*)transAcquireExHandle(transGetInstMgt(), (int64_t)shandle);
if (pTransInst == NULL) {
return TSDB_CODE_RPC_BROKEN_LINK;
return TSDB_CODE_RPC_MODULE_QUIT;
}
SCvtAddr cvtAddr = {0};
if (ip != NULL && fqdn != NULL) {
tstrncpy(cvtAddr.ip, ip, sizeof(cvtAddr.ip));
tstrncpy(cvtAddr.fqdn, fqdn, sizeof(cvtAddr.fqdn));
cvtAddr.cvt = true;
}
tstrncpy(cvtAddr.ip, ip, sizeof(cvtAddr.ip));
tstrncpy(cvtAddr.fqdn, fqdn, sizeof(cvtAddr.fqdn));
cvtAddr.cvt = true;
int32_t code = 0;
int8_t i = 0;
for (i = 0; i < pTransInst->numOfThreads; i++) {
for (int8_t i = 0; i < pTransInst->numOfThreads; i++) {
STransConnCtx* pCtx = taosMemoryCalloc(1, sizeof(STransConnCtx));
if (pCtx == NULL) {
code = TSDB_CODE_OUT_OF_MEMORY;
@ -3136,7 +3227,9 @@ int transSetDefaultAddr(void* shandle, const char* ip, const char* fqdn) {
if ((code = transAsyncSend(thrd->asyncPool, &(cliMsg->q))) != 0) {
destroyCmsg(cliMsg);
code = (code == TSDB_CODE_RPC_ASYNC_MODULE_QUIT ? TSDB_CODE_RPC_MODULE_QUIT : code);
if (code == TSDB_CODE_RPC_ASYNC_MODULE_QUIT) {
code = TSDB_CODE_RPC_MODULE_QUIT;
}
break;
}
}
@ -3145,7 +3238,7 @@ int transSetDefaultAddr(void* shandle, const char* ip, const char* fqdn) {
return code;
}
int64_t transAllocHandle() {
int32_t transAllocHandle(int64_t* refId) {
SExHandle* exh = taosMemoryCalloc(1, sizeof(SExHandle));
if (exh == NULL) {
return TSDB_CODE_OUT_OF_MEMORY;
@ -3166,5 +3259,43 @@ int64_t transAllocHandle() {
QUEUE_INIT(&exh->q);
taosInitRWLatch(&exh->latch);
tDebug("pre alloc refId %" PRId64 "", exh->refId);
return exh->refId;
*refId = exh->refId;
return 0;
}
int32_t transFreeConnById(void* shandle, int64_t transpointId) {
int32_t code = 0;
STrans* pTransInst = (STrans*)transAcquireExHandle(transGetInstMgt(), (int64_t)shandle);
if (pTransInst == NULL) {
return TSDB_CODE_RPC_MODULE_QUIT;
}
if (transpointId == 0) {
tDebug("not free by refId:%"PRId64"", transpointId);
TAOS_CHECK_GOTO(0, NULL, _exception);
}
SCliThrd* pThrd = transGetWorkThrdFromHandle(pTransInst, transpointId);
if (pThrd == NULL) {
TAOS_CHECK_GOTO(TSDB_CODE_REF_INVALID_ID, NULL, _exception);
}
SCliMsg* pCli = taosMemoryCalloc(1, sizeof(SCliMsg));
if (pCli == NULL) {
TAOS_CHECK_GOTO(TSDB_CODE_OUT_OF_MEMORY, NULL, _exception);
}
pCli->type = FreeById;
tDebug("release conn id %" PRId64 "", transpointId);
STransMsg msg = {.info.handle = (void*)transpointId};
pCli->msg = msg;
code = transAsyncSend(pThrd->asyncPool, &pCli->q);
if (code != 0) {
taosMemoryFree(pCli);
TAOS_CHECK_GOTO(code, NULL, _exception);
}
_exception:
transReleaseExHandle(transGetInstMgt(), (int64_t)shandle);
return code;
}

View File

@ -234,7 +234,7 @@ bool transReadComplete(SConnBuffer* connBuf) {
return (p->left == 0 || p->invalid) ? true : false;
}
int transSetConnOption(uv_tcp_t* stream, int keepalive) {
int32_t transSetConnOption(uv_tcp_t* stream, int keepalive) {
#if defined(WINDOWS) || defined(DARWIN)
#else
return uv_tcp_keepalive(stream, 1, keepalive);
@ -745,8 +745,7 @@ int32_t transRemoveExHandle(int32_t refMgt, int64_t refId) {
return taosRemoveRef(refMgt, refId);
}
void* transAcquireExHandle(int32_t refMgt, int64_t refId) {
// acquire extern handle
void* transAcquireExHandle(int32_t refMgt, int64_t refId) { // acquire extern handle
return (void*)taosAcquireRef(refMgt, refId);
}

View File

@ -1707,7 +1707,7 @@ void transUnrefSrvHandle(void* handle) {
}
}
int transReleaseSrvHandle(void* handle) {
int32_t transReleaseSrvHandle(void* handle) {
int32_t code = 0;
SRpcHandleInfo* info = handle;
SExHandle* exh = info->handle;
@ -1747,7 +1747,7 @@ _return2:
return code;
}
int transSendResponse(const STransMsg* msg) {
int32_t transSendResponse(const STransMsg* msg) {
int32_t code = 0;
if (msg->info.noResp) {
@ -1800,7 +1800,7 @@ _return2:
rpcFreeCont(msg->pCont);
return code;
}
int transRegisterMsg(const STransMsg* msg) {
int32_t transRegisterMsg(const STransMsg* msg) {
int32_t code = 0;
SExHandle* exh = msg->info.handle;
@ -1891,4 +1891,4 @@ int32_t transSetIpWhiteList(void* thandle, void* arg, FilteFunc* func) {
return code;
}
int transGetConnInfo(void* thandle, STransHandleInfo* pConnInfo) { return -1; }
int32_t transGetConnInfo(void* thandle, STransHandleInfo* pConnInfo) { return -1; }

View File

@ -1075,14 +1075,14 @@ int32_t taosGetFqdn(char *fqdn) {
freeaddrinfo(result);
#else
#elif WINDOWS
struct addrinfo hints = {0};
struct addrinfo *result = NULL;
hints.ai_flags = AI_CANONNAME;
int32_t ret = getaddrinfo(hostname, NULL, &hints, &result);
if (!result) {
fprintf(stderr, "failed to get fqdn, code:%d, reason:%s\n", ret, gai_strerror(ret));
fprintf(stderr, "failed to get fqdn, code:%d, hostname:%s, reason:%s\n", ret, hostname, gai_strerror(ret));
return -1;
}
strcpy(fqdn, result->ai_canonname);

View File

@ -496,6 +496,43 @@ class TDTestCase:
consumer.close()
print("consume_ts_4551 ok")
def consume_td_31283(self):
tdSql.execute(f'create database if not exists d31283')
tdSql.execute(f'use d31283')
tdSql.execute(f'create topic topic_31283 with meta as database d31283')
consumer_dict = {
"group.id": "g1",
"td.connect.user": "root",
"td.connect.pass": "taosdata",
"auto.offset.reset": "earliest",
"experimental.snapshot.enable": "true",
# "msg.enable.batchmeta": "true"
}
consumer = Consumer(consumer_dict)
try:
consumer.subscribe(["topic_31283"])
except TmqError:
tdLog.exit(f"subscribe error")
tdSql.execute(f'create table stt(ts timestamp, i int) tags(t int)')
hasData = False
try:
while True:
res = consumer.poll(1)
if not res:
break
hasData = True
finally:
consumer.close()
if not hasData:
tdLog.exit(f"consume_td_31283 error")
print("consume_td_31283 ok")
def consume_TS_5067_Test(self):
tdSql.execute(f'create database if not exists d1 vgroups 1')
tdSql.execute(f'use d1')
@ -632,6 +669,7 @@ class TDTestCase:
self.consume_ts_4544()
self.consume_ts_4551()
self.consume_TS_4540_Test()
self.consume_td_31283()
tdSql.prepare()
self.checkWal1VgroupOnlyMeta()