Merge branch '3.0' of github.com:taosdata/TDengine into test/chr/TD-14699

This commit is contained in:
tomchon 2022-08-01 19:45:41 +08:00
commit f7c7d4c8af
579 changed files with 22354 additions and 11090 deletions

4
.gitignore vendored
View File

@ -50,6 +50,10 @@ pysim/
tests/script/api/batchprepare
taosadapter
taosadapter-debug
tools/taos-tools/*
tools/taosws-rs/*
tools/taosadapter/*
tools/upx*
# Doxygen Generated files
html/

15
.gitmodules vendored
View File

@ -1,15 +0,0 @@
[submodule "src/connector/go"]
path = src/connector/go
url = git@github.com:taosdata/driver-go.git
[submodule "src/connector/hivemq-tdengine-extension"]
path = src/connector/hivemq-tdengine-extension
url = git@github.com:taosdata/hivemq-tdengine-extension.git
[submodule "deps/jemalloc"]
path = deps/jemalloc
url = https://github.com/jemalloc/jemalloc
[submodule "deps/TSZ"]
path = deps/TSZ
url = https://github.com/taosdata/TSZ.git
[submodule "examples/rust"]
path = examples/rust
url = https://github.com/songtianyi/tdengine-rust-bindings.git

View File

@ -118,6 +118,7 @@ def pre_test(){
git rm --cached tools/taos-tools 2>/dev/null || :
git rm --cached tools/taosadapter 2>/dev/null || :
git rm --cached tools/taosws-rs 2>/dev/null || :
git rm --cached examples/rust 2>/dev/null || :
'''
sh '''
cd ${WKC}
@ -269,6 +270,7 @@ def pre_test_win(){
git rm --cached tools/taos-tools 2>nul
git rm --cached tools/taosadapter 2>nul
git rm --cached tools/taosws-rs 2>nul
git rm --cached examples/rust 2>nul
exit 0
'''
bat '''
@ -443,7 +445,7 @@ pipeline {
}
}
}
catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') {
/*catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') {
timeout(time: 15, unit: 'MINUTES'){
script {
sh '''
@ -455,7 +457,7 @@ pipeline {
'''
}
}
}
}*/
}
}
}

View File

@ -47,15 +47,21 @@ IF(${TD_WINDOWS})
)
option(
BUILD_TEST
"If build unit tests using googletest"
ON
)
BUILD_TEST
"If build unit tests using googletest"
ON
)
option(
TDENGINE_3
"TDengine 3.x"
ON
TDENGINE_3
"TDengine 3.x for taos-tools"
ON
)
option(
BUILD_CRASHDUMP
"If build crashdump on Windows"
ON
)
ELSEIF (TD_DARWIN_64)
@ -84,6 +90,18 @@ ELSE ()
ENDIF ()
ENDIF ()
option(
RUST_BINDINGS
"If build with rust-bindings"
ON
)
option(
JEMALLOC_ENABLED
"If build with jemalloc"
OFF
)
option(
BUILD_SANITIZER
"If build sanitizer"
@ -145,18 +163,6 @@ option(
ON
)
option(
BUILD_WITH_CRAFT
"If build with canonical-raft"
OFF
)
option(
BUILD_WITH_TRAFT
"If build with traft"
OFF
)
IF(${TD_LINUX} MATCHES TRUE)
option(

View File

@ -1,14 +0,0 @@
# canonical-raft
ExternalProject_Add(craft
GIT_REPOSITORY https://github.com/canonical/raft.git
GIT_TAG v0.11.2
SOURCE_DIR "${TD_CONTRIB_DIR}/craft"
BINARY_DIR "${TD_CONTRIB_DIR}/craft"
#BUILD_IN_SOURCE TRUE
# https://answers.ros.org/question/333125/how-to-include-external-automakeautoconf-projects-into-ament_cmake/
CONFIGURE_COMMAND COMMAND autoreconf -i COMMAND ./configure --enable-example
BUILD_COMMAND "$(MAKE)"
INSTALL_COMMAND ""
TEST_COMMAND ""
)

View File

@ -0,0 +1,12 @@
# crashdump
ExternalProject_Add(crashdump
GIT_REPOSITORY https://github.com/Arnavion/crashdump.git
GIT_TAG master
SOURCE_DIR "${TD_CONTRIB_DIR}/crashdump"
BINARY_DIR "${TD_CONTRIB_DIR}/crashdump"
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
TEST_COMMAND ""
)

View File

@ -0,0 +1,14 @@
# jemalloc
ExternalProject_Add(jemalloc
GIT_REPOSITORY https://github.com/jemalloc/jemalloc.git
GIT_TAG 5.3.0
SOURCE_DIR "${TD_CONTRIB_DIR}/jemalloc"
BINARY_DIR ""
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
TEST_COMMAND ""
GIT_SHALLOW true
GIT_PROGRESS true
)

View File

@ -0,0 +1,12 @@
# rust-bindings
ExternalProject_Add(rust-bindings
GIT_REPOSITORY https://github.com/songtianyi/tdengine-rust-bindings.git
GIT_TAG 7ed7a97
SOURCE_DIR "${TD_SOURCE_DIR}/examples/rust"
BINARY_DIR "${TD_SOURCE_DIR}/examples/rust"
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
TEST_COMMAND ""
)

View File

@ -1,5 +1,5 @@
# zlib
# taosadapter
ExternalProject_Add(taosadapter
GIT_REPOSITORY https://github.com/taosdata/taosadapter.git
GIT_TAG df8678f

View File

@ -1,8 +1,8 @@
# zlib
# taos-tools
ExternalProject_Add(taos-tools
GIT_REPOSITORY https://github.com/taosdata/taos-tools.git
GIT_TAG 817cb6a
GIT_TAG f4e456a
SOURCE_DIR "${TD_SOURCE_DIR}/tools/taos-tools"
BINARY_DIR ""
#BUILD_IN_SOURCE TRUE

View File

@ -1,5 +1,5 @@
# zlib
# taosws-rs
ExternalProject_Add(taosws-rs
GIT_REPOSITORY https://github.com/taosdata/taosws-rs.git
GIT_TAG 9de599d

View File

@ -1,14 +0,0 @@
# traft
ExternalProject_Add(traft
GIT_REPOSITORY https://github.com/taosdata/traft.git
GIT_TAG for_3.0
SOURCE_DIR "${TD_CONTRIB_DIR}/traft"
BINARY_DIR "${TD_CONTRIB_DIR}/traft"
#BUILD_IN_SOURCE TRUE
# https://answers.ros.org/question/333125/how-to-include-external-automakeautoconf-projects-into-ament_cmake/
CONFIGURE_COMMAND COMMAND autoreconf -i COMMAND ./configure
BUILD_COMMAND "$(MAKE)"
INSTALL_COMMAND ""
TEST_COMMAND ""
)

View File

@ -105,6 +105,11 @@ if(${BUILD_WITH_SQLITE})
cat("${TD_SUPPORT_DIR}/sqlite_CMakeLists.txt.in" ${CONTRIB_TMP_FILE})
endif(${BUILD_WITH_SQLITE})
# rust-bindings
if(${RUST_BINDINGS})
cat("${TD_SUPPORT_DIR}/rust-bindings_CMakeLists.txt.in" ${CONTRIB_TMP_FILE})
endif(${RUST_BINDINGS})
# lucene
if(${BUILD_WITH_LUCENE})
cat("${TD_SUPPORT_DIR}/lucene_CMakeLists.txt.in" ${CONTRIB_TMP_FILE})
@ -116,6 +121,11 @@ if(${BUILD_WITH_NURAFT})
cat("${TD_SUPPORT_DIR}/nuraft_CMakeLists.txt.in" ${CONTRIB_TMP_FILE})
endif(${BUILD_WITH_NURAFT})
# crashdump
if(${BUILD_CRASHDUMP})
cat("${TD_SUPPORT_DIR}/crashdump_CMakeLists.txt.in" ${CONTRIB_TMP_FILE})
endif(${BUILD_CRASHDUMP})
# addr2line
if(${BUILD_ADDR2LINE})
if(NOT ${TD_WINDOWS})
@ -130,6 +140,24 @@ execute_process(COMMAND "${CMAKE_COMMAND}" -G "${CMAKE_GENERATOR}" .
WORKING_DIRECTORY "${TD_CONTRIB_DIR}/deps-download")
execute_process(COMMAND "${CMAKE_COMMAND}" --build .
WORKING_DIRECTORY "${TD_CONTRIB_DIR}/deps-download")
# clear submodule
execute_process(COMMAND git submodule deinit -f tools/taos-tools
WORKING_DIRECTORY "${TD_SOURCE_DIR}")
execute_process(COMMAND git rm --cached tools/taos-tools
WORKING_DIRECTORY "${TD_SOURCE_DIR}")
execute_process(COMMAND git submodule deinit -f tools/taosadapter
WORKING_DIRECTORY "${TD_SOURCE_DIR}")
execute_process(COMMAND git rm --cached tools/taosadapter
WORKING_DIRECTORY "${TD_SOURCE_DIR}")
execute_process(COMMAND git submodule deinit -f tools/taosws-rs
WORKING_DIRECTORY "${TD_SOURCE_DIR}")
execute_process(COMMAND git rm --cached tools/taosws-rs
WORKING_DIRECTORY "${TD_SOURCE_DIR}")
execute_process(COMMAND git submodule deinit -f examples/rust
WORKING_DIRECTORY "${TD_SOURCE_DIR}")
execute_process(COMMAND git rm --cached examples/rust
WORKING_DIRECTORY "${TD_SOURCE_DIR}")
# ================================================================================================
# Build
@ -253,6 +281,16 @@ if(${BUILD_PTHREAD})
target_link_libraries(pthread INTERFACE libpthreadVC3)
endif()
# crashdump
if(${BUILD_CRASHDUMP})
add_executable(dumper "crashdump/dumper/dumper.c")
target_link_libraries(dumper User32.lib dbghelp.lib)
file(READ "crashdump/crasher/crasher.c" CRASHDUMP_CONTENT)
string(REPLACE "main(" "main_crashdump(" CRASHDUMP_CONTENT "${CRASHDUMP_CONTENT}")
file(WRITE "crashdump/crasher/crasher.c" "${CRASHDUMP_CONTENT}")
add_library(crashdump STATIC "crashdump/crasher/crasher.c")
endif()
# iconv
if(${BUILD_WITH_ICONV})
add_library(iconv STATIC iconv/win_iconv.c)

View File

@ -23,7 +23,7 @@ A single line of text is used in OpenTSDB line protocol to represent one row of
- `metric` will be used as the STable name.
- `timestamp` is the timestamp of current row of data. The time precision will be determined automatically based on the length of the timestamp. Second and millisecond time precision are supported.
- `value` is a metric which must be a numeric value, the corresponding column name is "value".
- `value` is a metric which must be a numeric value, the corresponding column name is "_value".
- The last part is the tag set separated by spaces, all tags will be converted to nchar type automatically.
For example:
@ -74,7 +74,7 @@ taos> show STables;
Query OK, 2 row(s) in set (0.002544s)
taos> select tbname, * from `meters.current`;
tbname | ts | value | groupid | location |
tbname | _ts | _value | groupid | location |
==================================================================================================================================
t_0e7bcfa21a02331c06764f275... | 2022-03-28 09:56:51.249 | 10.800000000 | 3 | California.LoSangeles |
t_0e7bcfa21a02331c06764f275... | 2022-03-28 09:56:51.250 | 11.300000000 | 3 | California.LoSangeles |

View File

@ -91,7 +91,7 @@ taos> show STables;
Query OK, 2 row(s) in set (0.001954s)
taos> select * from `meters.current`;
ts | value | groupid | location |
_ts | _value | groupid | location |
===================================================================================================================
2022-03-28 09:56:51.249 | 10.300000000 | 2.000000000 | California.SanFrancisco |
2022-03-28 09:56:51.250 | 12.600000000 | 2.000000000 | California.SanFrancisco |

File diff suppressed because it is too large Load Diff

View File

@ -3,7 +3,7 @@ package main
import (
"fmt"
"github.com/taosdata/driver-go/v2/af"
"github.com/taosdata/driver-go/v3/af"
)
func main() {

View File

@ -4,7 +4,7 @@ import (
"database/sql"
"fmt"
_ "github.com/taosdata/driver-go/v2/taosSql"
_ "github.com/taosdata/driver-go/v3/taosSql"
)
func main() {

View File

@ -4,7 +4,7 @@ import (
"database/sql"
"fmt"
_ "github.com/taosdata/driver-go/v2/taosRestful"
_ "github.com/taosdata/driver-go/v3/taosRestful"
)
func main() {

View File

@ -3,7 +3,7 @@ package main
import (
"fmt"
"github.com/taosdata/driver-go/v2/wrapper"
"github.com/taosdata/driver-go/v3/wrapper"
)
func main() {

View File

@ -2,5 +2,5 @@ module goexample
go 1.17
require github.com/taosdata/driver-go/v2 develop
require github.com/taosdata/driver-go/v3 3.0

View File

@ -3,7 +3,7 @@ package main
import (
"fmt"
"github.com/taosdata/driver-go/v2/af"
"github.com/taosdata/driver-go/v3/af"
)
func prepareDatabase(conn *af.Connector) {

View File

@ -3,7 +3,7 @@ package main
import (
"fmt"
"github.com/taosdata/driver-go/v2/af"
"github.com/taosdata/driver-go/v3/af"
)
func prepareDatabase(conn *af.Connector) {

View File

@ -4,7 +4,7 @@ import (
"database/sql"
"fmt"
_ "github.com/taosdata/driver-go/v2/taosRestful"
_ "github.com/taosdata/driver-go/v3/taosRestful"
)
func createStable(taos *sql.DB) {

View File

@ -4,9 +4,9 @@ import (
"fmt"
"time"
"github.com/taosdata/driver-go/v2/af"
"github.com/taosdata/driver-go/v2/af/param"
"github.com/taosdata/driver-go/v2/common"
"github.com/taosdata/driver-go/v3/af"
"github.com/taosdata/driver-go/v3/af/param"
"github.com/taosdata/driver-go/v3/common"
)
func checkErr(err error, prompt string) {

View File

@ -3,7 +3,7 @@ package main
import (
"fmt"
"github.com/taosdata/driver-go/v2/af"
"github.com/taosdata/driver-go/v3/af"
)
func prepareDatabase(conn *af.Connector) {

View File

@ -5,7 +5,7 @@ import (
"fmt"
"time"
_ "github.com/taosdata/driver-go/v2/taosRestful"
_ "github.com/taosdata/driver-go/v3/taosRestful"
)
func main() {

View File

@ -1,53 +1,120 @@
package main
import (
"database/sql/driver"
"context"
"encoding/json"
"fmt"
"io"
"os"
"strconv"
"time"
taos "github.com/taosdata/driver-go/v2/af"
"github.com/taosdata/driver-go/v3/af"
"github.com/taosdata/driver-go/v3/af/tmq"
"github.com/taosdata/driver-go/v3/common"
"github.com/taosdata/driver-go/v3/errors"
"github.com/taosdata/driver-go/v3/wrapper"
)
func main() {
db, err := taos.Open("", "", "", "log", 0)
db, err := af.Open("", "root", "taosdata", "", 0)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
panic(err)
}
defer db.Close()
topic, err := db.Subscribe(false, "taoslogtail", "select ts, level, ipaddr, content from log", time.Second)
_, err = db.Exec("create database if not exists example_tmq")
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(2)
panic(err)
}
_, err = db.Exec("create topic if not exists example_tmq_topic with meta as DATABASE example_tmq")
if err != nil {
panic(err)
}
config := tmq.NewConfig()
defer config.Destroy()
err = config.SetGroupID("test")
if err != nil {
panic(err)
}
err = config.SetAutoOffsetReset("earliest")
if err != nil {
panic(err)
}
err = config.SetConnectIP("127.0.0.1")
if err != nil {
panic(err)
}
err = config.SetConnectUser("root")
if err != nil {
panic(err)
}
err = config.SetConnectPass("taosdata")
if err != nil {
panic(err)
}
err = config.SetConnectPort("6030")
if err != nil {
panic(err)
}
err = config.SetMsgWithTableName(true)
if err != nil {
panic(err)
}
err = config.EnableHeartBeat()
if err != nil {
panic(err)
}
err = config.EnableAutoCommit(func(result *wrapper.TMQCommitCallbackResult) {
if result.ErrCode != 0 {
errStr := wrapper.TMQErr2Str(result.ErrCode)
err := errors.NewError(int(result.ErrCode), errStr)
panic(err)
}
})
if err != nil {
panic(err)
}
consumer, err := tmq.NewConsumer(config)
if err != nil {
panic(err)
}
err = consumer.Subscribe([]string{"example_tmq_topic"})
if err != nil {
panic(err)
}
_, err = db.Exec("create table example_tmq.t1 (ts timestamp,v int)")
if err != nil {
panic(err)
}
defer topic.Unsubscribe(true)
for {
func() {
rows, err := topic.Consume()
defer func() { rows.Close(); time.Sleep(time.Second) }()
if err != nil {
fmt.Println(err)
os.Exit(3)
}
for {
values := make([]driver.Value, 4)
err := rows.Next(values)
if err == io.EOF {
break
} else if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(4)
}
ts := values[0].(time.Time)
level := values[1].(int8)
ipaddr := values[2].(string)
content := values[3].(string)
fmt.Printf("%s %d %s %s\n", ts.Format(time.StampMilli), level, ipaddr, content)
}
}()
result, err := consumer.Poll(time.Second)
if err != nil {
panic(err)
}
if result.Type != common.TMQ_RES_TABLE_META {
panic("want message type 2 got " + strconv.Itoa(int(result.Type)))
}
data, _ := json.Marshal(result.Meta)
fmt.Println(string(data))
consumer.Commit(context.Background(), result.Message)
consumer.FreeMessage(result.Message)
break
}
_, err = db.Exec("insert into example_tmq.t1 values(now,1)")
if err != nil {
panic(err)
}
for {
result, err := consumer.Poll(time.Second)
if err != nil {
panic(err)
}
if result.Type != common.TMQ_RES_DATA {
panic("want message type 1 got " + strconv.Itoa(int(result.Type)))
}
data, _ := json.Marshal(result.Data)
fmt.Println(string(data))
consumer.Commit(context.Background(), result.Message)
consumer.FreeMessage(result.Message)
break
}
consumer.Close()
}
// 未完成

View File

@ -4,11 +4,11 @@ sidebar_label: 文档首页
slug: /
---
TDengine 是一款[高性能](https://www.taosdata.com/fast)、[分布式](https://www.taosdata.com/scalable)、[支持 SQL](https://www.taosdata.com/sql-support) 的时序数据库 (Database)。本文档是 TDengine 用户手册,主要是介绍 TDengine 的基本概念、安装、使用、功能、开发接口、运营维护、TDengine 内核设计等等,它主要是面向架构师、开发者与系统管理员的。
TDengine是一款开源、[高性能](https://www.taosdata.com/fast)、云原生的专为物联网、工业互联网、金融等优化设计的时序数据库(Time-Series Database)。同时它还带有内建的缓存、流式计算、数据订阅等系统功能,能大幅减少系统设计的复杂度,降低研发和运营成本,是一极简的时序数据处理平台。本文档是 TDengine 用户手册,主要是介绍 TDengine 的基本概念、安装、使用、功能、开发接口、运营维护、TDengine 内核设计等等,它主要是面向架构师、开发者与系统管理员的。
TDengine 充分利用了时序数据的特点提出了“一个数据采集点一张表”与“超级表”的概念设计了创新的存储引擎让数据的写入、查询和存储效率都得到极大的提升。为正确理解并使用TDengine, 无论如何,请您仔细阅读[基本概念](./concept)一章。
如果你是开发者,请一定仔细阅读[开发指南](./develop)一章,该部分对数据库连接、建模、插入数据、查询、连续查询、缓存、数据订阅、用户自定义函数等功能都做了详细介绍,并配有各种编程语言的示例代码。大部分情况下,你只要把示例代码拷贝粘贴,针对自己的应用稍作改动,就能跑起来。
如果你是开发者,请一定仔细阅读[开发指南](./develop)一章,该部分对数据库连接、建模、插入数据、查询、流式计算、缓存、数据订阅、用户自定义函数等功能都做了详细介绍,并配有各种编程语言的示例代码。大部分情况下,你只要把示例代码拷贝粘贴,针对自己的应用稍作改动,就能跑起来。
我们已经生活在大数据的时代,纵向扩展已经无法满足日益增长的业务需求,任何系统都必须具有水平扩展的能力,集群成为大数据以及 database 系统的不可缺失功能。TDengine 团队不仅实现了集群功能,而且将这一重要核心功能开源。怎么部署、管理和维护 TDengine 集群,请参考[集群管理](./cluster)一章。

View File

@ -23,7 +23,7 @@ OpenTSDB 行协议同样采用一行字符串来表示一行数据。OpenTSDB
- metric 将作为超级表名。
- timestamp 本行数据对应的时间戳。根据时间戳的长度自动识别时间精度。支持秒和毫秒两种时间精度
- value 度量值,必须为一个数值。对应的列名是 “value”。
- value 度量值,必须为一个数值。对应的列名是 “_value”。
- 最后一部分是标签集, 用空格分隔不同标签, 所有标签自动转化为 nchar 数据类型;
例如:
@ -74,7 +74,7 @@ taos> show stables;
Query OK, 2 row(s) in set (0.002544s)
taos> select tbname, * from `meters.current`;
tbname | ts | value | groupid | location |
tbname | _ts | _value | groupid | location |
==================================================================================================================================
t_0e7bcfa21a02331c06764f275... | 2022-03-28 09:56:51.249 | 10.800000000 | 3 | California.LosAngeles |
t_0e7bcfa21a02331c06764f275... | 2022-03-28 09:56:51.250 | 11.300000000 | 3 | California.LosAngeles |

View File

@ -91,7 +91,7 @@ taos> show stables;
Query OK, 2 row(s) in set (0.001954s)
taos> select * from `meters.current`;
ts | value | groupid | location |
_ts | _value | groupid | location |
===================================================================================================================
2022-03-28 09:56:51.249 | 10.300000000 | 2.000000000 | California.SanFrancisco |
2022-03-28 09:56:51.250 | 12.600000000 | 2.000000000 | California.SanFrancisco |

View File

@ -401,7 +401,7 @@ SELECT CAST(expression AS type_name) FROM { tb_name | stb_name } [WHERE clause]
**返回结果类型**CAST 中指定的类型type_name)。
**适用数据类型**:输入参数 expression 的类型可以是BLOB、MEDIUMBLOB和JSON外的所有类型。
**适用数据类型**:输入参数 expression 的类型可以是JSON外的所有类型。
**嵌套子查询支持**:适用于内层查询和外层查询。
@ -410,10 +410,10 @@ SELECT CAST(expression AS type_name) FROM { tb_name | stb_name } [WHERE clause]
**使用说明**
- 对于不能支持的类型转换会直接报错。
- 对于类型支持但某些值无法正确转换的情况对应的转换后的值以转换函数输出为准。目前可能遇到的几种情况:
- 对于类型支持但某些值无法正确转换的情况对应的转换后的值以转换函数输出为准。目前可能遇到的几种情况:
1字符串类型转换数值类型时可能出现的无效字符情况例如"a"可能转为0但不会报错。
2转换到数值类型时数值大于type_name可表示的范围时则会溢出但不会报错。
3转换到字符串类型时如果转换后长度超过type_name的长度则会截断但不会报错。
3转换到字符串类型时如果转换后长度超过type_name中指定的长度,则会截断,但不会报错。
#### TO_ISO8601
@ -421,7 +421,7 @@ SELECT CAST(expression AS type_name) FROM { tb_name | stb_name } [WHERE clause]
SELECT TO_ISO8601(ts[, timezone]) FROM { tb_name | stb_name } [WHERE clause];
```
**功能说明**:将 UNIX 时间戳转换成为 ISO8601 标准的日期时间格式并附加时区信息。timezone 参数允许用户为输出结果指定附带任意时区信息。如果 timezone 参数省略,输出结果附带当前客户端的系统时区信息。
**功能说明**:将 UNIX 时间戳转换成为 ISO8601 标准的日期时间格式并附加时区信息。timezone 参数允许用户为输出结果指定附带任意时区信息。如果 timezone 参数省略,输出结果附带当前客户端的系统时区信息。
**返回结果数据类型**VARCHAR 类型。
@ -435,7 +435,7 @@ SELECT TO_ISO8601(ts[, timezone]) FROM { tb_name | stb_name } [WHERE clause];
- timezone 参数允许输入的时区格式为: [z/Z, +/-hhmm, +/-hh, +/-hh:mm]。例如TO_ISO8601(1, "+00:00")。
- 如果输入是表示 UNIX 时间戳的整形,返回格式精度由时间戳的位数决定;
- 如果输入是 TIMSTAMP 类型的列,返回格式的时间戳精度与当前 DATABASE 设置的时间精度一致。
- 如果输入是 TIMESTAMP 类型的列,返回格式的时间戳精度与当前 DATABASE 设置的时间精度一致。
#### TO_JSON
@ -516,7 +516,7 @@ SELECT TIMEDIFF(ts | datetime_string1, ts | datetime_string2 [, time_unit]) FROM
**功能说明**:计算两个时间戳之间的差值,并近似到时间单位 time_unit 指定的精度。
**返回结果数据类型**BIGINT。输入包含不符合时间日期格式字符串则返回 NULL。
**返回结果数据类型**BIGINT。
**应用字段**:表示 UNIX 时间戳的 BIGINT, TIMESTAMP 类型,或符合日期时间格式的 VARCHAR, NCHAR 类型。
@ -528,6 +528,7 @@ SELECT TIMEDIFF(ts | datetime_string1, ts | datetime_string2 [, time_unit]) FROM
- 支持的时间单位 time_unit 如下:
1b(纳秒), 1u(微秒)1a(毫秒)1s(秒)1m(分)1h(小时)1d(天), 1w(周)。
- 如果时间单位 time_unit 未指定, 返回的时间差值精度与当前 DATABASE 设置的时间精度一致。
- 输入包含不符合时间日期格式的字符串则返回 NULL。
#### TIMETRUNCATE
@ -548,6 +549,7 @@ SELECT TIMETRUNCATE(ts | datetime_string , time_unit) FROM { tb_name | stb_name
- 支持的时间单位 time_unit 如下:
1b(纳秒), 1u(微秒)1a(毫秒)1s(秒)1m(分)1h(小时)1d(天), 1w(周)。
- 返回的时间戳精度与当前 DATABASE 设置的时间精度一致。
- 输入包含不符合时间日期格式的字符串则返回 NULL。
#### TIMEZONE
@ -594,6 +596,24 @@ INSERT INTO tb_name VALUES (TODAY(), ...);
TDengine 支持针对数据的聚合查询。提供如下聚合函数。
### APERCENTILE
```sql
SELECT APERCENTILE(field_name, P[, algo_type]) FROM { tb_name | stb_name } [WHERE clause]
```
**功能说明**:统计表/超级表中指定列的值的近似百分比分位数,与 PERCENTILE 函数相似,但是返回近似结果。
**返回数据类型** DOUBLE。
**适用数据类型**:数值类型。
**适用于**:表和超级表。
**说明**
- P值范围是[0,100]当为0时等同于MIN为100时等同于MAX。
- algo_type 取值为 "default" 或 "t-digest"。 输入为 "default" 时函数使用基于直方图算法进行计算。输入为 "t-digest" 时使用t-digest算法计算分位数的近似结果。如果不指定 algo_type 则使用 "default" 算法。
### AVG
```sql
@ -641,8 +661,6 @@ SELECT ELAPSED(ts_primary_key [, time_unit]) FROM { tb_name | stb_name } [WHERE
**适用数据类型**TIMESTAMP。
**支持的版本**2.6.0.0 及以后的版本。
**适用于**: 表,超级表,嵌套查询的外层查询
**说明**
@ -656,6 +674,7 @@ SELECT ELAPSED(ts_primary_key [, time_unit]) FROM { tb_name | stb_name } [WHERE
- 对于嵌套查询仅当内层查询会输出隐式时间戳列时有效。例如select elapsed(ts) from (select diff(value) from sub1)语句diff函数会让内层查询输出隐式时间戳列此为主键列可以用于elapsed函数的第一个参数。相反例如select elapsed(ts) from (select * from sub1) 语句ts列输出到外层时已经没有了主键列的含义无法使用elapsed函数。此外elapsed函数作为一个与时间线强依赖的函数形如select elapsed(ts) from (select diff(value) from st group by tbname)尽管会返回一条计算结果,但并无实际意义,这种用法后续也将被限制。
- 不支持与leastsquares、diff、derivative、top、bottom、last_row、interp等函数混合使用。
### LEASTSQUARES
```sql
@ -671,21 +690,6 @@ SELECT LEASTSQUARES(field_name, start_val, step_val) FROM tb_name [WHERE clause]
**适用于**:表。
### MODE
```sql
SELECT MODE(field_name) FROM tb_name [WHERE clause];
```
**功能说明**返回出现频率最高的值若存在多个频率相同的最高值输出NULL。
**返回数据类型**:与输入数据类型一致。
**适用数据类型**:全部类型字段。
**适用于**:表和超级表。
### SPREAD
```sql
@ -763,44 +767,42 @@ SELECT HISTOGRAM(field_namebin_type, bin_description, normalized) FROM tb_nam
**适用于**: 表和超级表。
**详细说明**
1. bin_type 用户指定的分桶类型, 有效输入类型为"user_input“, ”linear_bin", "log_bin"。
2. bin_description 描述如何生成分桶区间,针对三种桶类型,分别为以下描述格式(均为 JSON 格式字符串)
- bin_type 用户指定的分桶类型, 有效输入类型为"user_input“, ”linear_bin", "log_bin"。
- bin_description 描述如何生成分桶区间,针对三种桶类型,分别为以下描述格式(均为 JSON 格式字符串)
- "user_input": "[1, 3, 5, 7]"
用户指定 bin 的具体数值。
- "linear_bin": "{"start": 0.0, "width": 5.0, "count": 5, "infinity": true}"
"start" 表示数据起始点,"width" 表示每次 bin 偏移量, "count" 为 bin 的总数,"infinity" 表示是否添加(-inf, inf作为区间起点终点,
"start" 表示数据起始点,"width" 表示每次 bin 偏移量, "count" 为 bin 的总数,"infinity" 表示是否添加(-inf, inf作为区间起点终点,
生成区间为[-inf, 0.0, 5.0, 10.0, 15.0, 20.0, +inf]。
- "log_bin": "{"start":1.0, "factor": 2.0, "count": 5, "infinity": true}"
"start" 表示数据起始点,"factor" 表示按指数递增的因子,"count" 为 bin 的总数,"infinity" 表示是否添加(-inf, inf作为区间起点终点,
"start" 表示数据起始点,"factor" 表示按指数递增的因子,"count" 为 bin 的总数,"infinity" 表示是否添加(-inf, inf作为区间起点终点,
生成区间为[-inf, 1.0, 2.0, 4.0, 8.0, 16.0, +inf]。
3. normalized 是否将返回结果归一化到 0~1 之间 。有效输入为 0 和 1。
- normalized 是否将返回结果归一化到 0~1 之间 。有效输入为 0 和 1。
### PERCENTILE
```sql
SELECT PERCENTILE(field_name, P) FROM { tb_name } [WHERE clause];
```
**功能说明**:统计表中某列的值百分比分位数。
**返回数据类型** DOUBLE。
**应用字段**:数值类型。
**适用于**:表。
**使用说明***P*值取值范围 0≤*P*≤100为 0 的时候等同于 MIN为 100 的时候等同于 MAX。
## 选择函数
选择函数根据语义在查询结果集中选择一行或多行结果返回。用户可以同时指定输出 ts 列或其他列(包括 tbname 和标签列),这样就可以方便地知道被选出的值是源于哪个数据行的。
### APERCENTILE
```sql
SELECT APERCENTILE(field_name, P[, algo_type])
FROM { tb_name | stb_name } [WHERE clause]
```
**功能说明**:统计表/超级表中指定列的值的近似百分比分位数,与 PERCENTILE 函数相似,但是返回近似结果。
**返回数据类型** DOUBLE。
**适用数据类型**:数值类型。
**适用于**:表和超级表。
**说明**
- P值范围是[0,100]当为0时等同于MIN为100时等同于MAX。
- algo_type 取值为 "default" 或 "t-digest"。 输入为 "default" 时函数使用基于直方图算法进行计算。输入为 "t-digest" 时使用t-digest算法计算分位数的近似结果。如果不指定 algo_type 则使用 "default" 算法。
### BOTTOM
```sql
@ -935,21 +937,41 @@ SELECT MIN(field_name) FROM {tb_name | stb_name} [WHERE clause];
**适用于**:表和超级表。
### PERCENTILE
### MODE
```sql
SELECT PERCENTILE(field_name, P) FROM { tb_name } [WHERE clause];
SELECT MODE(field_name) FROM tb_name [WHERE clause];
```
**功能说明**统计表中某列的值百分比分位数
**功能说明**返回出现频率最高的值若存在多个频率相同的最高值输出NULL
**返回数据类型** DOUBLE
**返回数据类型**与输入数据类型一致
**应用字段**:数值类型
**适用数据类型**:全部类型字段
**适用于**:表。
**适用于**:表和超级表
**使用说明***P*值取值范围 0≤*P*≤100为 0 的时候等同于 MIN为 100 的时候等同于 MAX。
### SAMPLE
```sql
SELECT SAMPLE(field_name, K) FROM { tb_name | stb_name } [WHERE clause]
```
**功能说明** 获取数据的 k 个采样值。参数 k 的合法输入范围是 1≤ k ≤ 1000。
**返回结果类型** 同原始数据类型, 返回结果中带有该行记录的时间戳。
**适用数据类型** 在超级表查询中使用时,不能应用在标签之上。
**嵌套子查询支持** 适用于内层查询和外层查询。
**适用于**:表和超级表。
**使用说明**
- 不能参与表达式计算;该函数可以应用在普通表和超级表上;
- 使用在超级表上的时候,需要搭配 PARTITION by tbname 使用,将结果强制规约到单个时间线。
### TAIL
@ -1016,7 +1038,7 @@ SELECT CSUM(field_name) FROM { tb_name | stb_name } [WHERE clause]
**功能说明**累加和Cumulative sum输出行与输入行数相同。
**返回结果类型** 输入列如果是整数类型返回值为长整型 int64_t浮点数返回值为双精度浮点数Double。无符号整数类型返回值为无符号长整型uint64_t 返回结果中同时带有每行记录对应的时间戳。
**返回结果类型** 输入列如果是整数类型返回值为长整型 int64_t浮点数返回值为双精度浮点数Double。无符号整数类型返回值为无符号长整型uint64_t
**适用数据类型**:数值类型。
@ -1026,9 +1048,9 @@ SELECT CSUM(field_name) FROM { tb_name | stb_name } [WHERE clause]
**使用说明**
- 不支持 +、-、*、/ 运算,如 csum(col1) + csum(col2)。
- 只能与聚合Aggregation函数一起使用。 该函数可以应用在普通表和超级表上。
- 使用在超级表上的时候,需要搭配 PARTITION BY tbname使用将结果强制规约到单个时间线。
- 不支持 +、-、*、/ 运算,如 csum(col1) + csum(col2)。
- 只能与聚合Aggregation函数一起使用。 该函数可以应用在普通表和超级表上。
- 使用在超级表上的时候,需要搭配 PARTITION BY tbname使用将结果强制规约到单个时间线。
### DERIVATIVE
@ -1045,8 +1067,10 @@ SELECT DERIVATIVE(field_name, time_interval, ignore_negative) FROM tb_name [WHER
**适用于**:表和超级表。
**使用说明**: DERIVATIVE 函数可以在由 PARTITION BY 划分出单独时间线的情况下用于超级表(也即 PARTITION BY tbname
**使用说明**:
- DERIVATIVE 函数可以在由 PARTITION BY 划分出单独时间线的情况下用于超级表(也即 PARTITION BY tbname
- 可以与选择相关联的列一起使用。 例如: select \_rowts, DERIVATIVE() from。
### DIFF
@ -1062,7 +1086,10 @@ SELECT {DIFF(field_name, ignore_negative) | DIFF(field_name)} FROM tb_name [WHER
**适用于**:表和超级表。
**使用说明**: 输出结果行数是范围内总行数减一,第一行没有结果输出。
**使用说明**:
- 输出结果行数是范围内总行数减一,第一行没有结果输出。
- 可以与选择相关联的列一起使用。 例如: select \_rowts, DIFF() from。
### IRATE
@ -1086,42 +1113,22 @@ SELECT IRATE(field_name) FROM tb_name WHERE clause;
SELECT MAVG(field_name, K) FROM { tb_name | stb_name } [WHERE clause]
```
**功能说明** 计算连续 k 个值的移动平均数moving average。如果输入行数小于 k则无结果输出。参数 k 的合法输入范围是 1≤ k ≤ 1000。
**功能说明** 计算连续 k 个值的移动平均数moving average。如果输入行数小于 k则无结果输出。参数 k 的合法输入范围是 1≤ k ≤ 1000。
**返回结果类型** DOUBLE。
**返回结果类型** DOUBLE。
**适用数据类型** 数值类型。
**适用数据类型** 数值类型。
**嵌套子查询支持** 适用于内层查询和外层查询。
**嵌套子查询支持** 适用于内层查询和外层查询。
**适用于**:表和超级表。
**适用于**:表和超级表。
**使用说明**
**使用说明**
- 不支持 +、-、*、/ 运算,如 mavg(col1, k1) + mavg(col2, k1);
- 只能与普通列选择Selection、投影Projection函数一起使用不能与聚合Aggregation函数一起使用
- 使用在超级表上的时候,需要搭配 PARTITION BY tbname使用将结果强制规约到单个时间线。
- 不支持 +、-、*、/ 运算,如 mavg(col1, k1) + mavg(col2, k1);
- 只能与普通列选择Selection、投影Projection函数一起使用不能与聚合Aggregation函数一起使用
- 使用在超级表上的时候,需要搭配 PARTITION BY tbname使用将结果强制规约到单个时间线。
### SAMPLE
```sql
SELECT SAMPLE(field_name, K) FROM { tb_name | stb_name } [WHERE clause]
```
**功能说明** 获取数据的 k 个采样值。参数 k 的合法输入范围是 1≤ k ≤ 1000。
**返回结果类型** 同原始数据类型, 返回结果中带有该行记录的时间戳。
**适用数据类型** 在超级表查询中使用时,不能应用在标签之上。
**嵌套子查询支持** 适用于内层查询和外层查询。
**适用于**:表和超级表。
**使用说明**
- 不能参与表达式计算;该函数可以应用在普通表和超级表上;
- 使用在超级表上的时候,需要搭配 PARTITION by tbname 使用,将结果强制规约到单个时间线。
### STATECOUNT
@ -1162,7 +1169,7 @@ SELECT stateDuration(field_name, oper, val, unit) FROM { tb_name | stb_name } [W
- oper : "LT" (小于)、"GT"(大于)、"LE"(小于等于)、"GE"(大于等于)、"NE"(不等于)、"EQ"(等于),不区分大小写。
- val : 数值型
- unit : 时间长度的单位,范围[1s、1m、1h ],不足一个单位舍去。默认为 1s
- unit : 时间长度的单位,可取值时间单位: 1b(纳秒), 1u(微秒)1a(毫秒)1s(秒)1m(分)1h(小时)1d(天), 1w(周)。如果省略,默认为当前数据库精度
**返回结果类型**INTEGER。

View File

@ -5,7 +5,7 @@ title: REST API
为支持各种不同类型平台的开发TDengine 提供符合 REST 设计标准的 API即 REST API。为最大程度降低学习成本不同于其他数据库 REST API 的设计方法TDengine 直接通过 HTTP POST 请求 BODY 中包含的 SQL 语句来操作数据库,仅需要一个 URL。REST 连接器的使用参见[视频教程](https://www.taosdata.com/blog/2020/11/11/1965.html)。
:::note
与原生连接器的一个区别是RESTful 接口是无状态的,因此 `USE db_name` 指令没有效果,所有对表名、超级表名的引用都需要指定数据库名前缀。从 2.2.0.0 版本开始,支持在 RESTful URL 中指定 db_name这时如果 SQL 语句中没有指定数据库名前缀的话,会使用 URL 中指定的这个 db_name。从 2.4.0.0 版本开始RESTful 默认由 taosAdapter 提供,要求必须在 URL 中指定 db_name。
与原生连接器的一个区别是RESTful 接口是无状态的,因此 `USE db_name` 指令没有效果,所有对表名、超级表名的引用都需要指定数据库名前缀。支持在 RESTful URL 中指定 db_name这时如果 SQL 语句中没有指定数据库名前缀的话,会使用 URL 中指定的这个 db_name。
:::
## 安装
@ -28,54 +28,204 @@ curl -L -H "Authorization: Basic cm9vdDp0YW9zZGF0YQ==" -d "show databases;" h1.t
```json
{
"status": "succ",
"head": [
"name",
"created_time",
"ntables",
"vgroups",
"replica",
"quorum",
"days",
"keep1,keep2,keep(D)",
"cache(MB)",
"blocks",
"minrows",
"maxrows",
"wallevel",
"fsync",
"comp",
"precision",
"status"
],
"data": [
[
"log",
"2020-09-02 17:23:00.039",
4,
1,
1,
1,
10,
"30,30,30",
1,
3,
100,
4096,
1,
3000,
2,
"us",
"ready"
]
],
"rows": 1
"code": 0,
"column_meta": [
[
"name",
"VARCHAR",
64
],
[
"create_time",
"TIMESTAMP",
8
],
[
"vgroups",
"SMALLINT",
2
],
[
"ntables",
"BIGINT",
8
],
[
"replica",
"TINYINT",
1
],
[
"strict",
"VARCHAR",
4
],
[
"duration",
"VARCHAR",
10
],
[
"keep",
"VARCHAR",
32
],
[
"buffer",
"INT",
4
],
[
"pagesize",
"INT",
4
],
[
"pages",
"INT",
4
],
[
"minrows",
"INT",
4
],
[
"maxrows",
"INT",
4
],
[
"comp",
"TINYINT",
1
],
[
"precision",
"VARCHAR",
2
],
[
"status",
"VARCHAR",
10
],
[
"retention",
"VARCHAR",
60
],
[
"single_stable",
"BOOL",
1
],
[
"cachemodel",
"VARCHAR",
11
],
[
"cachesize",
"INT",
4
],
[
"wal_level",
"TINYINT",
1
],
[
"wal_fsync_period",
"INT",
4
],
[
"wal_retention_period",
"INT",
4
],
[
"wal_retention_size",
"BIGINT",
8
],
[
"wal_roll_period",
"INT",
4
],
[
"wal_seg_size",
"BIGINT",
8
]
],
"data": [
[
"information_schema",
null,
null,
14,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
"ready",
null,
null,
null,
null,
null,
null,
null,
null,
null,
null
],
[
"performance_schema",
null,
null,
3,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
"ready",
null,
null,
null,
null,
null,
null,
null,
null,
null,
null
]
],
"rows": 2
}
```
## HTTP 请求格式
```
```text
http://<fqdn>:<port>/rest/sql/[db_name]
```
@ -83,21 +233,21 @@ http://<fqdn>:<port>/rest/sql/[db_name]
- fqnd: 集群中的任一台主机 FQDN 或 IP 地址
- port: 配置文件中 httpPort 配置项,缺省为 6041
- db_name: 可选参数,指定本次所执行的 SQL 语句的默认数据库库名。(从 2.2.0.0 版本开始支持)
- db_name: 可选参数,指定本次所执行的 SQL 语句的默认数据库库名。
例如:`http://h1.taos.com:6041/rest/sql/test` 是指向地址为 `h1.taos.com:6041` 的 URL并将默认使用的数据库库名设置为 `test`。
HTTP 请求的 Header 里需带有身份认证信息TDengine 支持 Basic 认证与自定义认证两种机制,后续版本将提供标准安全的数字签名机制来做身份验证。
- 自定义身份认证信息如下所示token 稍后介绍)
- [自定义身份认证信息](#自定义授权码)如下所示
```
```text
Authorization: Taosd <TOKEN>
```
- Basic 身份认证信息如下所示
```
```text
Authorization: Basic <TOKEN>
```
@ -119,41 +269,165 @@ curl -L -u username:password -d "<SQL>" <ip>:<PORT>/rest/sql/[db_name]
## HTTP 返回格式
返回值为 JSON 格式,如下:
### HTTP 响应码
| **response code** | **说明** |
|-------------------|----------------|
| 200 | 正确返回和 C 接口错误返回 |
| 400 | 参数错误返回 |
| 401 | 鉴权失败 |
| 404 | 接口不存在 |
| 500 | 内部错误 |
| 503 | 系统资源不足 |
### HTTP body 结构
<table>
<tr>
<th>执行结果</th>
<th>说明</th>
<th>样例</th>
</tr>
<tr>
<td>正确执行</td>
<td>
codeint0 代表成功
<br/>
<br/>
column_meta[][3]any列信息每个列会用三个值来说明分别为列名(string)、列类型(string)、类型长度(int)
<br/>
<br/>
rowsint数据返回行数
<br/>
<br/>
data[][]any具体数据内容
</td>
<td>
```json
{
"status": "succ",
"head": ["ts","current", …],
"column_meta": [["ts",9,8],["current",6,4], …],
"data": [
["2018-10-03 14:38:05.000", 10.3, …],
["2018-10-03 14:38:15.000", 12.6, …]
],
"rows": 2
"code": 0,
"column_meta": [["affected_rows", "INT", 4]],
"data": [[0]],
"rows": 1
}
```
说明:
</td>
</tr>
<tr>
<td>正确查询</td>
<td>
codeint0 代表成功
<br/>
<br/>
column_meta[][3]any 列信息每个列会用三个值来说明分别为列名string、列类型string、类型长度int
<br/>
<br/>
rowsint数据返回行数
<br/>
<br/>
data[][]any具体数据内容
</td>
<td>
- status: 告知操作结果是成功还是失败。
- head: 表的定义,如果不返回结果集,则仅有一列 “affected_rows”。从 2.0.17.0 版本开始,建议不要依赖 head 返回值来判断数据列类型,而推荐使用 column_meta。在后续版本中有可能会从返回值中去掉 head 这一项。)
- column_meta: 从 2.0.17.0 版本开始,返回值中增加这一项来说明 data 里每一列的数据类型。具体每个列会用三个值来说明,分别为:列名、列类型、类型长度。例如`["current",6,4]`表示列名为“current”列类型为 6也即 float 类型;类型长度为 4也即对应 4 个字节表示的 float。如果列类型为 binary 或 nchar则类型长度表示该列最多可以保存的内容长度而不是本次返回值中的具体数据长度。当列类型是 nchar 的时候,其类型长度表示可以保存的 unicode 字符数量,而不是 bytes。
- data: 具体返回的数据,一行一行的呈现,如果不返回结果集,那么就仅有 [[affected_rows]]。data 中每一行的数据列顺序,与 column_meta 中描述数据列的顺序完全一致。
- rows: 表明总共多少行数据。
```json
{
"code": 0,
"column_meta": [
["ts", "TIMESTAMP", 8],
["count", "BIGINT", 8],
["endpoint", "VARCHAR", 45],
["status_code", "INT", 4],
["client_ip", "VARCHAR", 40],
["request_method", "VARCHAR", 15],
["request_uri", "VARCHAR", 128]
],
"data": [
[
"2022-06-29T05:50:55.401Z",
2,
"LAPTOP-NNKFTLTG:6041",
200,
"172.23.208.1",
"POST",
"/rest/sql"
],
[
"2022-06-29T05:52:16.603Z",
1,
"LAPTOP-NNKFTLTG:6041",
200,
"172.23.208.1",
"POST",
"/rest/sql"
],
[
"2022-06-29T06:28:14.118Z",
1,
"LAPTOP-NNKFTLTG:6041",
200,
"172.23.208.1",
"POST",
"/rest/sql"
],
[
"2022-06-29T05:52:16.603Z",
2,
"LAPTOP-NNKFTLTG:6041",
401,
"172.23.208.1",
"POST",
"/rest/sql"
]
],
"rows": 4
}
```
column_meta 中的列类型说明:
</td>
</tr>
<tr>
<td>错误</td>
<td>
codeint错误码
<br/>
<br/>
descstring错误描述
</td>
<td>
- 1BOOL
- 2TINYINT
- 3SMALLINT
- 4INT
- 5BIGINT
- 6FLOAT
- 7DOUBLE
- 8BINARY
- 9TIMESTAMP
- 10NCHAR
```json
{
"code": 9728,
"desc": "syntax error near \"1\""
}
```
</td>
</tr>
</table>
### 说明
- 时间格式仅支持 RFC3339结果集为 0 时区
- 列类型使用如下字符串:
> "NULL"
> "BOOL"
> "TINYINT"
> "SMALLINT"
> "INT"
> "BIGINT"
> "FLOAT"
> "DOUBLE"
> "VARCHAR"
> "TIMESTAMP"
> "NCHAR"
> "TINYINT UNSIGNED"
> "SMALLINT UNSIGNED"
> "INT UNSIGNED"
> "BIGINT UNSIGNED"
> "JSON"
## 自定义授权码
@ -199,19 +473,44 @@ curl http://192.168.0.1:6041/rest/login/root/taosdata
```json
{
"status": "succ",
"head": ["ts", "current", "voltage", "phase"],
"column_meta": [
["ts", 9, 8],
["current", 6, 4],
["voltage", 4, 4],
["phase", 6, 4]
],
"data": [
["2018-10-03 14:38:05.000", 10.3, 219, 0.31],
["2018-10-03 14:38:15.000", 12.6, 218, 0.33]
],
"rows": 2
"code": 0,
"column_meta": [
[
"ts",
"TIMESTAMP",
8
],
[
"current",
"FLOAT",
4
],
[
"voltage",
"INT",
4
],
[
"phase",
"FLOAT",
4
]
],
"data": [
[
"2022-07-30T06:44:40.32Z",
10.3,
219,
0.31
],
[
"2022-07-30T06:44:41.32Z",
12.6,
218,
0.33
]
],
"rows": 2
}
```
@ -225,83 +524,23 @@ curl http://192.168.0.1:6041/rest/login/root/taosdata
```json
{
"status": "succ",
"head": ["affected_rows"],
"column_meta": [["affected_rows", 4, 4]],
"data": [[1]],
"rows": 1
"code": 0,
"column_meta": [
[
"affected_rows",
"INT",
4
]
],
"data": [
[
0
]
],
"rows": 1
}
```
## 其他用法
## 参考
### 结果集采用 Unix 时间戳
HTTP 请求 URL 采用 `/rest/sqlt` 时,返回结果集的时间戳将采用 Unix 时间戳格式表示,例如
```bash
curl -L -H "Authorization: Basic cm9vdDp0YW9zZGF0YQ==" -d "select * from demo.d1001" 192.168.0.1:6041/rest/sqlt
```
返回结果:
```json
{
"status": "succ",
"head": ["ts", "current", "voltage", "phase"],
"column_meta": [
["ts", 9, 8],
["current", 6, 4],
["voltage", 4, 4],
["phase", 6, 4]
],
"data": [
[1538548685000, 10.3, 219, 0.31],
[1538548695000, 12.6, 218, 0.33]
],
"rows": 2
}
```
### 结果集采用 UTC 时间字符串
HTTP 请求 URL 采用 `/rest/sqlutc` 时,返回结果集的时间戳将采用 UTC 时间字符串表示,例如
```bash
curl -L -H "Authorization: Basic cm9vdDp0YW9zZGF0YQ==" -d "select * from demo.t1" 192.168.0.1:6041/rest/sqlutc
```
返回值:
```json
{
"status": "succ",
"head": ["ts", "current", "voltage", "phase"],
"column_meta": [
["ts", 9, 8],
["current", 6, 4],
["voltage", 4, 4],
["phase", 6, 4]
],
"data": [
["2018-10-03T14:38:05.000+0800", 10.3, 219, 0.31],
["2018-10-03T14:38:15.000+0800", 12.6, 218, 0.33]
],
"rows": 2
}
```
## 重要配置项
下面仅列出一些与 RESTful 接口有关的配置参数,其他系统参数请看配置文件里的说明。
- 对外提供 RESTful 服务的端口号,默认绑定到 6041实际取值是 serverPort + 11因此可以通过修改 serverPort 参数的设置来修改)。
- httpMaxThreads: 启动的线程数量,默认为 22.0.17.0 版本开始,默认值改为 CPU 核数的一半向下取整)。
- restfulRowLimit: 返回结果集JSON 格式)的最大条数,默认值为 10240。
- httpEnableCompress: 是否支持压缩,默认不支持,目前 TDengine 仅支持 gzip 压缩格式。
- httpDebugFlag: 日志开关,默认 131。131仅错误和报警信息135调试信息143非常详细的调试信息。
- httpDbNameMandatory: 是否必须在 RESTful URL 中指定默认的数据库名。默认为 0即关闭此检查。如果设置为 1那么每个 RESTful URL 中都必须设置一个默认数据库名,否则无论此时执行的 SQL 语句是否需要指定数据库,都会返回一个执行错误,拒绝执行此 SQL 语句。
:::note
如果使用 taosd 提供的 REST API, 那么以上配置需要写在 taosd 的配置文件 taos.cfg 中。如果使用 taosAdapter 提供的 REST API, 那么需要参考 taosAdapter [对应的配置方法](/reference/taosadapter/)。
:::
[taosAdapter](/reference/taosadapter/)

View File

@ -65,7 +65,7 @@ REST 连接支持所有能运行 Go 的平台。
### 使用 go get 安装
`go get -u github.com/taosdata/driver-go/v2@develop`
`go get -u github.com/taosdata/driver-go/v3@latest`
### 使用 go mod 管理
@ -80,7 +80,7 @@ REST 连接支持所有能运行 Go 的平台。
```go
import (
"database/sql"
_ "github.com/taosdata/driver-go/v2/taosSql"
_ "github.com/taosdata/driver-go/v3/taosSql"
)
```
@ -132,7 +132,7 @@ import (
"database/sql"
"fmt"
_ "github.com/taosdata/driver-go/v2/taosSql"
_ "github.com/taosdata/driver-go/v3/taosSql"
)
func main() {
@ -164,7 +164,7 @@ import (
"database/sql"
"fmt"
_ "github.com/taosdata/driver-go/v2/taosRestful"
_ "github.com/taosdata/driver-go/v3/taosRestful"
)
func main() {
@ -205,14 +205,14 @@ func main() {
### 更多示例程序
* [示例程序](https://github.com/taosdata/TDengine/tree/develop/examples/go)
* [示例程序](https://github.com/taosdata/driver-go/tree/3.0/examples)
* [视频教程](https://www.taosdata.com/blog/2020/11/11/1951.html)。
## 使用限制
由于 REST 接口无状态所以 `use db` 语法不会生效,需要将 db 名称放到 SQL 语句中,如:`create table if not exists tb1 (ts timestamp, a int)`改为`create table if not exists test.tb1 (ts timestamp, a int)`否则将报错`[0x217] Database not specified or available`。
也可以将 db 名称放到 DSN 中,将 `root:taosdata@http(localhost:6041)/` 改为 `root:taosdata@http(localhost:6041)/test`,此方法在 TDengine 2.4.0.5 版本的 taosAdapter 开始支持。当指定的 db 不存在时执行 `create database` 语句不会报错,而执行针对该 db 的其他查询或写入操作会报错。
也可以将 db 名称放到 DSN 中,将 `root:taosdata@http(localhost:6041)/` 改为 `root:taosdata@http(localhost:6041)/test`。当指定的 db 不存在时执行 `create database` 语句不会报错,而执行针对该 db 的其他查询或写入操作会报错。
完整示例如下:
@ -224,7 +224,7 @@ import (
"fmt"
"time"
_ "github.com/taosdata/driver-go/v2/taosRestful"
_ "github.com/taosdata/driver-go/v3/taosRestful"
)
func main() {
@ -266,35 +266,27 @@ func main() {
## 常见问题
1. 无法找到包 `github.com/taosdata/driver-go/v2/taosRestful`
将 `go.mod` 中 require 块对`github.com/taosdata/driver-go/v2`的引用改为`github.com/taosdata/driver-go/v2 develop`,之后执行 `go mod tidy`。
2. database/sql 中 stmt参数绑定相关接口崩溃
1. database/sql 中 stmt参数绑定相关接口崩溃
REST 不支持参数绑定相关接口,建议使用`db.Exec`和`db.Query`。
3. 使用 `use db` 语句后执行其他语句报错 `[0x217] Database not specified or available`
2. 使用 `use db` 语句后执行其他语句报错 `[0x217] Database not specified or available`
在 REST 接口中 SQL 语句的执行无上下文关联,使用 `use db` 语句不会生效,解决办法见上方使用限制章节。
4. 使用 taosSql 不报错使用 taosRestful 报错 `[0x217] Database not specified or available`
3. 使用 taosSql 不报错使用 taosRestful 报错 `[0x217] Database not specified or available`
因为 REST 接口无状态,使用 `use db` 语句不会生效,解决办法见上方使用限制章节。
5. 升级 `github.com/taosdata/driver-go/v2/taosRestful`
将 `go.mod` 文件中对 `github.com/taosdata/driver-go/v2` 的引用改为 `github.com/taosdata/driver-go/v2 develop`,之后执行 `go mod tidy`。
6. `readBufferSize` 参数调大后无明显效果
4. `readBufferSize` 参数调大后无明显效果
`readBufferSize` 调大后会减少获取结果时 `syscall` 的调用。如果查询结果的数据量不大,修改该参数不会带来明显提升,如果该参数修改过大,瓶颈会在解析 JSON 数据。如果需要优化查询速度,需要根据实际情况调整该值来达到查询效果最优。
7. `disableCompression` 参数设置为 `false` 时查询效率降低
5. `disableCompression` 参数设置为 `false` 时查询效率降低
当 `disableCompression` 参数设置为 `false` 时查询结果会使用 `gzip` 压缩后传输,拿到数据后要先进行 `gzip` 解压。
8. `go get` 命令无法获取包,或者获取包超时
6. `go get` 命令无法获取包,或者获取包超时
设置 Go 代理 `go env -w GOPROXY=https://goproxy.cn,direct`。
@ -334,17 +326,33 @@ func main() {
#### 订阅
* `func (conn *Connector) Subscribe(restart bool, topic string, sql string, interval time.Duration) (Subscriber, error)`
* `func NewConsumer(conf *Config) (*Consumer, error)`
订阅数据
创建消费者
* `func (s *taosSubscriber) Consume() (driver.Rows, error)`
* `func (c *Consumer) Subscribe(topics []string) error`
消费订阅数据,返回 `database/sql/driver` 包的 `Rows` 结构
订阅主题
* `func (s *taosSubscriber) Unsubscribe(keepProgress bool)`
* `func (c *Consumer) Poll(timeout time.Duration) (*Result, error)`
取消订阅数据。
轮询消息。
* `func (c *Consumer) Commit(ctx context.Context, message unsafe.Pointer) error`
提交消息。
* `func (c *Consumer) FreeMessage(message unsafe.Pointer)`
释放消息。
* `func (c *Consumer) Unsubscribe() error`
取消订阅。
* `func (c *Consumer) Close() error`
关闭消费者。
#### schemaless
@ -366,10 +374,6 @@ func main() {
参数绑定单行插入。
* `func (conn *Connector) StmtQuery(sql string, params *param.Param) (rows driver.Rows, err error)`
参数绑定查询,返回 `database/sql/driver` 包的 `Rows` 结构。
* `func (conn *Connector) InsertStmt() *insertstmt.InsertStmt`
初始化参数。
@ -408,4 +412,4 @@ func main() {
## API 参考
全部 API 见 [driver-go 文档](https://pkg.go.dev/github.com/taosdata/driver-go/v2)
全部 API 见 [driver-go 文档](https://pkg.go.dev/github.com/taosdata/driver-go/v3)

View File

@ -30,7 +30,7 @@ taosAdapter 提供以下功能:
### 安装 taosAdapter
taosAdapter 从 TDengine v2.4.0.0 版本开始成为 TDengine 服务端软件 的一部分,如果您使用 TDengine server 您不需要任何额外的步骤来安装 taosAdapter。您可以从[涛思数据官方网站](https://taosdata.com/cn/all-downloads/)下载 TDengine servertaosAdapter 包含在 v2.4.0.0 及以上版本)安装包。如果需要将 taosAdapter 分离部署在 TDengine server 之外的服务器上,则应该在该服务器上安装完整的 TDengine 来安装 taosAdapter。如果您需要使用源代码编译生成 taosAdapter您可以参考[构建 taosAdapter](https://github.com/taosdata/taosadapter/blob/develop/BUILD-CN.md)文档。
taosAdapter 从 TDengine v2.4.0.0 版本开始成为 TDengine 服务端软件 的一部分,如果您使用 TDengine server 您不需要任何额外的步骤来安装 taosAdapter。您可以从[涛思数据官方网站](https://taosdata.com/cn/all-downloads/)下载 TDengine servertaosAdapter 包含在 v2.4.0.0 及以上版本)安装包。如果需要将 taosAdapter 分离部署在 TDengine server 之外的服务器上,则应该在该服务器上安装完整的 TDengine 来安装 taosAdapter。如果您需要使用源代码编译生成 taosAdapter您可以参考[构建 taosAdapter](https://github.com/taosdata/taosadapter/blob/3.0/BUILD-CN.md)文档。
### start/stop taosAdapter
@ -69,20 +69,23 @@ Usage of taosAdapter:
--debug enable debug mode. Env "TAOS_ADAPTER_DEBUG"
--help Print this help message and exit
--influxdb.enable enable influxdb. Env "TAOS_ADAPTER_INFLUXDB_ENABLE" (default true)
--log.enableRecordHttpSql whether to record http sql. Env "TAOS_ADAPTER_LOG_ENABLE_RECORD_HTTP_SQL"
--log.path string log path. Env "TAOS_ADAPTER_LOG_PATH" (default "/var/log/taos")
--log.rotationCount uint log rotation count. Env "TAOS_ADAPTER_LOG_ROTATION_COUNT" (default 30)
--log.rotationSize string log rotation size(KB MB GB), must be a positive integer. Env "TAOS_ADAPTER_LOG_ROTATION_SIZE" (default "1GB")
--log.rotationTime duration log rotation time. Env "TAOS_ADAPTER_LOG_ROTATION_TIME" (default 24h0m0s)
--log.sqlRotationCount uint record sql log rotation count. Env "TAOS_ADAPTER_LOG_SQL_ROTATION_COUNT" (default 2)
--log.sqlRotationSize string record sql log rotation size(KB MB GB), must be a positive integer. Env "TAOS_ADAPTER_LOG_SQL_ROTATION_SIZE" (default "1GB")
--log.sqlRotationTime duration record sql log rotation time. Env "TAOS_ADAPTER_LOG_SQL_ROTATION_TIME" (default 24h0m0s)
--logLevel string log level (panic fatal error warn warning info debug trace). Env "TAOS_ADAPTER_LOG_LEVEL" (default "info")
--monitor.collectDuration duration Set monitor duration. Env "TAOS_MONITOR_COLLECT_DURATION" (default 3s)
--monitor.identity string The identity of the current instance, or 'hostname:port' if it is empty. Env "TAOS_MONITOR_IDENTITY"
--monitor.incgroup Whether running in cgroup. Env "TAOS_MONITOR_INCGROUP"
--monitor.password string TDengine password. Env "TAOS_MONITOR_PASSWORD" (default "taosdata")
--monitor.pauseAllMemoryThreshold float Memory percentage threshold for pause all. Env "TAOS_MONITOR_PAUSE_ALL_MEMORY_THRESHOLD" (default 80)
--monitor.password string TDengine password. Env "TAOS_MONITOR_PASSWORD" (default "taosdata") --monitor.pauseAllMemoryThreshold float Memory percentage threshold for pause all. Env "TAOS_MONITOR_PAUSE_ALL_MEMORY_THRESHOLD" (default 80)
--monitor.pauseQueryMemoryThreshold float Memory percentage threshold for pause query. Env "TAOS_MONITOR_PAUSE_QUERY_MEMORY_THRESHOLD" (default 70)
--monitor.user string TDengine user. Env "TAOS_MONITOR_USER" (default "root")
--monitor.writeInterval duration Set write to TDengine interval. Env "TAOS_MONITOR_WRITE_INTERVAL" (default 30s)
--monitor.writeToTD Whether write metrics to TDengine. Env "TAOS_MONITOR_WRITE_TO_TD" (default true)
--monitor.writeToTD Whether write metrics to TDengine. Env "TAOS_MONITOR_WRITE_TO_TD"
--node_exporter.caCertFile string node_exporter ca cert file path. Env "TAOS_ADAPTER_NODE_EXPORTER_CA_CERT_FILE"
--node_exporter.certFile string node_exporter cert file path. Env "TAOS_ADAPTER_NODE_EXPORTER_CERT_FILE"
--node_exporter.db string node_exporter db name. Env "TAOS_ADAPTER_NODE_EXPORTER_DB" (default "node_exporter")
@ -98,8 +101,10 @@ Usage of taosAdapter:
--node_exporter.urls strings node_exporter urls. Env "TAOS_ADAPTER_NODE_EXPORTER_URLS" (default [http://localhost:9100])
--node_exporter.user string node_exporter user. Env "TAOS_ADAPTER_NODE_EXPORTER_USER" (default "root")
--opentsdb.enable enable opentsdb. Env "TAOS_ADAPTER_OPENTSDB_ENABLE" (default true)
--opentsdb_telnet.batchSize int opentsdb_telnet batch size. Env "TAOS_ADAPTER_OPENTSDB_TELNET_BATCH_SIZE" (default 1)
--opentsdb_telnet.dbs strings opentsdb_telnet db names. Env "TAOS_ADAPTER_OPENTSDB_TELNET_DBS" (default [opentsdb_telnet,collectd_tsdb,icinga2_tsdb,tcollector_tsdb])
--opentsdb_telnet.enable enable opentsdb telnet,warning: without auth info(default false). Env "TAOS_ADAPTER_OPENTSDB_TELNET_ENABLE"
--opentsdb_telnet.flushInterval duration opentsdb_telnet flush interval (0s means not valid) . Env "TAOS_ADAPTER_OPENTSDB_TELNET_FLUSH_INTERVAL"
--opentsdb_telnet.maxTCPConnections int max tcp connections. Env "TAOS_ADAPTER_OPENTSDB_TELNET_MAX_TCP_CONNECTIONS" (default 250)
--opentsdb_telnet.password string opentsdb_telnet password. Env "TAOS_ADAPTER_OPENTSDB_TELNET_PASSWORD" (default "taosdata")
--opentsdb_telnet.ports ints opentsdb telnet tcp port. Env "TAOS_ADAPTER_OPENTSDB_TELNET_PORTS" (default [6046,6047,6048,6049])
@ -111,9 +116,6 @@ Usage of taosAdapter:
-P, --port int http port. Env "TAOS_ADAPTER_PORT" (default 6041)
--prometheus.enable enable prometheus. Env "TAOS_ADAPTER_PROMETHEUS_ENABLE" (default true)
--restfulRowLimit int restful returns the maximum number of rows (-1 means no limit). Env "TAOS_ADAPTER_RESTFUL_ROW_LIMIT" (default -1)
--ssl.certFile string ssl cert file path. Env "TAOS_ADAPTER_SSL_CERT_FILE"
--ssl.enable enable ssl. Env "TAOS_ADAPTER_SSL_ENABLE"
--ssl.keyFile string ssl key file path. Env "TAOS_ADAPTER_SSL_KEY_FILE"
--statsd.allowPendingMessages int statsd allow pending messages. Env "TAOS_ADAPTER_STATSD_ALLOW_PENDING_MESSAGES" (default 50000)
--statsd.db string statsd db name. Env "TAOS_ADAPTER_STATSD_DB" (default "statsd")
--statsd.deleteCounters statsd delete counter cache after gather. Env "TAOS_ADAPTER_STATSD_DELETE_COUNTERS" (default true)
@ -149,12 +151,12 @@ AllowWebSockets
关于 CORS 协议细节请参考:[https://www.w3.org/wiki/CORS_Enabled](https://www.w3.org/wiki/CORS_Enabled) 或 [https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CORS](https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CORS)。
示例配置文件参见 [example/config/taosadapter.toml](https://github.com/taosdata/taosadapter/blob/develop/example/config/taosadapter.toml)。
示例配置文件参见 [example/config/taosadapter.toml](https://github.com/taosdata/taosadapter/blob/3.0/example/config/taosadapter.toml)。
## 功能列表
- RESTful 接口兼容
[https://www.taosdata.com/cn/documentation/connector#restful](https://www.taosdata.com/cn/documentation/connector#restful)
- RESTful 接口
[https://docs.taosdata.com/reference/rest-api/](https://docs.taosdata.com/reference/rest-api/)
- 兼容 InfluxDB v1 写接口
[https://docs.influxdata.com/influxdb/v2.0/reference/api/influxdb-1x/write/](https://docs.influxdata.com/influxdb/v2.0/reference/api/influxdb-1x/write/)
- 兼容 OpenTSDB JSON 和 telnet 格式写入
@ -167,7 +169,7 @@ AllowWebSockets
- 与 icinga2 的无缝连接
icinga2 是一个收集检查结果指标和性能数据的软件。请访问 [https://icinga.com/docs/icinga-2/latest/doc/14-features/#opentsdb-writer](https://icinga.com/docs/icinga-2/latest/doc/14-features/#opentsdb-writer) 了解更多信息。
- 与 tcollector 无缝连接
TCollector 是一个客户端进程,从本地收集器收集数据,并将数据推送到 OpenTSDB。请访问 [http://opentsdb.net/docs/build/html/user_guide/utilities/tcollector.html](http://opentsdb.net/docs/build/html/user_guide/utilities/tcollector.html) 了解更多信息。
TCollector是一个客户端进程从本地收集器收集数据并将数据推送到 OpenTSDB。请访问 [http://opentsdb.net/docs/build/html/user_guide/utilities/tcollector.html](http://opentsdb.net/docs/build/html/user_guide/utilities/tcollector.html) 了解更多信息。
- 无缝连接 node_exporter
node_export 是一个机器指标的导出器。请访问 [https://github.com/prometheus/node_exporter](https://github.com/prometheus/node_exporter) 了解更多信息。
- 支持 Prometheus remote_read 和 remote_write
@ -177,13 +179,7 @@ AllowWebSockets
### TDengine RESTful 接口
您可以使用任何支持 http 协议的客户端通过访问 RESTful 接口地址 `http://<fqdn>:6041/<APIEndPoint>` 来写入数据到 TDengine 或从 TDengine 中查询数据。细节请参考[官方文档](/reference/connector#restful)。支持如下 EndPoint
```text
/rest/sql
/rest/sqlt
/rest/sqlutc
```
您可以使用任何支持 http 协议的客户端通过访问 RESTful 接口地址 `http://<fqdn>:6041/rest/sql` 来写入数据到 TDengine 或从 TDengine 中查询数据。细节请参考[官方文档](/reference/rest-api/)。
### InfluxDB
@ -229,7 +225,7 @@ AllowWebSockets
### node_exporter
Prometheus 使用的由\*NIX 内核暴露的硬件和操作系统指标的输出器
Prometheus 使用的由 \*NIX 内核暴露的硬件和操作系统指标的输出器
- 启用 taosAdapter 的配置 node_exporter.enable
- 设置 node_exporter 的相关配置
@ -297,15 +293,15 @@ taosAdapter 支持将 http 监控、cpu 百分比和内存百分比写入 TDengi
有关配置参数
| **配置项** | **描述** | **默认值** |
| ----------------------- | --------------------------------------------------------- | ---------- |
| monitor.collectDuration | cpu 和内存采集间隔 | 3s |
| monitor.identity | 当前 taosadapter 的标识符如果不设置将使用 'hostname:port' | |
| monitor.incgroup | 是否是 cgroup 中运行(容器中运行设置为 true) | false |
| monitor.writeToTD | 是否写入到 TDengine | true |
| monitor.user | TDengine 连接用户名 | root |
| monitor.password | TDengine 连接密码 | taosdata |
| monitor.writeInterval | 写入 TDengine 间隔 | 30s |
| **配置项** | **描述** | **默认值** |
|-------------------------|--------------------------------------------|----------|
| monitor.collectDuration | cpu 和内存采集间隔 | 3s |
| monitor.identity | 当前taosadapter 的标识符如果不设置将使用 'hostname:port' | |
| monitor.incgroup | 是否是 cgroup 中运行(容器中运行设置为 true) | false |
| monitor.writeToTD | 是否写入到 TDengine | false |
| monitor.user | TDengine 连接用户名 | root |
| monitor.password | TDengine 连接密码 | taosdata |
| monitor.writeInterval | 写入TDengine 间隔 | 30s |
## 结果返回条数限制
@ -314,8 +310,6 @@ taosAdapter 通过参数 `restfulRowLimit` 来控制结果的返回条数,-1
该参数控制以下接口返回
- `http://<fqdn>:6041/rest/sql`
- `http://<fqdn>:6041/rest/sqlt`
- `http://<fqdn>:6041/rest/sqlutc`
- `http://<fqdn>:6041/prometheus/v1/remote_read/:db`
## 故障解决
@ -328,11 +322,11 @@ taosAdapter 通过参数 `restfulRowLimit` 来控制结果的返回条数,-1
在 TDengine server 2.2.x.x 或更早期版本中taosd 进程包含一个内嵌的 http 服务。如前面所述taosAdapter 是一个使用 systemd 管理的独立软件,拥有自己的进程。并且两者有一些配置参数和行为是不同的,请见下表:
| **#** | **embedded httpd** | **taosAdapter** | **comment** |
| ----- | ------------------- | ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------ |
| 1 | httpEnableRecordSql | --logLevel=debug | |
| 2 | httpMaxThreads | n/a | taosAdapter 自动管理线程池,无需此参数 |
| 3 | telegrafUseFieldNum | 请参考 taosAdapter telegraf 配置方法 | |
| 4 | restfulRowLimit | restfulRowLimit | 内嵌 httpd 默认输出 10240 行数据,最大允许值为 102400。taosAdapter 也提供 restfulRowLimit 但是默认不做限制。您可以根据实际场景需求进行配置 |
| 5 | httpDebugFlag | 不适用 | httpdDebugFlag 对 taosAdapter 不起作用 |
| 6 | httpDBNameMandatory | 不适用 | taosAdapter 要求 URL 中必须指定数据库名 |
| **#** | **embedded httpd** | **taosAdapter** | **comment** |
|-------|---------------------|-------------------------------|------------------------------------------------------------------------------------------------|
| 1 | httpEnableRecordSql | --logLevel=debug | |
| 2 | httpMaxThreads | n/a | taosAdapter 自动管理线程池,无需此参数 |
| 3 | telegrafUseFieldNum | 请参考 taosAdapter telegraf 配置方法 |
| 4 | restfulRowLimit | restfulRowLimit | 内嵌 httpd 默认输出 10240 行数据,最大允许值为 102400。taosAdapter 也提供 restfulRowLimit 但是默认不做限制。您可以根据实际场景需求进行配置 |
| 5 | httpDebugFlag | 不适用 | httpdDebugFlag 对 taosAdapter 不起作用 |
| 6 | httpDBNameMandatory | 不适用 | taosAdapter 要求 URL 中必须指定数据库名 |

View File

@ -1,6 +1,6 @@
---
title: 配置参数
description: 'TDengine 客户端和服务配置列表'
description: "TDengine 客户端和服务配置列表"
---
## 为服务端指定配置文件
@ -21,8 +21,6 @@ taosd -C
TDengine 系统的前台交互客户端应用程序为 taos以及应用驱动它可以与 taosd 共享同一个配置文件 taos.cfg也可以使用单独指定配置文件。运行 taos 时,使用参数-c 指定配置文件目录,如 taos -c /home/cfg表示使用/home/cfg/目录下的 taos.cfg 配置文件中的参数,缺省目录是/etc/taos。更多 taos 的使用方法请见帮助信息 `taos --help`
**2.0.10.0 之后版本支持命令行以下参数显示当前客户端参数的配置**
```bash
taos -C
```
@ -47,19 +45,19 @@ taos --dump-config
### firstEp
| 属性 | 说明 |
| -------- | --------------------------------------------------------------- |
| 适用范围 | 服务端和客户端均适用 |
| 属性 | 说明 |
| -------- | -------------------------------------------------------------- |
| 适用范围 | 服务端和客户端均适用 |
| 含义 | taosd 或者 taos 启动时,主动连接的集群中首个 dnode 的 endpoint |
| 缺省值 | localhost:6030 |
| 缺省值 | localhost:6030 |
### secondEp
| 属性 | 说明 |
| -------- | -------------------------------------------------------------------------------------- |
| 适用范围 | 服务端和客户端均适用 |
| 属性 | 说明 |
| -------- | ------------------------------------------------------------------------------------- |
| 适用范围 | 服务端和客户端均适用 |
| 含义 | taosd 或者 taos 启动时,如果 firstEp 连接不上,尝试连接集群中第二个 dnode 的 endpoint |
| 缺省值 | 无 |
| 缺省值 | 无 |
### fqdn
@ -77,7 +75,6 @@ taos --dump-config
| 适用范围 | 仅服务端适用 |
| 含义 | taosd 启动后,对外服务的端口号 |
| 缺省值 | 6030 |
| 补充说明 | RESTful 服务在 2.4.0.0 之前(不含)由 taosd 提供,默认端口为 6041; 在 2.4.0.0 及后续版本由 taosAdapter默认端口为 6041 |
:::note
确保集群中所有主机在端口 6030 上的 TCP 协议能够互通。(详细的端口情况请参见下表)
@ -87,8 +84,8 @@ taos --dump-config
| TCP | 6030 | 客户端与服务端之间通讯,多节点集群的节点间通讯。 | 由配置文件设置 serverPort 决定。 |
| TCP | 6041 | 客户端与服务端之间的 RESTful 通讯。 | 随 serverPort 端口变化。注意 taosAdapter 配置或有不同,请参考相应[文档](/reference/taosadapter/)。 |
| TCP | 6043 | TaosKeeper 监控服务端口。 | 随 TaosKeeper 启动参数设置变化。 |
| TCP | 6044 | 支持 StatsD 的数据接入端口。 | 随 taosAdapter 启动参数设置变化2.3.0.1+以上版本)。 |
| UDP | 6045 | 支持 collectd 数据接入端口。 | 随 taosAdapter 启动参数设置变化2.3.0.1+以上版本)。 |
| TCP | 6044 | 支持 StatsD 的数据接入端口。 | 随 taosAdapter 启动参数设置变化|
| UDP | 6045 | 支持 collectd 数据接入端口。 | 随 taosAdapter 启动参数设置变化 |
| TCP | 6060 | 企业版内 Monitor 服务的网络端口。 | |
### maxShellConns
@ -104,28 +101,28 @@ taos --dump-config
### monitor
| 属性 | 说明 |
| -------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| 适用范围 | 仅服务端适用 |
| 属性 | 说明 |
| -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 适用范围 | 仅服务端适用 |
| 含义 | 服务器内部的系统监控开关。监控主要负责收集物理节点的负载状况,包括 CPU、内存、硬盘、网络带宽的监控记录监控信息将通过 HTTP 协议发送给由 `monitorFqdn``monitorProt` 指定的 TaosKeeper 监控服务 |
| 取值范围 | 0关闭监控服务 1激活监控服务。 |
| 缺省值 | 1 |
| 取值范围 | 0关闭监控服务 1激活监控服务。 |
| 缺省值 | 1 |
### monitorFqdn
| 属性 | 说明 |
| -------- | -------------------------------------------- |
| 适用范围 | 仅服务端适用 |
| 属性 | 说明 |
| -------- | -------------------------- |
| 适用范围 | 仅服务端适用 |
| 含义 | TaosKeeper 监控服务的 FQDN |
| 缺省值 | 无 |
| 缺省值 | 无 |
### monitorPort
| 属性 | 说明 |
| -------- | -------------------------------------------- |
| 适用范围 | 仅服务端适用 |
| 属性 | 说明 |
| -------- | --------------------------- |
| 适用范围 | 仅服务端适用 |
| 含义 | TaosKeeper 监控服务的端口号 |
| 缺省值 | 6043 |
| 缺省值 | 6043 |
### monitorInterval
@ -134,10 +131,9 @@ taos --dump-config
| 适用范围 | 仅服务端适用 |
| 含义 | 监控数据库记录系统参数CPU/内存)的时间间隔 |
| 单位 | 秒 |
| 取值范围 | 1-200000 |
| 取值范围 | 1-200000 |
| 缺省值 | 30 |
### telemetryReporting
| 属性 | 说明 |
@ -149,25 +145,43 @@ taos --dump-config
## 查询相关
### queryBufferSize
### queryPolicy
| 属性 | 说明 |
| -------- | ----------------------------- |
| 适用范围 | 仅客户端适用 |
| 含义 | 查询语句的执行策略 |
| 单位 | 无 |
| 缺省值 | 1 |
| 补充说明 | 1: 只使用 vnode不使用 qnode |
2: 没有扫描算子的子任务在 qnode 执行,带扫描算子的子任务在 vnode 执行
3: vnode 只运行扫描算子,其余算子均在 qnode 执行 |
### querySmaOptimize
| 属性 | 说明 |
| -------- | -------------------- |
| 适用范围 | 仅客户端适用 |
| 含义 | sma index 的优化策略 |
| 单位 | 无 |
| 缺省值 | 0 |
| 补充说明 |
0: 表示不使用 sma index永远从原始数据进行查询
1: 表示使用 sma index对符合的语句直接从预计算的结果进行查询 |
| 属性 | 说明 |
| -------- | ------------------------------------------------------------------------------------------------------------------- |
| 适用范围 | 仅服务端适用 |
| 含义 | 为所有并发查询占用保留的内存大小。 |
| 单位 | MB |
| 缺省值 | 无 |
| 补充说明 | 计算规则可以根据实际应用可能的最大并发数和表的数字相乘,再乘 170 。<br/>2.0.15 以前的版本中,此参数的单位是字节) |
### maxNumOfDistinctRes
| 属性 | 说明 |
| -------- | -------------------------------- |
| -------- | -------------------------------- | --- |
| 适用范围 | 仅服务端适用 |
| 含义 | 允许返回的 distinct 结果最大行数 |
| 取值范围 | 默认值为 10 万,最大值 1 亿 |
| 缺省值 | 10 万 |
| 补充说明 | 2.3 版本新增。 | |
## 区域相关
@ -306,12 +320,12 @@ charset 的有效值是 UTF-8。
### supportVnodes
| 属性 | 说明 |
| -------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| 适用范围 | 仅服务端适用 |
| 含义 | dnode 支持的最大 vnode 数目 |
| 取值范围 | 0-4096 |
| 缺省值 | 256 |
| 属性 | 说明 |
| -------- | --------------------------- |
| 适用范围 | 仅服务端适用 |
| 含义 | dnode 支持的最大 vnode 数目 |
| 取值范围 | 0-4096 |
| 缺省值 | 256 |
## 时间相关
@ -366,37 +380,6 @@ charset 的有效值是 UTF-8。
| 单位 | bytes |
| 取值范围 | 0: 对所有查询结果均进行压缩 >0: 查询结果中任意列大小超过该值的消息才进行压缩 -1: 不压缩 |
| 缺省值 | -1 |
| 补充说明 | 2.3.0.0 版本新增。 |
### lossyColumns
| 属性 | 说明 |
| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| 适用范围 | 服务器端 |
| 含义 | 配置要进行有损压缩的浮点数据类型 |
| 取值范围 | 空字符串:关闭有损压缩 <br/> float只对 float 类型进行有损压缩 <br/>double只对 double 类型进行有损压缩 <br/> float \| doublefloat double 都进行有损压缩 |
| 缺省值 | 空字符串 |
| 补充说明 | 有损压缩默认为关闭状态,只有配置后才生效 |
### fPrecision
| 属性 | 说明 |
| -------- | -------------------------------- |
| 适用范围 | 服务器端 |
| 含义 | 设置 float 类型浮点数压缩精度 |
| 取值范围 | 0.1 ~ 0.00000001 |
| 缺省值 | 0.00000001 |
| 补充说明 | 小于此值的浮点数尾数部分将被截取 |
### dPrecision
| 属性 | 说明 |
| -------- | -------------------------------- |
| 适用范围 | 服务器端 |
| 含义 | 设置 double 类型浮点数压缩精度 |
| 取值范围 | 0.1 ~ 0.0000000000000001 |
| 缺省值 | 0.0000000000000001 |
| 补充说明 | 小于此值的浮点数尾数部分将被截取 |
## 日志相关
@ -453,50 +436,23 @@ charset 的有效值是 UTF-8。
| 取值范围 | 131输出错误和警告日志135输出错误、警告和调试日志143输出错误、警告、调试和跟踪日志 |
| 缺省值 | 131 或 135不同模块有不同的默认值 |
### mDebugFlag
| 属性 | 说明 |
| -------- | ------------------ |
| 适用范围 | 仅服务端适用 |
| 含义 | 管理模块的日志开关 |
| 取值范围 | 同上 |
| 缺省值 | 135 |
### dDebugFlag
### tmrDebugFlag
| 属性 | 说明 |
| -------- | -------------------- |
| 适用范围 | 服务端和客户端均适用 |
| 含义 | dnode 模块的日志开关 |
| 含义 | 定时器模块的日志开关 |
| 取值范围 | 同上 |
| 缺省值 | 135 |
| 缺省值 | |
### sDebugFlag
### uDebugFlag
| 属性 | 说明 |
| -------- | -------------------- |
| 适用范围 | 服务端和客户端均适用 |
| 含义 | sync 模块的日志开关 |
| 取值范围 | 同上 |
| 缺省值 | 135 |
### wDebugFlag
| 属性 | 说明 |
| -------- | -------------------- |
| 适用范围 | 服务端和客户端均适用 |
| 含义 | WAL 模块的日志开关 |
| 取值范围 | 同上 |
| 缺省值 | 135 |
### sdbDebugFlag
| 属性 | 说明 |
| -------- | -------------------- |
| 适用范围 | 服务端和客户端均适用 |
| 含义 | sdb 模块的日志开关 |
| 取值范围 | 同上 |
| 缺省值 | 135 |
| 属性 | 说明 |
| -------- | ---------------------- |
| 适用范围 | 服务端和客户端均适用 |
| 含义 | 共用功能模块的日志开关 |
| 取值范围 | 同上 |
| 缺省值 | |
### rpcDebugFlag
@ -507,12 +463,21 @@ charset 的有效值是 UTF-8。
| 取值范围 | 同上 |
| 缺省值 | |
### tmrDebugFlag
### jniDebugFlag
| 属性 | 说明 |
| -------- | ------------------ |
| 适用范围 | 仅客户端适用 |
| 含义 | jni 模块的日志开关 |
| 取值范围 | 同上 |
| 缺省值 | |
### qDebugFlag
| 属性 | 说明 |
| -------- | -------------------- |
| 适用范围 | 服务端和客户端均适用 |
| 含义 | 定时器模块的日志开关 |
| 含义 | query 模块的日志开关 |
| 取值范围 | 同上 |
| 缺省值 | |
@ -525,157 +490,142 @@ charset 的有效值是 UTF-8。
| 取值范围 | 同上 |
| 缺省值 | |
### jniDebugFlag
| 属性 | 说明 |
| -------- | ------------------ |
| 适用范围 | 仅客户端适用 |
| 含义 | jni 模块的日志开关 |
| 取值范围 | 同上 |
| 缺省值 | |
### odbcDebugFlag
| 属性 | 说明 |
| -------- | ------------------- |
| 适用范围 | 仅客户端适用 |
| 含义 | odbc 模块的日志开关 |
| 取值范围 | 同上 |
| 缺省值 | |
### uDebugFlag
| 属性 | 说明 |
| -------- | ---------------------- |
| 适用范围 | 服务端和客户端均适用 |
| 含义 | 共用功能模块的日志开关 |
| 取值范围 | 同上 |
| 缺省值 | |
### httpDebugFlag
| 属性 | 说明 |
| -------- | ------------------- |
| 适用范围 | 仅服务端适用 |
| 含义 | http 模块的日志开关 |
| 取值范围 | 同上 |
| 缺省值 | |
### mqttDebugFlag
| 属性 | 说明 |
| -------- | ------------------- |
| 适用范围 | 仅服务端适用 |
| 含义 | mqtt 模块的日志开关 |
| 取值范围 | 同上 |
| 缺省值 | |
### monitorDebugFlag
| 属性 | 说明 |
| -------- | ------------------ |
| 适用范围 | 仅服务端适用 |
| 含义 | 监控模块的日志开关 |
| 取值范围 | 同上 |
| 缺省值 | |
### qDebugFlag
### dDebugFlag
| 属性 | 说明 |
| -------- | -------------------- |
| 适用范围 | 服务端和客户端均适用 |
| 含义 | 查询模块的日志开关 |
| 适用范围 | 仅服务端适用 |
| 含义 | dnode 模块的日志开关 |
| 取值范围 | 同上 |
| 缺省值 | |
| 缺省值 | 135 |
### vDebugFlag
| 属性 | 说明 |
| -------- | -------------------- |
| 适用范围 | 服务端和客户端均适用 |
| 适用范围 | 仅服务端适用 |
| 含义 | vnode 模块的日志开关 |
| 取值范围 | 同上 |
| 缺省值 | |
### mDebugFlag
| 属性 | 说明 |
| -------- | -------------------- |
| 适用范围 | 仅服务端适用 |
| 含义 | mnode 模块的日志开关 |
| 取值范围 | 同上 |
| 缺省值 | 135 |
### wDebugFlag
| 属性 | 说明 |
| -------- | ------------------ |
| 适用范围 | 仅服务端适用 |
| 含义 | wal 模块的日志开关 |
| 取值范围 | 同上 |
| 缺省值 | 135 |
### sDebugFlag
| 属性 | 说明 |
| -------- | -------------------- |
| 适用范围 | 服务端和客户端均适用 |
| 含义 | sync 模块的日志开关 |
| 取值范围 | 同上 |
| 缺省值 | 135 |
### tsdbDebugFlag
| 属性 | 说明 |
| -------- | ------------------- |
| 适用范围 | 仅服务端适用 |
| 含义 | TSDB 模块的日志开关 |
| 含义 | tsdb 模块的日志开关 |
| 取值范围 | 同上 |
| 缺省值 | |
### cqDebugFlag
### tqDebugFlag
| 属性 | 说明 |
| -------- | ---------------------- |
| 适用范围 | 服务端和客户端均适用 |
| 含义 | 连续查询模块的日志开关 |
| 取值范围 | 同上 |
| 缺省值 | |
| 属性 | 说明 |
| -------- | ----------------- |
| 适用范围 | 服务端适用 |
| 含义 | tq 模块的日志开关 |
| 取值范围 | 同上 |
| 缺省值 | |
## 仅客户端适用
### fsDebugFlag
### maxSQLLength
| 属性 | 说明 |
| -------- | ----------------- |
| 适用范围 | 仅服务端适用 |
| 含义 | fs 模块的日志开关 |
| 取值范围 | 同上 |
| 缺省值 | |
| 属性 | 说明 |
| -------- | --------------------------- |
| 适用范围 | 仅客户端适用 |
| 含义 | 单条 SQL 语句允许的最长限制 |
| 单位 | bytes |
| 取值范围 | 65480-1048576 |
| 缺省值 | 1048576 |
### udfDebugFlag
### tscEnableRecordSql
| 属性 | 说明 |
| -------- | ------------------ |
| 适用范围 | 仅服务端适用 |
| 含义 | UDF 模块的日志开关 |
| 取值范围 | 同上 |
| 缺省值 | |
| 属性 | 说明 |
| -------- | ----------------------------------------------------------------------------------- |
| 含义 | 是否记录客户端 sql 语句到文件 |
| 取值范围 | 01是 |
| 缺省值 | 0 |
| 补充说明 | 生成的文件tscnote-xxxx.0/tscnote-xxx.1xxxx 是 pid与客户端日志所在目录相同。 |
### smaDebugFlag
### maxBinaryDisplayWidth
| 属性 | 说明 |
| -------- | ------------------ |
| 适用范围 | 仅服务端适用 |
| 含义 | sma 模块的日志开关 |
| 取值范围 | 同上 |
| 缺省值 | |
| 属性 | 说明 |
| -------- | -------------------------------------------------------------------------- |
| 含义 | Taos shell 中 binary 和 nchar 字段的显示宽度上限,超过此限制的部分将被隐藏 |
| 取值范围 | 5 - |
| 缺省值 | 30 |
### idxDebugFlag
:::info
实际上限按以下规则计算:如果字段值的长度大于 maxBinaryDisplayWidth则显示上限为 **字段名长度****maxBinaryDisplayWidth** 的较大者。<br/>否则,上限为 **字段名长度****字段值长度** 的较大者。<br/>可在 shell 中通过命令 set max_binary_display_width nn 动态修改此选项
| 属性 | 说明 |
| -------- | -------------------- |
| 适用范围 | 仅服务端适用 |
| 含义 | index 模块的日志开关 |
| 取值范围 | 同上 |
| 缺省值 | |
:::
### tdbDebugFlag
### maxWildCardsLength
| 属性 | 说明 |
| -------- | ------------------ |
| 适用范围 | 仅服务端适用 |
| 含义 | tdb 模块的日志开关 |
| 取值范围 | 同上 |
| 缺省值 | |
| 属性 | 说明 |
| -------- | ------------------------------------------ |
| 含义 | 设定 LIKE 算子的通配符字符串允许的最大长度 |
| 单位 | bytes |
| 取值范围 | 0-16384 |
| 缺省值 | 100 |
| 补充说明 | 2.1.6.1 版本新增。 |
## Schemaless 相关
### clientMerge
### smlChildTableName
| 属性 | 说明 |
| -------- | ---------------------------- |
| 含义 | 是否允许客户端对写入数据去重 |
| 取值范围 | 0不开启1开启 |
| 缺省值 | 0 |
| 补充说明 | 2.3 版本新增。 |
| 属性 | 说明 |
| -------- | ------------------------- |
| 适用范围 | 仅客户端适用 |
| 含义 | schemaless 自定义的子表名 |
| 类型 | 字符串 |
| 缺省值 | 无 |
### maxRegexStringLen
### smlTagName
| 属性 | 说明 |
| -------- | -------------------------- |
| 含义 | 正则表达式最大允许长度 |
| 取值范围 | 默认值 128最大长度 16384 |
| 缺省值 | 128 |
| 补充说明 | 2.3 版本新增。 |
| 属性 | 说明 |
| -------- | ------------------------------------ |
| 适用范围 | 仅客户端适用 |
| 含义 | schemaless tag 为空时默认的 tag 名字 |
| 类型 | 字符串 |
| 缺省值 | _tag_null |
### smlDataFormat
| 属性 | 说明 |
| -------- | ----------------------------- |
| 适用范围 | 仅客户端适用 |
| 含义 | schemaless 列数据是否顺序一致 |
| 值域 | 0不一致1: 一致 |
| 缺省值 | 1 |
## 其他
@ -688,3 +638,12 @@ charset 的有效值是 UTF-8。
| 取值范围 | 01是 |
| 缺省值 | 1 |
| 补充说明 | 不同的启动方式,生成 core 文件的目录如下1、systemctl start taosd 启动:生成的 core 在根目录下 <br/> 2、手动启动就在 taosd 执行目录下。 |
### udf
| 属性 | 说明 |
| -------- | ------------------ |
| 适用范围 | 仅服务端适用 |
| 含义 | 是否启动 udf 服务 |
| 取值范围 | 0: 不启动1启动 |
| 缺省值 | 1 |

View File

@ -5,7 +5,7 @@ title: 整体架构
## 集群与基本逻辑单元
TDengine 的设计是基于单个硬件、软件系统不可靠,基于任何单台计算机都无法提供足够计算能力和存储能力处理海量数据的假设进行设计的。因此 TDengine 从研发的第一天起,就按照分布式高可靠架构进行设计,是支持水平扩展的,这样任何单台或多台服务器发生硬件故障或软件错误都不影响系统的可用性和可靠性。同时,通过节点虚拟化并辅以自动化负载均衡技术TDengine 能最高效率地利用异构集群中的计算和存储资源降低硬件投资。
TDengine 的设计是基于单个硬件、软件系统不可靠,基于任何单台计算机都无法提供足够计算能力和存储能力处理海量数据的假设进行设计的。因此 TDengine 从研发的第一天起就按照分布式高可靠架构进行设计是支持水平扩展的这样任何单台或多台服务器发生硬件故障或软件错误都不影响系统的可用性和可靠性。同时通过节点虚拟化并辅以负载均衡技术TDengine 能最高效率地利用异构集群中的计算和存储资源降低硬件投资。
### 主要逻辑单元
@ -19,45 +19,43 @@ TDengine 分布式架构的逻辑结构图如下:
**物理节点pnode** pnode 是一独立运行、拥有自己的计算、存储和网络能力的计算机,可以是安装有 OS 的物理机、虚拟机或 Docker 容器。物理节点由其配置的 FQDNFully Qualified Domain Name来标识。TDengine 完全依赖 FQDN 来进行网络通讯,如果不了解 FQDN请看博文[《一篇文章说清楚 TDengine 的 FQDN》](https://www.taosdata.com/blog/2020/09/11/1824.html)。
**数据节点dnode** dnode 是 TDengine 服务器侧执行代码 taosd 在物理节点上的一个运行实例一个工作的系统必须有至少一个数据节点。dnode 包含零到多个逻辑的虚拟节点vnode零或者至多一个逻辑的管理节点mnode。dnode 在系统中的唯一标识由实例的 End PointEP决定。EP 是 dnode 所在物理节点的 FQDNFully Qualified Domain Name和系统所配置的网络端口号Port的组合。通过配置不同的端口一个物理节点一台物理机、虚拟机或容器可以运行多个实例或有多个数据节点。
**数据节点dnode** dnode 是 TDengine 服务器侧执行代码 taosd 在物理节点上的一个运行实例一个工作的系统必须有至少一个数据节点。dnode 包含零到多个逻辑的虚拟节点vnode零或者至多一个逻辑的管理节点mnode零或者至多一个逻辑的弹性计算节点qnode零或者至多一个逻辑的流计算节点snode。dnode 在系统中的唯一标识由实例的 End PointEP决定。EP 是 dnode 所在物理节点的 FQDNFully Qualified Domain Name和系统所配置的网络端口号Port的组合。通过配置不同的端口一个物理节点一台物理机、虚拟机或容器可以运行多个实例或有多个数据节点。
**虚拟节点vnode** 为更好的支持数据分片、负载均衡防止数据过热或倾斜数据节点被虚拟化成多个虚拟节点vnode图中 V2V3V4 等)。每个 vnode 都是一个相对独立的工作单元,是时序数据存储的基本单元,具有独立的运行线程、内存空间与持久化存储的路径。一个 vnode 包含一定数量的表(数据采集点)。当创建一张新表时,系统会检查是否需要创建新的 vnode。一个数据节点上能创建的 vnode 的数量取决于该数据节点所在物理节点的硬件资源。一个 vnode 只属于一个 DB但一个 DB 可以有多个 vnode。一个 vnode 除存储的时序数据外,也保存有所包含的表的 schema、标签值等。一个虚拟节点由所属的数据节点的 EP以及所属的 VGroup ID 在系统内唯一标识,由管理节点创建并管理。
**虚拟节点vnode** 为更好的支持数据分片、负载均衡防止数据过热或倾斜数据节点被虚拟化成多个虚拟节点vnode图中 V2V3V4 等)。每个 vnode 都是一个相对独立的工作单元,是时序数据存储的基本单元,具有独立的运行线程、内存空间与持久化存储的路径。一个 vnode 包含一定数量的表(数据采集点)。当创建一个新 DB 时,系统会创建新的 vnode。一个数据节点上能创建的 vnode 的数量取决于该数据节点所在物理节点的硬件资源。一个 vnode 只属于一个 DB但一个 DB 可以有多个 vnode。一个 vnode 除存储的时序数据外,也保存有所包含的表的 schema、标签值等。一个虚拟节点由所属的数据节点的 EP以及所属的 VGroup ID 在系统内唯一标识,由管理节点创建并管理。
**管理节点mnode** 一个虚拟的逻辑单元,负责所有数据节点运行状态的监控和维护,以及节点之间的负载均衡(图中 M。同时管理节点也负责元数据包括用户、数据库、表、静态标签等)的存储和管理,因此也称为 Meta Node。TDengine 集群中可配置多个(最多不超过 3 个mnode它们自动构建成为一个虚拟管理节点组图中 M0M1M2。mnode 间采用 master/slave 的机制进行管理,而且采取强一致方式进行数据同步,任何数据更新操作只能在 Master 上进行。mnode 集群的创建由系统自动完成,无需人工干预。每个 dnode 上至多有一个 mnode由所属的数据节点的 EP 来唯一标识。每个 dnode 通过内部消息交互自动获取整个集群中所有 mnode 所在的 dnode 的 EP。
**管理节点mnode** 一个虚拟的逻辑单元,负责所有数据节点运行状态的监控和维护,以及节点之间的负载均衡(图中 M。同时管理节点也负责元数据包括用户、数据库、超级表等)的存储和管理,因此也称为 Meta Node。TDengine 集群中可配置多个(最多不超过 3 个mnode它们自动构建成为一个虚拟管理节点组图中 M1M2M3。mnode 支持多副本,采用 RAFT 一致性协议,保证系统的高可用与高可靠,任何数据更新操作只能在 Leader 上进行。mnode 集群的第一个节点在集群部署时自动完成,其他节点的创建与删除由用户通过 SQL 命令完成。每个 dnode 上至多有一个 mnode由所属的数据节点的 EP 来唯一标识。每个 dnode 通过内部消息交互自动获取整个集群中所有 mnode 所在的 dnode 的 EP。
**虚拟节点组VGroup** 不同数据节点上的 vnode 可以组成一个虚拟节点组vgroup来保证系统的高可靠。虚拟节点组内采取 master/slave 的方式进行管理。写操作只能在 master vnode 上进行,系统采用异步复制的方式将数据同步到 slave vnode这样确保了一份数据在多个物理节点上有拷贝。一个 vgroup 里虚拟节点个数就是数据的副本数。如果一个 DB 的副本数为 N系统必须有至少 N 数据节点。副本数在创建 DB 时通过参数 replica 可以指定,缺省为 1。使用 TDengine 的多副本特性,可以不再需要昂贵的磁盘阵列等存储设备,就可以获得同样的数据高可靠性。虚拟节点组由管理节点创建、管理,并且由管理节点分配一个系统唯一的 IDVGroup ID。如果两个虚拟节点的 VGroup ID 相同说明他们属于同一个组数据互为备份。虚拟节点组里虚拟节点的个数是可以动态改变的容许只有一个也就是没有数据复制。VGroup ID 是永远不变的,即使一个虚拟节点组被删除,它的 ID 也不会被收回重复利用
**弹性计算节点qnode** 一个虚拟的逻辑单元,运行查询计算任务,也包括基于系统表来实现的 show 命令(图中 Q。集群中可配置多个 qnode在整个集群内部共享使用图中 Q1Q2Q3。qnode 不与具体的 DB 绑定,即一个 qnode 可以同时执行多个 DB 的查询任务。每个 dnode 上至多有一个 qnode由所属的数据节点的 EP 来唯一标识。客户端通过与 mnode 交互,获取可用的 qnode 列表,当没有可用的 qnode 时,计算任务在 vnode 中执行
**Taosc** taosc 是 TDengine 给应用提供的驱动程序driver负责处理应用与集群的接口交互提供 C/C++ 语言原生接口,内嵌于 JDBC、C#、Python、Go、Node.js 语言连接库里。应用都是通过 taosc 而不是直接连接集群中的数据节点与整个集群进行交互的。这个模块负责获取并缓存元数据;将插入、查询等请求转发到正确的数据节点;在把结果返回给应用时,还需要负责最后一级的聚合、排序、过滤等操作。对于 JDBC、C/C++、C#、Python、Go、Node.js 接口而言,这个模块是在应用所处的物理节点上运行。同时,为支持全分布式的 RESTful 接口taosc 在 TDengine 集群的每个 dnode 上都有一运行实例。
**流计算节点snode** 一个虚拟的逻辑单元,只运行流计算任务(图中 S。集群中可配置多个 snode在整个集群内部共享使用图中 S1S2S3。snode 不与具体的 stream 绑定,即一个 snode 可以同时执行多个 stream 的计算任务。每个 dnode 上至多有一个 snode由所属的数据节点的 EP 来唯一标识。由 mnode 调度可用的 snode 完成流计算任务,当没有可用的 snode 时,流计算任务在 vnode 中执行。
**虚拟节点组VGroup** 不同数据节点上的 vnode 可以组成一个虚拟节点组vgroup采用 RAFT 一致性协议,保证系统的高可用与高可靠。写操作只能在 leader vnode 上进行,系统采用异步复制的方式将数据同步到 follower vnode这样确保了一份数据在多个物理节点上有拷贝。一个 vgroup 里虚拟节点个数就是数据的副本数。如果一个 DB 的副本数为 N系统必须有至少 N 数据节点。副本数在创建 DB 时通过参数 replica 可以指定,缺省为 1。使用 TDengine 的多副本特性,可以不再需要昂贵的磁盘阵列等存储设备,就可以获得同样的数据高可靠性。虚拟节点组由管理节点创建、管理,并且由管理节点分配一个系统唯一的 IDVGroup ID。如果两个虚拟节点的 VGroup ID 相同说明他们属于同一个组数据互为备份。虚拟节点组里虚拟节点的个数是可以动态改变的容许只有一个也就是没有数据复制。VGroup ID 是永远不变的,即使一个虚拟节点组被删除,它的 ID 也不会被收回重复利用。
**Taosc** taosc 是 TDengine 给应用提供的驱动程序driver负责处理应用与集群的接口交互提供 C/C++ 语言原生接口,内嵌于 JDBC、C#、Python、Go、Node.js 语言连接库里。应用都是通过 taosc 而不是直接连接集群中的数据节点与整个集群进行交互的。这个模块负责获取并缓存元数据;将插入、查询等请求转发到正确的数据节点;在把结果返回给应用时,还需要负责最后一级的聚合、排序、过滤等操作。对于 JDBC、C/C++、C#、Python、Go、Node.js 接口而言这个模块是在应用所处的物理节点上运行。同时taosc 也可以与 taosAdapter 交互,支持全分布式的 RESTful 接口。
### 节点之间的通讯
**通讯方式:**TDengine 系统的各个数据节点之间,以及应用驱动与各数据节点之间的通讯是通过 TCP/UDP 进行的。因为考虑到物联网场景,数据写入的包一般不大,因此 TDengine 除采用 TCP 做传输之外,还采用 UDP 方式,因为 UDP 更加高效而且不受连接数的限制。TDengine 实现了自己的超时、重传、确认等机制,以确保 UDP 的可靠传输。对于数据量不到 15K 的数据包,采取 UDP 的方式进行传输,超过 15K 的,或者是查询类的操作,自动采取 TCP 的方式进行传输。同时TDengine 根据配置和数据包,会自动对数据进行压缩/解压缩,数字签名/认证等处理。对于数据节点之间的数据复制,只采用 TCP 方式进行数据传输。
**通讯方式:**TDengine 系统的各个数据节点之间,以及应用驱动与各数据节点之间的通讯是通过 TCP 进行的。TDengine 根据配置和数据包,会自动对数据进行压缩/解压缩,数字签名/认证等处理。
**FQDN 配置:**一个数据节点有一个或多个 FQDN可以在系统配置文件 taos.cfg 通过参数“fqdn”进行指定如果没有指定系统将自动获取计算机的 hostname 作为其 FQDN。如果节点没有配置 FQDN可以直接将该节点的配置参数 fqdn 设置为它的 IP 地址。但不建议使用 IP因为 IP 地址可变,一旦变化,将让集群无法正常工作。一个数据节点的 EPEnd Point由 FQDN + Port 组成。采用 FQDN需要保证 DNS 服务正常工作,或者在节点以及应用所在的节点配置好 hosts 文件。另外,这个参数值的长度需要控制在 96 个字符以内。
**端口配置:**一个数据节点对外的端口由 TDengine 的系统配置参数 serverPort 决定,对集群内部通讯的端口是 serverPort+5。为支持多线程高效的处理 UDP 数据,每个对内和对外的 UDP 连接,都需要占用 5 个连续的端口。
- 集群内数据节点之间的数据复制操作占用一个 TCP 端口,是 serverPort+10。
- 集群数据节点对外提供 RESTful 服务占用一个 TCP 端口,是 serverPort+11。
- 集群内数据节点与 Arbitrator 节点之间通讯占用一个 TCP 端口,是 serverPort+12。
因此一个数据节点总的端口范围为 serverPort 到 serverPort+12总共 13 个 TCP/UDP 端口。确保集群中所有主机在端口 6030-6042 上的 TCP/UDP 协议能够互通。详细的端口情况请参见 [TDengine 2.0 端口说明](/train-faq/faq#port)
**端口配置:**一个数据节点对外的端口由 TDengine 的系统配置参数 serverPort 决定,默认为 6030。
**集群对外连接:**TDengine 集群可以容纳单个、多个甚至几千个数据节点。应用只需要向集群中任何一个数据节点发起连接即可,连接需要提供的网络参数是一数据节点的 End PointFQDN 加配置的端口号)。通过命令行 CLI 启动应用 taos 时,可以通过选项-h 来指定数据节点的 FQDN-P 来指定其配置的端口号,如果端口不配置,将采用 TDengine 的系统配置参数 serverPort。
**集群内部通讯:**各个数据节点之间通过 TCP/UDP 进行连接。一个数据节点启动时,将获取 mnode 所在的 dnode 的 EP 信息,然后与系统中的 mnode 建立起连接,交换信息。获取 mnode 的 EP 信息有三步:
**集群内部通讯:**各个数据节点之间通过 TCP 进行连接。一个数据节点启动时,将获取 mnode 所在的 dnode 的 EP 信息,然后与系统中的 mnode 建立起连接,交换信息。获取 mnode 的 EP 信息有三步:
1. 检查 mnodeEpSet.json 文件是否存在,如果不存在或不能正常打开获得 mnode EP 信息,进入第二步;
1. 检查 dnode.json 文件是否存在,如果不存在或不能正常打开获得 mnode EP 信息,进入第二步;
2. 检查系统配置文件 taos.cfg获取节点配置参数 firstEp、secondEp这两个参数指定的节点可以是不带 mnode 的普通节点,这样的话,节点被连接时会尝试重定向到 mnode 节点),如果不存在或者 taos.cfg 里没有这两个配置参数,或无效,进入第三步;
3. 将自己的 EP 设为 mnode EP并独立运行起来。
获取 mnode EP 列表后,数据节点发起连接,如果连接成功,则成功加入进工作的集群,如果不成功,则尝试 mnode EP 列表中的下一个。如果都尝试了,但连接都仍然失败,则休眠几秒后,再进行尝试。
**Mnode 的选择:**TDengine 逻辑上有管理节点,但没有单独的执行代码,服务器侧只有一套执行代码 taosd。那么哪个数据节点会是管理节点呢这是系统自动决定的,无需任何人工干预。原则如下:一个数据节点启动时,会检查自己的 End Point并与获取的 mnode EP List 进行比对,如果在其中,该数据节点认为自己应该启动 mnode 模块,成为 mnode。如果自己的 EP 不在 mnode EP List 里,则不启动 mnode 模块。在系统的运行过程中由于负载均衡、宕机等原因mnode 有可能迁移至新的 dnode但一切都是透明的无需人工干预配置参数的修改是 mnode 自己根据资源做出的决定
**Mnode 的选择:**TDengine 逻辑上有管理节点,但没有单独的执行代码,服务器侧只有一套执行代码 taosd。那么哪个数据节点会是管理节点呢在集群部署时,第一个数据节点自动成为管理节点。集群中的其他管理节点的创建与删除,由用户通过 SQL 语句完成
**新数据节点的加入:**系统有了一个数据节点后,就已经成为一个工作的系统。添加新的节点进集群时,有两个步骤,第一步:使用 TDengine CLI 连接到现有工作的数据节点然后用命令“CREATE DNODE”将新的数据节点的 End Point 添加进去;第二步:在新的数据节点的系统配置参数文件 taos.cfg 里,将 firstEpsecondEp 参数设置为现有集群中任意两个数据节点的 EP 即可。具体添加的详细步骤请见详细的用户手册。这样就把集群一步一步的建立起来。
**重定向:**无论是 dnode 还是 taosc最先都是要发起与 mnode 的连接,但 mnode 是系统自动创建并维护的,因此对于用户来说,并不知道哪个 dnode 在运行 mnode。TDengine 只要求向系统中任何一个工作的 dnode 发起连接即可。因为任何一个正在运行的 dnode都维护有目前运行的 mnode EP List。当收到一个来自新启动的 dnode 或 taosc 的连接请求,如果自己不是 mnode则将 mnode EP List 回复给对方taosc 或新启动的 dnode 收到这个 list就重新尝试建立连接。当 mnode EP List 发生改变,通过节点之间的消息交互,各个数据节点就很快获取最新列表,并通知 taosc。
**重定向:**无论是 dnode 还是 taosc最先都是要发起与 mnode 的连接,由于 mnode 是可以动态调整的,所以对于用户来说,并不知道哪个 dnode 在运行 mnode。TDengine 只要求向系统中任何一个工作的 dnode 发起连接即可。因为任何一个正在运行的 dnode都维护有目前运行的 mnode EP List。当收到一个来自新启动的 dnode 或 taosc 的连接请求,如果自己不是 mnode则将 mnode EP List 回复给对方taosc 或新启动的 dnode 收到这个 list就重新尝试建立连接。当 mnode EP List 发生改变,通过节点之间的消息交互,各个数据节点就很快获取最新列表,并通知 taosc。
### 一个典型的消息流程
@ -68,15 +66,17 @@ TDengine 分布式架构的逻辑结构图如下:
<center> 图 2 TDengine 典型的操作流程 </center>
1. 应用通过 JDBC 或其他 API 接口发起插入数据的请求。
2. taosc 会检查缓存,看是否保存有该表的 meta data。如果有直接到第 4 步。如果没有taosc 将向 mnode 发出 get meta-data 请求。
3. mnode 将该表的 meta-data 返回给 taosc。Meta-data 包含有该表的 schema而且还有该表所属的 vgroup 信息vnode ID 以及所在的 dnode 的 End Point如果副本数为 N就有 N 组 End Point。如果 taosc 迟迟得不到 mnode 回应,而且存在多个 mnodetaosc 将向下一个 mnode 发出请求。
4. taosc 向 master vnode 发起插入请求。
5. vnode 插入数据后,给 taosc 一个应答,表示插入成功。如果 taosc 迟迟得不到 vnode 的回应taosc 会认为该节点已经离线。这种情况下如果被插入的数据库有多个副本taosc 将向 vgroup 里下一个 vnode 发出插入请求。
6. taosc 通知 APP写入成功。
2. taosc 会检查缓存,看是否保存有该表所在数据库的 vgroup-info 信息。如果有,直接到第 4 步。如果没有taosc 将向 mnode 发出 get vgroup-info 请求。
3. mnode 将该表所在数据库的 vgroup-info 返回给 taosc。Vgroup-info 包含数据库的 vgroup 分布信息vnode ID 以及所在的 dnode 的 End Point如果副本数为 N就有 N 组 End Point还包含每个 vgroup 中存储数据表的 hash 范围。如果 taosc 迟迟得不到 mnode 回应,而且存在多个 mnodetaosc 将向下一个 mnode 发出请求。
4. taosc 会继续检查缓存,看是否保存有该表的 meta-data。如果有直接到第 6 步。如果没有taosc 将向 vnode 发出 get meta-data 请求。
5. vnode 将该表的 meta-data 返回给 taosc。Meta-data 包含有该表的 schema。
6. taosc 向 leader vnode 发起插入请求。
7. vnode 插入数据后,给 taosc 一个应答,表示插入成功。如果 taosc 迟迟得不到 vnode 的回应taosc 会认为该节点已经离线。这种情况下如果被插入的数据库有多个副本taosc 将向 vgroup 里下一个 vnode 发出插入请求。
8. taosc 通知 APP写入成功。
对于第二和第三步taosc 启动时,并不知道 mnode 的 End Point因此会直接向配置的集群对外服务的 End Point 发起请求。如果接收到该请求的 dnode 并没有配置 mnode该 dnode 会在回复的消息中告知 mnode EP 列表,这样 taosc 会重新向新的 mnode 的 EP 发出获取 meta-data 的请求。
对于第二步taosc 启动时,并不知道 mnode 的 End Point因此会直接向配置的集群对外服务的 End Point 发起请求。如果接收到该请求的 dnode 并没有配置 mnode该 dnode 会在回复的消息中告知 mnode EP 列表,这样 taosc 会重新向新的 mnode 的 EP 发出获取 meta-data 的请求。
对于第四和第五步没有缓存的情况下taosc 无法知道虚拟节点组里谁是 master就假设第一个 vnodeID 就是 master向它发出请求。如果接收到请求的 vnode 并不是 master它会在回复中告知谁是 master这样 taosc 就向建议的 master vnode 发出请求。一旦得到插入成功的回复taosc 会缓存 master 节点的信息。
对于第四和第六步没有缓存的情况下taosc 无法知道虚拟节点组里谁是 leader就假设第一个 vnodeID 就是 leader向它发出请求。如果接收到请求的 vnode 并不是 leader它会在回复中告知谁是 leader这样 taosc 就向建议的 leader vnode 发出请求。一旦得到插入成功的回复taosc 会缓存 leader 节点的信息。
上述是插入数据的流程查询、计算的流程也完全一致。taosc 把这些复杂的流程全部封装屏蔽了,对于应用来说无感知也无需任何特别处理。
@ -89,13 +89,13 @@ TDengine 分布式架构的逻辑结构图如下:
TDengine 存储的数据包括采集的时序数据以及库、表相关的元数据、标签数据等,这些数据具体分为三部分:
- 时序数据:存放于 vnode 里,由 data、head 和 last 三个文件组成,数据量大,查询量取决于应用场景。容许乱序写入,但暂时不支持删除操作,并且仅在 update 参数设置为 1 时允许更新操作。通过采用一个采集点一张表的模型,一个时间段的数据是连续存储,对单张表的写入是简单的追加操作,一次读,可以读到多条记录,这样保证对单个采集点的插入和查询操作,性能达到最优。
- 标签数据:存放于 vnode 里的 meta 文件,支持增删改查四个标准操作。数据量不大,有 N 张表,就有 N 条记录,因此可以全内存存储。如果标签过滤操作很多,查询将十分频繁,因此 TDengine 支持多核多线程并发查询。只要计算资源足够,即使有数千万张表,过滤结果能毫秒级返回
- 元数据:存放于 mnode 里包含系统节点、用户、DB、Table Schema 等信息,支持增删改查四个标准操作。这部分数据的量不大,可以全内存保存,而且由于客户端有缓存,查询量也不大。因此目前的设计虽是集中式存储管理,但不会构成性能瓶颈。
- 数据表元数据:包含标签信息和 Table Schema 信息,存放于 vnode 里的 meta 文件,支持增删改查四个标准操作。数据量很大,有 N 张表,就有 N 条记录,因此采用 LRU 存储支持标签数据的索引。TDengine 支持多核多线程并发查询。只要计算内存足够,元数据全内存存储,千万级别规模的标签数据过滤结果能毫秒级返回。在内存资源不足的情况下,仍然可以支持数千万张表的快速查询
- 数据库元数据:存放于 mnode 里包含系统节点、用户、DB、STable Schema 等信息,支持增删改查四个标准操作。这部分数据的量不大,可以全内存保存,而且由于客户端有缓存,查询量也不大。因此目前的设计虽是集中式存储管理,但不会构成性能瓶颈。
与典型的 NoSQL 存储模型相比TDengine 将标签数据与时序数据完全分离存储,它具有两大优势:
- 能够极大地降低标签数据存储的冗余度:一般的 NoSQL 数据库或时序数据库,采用的 K-V 存储,其中的 Key 包含时间戳、设备 ID、各种标签。每条记录都带有这些重复的内容浪费存储空间。而且如果应用要在历史数据上增加、修改或删除标签需要遍历数据重写一遍操作成本极其昂贵。
- 能够实现极为高效的多表之间的聚合查询:做多表之间聚合查询时,先把符合标签过滤条件的表查找出来,然后再查找这些表相应的数据块,这样大幅减少要扫描的数据集,从而大幅提高查询效率。而且标签数据采用全内存的结构进行管理和维护,千万级别规模的标签数据查询可以在毫秒级别返回。
- 能够实现极为高效的多表之间的聚合查询:做多表之间聚合查询时,先把符合标签过滤条件的表查找出来,然后再查找这些表相应的数据块,这样大幅减少要扫描的数据集,从而大幅提高查询效率。
### 数据分片
@ -103,11 +103,11 @@ TDengine 存储的数据包括采集的时序数据以及库、表相关的元
vnode虚拟数据节点负责为采集的时序数据提供写入、查询和计算功能。为便于负载均衡、数据恢复、支持异构环境TDengine 将一个数据节点根据其计算和存储资源切分为多个 vnode。这些 vnode 的管理是 TDengine 自动完成的,对应用完全透明。
对于单独一个数据采集点,无论其数据量多大,一个 vnode或 vgroup如果副本数大于 1有足够的计算资源和存储资源来处理如果每秒生成一条 16 字节的记录,一年产生的原始数据不到 0.5G),因此 TDengine 将一张表(一个数据采集点)的所有数据都存放在一个 vnode 里,而不会让同一个采集点的数据分布到两个或多个 dnode 上。而且一个 vnode 可存储多个数据采集点(表)的数据,一个 vnode 可容纳的表的数目的上限为一百万。设计上,一个 vnode 里所有的表都属于同一个 DB。一个数据节点上,除非特殊配置,一个 DB 拥有的 vnode 数目不会超过系统核的数目。
对于单独一个数据采集点,无论其数据量多大,一个 vnode或 vgroup如果副本数大于 1有足够的计算资源和存储资源来处理如果每秒生成一条 16 字节的记录,一年产生的原始数据不到 0.5G),因此 TDengine 将一张表(一个数据采集点)的所有数据都存放在一个 vnode 里,而不会让同一个采集点的数据分布到两个或多个 dnode 上。而且一个 vnode 可存储多个数据采集点(表)的数据,一个 vnode 可容纳的表的数目的上限为一百万。设计上,一个 vnode 里所有的表都属于同一个 DB。
创建 DB 时,系统并不会马上分配资源。但当创建一张表时,系统将看是否有已经分配的 vnode且该 vnode 是否有空余的表空间,如果有,立即在该有空位的 vnode 创建表。如果没有,系统将从集群中,根据当前的负载情况,在一个 dnode 上创建一新的 vnode然后创建表。如果 DB 有多个副本,系统不是只创建一个 vnode而是一个 vgroup虚拟数据节点组。系统对 vnode 的数目没有任何限制,仅仅受限于物理节点本身的计算和存储资源。
TDengine 3.0 采用 hash 一致性算法,确定每张数据表所在的 vnode。创建 DB 时,系统会立刻分配指定数目的 vnode并确定每个 vnode 所负责的数据表范围。当创建一张表时,系统根据数据表名计算出所在的 vnodeID立即在该 vnode 创建表。如果 DB 有多个副本,系统不是只创建一个 vnode而是一个 vgroup虚拟数据节点组。系统对 vnode 的数目没有任何限制,仅仅受限于物理节点本身的计算和存储资源。
每张表的 meta data包含 schema标签等也存放于 vnode 里,而不是集中存放于 mnode实际上这是对 Meta 数据的分片,这样便于高效并行的进行标签过滤操作。
每张表的 meta data包含 schema标签等也存放于 vnode 里,而不是集中存放于 mnode实际上这是对 meta 数据的分片,这样便于高效并行的进行标签过滤操作。
### 数据分区
@ -117,77 +117,68 @@ TDengine 除 vnode 分片之外,还对时序数据按照时间段进行分区
### 负载均衡
每个 dnode 都定时向 mnode虚拟管理节点报告其状态包括硬盘空间、内存大小、CPU、网络、虚拟节点个数等因此 mnode 了解整个集群的状态。基于整体状态,当 mnode 发现某个 dnode 负载过重,它会将 dnode 上的一个或多个 vnode 挪到其他 dnode。在挪动过程中对外服务继续进行数据插入、查询和计算操作都不受影响。
每个 dnode 都定时向 mnode虚拟管理节点报告其状态包括硬盘空间、内存大小、CPU、网络、虚拟节点个数等因此 mnode 了解整个集群的状态。基于整体状态,当 mnode 发现某个 dnode 负载过重,它会将 dnode 上的一个或多个 vnode 挪到其他 dnode。在挪动过程中对外服务继续进行数据插入、查询和计算操作都不受影响。负载均衡的触发时间,由用户指定。
如果 mnode 一段时间没有收到 dnode 的状态报告mnode 会认为这个 dnode 已经离线。如果离线时间超过一定时长(时长由配置参数 offlineThreshold 决定),该 dnode 将被 mnode 强制剔除出集群。该 dnode 上的 vnodes 如果副本数大于 1系统将自动在其他 dnode 上创建新的副本,以保证数据的副本数。如果该 dnode 上还有 mnode而且 mnode 的副本数大于 1系统也将自动在其他 dnode 上创建新的 mnode以保证 mnode 的副本数。
当新的数据节点被添加进集群,因为新的计算和存储被添加进来,系统也将自动启动负载均衡流程。
负载均衡过程无需任何人工干预,应用也无需重启,将自动连接新的节点,完全透明。
当新的数据节点被添加进集群,因为新的计算和存储被添加进来,用户需要手动触发负载均衡流程,使得系统在最优的情况下运行。
**提示:负载均衡由参数 balance 控制,决定开启/关闭自动负载均衡。**
## 数据写入与复制流程
如果一个数据库有 N 个副本,那一个虚拟节点组就有 N 个虚拟节点,但是只有一个是 master其他都是 slave。当应用将新的记录写入系统时只有 master vnode 能接受写的请求。如果 slave vnode 收到写的请求,系统将通知 taosc 需要重新定向。
如果一个数据库有 N 个副本,那一个虚拟节点组就有 N 个虚拟节点,但是只有一个是 leader其他都是 follower。当应用将新的记录写入系统时只有 leader vnode 能接受写的请求。如果 follower vnode 收到写的请求,系统将通知 taosc 需要重新定向。
### Master Vnode 写入流程
### Leader Vnode 写入流程
Master Vnode 遵循下面的写入流程:
Leader Vnode 遵循下面的写入流程:
![TDengine Database Master写入流程](./write_master.webp)
![TDengine Database Leader写入流程](./write_leader.webp)
<center> 图 3 TDengine Master 写入流程 </center>
<center> 图 3 TDengine Leader 写入流程 </center>
1. master vnode 收到应用的数据插入请求,验证 OK进入下一步
2. 如果系统配置参数 walLevel 大于 0vnode 将该请求的原始数据包写入数据库日志文件 WAL。如果 walLevel 设置为 2而且 fsync 设置为 0TDengine 还将 WAL 数据立即落盘,以保证即使宕机,也能从数据库日志文件中恢复数据,避免数据的丢失;
3. 如果有多个副本vnode 将把数据包转发给同一虚拟节点组内的 slave vnodes该转发包带有数据的版本号version
4. 写入内存,并将记录加入到 skip list
5. master vnode 返回确认信息给应用,表示写入成功;
6. 如果第 2、3、4 步中任何一步失败,将直接返回错误给应用
1. leader vnode 收到应用的数据插入请求,验证 OK进入下一步
2. vnode 将该请求的原始数据包写入数据库日志文件 WAL。如果 walLevel 设置为 2而且 fsync 设置为 0TDengine 还将 WAL 数据立即落盘,以保证即使宕机,也能从数据库日志文件中恢复数据,避免数据的丢失;
3. 如果有多个副本vnode 将把数据包转发给同一虚拟节点组内的 follower vnodes该转发包带有数据的版本号version
4. 写入内存,并将记录加入到 skip list。但如果未达成一致,会触发回滚操作
5. leader vnode 返回确认信息给应用,表示写入成功;
6. 如果第 2、3、4 步中任何一步失败,将直接返回错误给应用
### Slave Vnode 写入流程
### Follower Vnode 写入流程
对于 slave vnode写入流程是
对于 follower vnode写入流程是
![TDengine Database Slave 写入流程](./write_slave.webp)
![TDengine Database Follower 写入流程](./write_follower.webp)
<center> 图 4 TDengine Slave 写入流程 </center>
<center> 图 4 TDengine Follower 写入流程 </center>
1. slave vnode 收到 Master vnode 转发了的数据插入请求。检查 last version 是否与 master 一致,如果一致,进入下一步。如果不一致,需要进入同步状态
2. 如果系统配置参数 walLevel 大于 0vnode 将把该请求的原始数据包写入数据库日志文件 WAL。如果 walLevel 设置为 2而且 fsync 设置为 0TDengine 还将 WAL 数据立即落盘,以保证即使宕机,也能从数据库日志文件中恢复数据,避免数据的丢失。
1. follower vnode 收到 leader vnode 转发了的数据插入请求
2. vnode 将把该请求的原始数据包写入数据库日志文件 WAL。如果 walLevel 设置为 2而且 fsync 设置为 0TDengine 还将 WAL 数据立即落盘,以保证即使宕机,也能从数据库日志文件中恢复数据,避免数据的丢失。
3. 写入内存,更新内存中的 skip list。
master vnode 相比slave vnode 不存在转发环节,也不存在回复确认环节,少了两步。但写内存与 WAL 是完全一样的。
leader vnode 相比follower vnode 不存在转发环节,也不存在回复确认环节,少了两步。但写内存与 WAL 是完全一样的。
### 主从选择
Vnode 会保持一个数据版本号version对内存数据进行持久化存储时对该版本号也进行持久化存储。每个数据更新操作无论是采集的时序数据还是元数据这个版本号将增加 1。
一个 vnode 启动时,角色(master、slave)是不定的,数据是处于未同步状态,它需要与虚拟节点组内其他节点建立 TCP 连接,并互相交换 status其中包括 version 和自己的角色。通过 status 的交换,系统进入选主流程,规则如下:
一个 vnode 启动时,角色(leader、follower)是不定的,数据是处于未同步状态,它需要与虚拟节点组内其他节点建立 TCP 连接,并互相交换 status按照标准的 raft 一致性算法完成选主。
1. 如果只有一个副本,该副本永远就是 master
2. 所有副本都在线时,版本最高的被选为 master
3. 在线的虚拟节点数过半,而且有虚拟节点是 slave 的话,该虚拟节点自动成为 master
4. 对于 2 和 3如果多个虚拟节点满足成为 master 的要求,那么虚拟节点组的节点列表里,最前面的选为 master
更多的关于数据复制的流程,请见[《TDengine 2.0 数据复制模块设计》](/tdinternal/replica/)。
更多的关于数据复制的流程,请见[《TDengine 3.0 数据复制模块设计》](/tdinternal/replica/)。
### 同步复制
对于数据一致性要求更高的场景,异步数据复制无法满足要求,因为有极小的概率丢失数据,因此 TDengine 提供同步复制的机制供用户选择。在创建数据库时,除指定副本数 replica 之外,用户还需要指定新的参数 quorum。如果 quorum 大于 1它表示每次 master 转发给副本时,需要等待 quorum-1 个回复确认,才能通知应用,数据在 slave 已经写入成功。如果在一定的时间内,得不到 quorum-1 个回复确认master vnode 将返回错误给应用。
对于数据一致性要求更高的场景,异步数据复制提供的最终一致性无法满足要求。因此 TDengine 提供同步复制的机制供用户选择。在创建数据库时,除指定副本数 replica 之外,用户还需要指定新的参数 strict。如果 strict 等于 1它表示每次 leader 转发给副本时,需要等待半数以上副本达成一致后,才能通知应用,数据在 follower 已经写入成功。如果在一定的时间内得不到半数以上副本的确认leader vnode 将返回错误给应用。
采用同步复制,系统的性能会有所下降,而且 latency 会增加。因为元数据要强一致mnode 之间的数据同步缺省就是采用的同步复制。
## 缓存与持久化
### 缓存
### 时序数据缓存
TDengine 采用时间驱动缓存管理策略First-In-First-OutFIFO又称为写驱动的缓存管理机制。这种策略有别于读驱动的数据缓存模式Least-Recent-UsedLRU直接将最近写入的数据保存在系统的缓存中。当缓存达到临界值的时候将最早的数据批量写入磁盘。一般意义上来说对于物联网数据的使用用户最为关心的是刚产生的数据即当前状态。TDengine 充分利用这一特性,将最近到达的(当前状态)数据保存在缓存中。
TDengine 通过查询函数向用户提供毫秒级的数据获取能力。直接将最近到达的数据保存在缓存中,可以更加快速地响应用户针对最近一条或一批数据的查询分析,整体上提供更快的数据库查询响应能力。从这个意义上来说,**可通过设置合适的配置参数将 TDengine 作为数据缓存来使用,而不需要再部署 Redis 或其他额外的缓存系统**可有效地简化系统架构降低运维的成本。需要注意的是TDengine 重启以后系统的缓存将被清空,之前缓存的数据均会被批量写入磁盘,缓存的数据将不会像专门的 key-value 缓存系统再将之前缓存的数据重新加载到缓存中。
每个 vnode 有自己独立的内存,而且由多个固定大小的内存块组成,不同 vnode 之间完全隔离。数据写入时,类似于日志的写法,数据被顺序追加写入内存,但每个 vnode 维护有自己的 skip list便于迅速查找。当三分之一以上的内存块写满时启动落盘操作而且后续写的操作在新的内存块进行。这样一个 vnode 里有三分之一内存块是保留有最近的数据的,以达到缓存、快速查找的目的。一个 vnode 的内存块的个数由配置参数 blocks 决定,内存块的大小由配置参数 cache 决定。
每个 vnode 有自己独立的内存,而且由多个固定大小的内存块组成,不同 vnode 之间完全隔离。数据写入时,类似于日志的写法,数据被顺序追加写入内存,但每个 vnode 维护有自己的 skip list便于迅速查找。当三分之一以上的内存块写满时启动落盘操作而且后续写的操作在新的内存块进行。这样一个 vnode 里有三分之一内存块是保留有最近的数据的,以达到缓存、快速查找的目的。一个 vnode 的内存大小由配置参数 buffer 决定。
### 持久化存储

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

View File

@ -29,7 +29,7 @@ static void msg_process(TAOS_RES* msg) {
printf("vg: %d\n", tmq_get_vgroup_id(msg));
if (tmq_get_res_type(msg) == TMQ_RES_TABLE_META) {
tmq_raw_data raw = {0};
int32_t code = tmq_get_raw(msg, &raw);
int32_t code = tmq_get_raw(msg, &raw);
if (code == 0) {
TAOS* pConn = taos_connect("192.168.1.86", "root", "taosdata", NULL, 0);
if (pConn == NULL) {
@ -302,7 +302,7 @@ int32_t create_topic() {
}
taos_free_result(pRes);
// pRes = taos_query(pConn, "create topic topic_ctb_column with meta as database abc1");
// pRes = taos_query(pConn, "create topic topic_ctb_column with meta as database abc1");
pRes = taos_query(pConn, "create topic topic_ctb_column as select ts, c1, c2, c3 from st1");
if (taos_errno(pRes) != 0) {
printf("failed to create topic topic_ctb_column, reason:%s\n", taos_errstr(pRes));

@ -1 +0,0 @@
Subproject commit 7ed7a97715388fa144718764d6bf20f9bfc29a12

View File

@ -271,8 +271,6 @@ DLL_EXPORT tmq_res_t tmq_get_res_type(TAOS_RES *res);
DLL_EXPORT int32_t tmq_get_raw(TAOS_RES *res, tmq_raw_data *raw);
DLL_EXPORT int32_t tmq_write_raw(TAOS *taos, tmq_raw_data raw);
DLL_EXPORT int taos_write_raw_block(TAOS *taos, int numOfRows, char *pData, const char* tbname);
DLL_EXPORT void tmq_free_raw(tmq_raw_data raw);
DLL_EXPORT char *tmq_get_json_meta(TAOS_RES *res); // Returning null means error. Returned result need to be freed by tmq_free_json_meta
DLL_EXPORT void tmq_free_json_meta(char* jsonMeta);

View File

@ -56,7 +56,6 @@ enum {
STREAM_INPUT__DATA_SUBMIT = 1,
STREAM_INPUT__DATA_BLOCK,
STREAM_INPUT__MERGED_SUBMIT,
// STREAM_INPUT__TABLE_SCAN,
STREAM_INPUT__TQ_SCAN,
STREAM_INPUT__DATA_RETRIEVE,
STREAM_INPUT__GET_RES,
@ -154,7 +153,7 @@ typedef struct SQueryTableDataCond {
int32_t order; // desc|asc order to iterate the data block
int32_t numOfCols;
SColumnInfo* colList;
int32_t type; // data block load type:
int32_t type; // data block load type:
STimeWindow twindows;
int64_t startVersion;
int64_t endVersion;

View File

@ -41,10 +41,8 @@ extern int32_t tsCompressMsgSize;
extern int32_t tsCompressColData;
extern int32_t tsMaxNumOfDistinctResults;
extern int32_t tsCompatibleModel;
extern bool tsEnableSlaveQuery;
extern bool tsPrintAuth;
extern int64_t tsTickPerMin[3];
extern int32_t tsCountAlwaysReturnValue;
// multi-process
@ -91,9 +89,6 @@ extern uint16_t tsTelemPort;
// query buffer management
extern int32_t tsQueryBufferSize; // maximum allowed usage buffer size in MB for each data node during query processing
extern int64_t tsQueryBufferSizeBytes; // maximum allowed usage buffer size in byte for each data node
extern bool tsRetrieveBlockingModel; // retrieve threads will be blocked
extern bool tsKeepOriginalColumnName;
extern bool tsDeadLockKillQuery;
// query client
extern int32_t tsQueryPolicy;
@ -151,6 +146,7 @@ struct SConfig *taosGetCfg();
void taosSetAllDebugFlag(int32_t flag);
void taosSetDebugFlag(int32_t *pFlagPtr, const char *flagName, int32_t flagVal);
int32_t taosSetCfg(SConfig *pCfg, char *name);
void taosLocalCfgForbiddenToChange(char* name, bool* forbidden);
#ifdef __cplusplus
}

View File

@ -1404,7 +1404,7 @@ typedef struct STableScanAnalyzeInfo {
uint32_t skipBlocks;
uint32_t filterOutBlocks;
double elapsedTime;
uint64_t filterTime;
double filterTime;
} STableScanAnalyzeInfo;
int32_t tSerializeSExplainRsp(void* buf, int32_t bufLen, SExplainRsp* pRsp);

View File

@ -143,84 +143,84 @@ typedef struct {
} \
} while (0)
#define SET_TYPED_DATA_MIN(_v, _type) \
do { \
switch (_type) { \
case TSDB_DATA_TYPE_BOOL: \
case TSDB_DATA_TYPE_TINYINT: \
*(int8_t *)(_v) = INT8_MIN; \
break; \
case TSDB_DATA_TYPE_SMALLINT: \
*(int16_t *)(_v) = INT16_MIN; \
break; \
case TSDB_DATA_TYPE_INT: \
*(int32_t *)(_v) = INT32_MIN; \
break; \
case TSDB_DATA_TYPE_BIGINT: \
case TSDB_DATA_TYPE_TIMESTAMP: \
*(int64_t *)(_v) = INT64_MIN; \
break; \
case TSDB_DATA_TYPE_FLOAT: \
*(float *)(_v) = FLT_MIN; \
break; \
case TSDB_DATA_TYPE_DOUBLE: \
*(double *)(_v) = DBL_MIN; \
break; \
case TSDB_DATA_TYPE_UTINYINT: \
*(uint8_t *)(_v) = 0; \
break; \
case TSDB_DATA_TYPE_USMALLINT: \
*(uint16_t *)(_v) = 0; \
break; \
case TSDB_DATA_TYPE_UBIGINT: \
*(uint64_t *)(_v) = 0; \
break; \
case TSDB_DATA_TYPE_UINT: \
*(uint32_t *)(_v) = 0; \
break; \
default: \
break; \
} \
#define SET_TYPED_DATA_MIN(_v, _type) \
do { \
switch (_type) { \
case TSDB_DATA_TYPE_BOOL: \
case TSDB_DATA_TYPE_TINYINT: \
*(int8_t *)(_v) = INT8_MIN; \
break; \
case TSDB_DATA_TYPE_SMALLINT: \
*(int16_t *)(_v) = INT16_MIN; \
break; \
case TSDB_DATA_TYPE_INT: \
*(int32_t *)(_v) = INT32_MIN; \
break; \
case TSDB_DATA_TYPE_BIGINT: \
case TSDB_DATA_TYPE_TIMESTAMP: \
*(int64_t *)(_v) = INT64_MIN; \
break; \
case TSDB_DATA_TYPE_FLOAT: \
*(float *)(_v) = FLT_MIN; \
break; \
case TSDB_DATA_TYPE_DOUBLE: \
*(double *)(_v) = DBL_MIN; \
break; \
case TSDB_DATA_TYPE_UTINYINT: \
*(uint8_t *)(_v) = 0; \
break; \
case TSDB_DATA_TYPE_USMALLINT: \
*(uint16_t *)(_v) = 0; \
break; \
case TSDB_DATA_TYPE_UBIGINT: \
*(uint64_t *)(_v) = 0; \
break; \
case TSDB_DATA_TYPE_UINT: \
*(uint32_t *)(_v) = 0; \
break; \
default: \
break; \
} \
} while (0)
#define SET_TYPED_DATA_MAX(_v, _type) \
do { \
switch (_type) { \
case TSDB_DATA_TYPE_BOOL: \
case TSDB_DATA_TYPE_TINYINT: \
*(int8_t *)(_v) = INT8_MAX; \
break; \
case TSDB_DATA_TYPE_SMALLINT: \
*(int16_t *)(_v) = INT16_MAX; \
break; \
case TSDB_DATA_TYPE_INT: \
*(int32_t *)(_v) = INT32_MAX; \
break; \
case TSDB_DATA_TYPE_BIGINT: \
case TSDB_DATA_TYPE_TIMESTAMP: \
*(int64_t *)(_v) = INT64_MAX; \
break; \
case TSDB_DATA_TYPE_FLOAT: \
*(float *)(_v) = FLT_MAX; \
break; \
case TSDB_DATA_TYPE_DOUBLE: \
*(double *)(_v) = DBL_MAX; \
break; \
case TSDB_DATA_TYPE_UTINYINT: \
*(uint8_t *)(_v) = UINT8_MAX; \
break; \
case TSDB_DATA_TYPE_USMALLINT: \
*(uint16_t *)(_v) = UINT16_MAX; \
break; \
case TSDB_DATA_TYPE_UINT: \
*(uint32_t *)(_v) = UINT32_MAX; \
break; \
case TSDB_DATA_TYPE_UBIGINT: \
*(uint64_t *)(_v) = UINT64_MAX; \
break; \
default: \
break; \
} \
#define SET_TYPED_DATA_MAX(_v, _type) \
do { \
switch (_type) { \
case TSDB_DATA_TYPE_BOOL: \
case TSDB_DATA_TYPE_TINYINT: \
*(int8_t *)(_v) = INT8_MAX; \
break; \
case TSDB_DATA_TYPE_SMALLINT: \
*(int16_t *)(_v) = INT16_MAX; \
break; \
case TSDB_DATA_TYPE_INT: \
*(int32_t *)(_v) = INT32_MAX; \
break; \
case TSDB_DATA_TYPE_BIGINT: \
case TSDB_DATA_TYPE_TIMESTAMP: \
*(int64_t *)(_v) = INT64_MAX; \
break; \
case TSDB_DATA_TYPE_FLOAT: \
*(float *)(_v) = FLT_MAX; \
break; \
case TSDB_DATA_TYPE_DOUBLE: \
*(double *)(_v) = DBL_MAX; \
break; \
case TSDB_DATA_TYPE_UTINYINT: \
*(uint8_t *)(_v) = UINT8_MAX; \
break; \
case TSDB_DATA_TYPE_USMALLINT: \
*(uint16_t *)(_v) = UINT16_MAX; \
break; \
case TSDB_DATA_TYPE_UINT: \
*(uint32_t *)(_v) = UINT32_MAX; \
break; \
case TSDB_DATA_TYPE_UBIGINT: \
*(uint64_t *)(_v) = UINT64_MAX; \
break; \
default: \
break; \
} \
} while (0)
#define NUM_TO_STRING(_inputType, _input, _outputBytes, _output) \
@ -260,10 +260,9 @@ typedef struct {
} \
} while (0)
//TODO: use varchar(0) to represent NULL type
#define IS_VAR_NULL_TYPE(_t, _b) ((_t) == TSDB_DATA_TYPE_VARCHAR && (_b) == 0)
#define IS_NULL_TYPE(_t) ((_t) == TSDB_DATA_TYPE_NULL)
// TODO: use varchar(0) to represent NULL type
#define IS_VAR_NULL_TYPE(_t, _b) ((_t) == TSDB_DATA_TYPE_VARCHAR && (_b) == 0)
#define IS_NULL_TYPE(_t) ((_t) == TSDB_DATA_TYPE_NULL)
#define IS_SIGNED_NUMERIC_TYPE(_t) ((_t) >= TSDB_DATA_TYPE_TINYINT && (_t) <= TSDB_DATA_TYPE_BIGINT)
#define IS_UNSIGNED_NUMERIC_TYPE(_t) ((_t) >= TSDB_DATA_TYPE_UTINYINT && (_t) <= TSDB_DATA_TYPE_UBIGINT)
@ -329,7 +328,7 @@ typedef struct tDataTypeDescriptor {
int16_t type;
int16_t nameLen;
int32_t bytes;
char * name;
char *name;
int64_t minValue;
int64_t maxValue;
int32_t (*compFunc)(const char *const input, int32_t inputSize, const int32_t nelements, char *const output,

View File

@ -155,7 +155,7 @@ int32_t qGetQualifiedTableIdList(void* pTableList, const char* tagCond, int32_t
void qProcessRspMsg(void* parent, struct SRpcMsg* pMsg, struct SEpSet* pEpSet);
int32_t qGetExplainExecInfo(qTaskInfo_t tinfo, int32_t* resNum, SExplainExecInfo** pRes);
int32_t qGetExplainExecInfo(qTaskInfo_t tinfo, SArray* pExecInfoList/*,int32_t* resNum, SExplainExecInfo** pRes*/);
int32_t qSerializeTaskStatus(qTaskInfo_t tinfo, char** pOutput, int32_t* len);

View File

@ -157,6 +157,13 @@ typedef enum EFunctionType {
FUNCTION_TYPE_UDF = 10000
} EFunctionType;
typedef enum EFuncReturnRows {
FUNC_RETURN_ROWS_NORMAL = 1,
FUNC_RETURN_ROWS_INDEFINITE,
FUNC_RETURN_ROWS_N,
FUNC_RETURN_ROWS_N_MINUS_1
} EFuncReturnRows;
struct SqlFunctionCtx;
struct SResultRowEntryInfo;
struct STimeWindow;
@ -167,6 +174,8 @@ void fmFuncMgtDestroy();
int32_t fmGetFuncInfo(SFunctionNode* pFunc, char* pMsg, int32_t msgLen);
EFuncReturnRows fmGetFuncReturnRows(SFunctionNode* pFunc);
bool fmIsBuiltinFunc(const char* pFunc);
bool fmIsAggFunc(int32_t funcId);
@ -193,11 +202,13 @@ bool fmIsForbidStreamFunc(int32_t funcId);
bool fmIsIntervalInterpoFunc(int32_t funcId);
bool fmIsInterpFunc(int32_t funcId);
bool fmIsLastRowFunc(int32_t funcId);
bool fmIsSelectValueFunc(int32_t funcId);
bool fmIsSystemInfoFunc(int32_t funcId);
bool fmIsImplicitTsFunc(int32_t funcId);
bool fmIsClientPseudoColumnFunc(int32_t funcId);
bool fmIsMultiRowsFunc(int32_t funcId);
bool fmIsKeepOrderFunc(int32_t funcId);
bool fmIsCumulativeFunc(int32_t funcId);
int32_t fmGetDistMethod(const SFunctionNode* pFunc, SFunctionNode** pPartialFunc, SFunctionNode** pMergeFunc);

View File

@ -283,6 +283,7 @@ typedef struct SCreateIndexStmt {
EIndexType indexType;
bool ignoreExists;
char indexName[TSDB_INDEX_NAME_LEN];
char dbName[TSDB_DB_NAME_LEN];
char tableName[TSDB_TABLE_NAME_LEN];
SNodeList* pCols;
SIndexOptions* pOptions;

View File

@ -96,6 +96,7 @@ typedef struct SScanLogicNode {
bool groupSort;
int8_t cacheLastMode;
bool hasNormalCols; // neither tag column nor primary key tag column
bool sortPrimaryKey;
} SScanLogicNode;
typedef struct SJoinLogicNode {
@ -204,6 +205,7 @@ typedef struct SWindowLogicNode {
int8_t igExpired;
EWindowAlgorithm windowAlgo;
EOrder inputTsOrder;
EOrder outputTsOrder;
} SWindowLogicNode;
typedef struct SFillLogicNode {
@ -212,6 +214,7 @@ typedef struct SFillLogicNode {
SNode* pWStartTs;
SNode* pValues; // SNodeListNode
STimeWindow timeRange;
EOrder inputTsOrder;
} SFillLogicNode;
typedef struct SSortLogicNode {
@ -410,6 +413,8 @@ typedef struct SWinodwPhysiNode {
int8_t triggerType;
int64_t watermark;
int8_t igExpired;
EOrder inputTsOrder;
EOrder outputTsOrder;
} SWinodwPhysiNode;
typedef struct SIntervalPhysiNode {
@ -434,6 +439,7 @@ typedef struct SFillPhysiNode {
SNode* pValues; // SNodeListNode
SNodeList* pTargets;
STimeWindow timeRange;
EOrder inputTsOrder;
} SFillPhysiNode;
typedef struct SMultiTableIntervalPhysiNode {

View File

@ -253,6 +253,7 @@ typedef struct SSelectStmt {
char stmtName[TSDB_TABLE_NAME_LEN];
uint8_t precision;
int32_t selectFuncNum;
int32_t returnRows; // EFuncReturnRows
bool isEmptyResult;
bool isTimeLineResult;
bool isSubquery;
@ -417,8 +418,6 @@ void nodesValueNodeToVariant(const SValueNode* pNode, SVariant* pVal);
char* nodesGetFillModeString(EFillMode mode);
int32_t nodesMergeConds(SNode** pDst, SNodeList** pSrc);
int32_t nodesPartitionCond(SNode** pCondition, SNode** pPrimaryKeyCond, SNode** pTagIndexCond, SNode** pTagCond,
SNode** pOtherCond);
#ifdef __cplusplus
}

View File

@ -46,6 +46,10 @@ extern int32_t filterFreeNcharColumns(SFilterInfo *pFilterInfo);
extern void filterFreeInfo(SFilterInfo *info);
extern bool filterRangeExecute(SFilterInfo *info, SColumnDataAgg *pDataStatis, int32_t numOfCols, int32_t numOfRows);
/* condition split interface */
int32_t filterPartitionCond(SNode **pCondition, SNode **pPrimaryKeyCond, SNode **pTagIndexCond, SNode **pTagCond,
SNode **pOtherCond);
#ifdef __cplusplus
}
#endif

View File

@ -25,7 +25,7 @@ extern "C" {
typedef struct SFilterInfo SFilterInfo;
int32_t scalarGetOperatorResultType(SOperatorNode* pOp);
int32_t scalarGetOperatorResultType(SOperatorNode *pOp);
/*
pNode will be freed in API;
@ -43,7 +43,7 @@ int32_t scalarGetOperatorParamNum(EOperatorType type);
int32_t scalarGenerateSetFromList(void **data, void *pNode, uint32_t type);
int32_t vectorGetConvertType(int32_t type1, int32_t type2);
int32_t vectorConvertImpl(const SScalarParam* pIn, SScalarParam* pOut, int32_t* overflow);
int32_t vectorConvertImpl(const SScalarParam *pIn, SScalarParam *pOut, int32_t *overflow);
/* Math functions */
int32_t absFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput);
@ -86,7 +86,7 @@ int32_t nowFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutpu
int32_t todayFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput);
int32_t timezoneFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput);
bool getTimePseudoFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv);
bool getTimePseudoFuncEnv(struct SFunctionNode *pFunc, SFuncExecEnv *pEnv);
int32_t winStartTsFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput);
int32_t winEndTsFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput);

View File

@ -55,7 +55,6 @@ enum {
TASK_INPUT_STATUS__NORMAL = 1,
TASK_INPUT_STATUS__BLOCKED,
TASK_INPUT_STATUS__RECOVER,
TASK_INPUT_STATUS__PROCESSING,
TASK_INPUT_STATUS__STOP,
TASK_INPUT_STATUS__FAILED,
};
@ -320,17 +319,6 @@ int32_t tDecodeSStreamTask(SDecoder* pDecoder, SStreamTask* pTask);
void tFreeSStreamTask(SStreamTask* pTask);
static FORCE_INLINE int32_t streamTaskInput(SStreamTask* pTask, SStreamQueueItem* pItem) {
#if 0
while (1) {
int8_t inputStatus =
atomic_val_compare_exchange_8(&pTask->inputStatus, TASK_INPUT_STATUS__NORMAL, TASK_INPUT_STATUS__PROCESSING);
if (inputStatus == TASK_INPUT_STATUS__NORMAL) {
break;
}
ASSERT(0);
}
#endif
if (pItem->type == STREAM_INPUT__DATA_SUBMIT) {
SStreamDataSubmit* pSubmitClone = streamSubmitRefClone((SStreamDataSubmit*)pItem);
if (pSubmitClone == NULL) {
@ -443,13 +431,14 @@ typedef struct {
typedef struct {
int64_t streamId;
int32_t taskId;
int32_t sourceTaskId;
int32_t sourceVg;
int32_t upstreamTaskId;
int32_t upstreamNodeId;
} SStreamTaskRecoverReq;
typedef struct {
int64_t streamId;
int32_t taskId;
int32_t rspTaskId;
int32_t reqTaskId;
int8_t inputStatus;
} SStreamTaskRecoverRsp;

View File

@ -34,11 +34,16 @@ typedef struct SUpdateInfo {
TSKEY minTS;
SScalableBf* pCloseWinSBF;
SHashObj* pMap;
STimeWindow scanWindow;
uint64_t scanGroupId;
uint64_t maxVersion;
} SUpdateInfo;
SUpdateInfo *updateInfoInitP(SInterval* pInterval, int64_t watermark);
SUpdateInfo *updateInfoInit(int64_t interval, int32_t precision, int64_t watermark);
bool updateInfoIsUpdated(SUpdateInfo *pInfo, uint64_t tableId, TSKEY ts);
void updateInfoSetScanRange(SUpdateInfo *pInfo, STimeWindow* pWin, uint64_t groupId, uint64_t version);
bool updateInfoIgnore(SUpdateInfo *pInfo, STimeWindow* pWin, uint64_t groupId, uint64_t version);
void updateInfoDestroy(SUpdateInfo *pInfo);
void updateInfoAddCloseWindowSBF(SUpdateInfo *pInfo);
void updateInfoDestoryColseWinSBF(SUpdateInfo *pInfo);

View File

@ -210,7 +210,7 @@ SyncGroupId syncGetVgId(int64_t rid);
void syncGetEpSet(int64_t rid, SEpSet* pEpSet);
void syncGetRetryEpSet(int64_t rid, SEpSet* pEpSet);
int32_t syncPropose(int64_t rid, SRpcMsg* pMsg, bool isWeak);
int32_t syncProposeBatch(int64_t rid, SRpcMsg* pMsgArr, bool* pIsWeakArr, int32_t arrSize);
int32_t syncProposeBatch(int64_t rid, SRpcMsg** pMsgPArr, bool* pIsWeakArr, int32_t arrSize);
bool syncEnvIsStart();
const char* syncStr(ESyncState state);
bool syncIsRestoreFinish(int64_t rid);

View File

@ -238,7 +238,7 @@ typedef struct SyncClientRequestBatch {
char data[]; // block2, block3
} SyncClientRequestBatch;
SyncClientRequestBatch* syncClientRequestBatchBuild(SRpcMsg* rpcMsgArr, SRaftMeta* raftArr, int32_t arrSize,
SyncClientRequestBatch* syncClientRequestBatchBuild(SRpcMsg** rpcMsgPArr, SRaftMeta* raftArr, int32_t arrSize,
int32_t vgId);
void syncClientRequestBatch2RpcMsg(const SyncClientRequestBatch* pSyncMsg, SRpcMsg* pRpcMsg);
void syncClientRequestBatchDestroy(SyncClientRequestBatch* pMsg);

View File

@ -41,7 +41,7 @@ extern "C" {
#define WAL_REFRESH_MS 1000
#define WAL_PATH_LEN (TSDB_FILENAME_LEN + 12)
#define WAL_FILE_LEN (WAL_PATH_LEN + 32)
#define WAL_MAGIC 0xFAFBFCFDULL
#define WAL_MAGIC 0xFAFBFCFDF4F3F2F1ULL
#define WAL_SCAN_BUF_SIZE (1024 * 1024 * 3)
typedef enum {

View File

@ -62,6 +62,8 @@ typedef int32_t TdUcs4;
int32_t taosUcs4len(TdUcs4 *ucs4);
int64_t taosStr2int64(const char *str);
void taosConvInit(void);
void taosConvDestroy();
int32_t taosUcs4ToMbs(TdUcs4 *ucs4, int32_t ucs4_max_len, char *mbs);
bool taosMbsToUcs4(const char *mbs, size_t mbs_len, TdUcs4 *ucs4, int32_t ucs4_max_len, int32_t *len);
int32_t tasoUcs4Compare(TdUcs4 *f1_ucs4, TdUcs4 *f2_ucs4, int32_t bytes);

View File

@ -258,6 +258,7 @@ int32_t* taosGetErrno();
#define TSDB_CODE_MND_SINGLE_STB_MODE_DB TAOS_DEF_ERROR_CODE(0, 0x03C5)
#define TSDB_CODE_MND_INVALID_SCHEMA_VER TAOS_DEF_ERROR_CODE(0, 0x03C6)
#define TSDB_CODE_MND_STABLE_UID_NOT_MATCH TAOS_DEF_ERROR_CODE(0, 0x03C7)
#define TSDB_CODE_MND_FIELD_CONFLICT_WITH_TSMA TAOS_DEF_ERROR_CODE(0, 0x03C8)
// mnode-trans
#define TSDB_CODE_MND_TRANS_ALREADY_EXIST TAOS_DEF_ERROR_CODE(0, 0x03D0)
@ -555,6 +556,8 @@ int32_t* taosGetErrno();
#define TSDB_CODE_PAR_ONLY_SUPPORT_SINGLE_TABLE TAOS_DEF_ERROR_CODE(0, 0x265F)
#define TSDB_CODE_PAR_INVALID_SMA_INDEX TAOS_DEF_ERROR_CODE(0, 0x2660)
#define TSDB_CODE_PAR_INVALID_SELECTED_EXPR TAOS_DEF_ERROR_CODE(0, 0x2661)
#define TSDB_CODE_PAR_GET_META_ERROR TAOS_DEF_ERROR_CODE(0, 0x2662)
#define TSDB_CODE_PAR_NOT_UNIQUE_TABLE_ALIAS TAOS_DEF_ERROR_CODE(0, 0x2663)
#define TSDB_CODE_PAR_INTERNAL_ERROR TAOS_DEF_ERROR_CODE(0, 0x26FF)
//planner

View File

@ -81,11 +81,11 @@ static FORCE_INLINE double taos_align_get_double(const char *pBuf) {
typedef uint16_t VarDataLenT; // maxVarDataLen: 32767
#define VARSTR_HEADER_SIZE sizeof(VarDataLenT)
#define varDataLen(v) ((VarDataLenT *)(v))[0]
#define varDataVal(v) ((char *)(v) + VARSTR_HEADER_SIZE)
#define varDataLen(v) ((VarDataLenT *)(v))[0]
#define varDataVal(v) ((char *)(v) + VARSTR_HEADER_SIZE)
#define varDataTLen(v) (sizeof(VarDataLenT) + varDataLen(v))
#define NCHAR_WIDTH_TO_BYTES(n) ((n) * TSDB_NCHAR_SIZE + VARSTR_HEADER_SIZE)
#define NCHAR_WIDTH_TO_BYTES(n) ((n)*TSDB_NCHAR_SIZE + VARSTR_HEADER_SIZE)
typedef int32_t VarDataOffsetT;
@ -98,4 +98,4 @@ typedef struct tstr {
}
#endif
#endif /*_TD_TYPES_H_*/
#endif /*_TD_TYPES_H_*/

View File

@ -1,6 +1,7 @@
@echo off
goto %1
:needAdmin
mshta vbscript:createobject("shell.application").shellexecute("%~s0",":hasAdmin","","runas",1)(window.close)&goto :eof
mshta vbscript:createobject("shell.application").shellexecute("%~s0",":hasAdmin","","runas",1)(window.close)&& echo To start/stop TDengine with administrator privileges: sc start/stop taosd &goto :eof
:hasAdmin
cp -f C:\\TDengine\\driver\\taos.dll C:\\Windows\\System32
cp -f C:\\TDengine\\driver\\taos.dll C:\\Windows\\System32
sc query "taosd" >nul || sc create "taosd" binPath= "C:\\TDengine\\taosd.exe --win_service" start= DEMAND

View File

@ -20,11 +20,6 @@ target_link_libraries(
)
if(TD_WINDOWS)
set_target_properties(taos
PROPERTIES
LINK_FLAGS
/DEF:${CMAKE_CURRENT_SOURCE_DIR}/src/taos.def
)
INCLUDE_DIRECTORIES(jni/windows)
INCLUDE_DIRECTORIES(jni/windows/win32)
INCLUDE_DIRECTORIES(jni/windows/win32/bridge)

View File

@ -225,9 +225,9 @@ typedef struct SRequestObj {
SArray* targetTableList;
SQueryExecMetric metric;
SRequestSendRecvBody body;
bool syncQuery; // todo refactor: async query object
bool stableQuery; // todo refactor
bool validateOnly; // todo refactor
bool syncQuery; // todo refactor: async query object
bool stableQuery; // todo refactor
bool validateOnly; // todo refactor
bool killed;
uint32_t prevCode; // previous error code: todo refactor, add update flag for catalog
uint32_t retry;

View File

@ -316,6 +316,7 @@ void doDestroyRequest(void *p) {
taosArrayDestroy(pRequest->tableList);
taosArrayDestroy(pRequest->dbList);
taosArrayDestroy(pRequest->targetTableList);
destroyQueryExecRes(&pRequest->body.resInfo.execRes);
@ -361,6 +362,8 @@ void taos_init_imp(void) {
initQueryModuleMsgHandle();
taosConvInit();
rpcInit();
SCatalogCfg cfg = {.maxDBCacheNum = 100, .maxTblCacheNum = 100};

View File

@ -353,6 +353,8 @@ int32_t hbBuildQueryDesc(SQueryHbReqBasic *hbBasic, STscObj *pObj) {
desc.subDesc = NULL;
desc.subPlanNum = 0;
}
desc.subPlanNum = taosArrayGetSize(desc.subDesc);
ASSERT(desc.subPlanNum == taosArrayGetSize(desc.subDesc));
} else {
desc.subDesc = NULL;
}

View File

@ -591,7 +591,7 @@ int32_t buildAsyncExecNodeList(SRequestObj* pRequest, SArray** pNodeList, SArray
return code;
}
void freeVgList(void *list) {
void freeVgList(void* list) {
SArray* pList = *(SArray**)list;
taosArrayDestroy(pList);
}
@ -1278,8 +1278,8 @@ int32_t doProcessMsgFromServer(void* param) {
char tbuf[40] = {0};
TRACE_TO_STR(trace, tbuf);
tscDebug("processMsgFromServer handle %p, message: %s, code: %s, gtid: %s", pMsg->info.handle, TMSG_INFO(pMsg->msgType), tstrerror(pMsg->code),
tbuf);
tscDebug("processMsgFromServer handle %p, message: %s, code: %s, gtid: %s", pMsg->info.handle,
TMSG_INFO(pMsg->msgType), tstrerror(pMsg->code), tbuf);
if (pSendInfo->requestObjRefId != 0) {
SRequestObj* pRequest = (SRequestObj*)taosAcquireRef(clientReqRefPool, pSendInfo->requestObjRefId);
@ -2114,7 +2114,7 @@ TAOS_RES* taosQueryImpl(TAOS* taos, const char* sql, bool validateOnly) {
return NULL;
}
TAOS_RES* pRes = execQuery(connId, sql, sqlLen, validateOnly);
TAOS_RES* pRes = execQuery(*(int64_t*)taos, sql, sqlLen, validateOnly);
return pRes;
#endif
}

View File

@ -75,6 +75,8 @@ void taos_cleanup(void) {
cleanupTaskQueue();
taosConvDestroy();
tscInfo("all local resources released");
taosCleanupCfg();
taosCloseLog();

View File

@ -84,32 +84,11 @@
typedef TSDB_SML_PROTOCOL_TYPE SMLProtocolType;
typedef enum {
SCHEMA_ACTION_CREATE_STABLE,
SCHEMA_ACTION_ADD_COLUMN,
SCHEMA_ACTION_ADD_TAG,
SCHEMA_ACTION_CHANGE_COLUMN_SIZE,
SCHEMA_ACTION_CHANGE_TAG_SIZE,
SCHEMA_ACTION_NULL,
SCHEMA_ACTION_COLUMN,
SCHEMA_ACTION_TAG
} ESchemaAction;
typedef struct {
char sTableName[TSDB_TABLE_NAME_LEN];
SArray *tags;
SArray *fields;
} SCreateSTableActionInfo;
typedef struct {
char sTableName[TSDB_TABLE_NAME_LEN];
SSmlKv *field;
} SAlterSTableActionInfo;
typedef struct {
ESchemaAction action;
union {
SCreateSTableActionInfo createSTable;
SAlterSTableActionInfo alterSTable;
};
} SSchemaAction;
typedef struct {
const char *measure;
const char *tags;
@ -226,18 +205,20 @@ static inline bool smlCheckDuplicateKey(const char *key, int32_t keyLen, SHashOb
}
static int32_t smlBuildInvalidDataMsg(SSmlMsgBuf *pBuf, const char *msg1, const char *msg2) {
memset(pBuf->buf, 0, pBuf->len);
if (msg1) strncat(pBuf->buf, msg1, pBuf->len);
int32_t left = pBuf->len - strlen(pBuf->buf);
if (left > 2 && msg2) {
strncat(pBuf->buf, ":", left - 1);
strncat(pBuf->buf, msg2, left - 2);
if(pBuf->buf){
memset(pBuf->buf, 0, pBuf->len);
if (msg1) strncat(pBuf->buf, msg1, pBuf->len);
int32_t left = pBuf->len - strlen(pBuf->buf);
if (left > 2 && msg2) {
strncat(pBuf->buf, ":", left - 1);
strncat(pBuf->buf, msg2, left - 2);
}
}
return TSDB_CODE_SML_INVALID_DATA;
}
static int32_t smlGenerateSchemaAction(SSchema *colField, SHashObj *colHash, SSmlKv *kv, bool isTag,
SSchemaAction *action, bool *actionNeeded, SSmlHandle *info) {
ESchemaAction *action, SSmlHandle *info) {
uint16_t *index = (uint16_t *)taosHashGet(colHash, kv->key, kv->keyLen);
if (index) {
if (colField[*index].type != kv->type) {
@ -251,25 +232,17 @@ static int32_t smlGenerateSchemaAction(SSchema *colField, SHashObj *colHash, SSm
(colField[*index].type == TSDB_DATA_TYPE_NCHAR &&
((colField[*index].bytes - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE < kv->length))) {
if (isTag) {
action->action = SCHEMA_ACTION_CHANGE_TAG_SIZE;
*action = SCHEMA_ACTION_TAG;
} else {
action->action = SCHEMA_ACTION_CHANGE_COLUMN_SIZE;
*action = SCHEMA_ACTION_COLUMN;
}
action->alterSTable.field = kv;
*actionNeeded = true;
}
} else {
if (isTag) {
action->action = SCHEMA_ACTION_ADD_TAG;
*action = SCHEMA_ACTION_TAG;
} else {
action->action = SCHEMA_ACTION_ADD_COLUMN;
*action = SCHEMA_ACTION_COLUMN;
}
action->alterSTable.field = kv;
*actionNeeded = true;
}
if (*actionNeeded) {
uDebug("SML:0x%" PRIx64 " generate schema action. kv->name: %s, action: %d", info->id, kv->key,
action->action);
}
return 0;
}
@ -284,171 +257,25 @@ static int32_t smlFindNearestPowerOf2(int32_t length, uint8_t type) {
} else if (type == TSDB_DATA_TYPE_NCHAR && result > (TSDB_MAX_BINARY_LEN - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE){
result = (TSDB_MAX_BINARY_LEN - VARSTR_HEADER_SIZE) / TSDB_NCHAR_SIZE;
}
if (type == TSDB_DATA_TYPE_NCHAR){
result = result * TSDB_NCHAR_SIZE + VARSTR_HEADER_SIZE;
}else if (type == TSDB_DATA_TYPE_BINARY){
result = result + VARSTR_HEADER_SIZE;
}
return result;
}
static int32_t smlBuildColumnDescription(SSmlKv *field, char *buf, int32_t bufSize, int32_t *outBytes) {
uint8_t type = field->type;
char tname[TSDB_TABLE_NAME_LEN] = {0};
memcpy(tname, field->key, field->keyLen);
if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) {
int32_t bytes = smlFindNearestPowerOf2(field->length, type);
int out = snprintf(buf, bufSize, "`%s` %s(%d)", tname, tDataTypes[field->type].name, bytes);
*outBytes = out;
} else {
int out = snprintf(buf, bufSize, "`%s` %s", tname, tDataTypes[type].name);
*outBytes = out;
}
return 0;
}
static int32_t smlApplySchemaAction(SSmlHandle *info, SSchemaAction *action) {
int32_t code = 0;
int32_t outBytes = 0;
char *result = (char *)taosMemoryCalloc(1, TSDB_MAX_ALLOWED_SQL_LEN);
int32_t capacity = TSDB_MAX_ALLOWED_SQL_LEN;
uDebug("SML:0x%" PRIx64 " apply schema action. action: %d", info->id, action->action);
switch (action->action) {
case SCHEMA_ACTION_ADD_COLUMN: {
int n = sprintf(result, "alter stable `%s` add column ", action->alterSTable.sTableName);
smlBuildColumnDescription(action->alterSTable.field, result + n, capacity - n, &outBytes);
TAOS_RES *res = taos_query((TAOS*)&info->taos->id, result); // TODO async doAsyncQuery
code = taos_errno(res);
const char *errStr = taos_errstr(res);
if (code != TSDB_CODE_SUCCESS) {
uError("SML:0x%" PRIx64 " apply schema action. error: %s", info->id, errStr);
taosMsleep(100);
}
taos_free_result(res);
break;
}
case SCHEMA_ACTION_ADD_TAG: {
int n = sprintf(result, "alter stable `%s` add tag ", action->alterSTable.sTableName);
smlBuildColumnDescription(action->alterSTable.field, result + n, capacity - n, &outBytes);
TAOS_RES *res = taos_query((TAOS*)&info->taos->id, result); // TODO async doAsyncQuery
code = taos_errno(res);
const char *errStr = taos_errstr(res);
if (code != TSDB_CODE_SUCCESS) {
uError("SML:0x%" PRIx64 " apply schema action. error : %s", info->id, taos_errstr(res));
taosMsleep(100);
}
taos_free_result(res);
break;
}
case SCHEMA_ACTION_CHANGE_COLUMN_SIZE: {
int n = sprintf(result, "alter stable `%s` modify column ", action->alterSTable.sTableName);
smlBuildColumnDescription(action->alterSTable.field, result + n, capacity - n, &outBytes);
TAOS_RES *res = taos_query((TAOS*)&info->taos->id, result); // TODO async doAsyncQuery
code = taos_errno(res);
if (code != TSDB_CODE_SUCCESS) {
uError("SML:0x%" PRIx64 " apply schema action. error : %s", info->id, taos_errstr(res));
taosMsleep(100);
}
taos_free_result(res);
break;
}
case SCHEMA_ACTION_CHANGE_TAG_SIZE: {
int n = sprintf(result, "alter stable `%s` modify tag ", action->alterSTable.sTableName);
smlBuildColumnDescription(action->alterSTable.field, result + n, capacity - n, &outBytes);
TAOS_RES *res = taos_query((TAOS*)&info->taos->id, result); // TODO async doAsyncQuery
code = taos_errno(res);
if (code != TSDB_CODE_SUCCESS) {
uError("SML:0x%" PRIx64 " apply schema action. error : %s", info->id, taos_errstr(res));
taosMsleep(100);
}
taos_free_result(res);
break;
}
case SCHEMA_ACTION_CREATE_STABLE: {
int n = sprintf(result, "create stable `%s` (", action->createSTable.sTableName);
char *pos = result + n;
int freeBytes = capacity - n;
SArray *cols = action->createSTable.fields;
for (int i = 0; i < taosArrayGetSize(cols); i++) {
SSmlKv *kv = (SSmlKv *)taosArrayGetP(cols, i);
smlBuildColumnDescription(kv, pos, freeBytes, &outBytes);
pos += outBytes;
freeBytes -= outBytes;
*pos = ',';
++pos;
--freeBytes;
}
--pos;
++freeBytes;
outBytes = snprintf(pos, freeBytes, ") tags (");
pos += outBytes;
freeBytes -= outBytes;
cols = action->createSTable.tags;
for (int i = 0; i < taosArrayGetSize(cols); i++) {
SSmlKv *kv = (SSmlKv *)taosArrayGetP(cols, i);
smlBuildColumnDescription(kv, pos, freeBytes, &outBytes);
pos += outBytes;
freeBytes -= outBytes;
*pos = ',';
++pos;
--freeBytes;
}
if (taosArrayGetSize(cols) == 0) {
outBytes = snprintf(pos, freeBytes, "`%s` %s(%d)", tsSmlTagName, tDataTypes[TSDB_DATA_TYPE_NCHAR].name, 1);
pos += outBytes;
freeBytes -= outBytes;
*pos = ',';
++pos;
--freeBytes;
}
pos--;
++freeBytes;
outBytes = snprintf(pos, freeBytes, ")");
TAOS_RES *res = taos_query((TAOS*)&info->taos->id, result);
code = taos_errno(res);
if (code != TSDB_CODE_SUCCESS) {
uError("SML:0x%" PRIx64 " apply schema action. error : %s", info->id, taos_errstr(res));
taosMsleep(100);
}
taos_free_result(res);
break;
}
default:
break;
}
taosMemoryFreeClear(result);
if (code != 0) {
uError("SML:0x%" PRIx64 " apply schema action failure. %s", info->id, tstrerror(code));
}
return code;
}
static int32_t smlProcessSchemaAction(SSmlHandle *info, SSchema *schemaField, SHashObj *schemaHash, SArray *cols,
SSchemaAction *action, bool isTag) {
ESchemaAction *action, bool isTag) {
int32_t code = TSDB_CODE_SUCCESS;
for (int j = 0; j < taosArrayGetSize(cols); ++j) {
if(j == 0 && !isTag) continue;
SSmlKv *kv = (SSmlKv *)taosArrayGetP(cols, j);
bool actionNeeded = false;
code = smlGenerateSchemaAction(schemaField, schemaHash, kv, isTag, action, &actionNeeded, info);
code = smlGenerateSchemaAction(schemaField, schemaHash, kv, isTag, action, info);
if (code != TSDB_CODE_SUCCESS) {
return code;
}
if (actionNeeded) {
code = smlApplySchemaAction(info, action);
if (code != TSDB_CODE_SUCCESS) {
return code;
}
}
}
return TSDB_CODE_SUCCESS;
}
@ -475,6 +302,144 @@ static int32_t smlCheckMeta(SSchema *schema, int32_t length, SArray *cols, bool
return 0;
}
static int32_t getBytes(uint8_t type, int32_t length){
if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) {
return smlFindNearestPowerOf2(length, type);
} else {
return tDataTypes[type].bytes;
}
}
//static int32_t smlSendMetaMsg(SSmlHandle *info, SName *pName, SSmlSTableMeta *sTableData,
// int32_t colVer, int32_t tagVer, int8_t source, uint64_t suid){
static int32_t smlSendMetaMsg(SSmlHandle *info, SName *pName, SSmlSTableMeta *sTableData,
STableMeta *pTableMeta, ESchemaAction action){
SRequestObj* pRequest = NULL;
SMCreateStbReq pReq = {0};
int32_t code = TSDB_CODE_SUCCESS;
SCmdMsgInfo pCmdMsg = {0};
code = buildRequest(info->taos->id, "", 0, NULL, false, &pRequest);
if (code != TSDB_CODE_SUCCESS) {
goto end;
}
if (!pRequest->pDb) {
code = TSDB_CODE_PAR_DB_NOT_SPECIFIED;
goto end;
}
if (action == SCHEMA_ACTION_NULL){
pReq.colVer = 1;
pReq.tagVer = 1;
pReq.suid = 0;
pReq.source = TD_REQ_FROM_APP;
} else if (action == SCHEMA_ACTION_TAG){
pReq.colVer = pTableMeta->sversion;
pReq.tagVer = pTableMeta->tversion + 1;
pReq.suid = pTableMeta->uid;
pReq.source = TD_REQ_FROM_TAOX;
} else if (action == SCHEMA_ACTION_COLUMN){
pReq.colVer = pTableMeta->sversion + 1;
pReq.tagVer = pTableMeta->tversion;
pReq.suid = pTableMeta->uid;
pReq.source = TD_REQ_FROM_TAOX;
}
pReq.commentLen = -1;
pReq.igExists = true;
tNameExtractFullName(pName, pReq.name);
if(action == SCHEMA_ACTION_NULL || action == SCHEMA_ACTION_COLUMN){
pReq.numOfColumns = taosArrayGetSize(sTableData->cols);
pReq.pColumns = taosArrayInit(pReq.numOfColumns, sizeof(SField));
for (int i = 0; i < pReq.numOfColumns; i++) {
SSmlKv *kv = (SSmlKv *)taosArrayGetP(sTableData->cols, i);
SField field = {0};
field.type = kv->type;
field.bytes = getBytes(kv->type, kv->length);
memcpy(field.name, kv->key, kv->keyLen);
taosArrayPush(pReq.pColumns, &field);
}
}else if (action == SCHEMA_ACTION_TAG){
pReq.numOfColumns = pTableMeta->tableInfo.numOfColumns;
pReq.pColumns = taosArrayInit(pReq.numOfColumns, sizeof(SField));
for (int i = 0; i < pReq.numOfColumns; i++) {
SSchema *s = &pTableMeta->schema[i];
SField field = {0};
field.type = s->type;
field.bytes = s->bytes;
strcpy(field.name, s->name);
taosArrayPush(pReq.pColumns, &field);
}
}
if(action == SCHEMA_ACTION_NULL || action == SCHEMA_ACTION_TAG){
pReq.numOfTags = taosArrayGetSize(sTableData->tags);
if (pReq.numOfTags == 0){
pReq.numOfTags = 1;
pReq.pTags = taosArrayInit(pReq.numOfTags, sizeof(SField));
SField field = {0};
field.type = TSDB_DATA_TYPE_NCHAR;
field.bytes = 1;
strcpy(field.name, tsSmlTagName);
taosArrayPush(pReq.pTags, &field);
}else{
pReq.pTags = taosArrayInit(pReq.numOfTags, sizeof(SField));
for (int i = 0; i < pReq.numOfTags; i++) {
SSmlKv *kv = (SSmlKv *)taosArrayGetP(sTableData->tags, i);
SField field = {0};
field.type = kv->type;
field.bytes = getBytes(kv->type, kv->length);
memcpy(field.name, kv->key, kv->keyLen);
taosArrayPush(pReq.pTags, &field);
}
}
}else if (action == SCHEMA_ACTION_COLUMN){
pReq.numOfTags = pTableMeta->tableInfo.numOfTags;
pReq.pTags = taosArrayInit(pReq.numOfTags, sizeof(SField));
for (int i = 0; i < pReq.numOfTags; i++) {
SSchema *s = &pTableMeta->schema[i + pTableMeta->tableInfo.numOfColumns];
SField field = {0};
field.type = s->type;
field.bytes = s->bytes;
strcpy(field.name, s->name);
taosArrayPush(pReq.pTags, &field);
}
}
pCmdMsg.epSet = getEpSet_s(&info->taos->pAppInfo->mgmtEp);
pCmdMsg.msgType = TDMT_MND_CREATE_STB;
pCmdMsg.msgLen = tSerializeSMCreateStbReq(NULL, 0, &pReq);
pCmdMsg.pMsg = taosMemoryMalloc(pCmdMsg.msgLen);
if (NULL == pCmdMsg.pMsg) {
tFreeSMCreateStbReq(&pReq);
code = TSDB_CODE_OUT_OF_MEMORY;
goto end;
}
tSerializeSMCreateStbReq(pCmdMsg.pMsg, pCmdMsg.msgLen, &pReq);
SQuery pQuery;
pQuery.execMode = QUERY_EXEC_MODE_RPC;
pQuery.pCmdMsg = &pCmdMsg;
pQuery.msgType = pQuery.pCmdMsg->msgType;
pQuery.stableQuery = true;
launchQueryImpl(pRequest, &pQuery, true, NULL);
if(pRequest->code == TSDB_CODE_SUCCESS){
catalogRemoveTableMeta(info->pCatalog, pName);
}
code = pRequest->code;
taosMemoryFree(pCmdMsg.pMsg);
end:
destroyRequest(pRequest);
tFreeSMCreateStbReq(&pReq);
return code;
}
static int32_t smlModifyDBSchemas(SSmlHandle *info) {
int32_t code = 0;
SName pName = {TSDB_TABLE_NAME_T, info->taos->acctId, {0}, {0}};
@ -500,16 +465,9 @@ static int32_t smlModifyDBSchemas(SSmlHandle *info) {
code = catalogGetSTableMeta(info->pCatalog, &conn, &pName, &pTableMeta);
if (code == TSDB_CODE_PAR_TABLE_NOT_EXIST || code == TSDB_CODE_MND_STB_NOT_EXIST) {
SSchemaAction schemaAction;
schemaAction.action = SCHEMA_ACTION_CREATE_STABLE;
memset(&schemaAction.createSTable, 0, sizeof(SCreateSTableActionInfo));
memcpy(schemaAction.createSTable.sTableName, superTable, superTableLen);
schemaAction.createSTable.tags = sTableData->tags;
schemaAction.createSTable.fields = sTableData->cols;
code = smlApplySchemaAction(info, &schemaAction);
code = smlSendMetaMsg(info, &pName, sTableData, NULL, SCHEMA_ACTION_NULL);
if (code != TSDB_CODE_SUCCESS) {
uError("SML:0x%" PRIx64 " smlApplySchemaAction failed. can not create %s", info->id,
schemaAction.createSTable.sTableName);
uError("SML:0x%" PRIx64 " smlSendMetaMsg failed. can not create %s", info->id, superTable);
goto end;
}
info->cost.numOfCreateSTables++;
@ -521,24 +479,42 @@ static int32_t smlModifyDBSchemas(SSmlHandle *info) {
taosHashPut(hashTmp, pTableMeta->schema[i].name, strlen(pTableMeta->schema[i].name), &i, SHORT_BYTES);
}
SSchemaAction schemaAction;
memset(&schemaAction, 0, sizeof(SSchemaAction));
memcpy(schemaAction.createSTable.sTableName, superTable, superTableLen);
code = smlProcessSchemaAction(info, pTableMeta->schema, hashTmp, sTableData->tags, &schemaAction, true);
ESchemaAction action = SCHEMA_ACTION_NULL;
code = smlProcessSchemaAction(info, pTableMeta->schema, hashTmp, sTableData->tags, &action, true);
if (code != TSDB_CODE_SUCCESS) {
taosHashCleanup(hashTmp);
goto end;
}
if (action == SCHEMA_ACTION_TAG){
code = smlSendMetaMsg(info, &pName, sTableData, pTableMeta, action);
if (code != TSDB_CODE_SUCCESS) {
uError("SML:0x%" PRIx64 " smlSendMetaMsg failed. can not create %s", info->id, superTable);
goto end;
}
}
code = catalogRefreshTableMeta(info->pCatalog, &conn, &pName, -1);
if (code != TSDB_CODE_SUCCESS) {
goto end;
}
taosHashClear(hashTmp);
for (uint16_t i = 1; i < pTableMeta->tableInfo.numOfColumns; i++) {
taosHashPut(hashTmp, pTableMeta->schema[i].name, strlen(pTableMeta->schema[i].name), &i, SHORT_BYTES);
}
code = smlProcessSchemaAction(info, pTableMeta->schema, hashTmp, sTableData->cols, &schemaAction, false);
action = SCHEMA_ACTION_NULL;
code = smlProcessSchemaAction(info, pTableMeta->schema, hashTmp, sTableData->cols, &action, false);
taosHashCleanup(hashTmp);
if (code != TSDB_CODE_SUCCESS) {
goto end;
}
if (action == SCHEMA_ACTION_COLUMN){
code = smlSendMetaMsg(info, &pName, sTableData, pTableMeta, action);
if (code != TSDB_CODE_SUCCESS) {
uError("SML:0x%" PRIx64 " smlSendMetaMsg failed. can not create %s", info->id, superTable);
goto end;
}
}
code = catalogRefreshTableMeta(info->pCatalog, &conn, &pName, -1);
if (code != TSDB_CODE_SUCCESS) {
@ -1504,11 +1480,13 @@ static SSmlHandle* smlBuildSmlInfo(STscObj* pTscObj, SRequestObj* request, SMLPr
}
((SVnodeModifOpStmt *)(info->pQuery->pRoot))->payloadType = PAYLOAD_TYPE_KV;
info->taos = pTscObj;
code = catalogGetHandle(info->taos->pAppInfo->clusterId, &info->pCatalog);
if (code != TSDB_CODE_SUCCESS) {
uError("SML:0x%" PRIx64 " get catalog error %d", info->id, code);
goto cleanup;
if (pTscObj){
info->taos = pTscObj;
code = catalogGetHandle(info->taos->pAppInfo->clusterId, &info->pCatalog);
if (code != TSDB_CODE_SUCCESS) {
uError("SML:0x%" PRIx64 " get catalog error %d", info->id, code);
goto cleanup;
}
}
info->precision = precision;
@ -1518,9 +1496,12 @@ static SSmlHandle* smlBuildSmlInfo(STscObj* pTscObj, SRequestObj* request, SMLPr
} else {
info->dataFormat = true;
}
info->pRequest = request;
info->msgBuf.buf = info->pRequest->msgBuf;
info->msgBuf.len = ERROR_MSG_BUF_DEFAULT_SIZE;
if(request){
info->pRequest = request;
info->msgBuf.buf = info->pRequest->msgBuf;
info->msgBuf.len = ERROR_MSG_BUF_DEFAULT_SIZE;
}
info->exec = smlInitHandle(info->pQuery);
info->childTables = taosHashInit(32, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK);

View File

@ -1,81 +0,0 @@
taos_cleanup
taos_options
taos_set_config
taos_init
taos_connect
taos_connect_l
taos_connect_auth
taos_close
taos_data_type
taos_stmt_init
taos_stmt_prepare
taos_stmt_set_tbname_tags
taos_stmt_set_tbname
taos_stmt_set_sub_tbname
taos_stmt_is_insert
taos_stmt_num_params
taos_stmt_get_param
taos_stmt_bind_param
taos_stmt_bind_param_batch
taos_stmt_bind_single_param_batch
taos_stmt_add_batch
taos_stmt_execute
taos_stmt_use_result
taos_stmt_close
taos_stmt_errstr
taos_stmt_affected_rows
taos_stmt_affected_rows_once
taos_query
taos_query_l
taos_fetch_row
taos_result_precision
taos_free_result
taos_field_count
taos_num_fields
taos_affected_rows
taos_fetch_fields
taos_select_db
taos_print_row
taos_stop_query
taos_is_null
taos_is_update_query
taos_fetch_block
taos_fetch_block_s
taos_fetch_raw_block
taos_get_column_data_offset
taos_validate_sql
taos_reset_current_db
taos_fetch_lengths
taos_result_block
taos_get_server_info
taos_get_client_info
taos_errstr
taos_errno
taos_query_a
taos_fetch_rows_a
taos_subscribe
taos_consume
taos_unsubscribe
taos_load_table_info
taos_schemaless_insert
tmq_list_new
tmq_list_append
tmq_list_destroy
tmq_list_get_size
tmq_list_to_c_array
tmq_consumer_new
tmq_err2str
tmq_subscribe
tmq_unsubscribe
tmq_subscription
tmq_consumer_poll
tmq_consumer_close
tmq_commit
tmq_conf_new
tmq_conf_set
tmq_conf_destroy
tmq_conf_set_offset_commit_cb
tmq_get_topic_name
tmq_get_vgroup_id
tmq_create_stream
taos_check_server_status

View File

@ -123,7 +123,7 @@ void createNewTable(TAOS* pConn, int32_t index) {
}
taos_free_result(pRes);
for(int32_t i = 0; i < 1000; i += 20) {
for(int32_t i = 0; i < 100000; 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)"
@ -154,7 +154,7 @@ TEST(testCase, driverInit_Test) {
}
TEST(testCase, connect_Test) {
// taos_options(TSDB_OPTION_CONFIGDIR, "/home/ubuntu/first/cfg");
taos_options(TSDB_OPTION_CONFIGDIR, "/home/lisa/Documents/workspace/tdengine/sim/dnode1/cfg");
TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0);
if (pConn == NULL) {
@ -501,7 +501,6 @@ TEST(testCase, show_vgroup_Test) {
taos_close(pConn);
}
TEST(testCase, create_multiple_tables) {
TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0);
ASSERT_NE(pConn, nullptr);
@ -665,6 +664,7 @@ TEST(testCase, insert_test) {
taos_free_result(pRes);
taos_close(pConn);
}
#endif
TEST(testCase, projection_query_tables) {
TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0);
@ -697,7 +697,7 @@ TEST(testCase, projection_query_tables) {
}
taos_free_result(pRes);
for(int32_t i = 0; i < 100; ++i) {
for(int32_t i = 0; i < 1; ++i) {
printf("create table :%d\n", i);
createNewTable(pConn, i);
}
@ -723,6 +723,7 @@ TEST(testCase, projection_query_tables) {
taos_close(pConn);
}
#if 0
TEST(testCase, projection_query_stables) {
TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0);
ASSERT_NE(pConn, nullptr);
@ -820,21 +821,8 @@ TEST(testCase, async_api_test) {
getchar();
taos_close(pConn);
}
#endif
TEST(testCase, update_test) {
SInterval interval = {0};
interval.offset = 8000;
interval.interval = 10000;
interval.sliding = 4000;
interval.intervalUnit = 's';
interval.offsetUnit = 's';
interval.slidingUnit = 's';
// STimeWindow w = getAlignQueryTimeWindow(&interval, 0, 1630000000000);
STimeWindow w = getAlignQueryTimeWindow(&interval, 0, 1629999999999);
TAOS* pConn = taos_connect("localhost", "root", "taosdata", NULL, 0);
ASSERT_NE(pConn, nullptr);
@ -869,4 +857,8 @@ TEST(testCase, update_test) {
taos_free_result(pRes);
}
}
#endif
#pragma GCC diagnostic pop

File diff suppressed because one or more lines are too long

View File

@ -257,14 +257,13 @@ static const SSysTableMeta infosMeta[] = {
{TSDB_INS_TABLE_MNODES, mnodesSchema, tListLen(mnodesSchema)},
{TSDB_INS_TABLE_MODULES, modulesSchema, tListLen(modulesSchema)},
{TSDB_INS_TABLE_QNODES, qnodesSchema, tListLen(qnodesSchema)},
{TSDB_INS_TABLE_SNODES, snodesSchema, tListLen(snodesSchema)},
{TSDB_INS_TABLE_BNODES, bnodesSchema, tListLen(bnodesSchema)},
// {TSDB_INS_TABLE_SNODES, snodesSchema, tListLen(snodesSchema)},
// {TSDB_INS_TABLE_BNODES, bnodesSchema, tListLen(bnodesSchema)},
{TSDB_INS_TABLE_CLUSTER, clusterSchema, tListLen(clusterSchema)},
{TSDB_INS_TABLE_USER_DATABASES, userDBSchema, tListLen(userDBSchema)},
{TSDB_INS_TABLE_USER_FUNCTIONS, userFuncSchema, tListLen(userFuncSchema)},
{TSDB_INS_TABLE_USER_INDEXES, userIdxSchema, tListLen(userIdxSchema)},
{TSDB_INS_TABLE_USER_STABLES, userStbsSchema, tListLen(userStbsSchema)},
{TSDB_PERFS_TABLE_STREAMS, streamSchema, tListLen(streamSchema)},
{TSDB_INS_TABLE_USER_TABLES, userTblsSchema, tListLen(userTblsSchema)},
{TSDB_INS_TABLE_USER_TAGS, userTagsSchema, tListLen(userTagsSchema)},
// {TSDB_INS_TABLE_USER_TABLE_DISTRIBUTED, userTblDistSchema, tListLen(userTblDistSchema)},

View File

@ -16,65 +16,9 @@
#define _DEFAULT_SOURCE
#include "tdatablock.h"
#include "tcompare.h"
#include "tglobal.h"
#include "tlog.h"
#include "tname.h"
int32_t taosGetFqdnPortFromEp(const char* ep, SEp* pEp) {
pEp->port = 0;
strcpy(pEp->fqdn, ep);
char* temp = strchr(pEp->fqdn, ':');
if (temp) {
*temp = 0;
pEp->port = atoi(temp + 1);
}
if (pEp->port == 0) {
pEp->port = tsServerPort;
}
return 0;
}
void addEpIntoEpSet(SEpSet* pEpSet, const char* fqdn, uint16_t port) {
if (pEpSet == NULL || fqdn == NULL || strlen(fqdn) == 0) {
return;
}
int32_t index = pEpSet->numOfEps;
tstrncpy(pEpSet->eps[index].fqdn, fqdn, tListLen(pEpSet->eps[index].fqdn));
pEpSet->eps[index].port = port;
pEpSet->numOfEps += 1;
}
bool isEpsetEqual(const SEpSet* s1, const SEpSet* s2) {
if (s1->numOfEps != s2->numOfEps || s1->inUse != s2->inUse) {
return false;
}
for (int32_t i = 0; i < s1->numOfEps; i++) {
if (s1->eps[i].port != s2->eps[i].port || strncmp(s1->eps[i].fqdn, s2->eps[i].fqdn, TSDB_FQDN_LEN) != 0)
return false;
}
return true;
}
void updateEpSet_s(SCorEpSet* pEpSet, SEpSet* pNewEpSet) {
taosCorBeginWrite(&pEpSet->version);
pEpSet->epSet = *pNewEpSet;
taosCorEndWrite(&pEpSet->version);
}
SEpSet getEpSet_s(SCorEpSet* pEpSet) {
SEpSet ep = {0};
taosCorBeginRead(&pEpSet->version);
ep = pEpSet->epSet;
taosCorEndRead(&pEpSet->version);
return ep;
}
int32_t colDataGetLength(const SColumnInfoData* pColumnInfoData, int32_t numOfRows) {
ASSERT(pColumnInfoData != NULL);
if (IS_VAR_DATA_TYPE(pColumnInfoData->info.type)) {
@ -1287,9 +1231,7 @@ int32_t copyDataBlock(SSDataBlock* dst, const SSDataBlock* src) {
colDataAssign(pDst, pSrc, src->info.rows, &src->info);
}
dst->info.rows = src->info.rows;
dst->info.window = src->info.window;
dst->info.type = src->info.type;
dst->info = src->info;
return TSDB_CODE_SUCCESS;
}
@ -1713,8 +1655,9 @@ void blockDebugShowDataBlocks(const SArray* dataBlocks, const char* flag) {
size_t numOfCols = taosArrayGetSize(pDataBlock->pDataBlock);
int32_t rows = pDataBlock->info.rows;
printf("%s |block type %d |child id %d|group id %zX\n", flag, (int32_t)pDataBlock->info.type,
pDataBlock->info.childId, pDataBlock->info.groupId);
printf("%s |block ver %" PRIi64 " |block type %d |child id %d|group id %" PRIu64 "\n", flag,
pDataBlock->info.version, (int32_t)pDataBlock->info.type, pDataBlock->info.childId,
pDataBlock->info.groupId);
for (int32_t j = 0; j < rows; j++) {
printf("%s |", flag);
for (int32_t k = 0; k < numOfCols; k++) {
@ -1763,9 +1706,9 @@ char* dumpBlockData(SSDataBlock* pDataBlock, const char* flag, char** pDataBuf)
int32_t colNum = taosArrayGetSize(pDataBlock->pDataBlock);
int32_t rows = pDataBlock->info.rows;
int32_t len = 0;
len += snprintf(dumpBuf + len, size - len, "===stream===%s |block type %d|child id %d|group id:%" PRIu64 "|uid:%ld|rows:%d\n", flag,
len += snprintf(dumpBuf + len, size - len, "===stream===%s|block type %d|child id %d|group id:%" PRIu64 "|uid:%ld|rows:%d|version:%" PRIu64 "\n", flag,
(int32_t)pDataBlock->info.type, pDataBlock->info.childId, pDataBlock->info.groupId,
pDataBlock->info.uid, pDataBlock->info.rows);
pDataBlock->info.uid, pDataBlock->info.rows, pDataBlock->info.version);
if (len >= size - 1) return dumpBuf;
for (int32_t j = 0; j < rows; j++) {

View File

@ -35,7 +35,6 @@ int32_t tsNumOfSupportVnodes = 256;
// common
int32_t tsMaxShellConns = 50000;
int32_t tsShellActivityTimer = 3; // second
bool tsEnableSlaveQuery = true;
bool tsPrintAuth = false;
// multi process
@ -50,7 +49,7 @@ int32_t tsNumOfShmThreads = 1;
// queue & threads
int32_t tsNumOfRpcThreads = 1;
int32_t tsNumOfCommitThreads = 2;
int32_t tsNumOfTaskQueueThreads = 1;
int32_t tsNumOfTaskQueueThreads = 4;
int32_t tsNumOfMnodeQueryThreads = 4;
int32_t tsNumOfMnodeFetchThreads = 1;
int32_t tsNumOfMnodeReadThreads = 1;
@ -125,15 +124,6 @@ int32_t tsMinIntervalTime = 1;
int32_t tsQueryBufferSize = -1;
int64_t tsQueryBufferSizeBytes = -1;
// in retrieve blocking model, the retrieve threads will wait for the completion of the query processing.
bool tsRetrieveBlockingModel = false;
// last_row(*), first(*), last_row(ts, col1, col2) query, the result fields will be the original column name
bool tsKeepOriginalColumnName = false;
// kill long query
bool tsDeadLockKillQuery = false;
// tsdb config
// For backward compatibility
bool tsdbForceKeepFile = false;
@ -303,6 +293,7 @@ static int32_t taosAddServerLogCfg(SConfig *pCfg) {
if (cfgAddInt32(pCfg, "smaDebugFlag", smaDebugFlag, 0, 255, 0) != 0) return -1;
if (cfgAddInt32(pCfg, "idxDebugFlag", idxDebugFlag, 0, 255, 0) != 0) return -1;
if (cfgAddInt32(pCfg, "tdbDebugFlag", tdbDebugFlag, 0, 255, 0) != 0) return -1;
if (cfgAddInt32(pCfg, "metaDebugFlag", metaDebugFlag, 0, 255, 0) != 0) return -1;
return 0;
}
@ -320,16 +311,15 @@ static int32_t taosAddClientCfg(SConfig *pCfg) {
if (cfgAddInt32(pCfg, "shellActivityTimer", tsShellActivityTimer, 1, 120, 1) != 0) return -1;
if (cfgAddInt32(pCfg, "compressMsgSize", tsCompressMsgSize, -1, 100000000, 1) != 0) return -1;
if (cfgAddInt32(pCfg, "compressColData", tsCompressColData, -1, 100000000, 1) != 0) return -1;
if (cfgAddBool(pCfg, "keepColumnName", tsKeepOriginalColumnName, 1) != 0) return -1;
if (cfgAddInt32(pCfg, "queryPolicy", tsQueryPolicy, 1, 3, 1) != 0) return -1;
if (cfgAddInt32(pCfg, "querySmaOptimize", tsQuerySmaOptimize, 0, 1, 1) != 0) return -1;
if (cfgAddString(pCfg, "smlChildTableName", "", 1) != 0) return -1;
if (cfgAddString(pCfg, "smlTagName", tsSmlTagName, 1) != 0) return -1;
if (cfgAddBool(pCfg, "smlDataFormat", tsSmlDataFormat, 1) != 0) return -1;
tsNumOfTaskQueueThreads = tsNumOfCores / 4;
tsNumOfTaskQueueThreads = TRANGE(tsNumOfTaskQueueThreads, 1, 2);
if (cfgAddInt32(pCfg, "numOfTaskQueueThreads", tsNumOfTaskQueueThreads, 1, 1024, 0) != 0) return -1;
tsNumOfTaskQueueThreads = tsNumOfCores / 2;
tsNumOfTaskQueueThreads = TMAX(tsNumOfTaskQueueThreads, 4);
if (cfgAddInt32(pCfg, "numOfTaskQueueThreads", tsNumOfTaskQueueThreads, 4, 1024, 0) != 0) return -1;
return 0;
}
@ -370,10 +360,7 @@ static int32_t taosAddServerCfg(SConfig *pCfg) {
if (cfgAddInt32(pCfg, "maxNumOfDistinctRes", tsMaxNumOfDistinctResults, 10 * 10000, 10000 * 10000, 0) != 0) return -1;
if (cfgAddInt32(pCfg, "countAlwaysReturnValue", tsCountAlwaysReturnValue, 0, 1, 0) != 0) return -1;
if (cfgAddInt32(pCfg, "queryBufferSize", tsQueryBufferSize, -1, 500000000000, 0) != 0) return -1;
if (cfgAddBool(pCfg, "retrieveBlockingModel", tsRetrieveBlockingModel, 0) != 0) return -1;
if (cfgAddBool(pCfg, "printAuth", tsPrintAuth, 0) != 0) return -1;
if (cfgAddBool(pCfg, "slaveQuery", tsEnableSlaveQuery, 0) != 0) return -1;
if (cfgAddBool(pCfg, "deadLockKillQuery", tsDeadLockKillQuery, 0) != 0) return -1;
if (cfgAddInt32(pCfg, "multiProcess", tsMultiProcess, 0, 2, 0) != 0) return -1;
if (cfgAddInt32(pCfg, "mnodeShmSize", tsMnodeShmSize, TSDB_MAX_MSG_SIZE * 2 + 1024, INT32_MAX, 0) != 0) return -1;
@ -381,7 +368,7 @@ static int32_t taosAddServerCfg(SConfig *pCfg) {
if (cfgAddInt32(pCfg, "qnodeShmSize", tsQnodeShmSize, TSDB_MAX_MSG_SIZE * 2 + 1024, INT32_MAX, 0) != 0) return -1;
if (cfgAddInt32(pCfg, "snodeShmSize", tsSnodeShmSize, TSDB_MAX_MSG_SIZE * 2 + 1024, INT32_MAX, 0) != 0) return -1;
if (cfgAddInt32(pCfg, "bnodeShmSize", tsBnodeShmSize, TSDB_MAX_MSG_SIZE * 2 + 1024, INT32_MAX, 0) != 0) return -1;
if (cfgAddInt32(pCfg, "mumOfShmThreads", tsNumOfShmThreads, 1, 1024, 0) != 0) return -1;
if (cfgAddInt32(pCfg, "numOfShmThreads", tsNumOfShmThreads, 1, 1024, 0) != 0) return -1;
tsNumOfRpcThreads = tsNumOfCores / 2;
tsNumOfRpcThreads = TRANGE(tsNumOfRpcThreads, 1, 4);
@ -391,25 +378,21 @@ static int32_t taosAddServerCfg(SConfig *pCfg) {
tsNumOfCommitThreads = TRANGE(tsNumOfCommitThreads, 2, 4);
if (cfgAddInt32(pCfg, "numOfCommitThreads", tsNumOfCommitThreads, 1, 1024, 0) != 0) return -1;
tsNumOfMnodeQueryThreads = tsNumOfCores * 2;
tsNumOfMnodeQueryThreads = TRANGE(tsNumOfMnodeQueryThreads, 4, 8);
if (cfgAddInt32(pCfg, "numOfMnodeQueryThreads", tsNumOfMnodeQueryThreads, 1, 1024, 0) != 0) return -1;
tsNumOfMnodeReadThreads = tsNumOfCores / 8;
tsNumOfMnodeReadThreads = TRANGE(tsNumOfMnodeReadThreads, 1, 4);
if (cfgAddInt32(pCfg, "numOfMnodeReadThreads", tsNumOfMnodeReadThreads, 1, 1024, 0) != 0) return -1;
tsNumOfVnodeQueryThreads = tsNumOfCores * 2;
tsNumOfVnodeQueryThreads = TMAX(tsNumOfVnodeQueryThreads, 4);
if (cfgAddInt32(pCfg, "numOfVnodeQueryThreads", tsNumOfVnodeQueryThreads, 1, 1024, 0) != 0) return -1;
if (cfgAddInt32(pCfg, "numOfVnodeQueryThreads", tsNumOfVnodeQueryThreads, 4, 1024, 0) != 0) return -1;
tsNumOfVnodeStreamThreads = tsNumOfCores / 4;
tsNumOfVnodeStreamThreads = TMAX(tsNumOfVnodeStreamThreads, 4);
if (cfgAddInt32(pCfg, "numOfVnodeStreamThreads", tsNumOfVnodeStreamThreads, 1, 1024, 0) != 0) return -1;
if (cfgAddInt32(pCfg, "numOfVnodeStreamThreads", tsNumOfVnodeStreamThreads, 4, 1024, 0) != 0) return -1;
tsNumOfVnodeFetchThreads = tsNumOfCores / 4;
tsNumOfVnodeFetchThreads = TMAX(tsNumOfVnodeFetchThreads, 4);
if (cfgAddInt32(pCfg, "numOfVnodeFetchThreads", tsNumOfVnodeFetchThreads, 1, 1024, 0) != 0) return -1;
if (cfgAddInt32(pCfg, "numOfVnodeFetchThreads", tsNumOfVnodeFetchThreads, 4, 1024, 0) != 0) return -1;
tsNumOfVnodeWriteThreads = tsNumOfCores;
tsNumOfVnodeWriteThreads = TMAX(tsNumOfVnodeWriteThreads, 1);
@ -429,11 +412,11 @@ static int32_t taosAddServerCfg(SConfig *pCfg) {
tsNumOfSnodeSharedThreads = tsNumOfCores / 4;
tsNumOfSnodeSharedThreads = TRANGE(tsNumOfSnodeSharedThreads, 2, 4);
if (cfgAddInt32(pCfg, "numOfSnodeSharedThreads", tsNumOfSnodeSharedThreads, 1, 1024, 0) != 0) return -1;
if (cfgAddInt32(pCfg, "numOfSnodeSharedThreads", tsNumOfSnodeSharedThreads, 2, 1024, 0) != 0) return -1;
tsNumOfSnodeUniqueThreads = tsNumOfCores / 4;
tsNumOfSnodeUniqueThreads = TRANGE(tsNumOfSnodeUniqueThreads, 2, 4);
if (cfgAddInt32(pCfg, "numOfSnodeUniqueThreads", tsNumOfSnodeUniqueThreads, 1, 1024, 0) != 0) return -1;
if (cfgAddInt32(pCfg, "numOfSnodeUniqueThreads", tsNumOfSnodeUniqueThreads, 2, 1024, 0) != 0) return -1;
tsRpcQueueMemoryAllowed = tsTotalMemoryKB * 1024 * 0.1;
tsRpcQueueMemoryAllowed = TRANGE(tsRpcQueueMemoryAllowed, TSDB_MAX_MSG_SIZE * 10L, TSDB_MAX_MSG_SIZE * 10000L);
@ -490,6 +473,7 @@ static void taosSetServerLogCfg(SConfig *pCfg) {
smaDebugFlag = cfgGetItem(pCfg, "smaDebugFlag")->i32;
idxDebugFlag = cfgGetItem(pCfg, "idxDebugFlag")->i32;
tdbDebugFlag = cfgGetItem(pCfg, "tdbDebugFlag")->i32;
metaDebugFlag = cfgGetItem(pCfg, "metaDebugFlag")->i32;
}
static int32_t taosSetClientCfg(SConfig *pCfg) {
@ -527,7 +511,6 @@ static int32_t taosSetClientCfg(SConfig *pCfg) {
tsShellActivityTimer = cfgGetItem(pCfg, "shellActivityTimer")->i32;
tsCompressMsgSize = cfgGetItem(pCfg, "compressMsgSize")->i32;
tsCompressColData = cfgGetItem(pCfg, "compressColData")->i32;
tsKeepOriginalColumnName = cfgGetItem(pCfg, "keepColumnName")->bval;
tsNumOfTaskQueueThreads = cfgGetItem(pCfg, "numOfTaskQueueThreads")->i32;
tsQueryPolicy = cfgGetItem(pCfg, "queryPolicy")->i32;
tsQuerySmaOptimize = cfgGetItem(pCfg, "querySmaOptimize")->i32;
@ -562,10 +545,7 @@ static int32_t taosSetServerCfg(SConfig *pCfg) {
tsMaxNumOfDistinctResults = cfgGetItem(pCfg, "maxNumOfDistinctRes")->i32;
tsCountAlwaysReturnValue = cfgGetItem(pCfg, "countAlwaysReturnValue")->i32;
tsQueryBufferSize = cfgGetItem(pCfg, "queryBufferSize")->i32;
tsRetrieveBlockingModel = cfgGetItem(pCfg, "retrieveBlockingModel")->bval;
tsPrintAuth = cfgGetItem(pCfg, "printAuth")->bval;
tsEnableSlaveQuery = cfgGetItem(pCfg, "slaveQuery")->bval;
tsDeadLockKillQuery = cfgGetItem(pCfg, "deadLockKillQuery")->i32;
tsMultiProcess = cfgGetItem(pCfg, "multiProcess")->bval;
tsMnodeShmSize = cfgGetItem(pCfg, "mnodeShmSize")->i32;
@ -576,7 +556,6 @@ static int32_t taosSetServerCfg(SConfig *pCfg) {
tsNumOfRpcThreads = cfgGetItem(pCfg, "numOfRpcThreads")->i32;
tsNumOfCommitThreads = cfgGetItem(pCfg, "numOfCommitThreads")->i32;
tsNumOfMnodeQueryThreads = cfgGetItem(pCfg, "numOfMnodeQueryThreads")->i32;
tsNumOfMnodeReadThreads = cfgGetItem(pCfg, "numOfMnodeReadThreads")->i32;
tsNumOfVnodeQueryThreads = cfgGetItem(pCfg, "numOfVnodeQueryThreads")->i32;
tsNumOfVnodeStreamThreads = cfgGetItem(pCfg, "numOfVnodeStreamThreads")->i32;
@ -615,6 +594,20 @@ static int32_t taosSetServerCfg(SConfig *pCfg) {
return 0;
}
void taosLocalCfgForbiddenToChange(char* name, bool* forbidden) {
int32_t len = strlen(name);
char lowcaseName[CFG_NAME_MAX_LEN + 1] = {0};
strntolower(lowcaseName, name, TMIN(CFG_NAME_MAX_LEN, len));
if (strcasecmp("charset", name) == 0) {
*forbidden = true;
return;
}
*forbidden = false;
}
int32_t taosSetCfg(SConfig *pCfg, char *name) {
int32_t len = strlen(name);
char lowcaseName[CFG_NAME_MAX_LEN + 1] = {0};
@ -651,9 +644,7 @@ int32_t taosSetCfg(SConfig *pCfg, char *name) {
break;
}
case 'd': {
if (strcasecmp("deadLockKillQuery", name) == 0) {
tsDeadLockKillQuery = cfgGetItem(pCfg, "deadLockKillQuery")->i32;
} else if (strcasecmp("dDebugFlag", name) == 0) {
if (strcasecmp("dDebugFlag", name) == 0) {
dDebugFlag = cfgGetItem(pCfg, "dDebugFlag")->i32;
}
break;
@ -710,9 +701,6 @@ int32_t taosSetCfg(SConfig *pCfg, char *name) {
break;
}
case 'k': {
if (strcasecmp("keepColumnName", name) == 0) {
tsKeepOriginalColumnName = cfgGetItem(pCfg, "keepColumnName")->bval;
}
break;
}
case 'l': {
@ -808,8 +796,6 @@ int32_t taosSetCfg(SConfig *pCfg, char *name) {
tsNumOfRpcThreads = cfgGetItem(pCfg, "numOfRpcThreads")->i32;
} else if (strcasecmp("numOfCommitThreads", name) == 0) {
tsNumOfCommitThreads = cfgGetItem(pCfg, "numOfCommitThreads")->i32;
} else if (strcasecmp("numOfMnodeQueryThreads", name) == 0) {
tsNumOfMnodeQueryThreads = cfgGetItem(pCfg, "numOfMnodeQueryThreads")->i32;
} else if (strcasecmp("numOfMnodeReadThreads", name) == 0) {
tsNumOfMnodeReadThreads = cfgGetItem(pCfg, "numOfMnodeReadThreads")->i32;
} else if (strcasecmp("numOfVnodeQueryThreads", name) == 0) {
@ -857,9 +843,7 @@ int32_t taosSetCfg(SConfig *pCfg, char *name) {
break;
}
case 'r': {
if (strcasecmp("retrieveBlockingModel", name) == 0) {
tsRetrieveBlockingModel = cfgGetItem(pCfg, "retrieveBlockingModel")->bval;
} else if (strcasecmp("rpcQueueMemoryAllowed", name) == 0) {
if (strcasecmp("rpcQueueMemoryAllowed", name) == 0) {
tsRpcQueueMemoryAllowed = cfgGetItem(pCfg, "rpcQueueMemoryAllowed")->i64;
} else if (strcasecmp("rpcDebugFlag", name) == 0) {
rpcDebugFlag = cfgGetItem(pCfg, "rpcDebugFlag")->i32;
@ -885,8 +869,6 @@ int32_t taosSetCfg(SConfig *pCfg, char *name) {
tsNumOfSupportVnodes = cfgGetItem(pCfg, "supportVnodes")->i32;
} else if (strcasecmp("statusInterval", name) == 0) {
tsStatusInterval = cfgGetItem(pCfg, "statusInterval")->i32;
} else if (strcasecmp("slaveQuery", name) == 0) {
tsEnableSlaveQuery = cfgGetItem(pCfg, "slaveQuery")->bval;
} else if (strcasecmp("snodeShmSize", name) == 0) {
tsSnodeShmSize = cfgGetItem(pCfg, "snodeShmSize")->i32;
} else if (strcasecmp("serverPort", name) == 0) {
@ -1127,12 +1109,12 @@ void taosCfgDynamicOptions(const char *option, const char *value) {
const char *options[] = {
"dDebugFlag", "vDebugFlag", "mDebugFlag", "wDebugFlag", "sDebugFlag", "tsdbDebugFlag",
"tqDebugFlag", "fsDebugFlag", "udfDebugFlag", "smaDebugFlag", "idxDebugFlag", "tdbDebugFlag",
"tmrDebugFlag", "uDebugFlag", "smaDebugFlag", "rpcDebugFlag", "qDebugFlag",
"tmrDebugFlag", "uDebugFlag", "smaDebugFlag", "rpcDebugFlag", "qDebugFlag", "metaDebugFlag",
};
int32_t *optionVars[] = {
&dDebugFlag, &vDebugFlag, &mDebugFlag, &wDebugFlag, &sDebugFlag, &tsdbDebugFlag,
&tqDebugFlag, &fsDebugFlag, &udfDebugFlag, &smaDebugFlag, &idxDebugFlag, &tdbDebugFlag,
&tmrDebugFlag, &uDebugFlag, &smaDebugFlag, &rpcDebugFlag, &qDebugFlag,
&tmrDebugFlag, &uDebugFlag, &smaDebugFlag, &rpcDebugFlag, &qDebugFlag, &metaDebugFlag,
};
int32_t optionSize = tListLen(options);
@ -1179,5 +1161,6 @@ void taosSetAllDebugFlag(int32_t flag) {
taosSetDebugFlag(&smaDebugFlag, "smaDebugFlag", flag);
taosSetDebugFlag(&idxDebugFlag, "idxDebugFlag", flag);
taosSetDebugFlag(&tdbDebugFlag, "tdbDebugFlag", flag);
taosSetDebugFlag(&metaDebugFlag, "metaDebugFlag", flag);
uInfo("all debug flag are set to %d", flag);
}

View File

@ -0,0 +1,77 @@
/*
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
*
* This program is free software: you can use, redistribute, and/or modify
* it under the terms of the GNU Affero General Public License, version 3
* or later ("AGPL"), as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define _DEFAULT_SOURCE
#include "tdatablock.h"
#include "tglobal.h"
#include "tlog.h"
#include "tname.h"
int32_t taosGetFqdnPortFromEp(const char* ep, SEp* pEp) {
pEp->port = 0;
strcpy(pEp->fqdn, ep);
char* temp = strchr(pEp->fqdn, ':');
if (temp) {
*temp = 0;
pEp->port = atoi(temp + 1);
}
if (pEp->port == 0) {
pEp->port = tsServerPort;
}
return 0;
}
void addEpIntoEpSet(SEpSet* pEpSet, const char* fqdn, uint16_t port) {
if (pEpSet == NULL || fqdn == NULL || strlen(fqdn) == 0) {
return;
}
int32_t index = pEpSet->numOfEps;
tstrncpy(pEpSet->eps[index].fqdn, fqdn, tListLen(pEpSet->eps[index].fqdn));
pEpSet->eps[index].port = port;
pEpSet->numOfEps += 1;
}
bool isEpsetEqual(const SEpSet* s1, const SEpSet* s2) {
if (s1->numOfEps != s2->numOfEps || s1->inUse != s2->inUse) {
return false;
}
for (int32_t i = 0; i < s1->numOfEps; i++) {
if (s1->eps[i].port != s2->eps[i].port || strncmp(s1->eps[i].fqdn, s2->eps[i].fqdn, TSDB_FQDN_LEN) != 0)
return false;
}
return true;
}
void updateEpSet_s(SCorEpSet* pEpSet, SEpSet* pNewEpSet) {
taosCorBeginWrite(&pEpSet->version);
pEpSet->epSet = *pNewEpSet;
taosCorEndWrite(&pEpSet->version);
}
SEpSet getEpSet_s(SCorEpSet* pEpSet) {
SEpSet ep = {0};
taosCorBeginRead(&pEpSet->version);
ep = pEpSet->epSet;
taosCorEndRead(&pEpSet->version);
return ep;
}

View File

@ -305,6 +305,8 @@ static int32_t tDeserializeSClientHbReq(SDecoder *pDecoder, SClientHbReq *pReq)
taosArrayPush(desc.subDesc, &sDesc);
}
}
ASSERT(desc.subPlanNum == taosArrayGetSize(desc.subDesc));
taosArrayPush(pReq->query->queryDesc, &desc);
}

View File

@ -20,34 +20,6 @@
#define VALID_NAME_TYPE(x) ((x) == TSDB_DB_NAME_T || (x) == TSDB_TABLE_NAME_T)
bool tscValidateTableNameLength(size_t len) { return len < TSDB_TABLE_NAME_LEN; }
#if 0
// TODO refactor
SColumnFilterInfo* tFilterInfoDup(const SColumnFilterInfo* src, int32_t numOfFilters) {
if (numOfFilters == 0 || src == NULL) {
assert(src == NULL);
return NULL;
}
SColumnFilterInfo* pFilter = taosMemoryCalloc(1, numOfFilters * sizeof(SColumnFilterInfo));
memcpy(pFilter, src, sizeof(SColumnFilterInfo) * numOfFilters);
for (int32_t j = 0; j < numOfFilters; ++j) {
if (pFilter[j].filterstr) {
size_t len = (size_t) pFilter[j].len + 1 * TSDB_NCHAR_SIZE;
pFilter[j].pz = (int64_t) taosMemoryCalloc(1, len);
memcpy((char*)pFilter[j].pz, (char*)src[j].pz, (size_t) pFilter[j].len);
}
}
assert(src->filterstr == 0 || src->filterstr == 1);
assert(!(src->lowerRelOptr == 0 && src->upperRelOptr == 0));
return pFilter;
}
#endif
#if 0
int64_t taosGetIntervalStartTimestamp(int64_t startTime, int64_t slidingTime, int64_t intervalTime, char timeUnit, int16_t precision) {
if (slidingTime == 0) {
@ -190,10 +162,7 @@ int32_t tNameGetDbName(const SName* name, char* dst) {
return 0;
}
const char* tNameGetDbNameP(const SName* name) {
return &name->dbname[0];
}
const char* tNameGetDbNameP(const SName* name) { return &name->dbname[0]; }
int32_t tNameGetFullDbName(const SName* name, char* dst) {
assert(name != NULL && dst != NULL);
@ -240,7 +209,6 @@ int32_t tNameAddTbName(SName* dst, const char* tbName, size_t nameLen) {
return 0;
}
int32_t tNameSetAcctId(SName* dst, int32_t acctId) {
assert(dst != NULL);
dst->acctId = acctId;
@ -368,7 +336,7 @@ void buildChildTableName(RandTableName* rName) {
char temp[8] = {0};
rName->childTableName[0] = 't';
rName->childTableName[1] = '_';
for(int i = 0; i < 16; i++){
for (int i = 0; i < 16; i++) {
sprintf(temp, "%02x", context.digest[i]);
strcat(rName->childTableName, temp);
}

View File

@ -14,4 +14,7 @@ target_include_directories(
taosd
PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/node_mgmt/inc"
)
IF (TD_LINUX_64 AND JEMALLOC_ENABLED)
add_dependencies(taosd jemalloc)
ENDIF ()
target_link_libraries(taosd dnode)

View File

@ -27,6 +27,9 @@
#define DM_VERSION "Print program version."
#define DM_EMAIL "<support@taosdata.com>"
static struct {
#ifdef WINDOWS
bool winServiceMode;
#endif
bool dumpConfig;
bool generateGrant;
bool printAuth;
@ -93,6 +96,10 @@ static int32_t dmParseArgs(int32_t argc, char const *argv[]) {
global.dumpConfig = true;
} else if (strcmp(argv[i], "-V") == 0) {
global.printVersion = true;
#ifdef WINDOWS
} else if (strcmp(argv[i], "--win_service") == 0) {
global.winServiceMode = true;
#endif
} else if (strcmp(argv[i], "-e") == 0) {
global.envCmd[cmdEnvIndex] = argv[++i];
cmdEnvIndex++;
@ -169,6 +176,18 @@ int main(int argc, char const *argv[]) {
return -1;
}
#ifdef WINDOWS
int mainWindows(int argc,char** argv);
if (global.winServiceMode) {
stratWindowsService(mainWindows);
} else {
return mainWindows(argc, argv);
}
return 0;
}
int mainWindows(int argc,char** argv) {
#endif
if (global.generateGrant) {
dmGenerateGrant();
taosCleanupArgs();
@ -199,6 +218,8 @@ int main(int argc, char const *argv[]) {
taosCleanupArgs();
return -1;
}
taosConvInit();
if (global.dumpConfig) {
dmDumpCfg();

View File

@ -215,6 +215,7 @@ void dmCleanupDnode(SDnode *pDnode) {
dmClearVars(pDnode);
rpcCleanup();
indexCleanup();
taosConvDestroy();
dDebug("dnode is closed, ptr:%p", pDnode);
}

View File

@ -37,8 +37,6 @@ const char *mndTopicGetShowName(const char topic[TSDB_TOPIC_FNAME_LEN]);
int32_t mndSetTopicCommitLogs(SMnode *pMnode, STrans *pTrans, SMqTopicObj *pTopic);
int32_t mndCheckColAndTagModifiable(SMnode *pMnode, const char* stbname, int64_t suid, col_id_t colId);
#ifdef __cplusplus
}
#endif

View File

@ -1639,10 +1639,10 @@ static void dumpDbInfoData(SSDataBlock *pBlock, SDbObj *pDb, SShowObj *pShow, in
colDataAppend(pColInfo, rows, (const char *)&pDb->cfg.walRetentionPeriod, false);
pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
colDataAppend(pColInfo, rows, (const char *)&pDb->cfg.walRollPeriod, false);
colDataAppend(pColInfo, rows, (const char *)&pDb->cfg.walRetentionSize, false);
pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
colDataAppend(pColInfo, rows, (const char *)&pDb->cfg.walRetentionSize, false);
colDataAppend(pColInfo, rows, (const char *)&pDb->cfg.walRollPeriod, false);
pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
colDataAppend(pColInfo, rows, (const char *)&pDb->cfg.walSegmentSize, false);

View File

@ -788,9 +788,9 @@ _OVER:
static int32_t mndProcessConfigDnodeReq(SRpcMsg *pReq) {
SMnode *pMnode = pReq->info.node;
const char *options[] = {
"debugFlag", "dDebugFlag", "vDebugFlag", "mDebugFlag", "wDebugFlag", "sDebugFlag",
"tsdbDebugFlag", "tqDebugFlag", "fsDebugFlag", "udfDebugFlag", "smaDebugFlag", "idxDebugFlag",
"tdbDebugFlag", "tmrDebugFlag", "uDebugFlag", "smaDebugFlag", "rpcDebugFlag", "qDebugFlag",
"debugFlag", "dDebugFlag", "vDebugFlag", "mDebugFlag", "wDebugFlag", "sDebugFlag", "tsdbDebugFlag",
"tqDebugFlag", "fsDebugFlag", "udfDebugFlag", "smaDebugFlag", "idxDebugFlag", "tdbDebugFlag", "tmrDebugFlag",
"uDebugFlag", "smaDebugFlag", "rpcDebugFlag", "qDebugFlag", "metaDebugFlag",
};
int32_t optionSize = tListLen(options);

View File

@ -416,7 +416,7 @@ int32_t mndStart(SMnode *pMnode) {
}
mndSetRestore(pMnode, true);
}
grantReset(pMnode, TSDB_GRANT_ALL, 0);
return mndInitTimer(pMnode);
@ -446,20 +446,6 @@ int32_t mndProcessSyncMsg(SRpcMsg *pMsg) {
return -1;
}
do {
char *syncNodeStr = sync2SimpleStr(pMgmt->sync);
static int64_t mndTick = 0;
if (++mndTick % 10 == 1) {
mTrace("vgId:%d, sync trace msg:%s, %s", syncGetVgId(pMgmt->sync), TMSG_INFO(pMsg->msgType), syncNodeStr);
}
if (gRaftDetailLog) {
char logBuf[512] = {0};
snprintf(logBuf, sizeof(logBuf), "==mndProcessSyncMsg== msgType:%d, syncNode: %s", pMsg->msgType, syncNodeStr);
syncRpcMsgLog2(logBuf, pMsg);
}
taosMemoryFree(syncNodeStr);
} while (0);
// ToDo: ugly! use function pointer
if (syncNodeStrategy(pSyncNode) == SYNC_STRATEGY_STANDARD_SNAPSHOT) {
if (pMsg->msgType == TDMT_SYNC_TIMEOUT) {

View File

@ -687,6 +687,7 @@ static int32_t mndRetrieveConns(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBl
int32_t numOfRows = 0;
int32_t cols = 0;
SConnObj *pConn = NULL;
int32_t keepTime = tsShellActivityTimer * 3;
if (pShow->pIter == NULL) {
SProfileMgmt *pMgmt = &pMnode->profileMgmt;
@ -700,6 +701,10 @@ static int32_t mndRetrieveConns(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBl
break;
}
if ((taosGetTimestampMs() - pConn->lastAccessTimeMs) > (keepTime * 1000)) {
continue;
}
cols = 0;
SColumnInfoData *pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);

View File

@ -45,7 +45,9 @@ static int32_t mndProcessTableMetaReq(SRpcMsg *pReq);
static int32_t mndRetrieveStb(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBlock, int32_t rows);
static void mndCancelGetNextStb(SMnode *pMnode, void *pIter);
static int32_t mndProcessTableCfgReq(SRpcMsg *pReq);
static int32_t mndAlterStbImp(SMnode *pMnode, SRpcMsg *pReq, SDbObj *pDb, SStbObj *pStb, bool needRsp, void* alterOriData, int32_t alterOriDataLen);
static int32_t mndAlterStbImp(SMnode *pMnode, SRpcMsg *pReq, SDbObj *pDb, SStbObj *pStb, bool needRsp,
void *alterOriData, int32_t alterOriDataLen);
static int32_t mndCheckColAndTagModifiable(SMnode *pMnode, const char *stbname, int64_t suid, col_id_t colId);
int32_t mndInitStb(SMnode *pMnode) {
SSdbTable table = {
@ -409,7 +411,8 @@ static FORCE_INLINE int32_t schemaExColIdCompare(const void *colId, const void *
return 0;
}
static void *mndBuildVCreateStbReq(SMnode *pMnode, SVgObj *pVgroup, SStbObj *pStb, int32_t *pContLen, void* alterOriData, int32_t alterOriDataLen) {
static void *mndBuildVCreateStbReq(SMnode *pMnode, SVgObj *pVgroup, SStbObj *pStb, int32_t *pContLen,
void *alterOriData, int32_t alterOriDataLen) {
SEncoder encoder = {0};
int32_t contLen;
SName name = {0};
@ -709,7 +712,8 @@ int32_t mndBuildStbFromReq(SMnode *pMnode, SStbObj *pDst, SMCreateStbReq *pCreat
memcpy(pDst->db, pDb->name, TSDB_DB_FNAME_LEN);
pDst->createdTime = taosGetTimestampMs();
pDst->updateTime = pDst->createdTime;
pDst->uid = (pCreate->source == TD_REQ_FROM_TAOX) ? pCreate->suid : mndGenerateUid(pCreate->name, TSDB_TABLE_FNAME_LEN);
pDst->uid =
(pCreate->source == TD_REQ_FROM_TAOX) ? pCreate->suid : mndGenerateUid(pCreate->name, TSDB_TABLE_FNAME_LEN);
pDst->dbUid = pDb->uid;
pDst->tagVer = 1;
pDst->colVer = 1;
@ -895,9 +899,9 @@ static int32_t mndBuildStbFromAlter(SStbObj *pStb, SStbObj *pDst, SMCreateStbReq
pSchema->flags = pField->flags;
memcpy(pSchema->name, pField->name, TSDB_COL_NAME_LEN);
int32_t cIndex = mndFindSuperTableColumnIndex(pStb, pField->name);
if (cIndex >= 0){
if (cIndex >= 0) {
pSchema->colId = pStb->pColumns[cIndex].colId;
}else{
} else {
pSchema->colId = pDst->nextColId++;
}
}
@ -909,12 +913,11 @@ static int32_t mndBuildStbFromAlter(SStbObj *pStb, SStbObj *pDst, SMCreateStbReq
pSchema->bytes = pField->bytes;
memcpy(pSchema->name, pField->name, TSDB_COL_NAME_LEN);
int32_t cIndex = mndFindSuperTableTagIndex(pStb, pField->name);
if (cIndex >= 0){
if (cIndex >= 0) {
pSchema->colId = pStb->pTags[cIndex].colId;
}else{
} else {
pSchema->colId = pDst->nextColId++;
}
}
pDst->tagVer = createReq->tagVer;
pDst->colVer = createReq->colVer;
@ -982,7 +985,7 @@ static int32_t mndProcessCreateStbReq(SRpcMsg *pReq) {
}
} else if (terrno != TSDB_CODE_MND_STB_NOT_EXIST) {
goto _OVER;
} else if (createReq.source == TD_REQ_FROM_TAOX && (createReq.tagVer != 1 || createReq.colVer != 1)){
} else if (createReq.source == TD_REQ_FROM_TAOX && (createReq.tagVer != 1 || createReq.colVer != 1)) {
mInfo("stb:%s, alter table does not need to be done, because table is deleted", createReq.name);
code = 0;
goto _OVER;
@ -1009,7 +1012,7 @@ static int32_t mndProcessCreateStbReq(SRpcMsg *pReq) {
}
if (isAlter) {
bool needRsp = false;
bool needRsp = false;
SStbObj pDst = {0};
if (mndBuildStbFromAlter(pStb, &pDst, &createReq) != 0) {
taosMemoryFreeClear(pDst.pTags);
@ -1137,6 +1140,99 @@ static int32_t mndAddSuperTableTag(const SStbObj *pOld, SStbObj *pNew, SArray *p
return 0;
}
int32_t mndCheckColAndTagModifiable(SMnode *pMnode, const char *stbname, int64_t suid, col_id_t colId) {
SSdb *pSdb = pMnode->pSdb;
void *pIter = NULL;
while (1) {
SMqTopicObj *pTopic = NULL;
pIter = sdbFetch(pSdb, SDB_TOPIC, pIter, (void **)&pTopic);
if (pIter == NULL) break;
mDebug("topic:%s, check tag and column modifiable, stb:%s suid:%" PRId64 " colId:%d, subType:%d sql:%s",
pTopic->name, stbname, suid, colId, pTopic->subType, pTopic->sql);
if (pTopic->subType != TOPIC_SUB_TYPE__COLUMN) {
sdbRelease(pSdb, pTopic);
continue;
}
SNode *pAst = NULL;
if (nodesStringToNode(pTopic->ast, &pAst) != 0) {
ASSERT(0);
return -1;
}
SNodeList *pNodeList = NULL;
nodesCollectColumns((SSelectStmt *)pAst, SQL_CLAUSE_FROM, NULL, COLLECT_COL_TYPE_ALL, &pNodeList);
SNode *pNode = NULL;
FOREACH(pNode, pNodeList) {
SColumnNode *pCol = (SColumnNode *)pNode;
mDebug("topic:%s, check colId:%d tableId:%" PRId64 " ctbStbUid:%" PRId64, pTopic->name, pCol->colId,
pCol->tableId, pTopic->ctbStbUid);
if (pCol->tableId != suid && pTopic->ctbStbUid != suid) {
mDebug("topic:%s, check colId:%d passed", pTopic->name, pCol->colId);
goto NEXT;
}
if (pCol->colId > 0 && pCol->colId == colId) {
sdbRelease(pSdb, pTopic);
nodesDestroyNode(pAst);
terrno = TSDB_CODE_MND_FIELD_CONFLICT_WITH_TOPIC;
mError("topic:%s, check colId:%d conflicted", pTopic->name, pCol->colId);
return -1;
}
mDebug("topic:%s, check colId:%d passed", pTopic->name, pCol->colId);
}
NEXT:
sdbRelease(pSdb, pTopic);
nodesDestroyNode(pAst);
}
while (1) {
SSmaObj *pSma = NULL;
pIter = sdbFetch(pSdb, SDB_SMA, pIter, (void **)&pSma);
if (pIter == NULL) break;
mDebug("tsma:%s, check tag and column modifiable, stb:%s suid:%" PRId64 " colId:%d, sql:%s", pSma->name, stbname,
suid, colId, pSma->sql);
SNode *pAst = NULL;
if (nodesStringToNode(pSma->ast, &pAst) != 0) {
terrno = TSDB_CODE_SDB_INVALID_DATA_CONTENT;
mError("tsma:%s, check tag and column modifiable, stb:%s suid:%" PRId64 " colId:%d failed since parse AST err",
pSma->name, stbname, suid, colId);
return -1;
}
SNodeList *pNodeList = NULL;
nodesCollectColumns((SSelectStmt *)pAst, SQL_CLAUSE_FROM, NULL, COLLECT_COL_TYPE_ALL, &pNodeList);
SNode *pNode = NULL;
FOREACH(pNode, pNodeList) {
SColumnNode *pCol = (SColumnNode *)pNode;
mDebug("tsma:%s, check colId:%d tableId:%" PRId64, pSma->name, pCol->colId, pCol->tableId);
if ((pCol->tableId != suid) && (pSma->stbUid != suid)) {
mDebug("tsma:%s, check colId:%d passed", pSma->name, pCol->colId);
goto NEXT2;
}
if ((pCol->colId) > 0 && (pCol->colId == colId)) {
sdbRelease(pSdb, pSma);
nodesDestroyNode(pAst);
terrno = TSDB_CODE_MND_FIELD_CONFLICT_WITH_TSMA;
mError("tsma:%s, check colId:%d conflicted", pSma->name, pCol->colId);
return -1;
}
mDebug("tsma:%s, check colId:%d passed", pSma->name, pCol->colId);
}
NEXT2:
sdbRelease(pSdb, pSma);
nodesDestroyNode(pAst);
}
return 0;
}
static int32_t mndDropSuperTableTag(SMnode *pMnode, const SStbObj *pOld, SStbObj *pNew, const char *tagName) {
int32_t tag = mndFindSuperTableTagIndex(pOld, tagName);
if (tag < 0) {
@ -1380,7 +1476,8 @@ static int32_t mndSetAlterStbCommitLogs(SMnode *pMnode, STrans *pTrans, SDbObj *
return 0;
}
static int32_t mndSetAlterStbRedoActions(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SStbObj *pStb, void* alterOriData, int32_t alterOriDataLen) {
static int32_t mndSetAlterStbRedoActions(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, SStbObj *pStb, void *alterOriData,
int32_t alterOriDataLen) {
SSdb *pSdb = pMnode->pSdb;
SVgObj *pVgroup = NULL;
void *pIter = NULL;
@ -1607,7 +1704,8 @@ static int32_t mndBuildSMAlterStbRsp(SDbObj *pDb, SStbObj *pObj, void **pCont, i
return 0;
}
static int32_t mndAlterStbImp(SMnode *pMnode, SRpcMsg *pReq, SDbObj *pDb, SStbObj *pStb, bool needRsp, void* alterOriData, int32_t alterOriDataLen) {
static int32_t mndAlterStbImp(SMnode *pMnode, SRpcMsg *pReq, SDbObj *pDb, SStbObj *pStb, bool needRsp,
void *alterOriData, int32_t alterOriDataLen) {
int32_t code = -1;
STrans *pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_DB_INSIDE, pReq);
if (pTrans == NULL) goto _OVER;
@ -2204,12 +2302,12 @@ static int32_t mndRetrieveStb(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBloc
pColInfo = taosArrayGet(pBlock->pDataBlock, cols++);
colDataAppend(pColInfo, numOfRows, (const char *)maxDelay, false);
char rollup[128 + VARSTR_HEADER_SIZE] = {0};
char rollup[128 + VARSTR_HEADER_SIZE] = {0};
int32_t rollupNum = (int32_t)taosArrayGetSize(pStb->pFuncs);
for (int32_t i = 0; i < rollupNum; ++i) {
char *funcName = taosArrayGet(pStb->pFuncs, i);
if (i) {
strcat(varDataVal(rollup), ", ");
strcat(varDataVal(rollup), ", ");
}
strcat(varDataVal(rollup), funcName);
}

View File

@ -72,56 +72,6 @@ const char *mndTopicGetShowName(const char topic[TSDB_TOPIC_FNAME_LEN]) {
return strchr(topic, '.') + 1;
}
int32_t mndCheckColAndTagModifiable(SMnode *pMnode, const char* stbname, int64_t suid, col_id_t colId) {
SSdb *pSdb = pMnode->pSdb;
void *pIter = NULL;
while (1) {
SMqTopicObj *pTopic = NULL;
pIter = sdbFetch(pSdb, SDB_TOPIC, pIter, (void **)&pTopic);
if (pIter == NULL) break;
mDebug("topic:%s, check tag and column modifiable, stb:%s suid:%" PRId64 " colId:%d, subType:%d sql:%s",
pTopic->name, stbname, suid, colId, pTopic->subType, pTopic->sql);
if (pTopic->subType != TOPIC_SUB_TYPE__COLUMN) {
sdbRelease(pSdb, pTopic);
continue;
}
SNode *pAst = NULL;
if (nodesStringToNode(pTopic->ast, &pAst) != 0) {
ASSERT(0);
return -1;
}
SNodeList *pNodeList = NULL;
nodesCollectColumns((SSelectStmt *)pAst, SQL_CLAUSE_FROM, NULL, COLLECT_COL_TYPE_ALL, &pNodeList);
SNode *pNode = NULL;
FOREACH(pNode, pNodeList) {
SColumnNode *pCol = (SColumnNode *)pNode;
mDebug("topic:%s, check colId:%d tableId:%" PRId64 " ctbStbUid:%" PRId64, pTopic->name, pCol->colId, pCol->tableId, pTopic->ctbStbUid);
if (pCol->tableId != suid && pTopic->ctbStbUid != suid) {
mDebug("topic:%s, check colId:%d passed", pTopic->name, pCol->colId);
goto NEXT;
}
if (pCol->colId > 0 && pCol->colId == colId) {
sdbRelease(pSdb, pTopic);
nodesDestroyNode(pAst);
terrno = TSDB_CODE_MND_FIELD_CONFLICT_WITH_TOPIC;
mError("topic:%s, check colId:%d conflicted", pTopic->name, pCol->colId);
return -1;
}
mDebug("topic:%s, check colId:%d passed", pTopic->name, pCol->colId);
}
NEXT:
sdbRelease(pSdb, pTopic);
nodesDestroyNode(pAst);
}
return 0;
}
SSdbRaw *mndTopicActionEncode(SMqTopicObj *pTopic) {
terrno = TSDB_CODE_OUT_OF_MEMORY;

View File

@ -179,7 +179,7 @@ static int32_t sndProcessTaskRecoverRsp(SSnode *pNode, SRpcMsg *pMsg) {
SStreamMeta *pMeta = pNode->pMeta;
SStreamTaskRecoverRsp *pRsp = pMsg->pCont;
int32_t taskId = pRsp->taskId;
int32_t taskId = pRsp->rspTaskId;
SStreamTask *pTask = *(SStreamTask **)taosHashGet(pMeta->pHash, &taskId, sizeof(int32_t));
streamProcessRecoverRsp(pTask, pRsp);
return 0;

View File

@ -31,6 +31,7 @@ target_sources(
"src/sma/smaOpen.c"
"src/sma/smaCommit.c"
"src/sma/smaRollup.c"
"src/sma/smaSnapshot.c"
"src/sma/smaTimeRange.c"
# tsdb

View File

@ -89,13 +89,13 @@ void metaReaderClear(SMetaReader *pReader);
int32_t metaGetTableEntryByUid(SMetaReader *pReader, tb_uid_t uid);
int32_t metaReadNext(SMetaReader *pReader);
const void *metaGetTableTagVal(SMetaEntry *pEntry, int16_t type, STagVal *tagVal);
int metaGetTableNameByUid(void* meta, uint64_t uid, char* tbName);
int metaGetTableNameByUid(void *meta, uint64_t uid, char *tbName);
typedef struct SMetaFltParam {
tb_uid_t suid;
int16_t cid;
int16_t type;
char *val;
void *val;
bool reverse;
int (*filterFunc)(void *a, void *b, int16_t type);
@ -137,6 +137,7 @@ int32_t tsdbGetFileBlocksDistInfo(STsdbReader *pReader, STableBlockDistInfo *pTa
int64_t tsdbGetNumOfRowsInMemTable(STsdbReader *pHandle);
void *tsdbGetIdx(SMeta *pMeta);
void *tsdbGetIvtIdx(SMeta *pMeta);
uint64_t getReaderMaxVersion(STsdbReader *pReader);
int32_t tsdbLastRowReaderOpen(void *pVnode, int32_t type, SArray *pTableIdList, int32_t numOfCols, void **pReader);
int32_t tsdbRetrieveLastRow(void *pReader, SSDataBlock *pResBlock, const int32_t *slotIds, SArray *pTableUids);

View File

@ -78,7 +78,10 @@ struct SMeta {
TTB* pTagIdx;
TTB* pTtlIdx;
TTB* pSmaIdx;
TTB* pSmaIdx;
TTB* pTaskIdx;
SMetaIdx* pIdx;
};

View File

@ -209,6 +209,9 @@ int32_t tdProcessTSmaGetDaysImpl(SVnodeCfg *pCfg, void *pCont, uint32_t contLen,
// smaFileUtil ================
typedef struct SQTaskFReader SQTaskFReader;
typedef struct SQTaskFWriter SQTaskFWriter;
#define TD_FILE_HEAD_SIZE 512
typedef struct STFInfo STFInfo;

View File

@ -43,6 +43,7 @@ typedef struct STbDataIter STbDataIter;
typedef struct SMapData SMapData;
typedef struct SBlockIdx SBlockIdx;
typedef struct SBlock SBlock;
typedef struct SBlockL SBlockL;
typedef struct SColData SColData;
typedef struct SBlockDataHdr SBlockDataHdr;
typedef struct SBlockData SBlockData;
@ -90,6 +91,9 @@ int32_t tsdbRowCmprFn(const void *p1, const void *p2);
void tRowIterInit(SRowIter *pIter, TSDBROW *pRow, STSchema *pTSchema);
SColVal *tRowIterNext(SRowIter *pIter);
// SRowMerger
int32_t tRowMergerInit2(SRowMerger *pMerger, STSchema *pResTSchema, TSDBROW *pRow, STSchema *pTSchema);
int32_t tRowMergerAdd(SRowMerger *pMerger, TSDBROW *pRow, STSchema *pTSchema);
int32_t tRowMergerInit(SRowMerger *pMerger, TSDBROW *pRow, STSchema *pTSchema);
void tRowMergerClear(SRowMerger *pMerger);
int32_t tRowMerge(SRowMerger *pMerger, TSDBROW *pRow);
@ -97,7 +101,6 @@ int32_t tRowMergerGetRow(SRowMerger *pMerger, STSRow **ppRow);
// TABLEID
int32_t tTABLEIDCmprFn(const void *p1, const void *p2);
// TSDBKEY
int32_t tsdbKeyCmprFn(const void *p1, const void *p2);
#define MIN_TSDBKEY(KEY1, KEY2) ((tsdbKeyCmprFn(&(KEY1), &(KEY2)) < 0) ? (KEY1) : (KEY2))
#define MAX_TSDBKEY(KEY1, KEY2) ((tsdbKeyCmprFn(&(KEY1), &(KEY2)) > 0) ? (KEY1) : (KEY2))
// SBlockCol
@ -412,6 +415,29 @@ struct SBlock {
SSubBlock aSubBlock[TSDB_MAX_SUBBLOCKS];
};
struct SBlockL {
struct {
int64_t uid;
int64_t version;
TSKEY ts;
} minKey;
struct {
int64_t uid;
int64_t version;
TSKEY ts;
} maxKey;
int64_t minVer;
int64_t maxVer;
int32_t nRow;
int8_t cmprAlg;
int64_t offset;
int32_t szBlock;
int32_t szBlockCol;
int32_t szUid;
int32_t szVer;
int32_t szTSKEY;
};
struct SColData {
int16_t cid;
int8_t type;
@ -558,6 +584,26 @@ struct STsdbReadSnap {
STsdbFS fs;
};
// ========== inline functions ==========
static FORCE_INLINE int32_t tsdbKeyCmprFn(const void *p1, const void *p2) {
TSDBKEY *pKey1 = (TSDBKEY *)p1;
TSDBKEY *pKey2 = (TSDBKEY *)p2;
if (pKey1->ts < pKey2->ts) {
return -1;
} else if (pKey1->ts > pKey2->ts) {
return 1;
}
if (pKey1->version < pKey2->version) {
return -1;
} else if (pKey1->version > pKey2->version) {
return 1;
}
return 0;
}
#ifdef __cplusplus
}
#endif

View File

@ -62,6 +62,8 @@ typedef struct SMetaSnapReader SMetaSnapReader;
typedef struct SMetaSnapWriter SMetaSnapWriter;
typedef struct STsdbSnapReader STsdbSnapReader;
typedef struct STsdbSnapWriter STsdbSnapWriter;
typedef struct SRsmaSnapReader SRsmaSnapReader;
typedef struct SRsmaSnapWriter SRsmaSnapWriter;
typedef struct SSnapDataHdr SSnapDataHdr;
#define VNODE_META_DIR "meta"
@ -133,6 +135,7 @@ int32_t tsdbInsertTableData(STsdb* pTsdb, int64_t version, SSubmitMsgIter* p
int32_t tsdbDeleteTableData(STsdb* pTsdb, int64_t version, tb_uid_t suid, tb_uid_t uid, TSKEY sKey, TSKEY eKey);
STsdbReader tsdbQueryCacheLastT(STsdb* tsdb, SQueryTableDataCond* pCond, STableListInfo* tableList, uint64_t qId,
void* pMemRef);
int32_t tsdbSetKeepCfg(STsdb* pTsdb, STsdbCfg* pCfg);
// tq
int tqInit();
@ -150,7 +153,7 @@ int32_t tqProcessOffsetCommitReq(STQ* pTq, char* msg, int32_t msgLen);
int32_t tqProcessPollReq(STQ* pTq, SRpcMsg* pMsg);
int32_t tqProcessTaskDeployReq(STQ* pTq, char* msg, int32_t msgLen);
int32_t tqProcessTaskDropReq(STQ* pTq, char* msg, int32_t msgLen);
int32_t tqProcessStreamTrigger(STQ* pTq, SSubmitReq* data);
int32_t tqProcessStreamTrigger(STQ* pTq, SSubmitReq* data, int64_t ver);
int32_t tqProcessTaskRunReq(STQ* pTq, SRpcMsg* pMsg);
int32_t tqProcessTaskDispatchReq(STQ* pTq, SRpcMsg* pMsg);
int32_t tqProcessTaskRecoverReq(STQ* pTq, SRpcMsg* pMsg);
@ -196,13 +199,21 @@ int32_t metaSnapWriterOpen(SMeta* pMeta, int64_t sver, int64_t ever, SMetaSnapWr
int32_t metaSnapWrite(SMetaSnapWriter* pWriter, uint8_t* pData, uint32_t nData);
int32_t metaSnapWriterClose(SMetaSnapWriter** ppWriter, int8_t rollback);
// STsdbSnapReader ========================================
int32_t tsdbSnapReaderOpen(STsdb* pTsdb, int64_t sver, int64_t ever, STsdbSnapReader** ppReader);
int32_t tsdbSnapReaderOpen(STsdb* pTsdb, int64_t sver, int64_t ever, int8_t type, STsdbSnapReader** ppReader);
int32_t tsdbSnapReaderClose(STsdbSnapReader** ppReader);
int32_t tsdbSnapRead(STsdbSnapReader* pReader, uint8_t** ppData);
// STsdbSnapWriter ========================================
int32_t tsdbSnapWriterOpen(STsdb* pTsdb, int64_t sver, int64_t ever, STsdbSnapWriter** ppWriter);
int32_t tsdbSnapWrite(STsdbSnapWriter* pWriter, uint8_t* pData, uint32_t nData);
int32_t tsdbSnapWriterClose(STsdbSnapWriter** ppWriter, int8_t rollback);
// SRsmaSnapReader ========================================
int32_t rsmaSnapReaderOpen(SSma* pSma, int64_t sver, int64_t ever, SRsmaSnapReader** ppReader);
int32_t rsmaSnapReaderClose(SRsmaSnapReader** ppReader);
int32_t rsmaSnapRead(SRsmaSnapReader* pReader, uint8_t** ppData);
// SRsmaSnapWriter ========================================
int32_t rsmaSnapWriterOpen(SSma* pSma, int64_t sver, int64_t ever, SRsmaSnapWriter** ppWriter);
int32_t rsmaSnapWrite(SRsmaSnapWriter* pWriter, uint8_t* pData, uint32_t nData);
int32_t rsmaSnapWriterClose(SRsmaSnapWriter** ppWriter, int8_t rollback);
typedef struct {
int8_t streamType; // sma or other
@ -314,6 +325,15 @@ struct SSma {
// sma
void smaHandleRes(void* pVnode, int64_t smaId, const SArray* data);
enum {
SNAP_DATA_META = 0,
SNAP_DATA_TSDB = 1,
SNAP_DATA_DEL = 2,
SNAP_DATA_RSMA1 = 3,
SNAP_DATA_RSMA2 = 4,
SNAP_DATA_QTASK = 5,
};
struct SSnapDataHdr {
int8_t type;
int64_t index;

View File

@ -22,6 +22,7 @@ static int tagIdxKeyCmpr(const void *pKey1, int kLen1, const void *pKey2, int kL
static int ttlIdxKeyCmpr(const void *pKey1, int kLen1, const void *pKey2, int kLen2);
static int uidIdxKeyCmpr(const void *pKey1, int kLen1, const void *pKey2, int kLen2);
static int smaIdxKeyCmpr(const void *pKey1, int kLen1, const void *pKey2, int kLen2);
static int taskIdxKeyCmpr(const void *pKey1, int kLen1, const void *pKey2, int kLen2);
static int32_t metaInitLock(SMeta *pMeta) { return taosThreadRwlockInit(&pMeta->lock, NULL); }
static int32_t metaDestroyLock(SMeta *pMeta) { return taosThreadRwlockDestroy(&pMeta->lock); }
@ -130,6 +131,12 @@ int metaOpen(SVnode *pVnode, SMeta **ppMeta) {
goto _err;
}
ret = tdbTbOpen("stream.task.db", sizeof(int64_t), -1, taskIdxKeyCmpr, pMeta->pEnv, &pMeta->pTaskIdx);
if (ret < 0) {
metaError("vgId: %d, failed to open meta stream task index since %s", TD_VID(pVnode), tstrerror(terrno));
goto _err;
}
// open index
if (metaOpenIdx(pMeta) < 0) {
metaError("vgId:%d, failed to open meta index since %s", TD_VID(pVnode), tstrerror(terrno));
@ -143,6 +150,7 @@ int metaOpen(SVnode *pVnode, SMeta **ppMeta) {
_err:
if (pMeta->pIdx) metaCloseIdx(pMeta);
if (pMeta->pTaskIdx) tdbTbClose(pMeta->pTaskIdx);
if (pMeta->pSmaIdx) tdbTbClose(pMeta->pSmaIdx);
if (pMeta->pTtlIdx) tdbTbClose(pMeta->pTtlIdx);
if (pMeta->pTagIvtIdx) indexClose(pMeta->pTagIvtIdx);
@ -162,6 +170,7 @@ _err:
int metaClose(SMeta *pMeta) {
if (pMeta) {
if (pMeta->pIdx) metaCloseIdx(pMeta);
if (pMeta->pTaskIdx) tdbTbClose(pMeta->pTaskIdx);
if (pMeta->pSmaIdx) tdbTbClose(pMeta->pSmaIdx);
if (pMeta->pTtlIdx) tdbTbClose(pMeta->pTtlIdx);
if (pMeta->pTagIvtIdx) indexClose(pMeta->pTagIvtIdx);
@ -183,11 +192,11 @@ int metaClose(SMeta *pMeta) {
int32_t metaRLock(SMeta *pMeta) {
int32_t ret = 0;
metaDebug("meta rlock %p B", &pMeta->lock);
metaTrace("meta rlock %p B", &pMeta->lock);
ret = taosThreadRwlockRdlock(&pMeta->lock);
metaDebug("meta rlock %p E", &pMeta->lock);
metaTrace("meta rlock %p E", &pMeta->lock);
return ret;
}
@ -195,11 +204,11 @@ int32_t metaRLock(SMeta *pMeta) {
int32_t metaWLock(SMeta *pMeta) {
int32_t ret = 0;
metaDebug("meta wlock %p B", &pMeta->lock);
metaTrace("meta wlock %p B", &pMeta->lock);
ret = taosThreadRwlockWrlock(&pMeta->lock);
metaDebug("meta wlock %p E", &pMeta->lock);
metaTrace("meta wlock %p E", &pMeta->lock);
return ret;
}
@ -207,11 +216,11 @@ int32_t metaWLock(SMeta *pMeta) {
int32_t metaULock(SMeta *pMeta) {
int32_t ret = 0;
metaDebug("meta ulock %p B", &pMeta->lock);
metaTrace("meta ulock %p B", &pMeta->lock);
ret = taosThreadRwlockUnlock(&pMeta->lock);
metaDebug("meta ulock %p E", &pMeta->lock);
metaTrace("meta ulock %p E", &pMeta->lock);
return ret;
}
@ -315,7 +324,8 @@ static int tagIdxKeyCmpr(const void *pKey1, int kLen1, const void *pKey2, int kL
return 1;
} else if (!pTagIdxKey1->isNull && !pTagIdxKey2->isNull) {
// all not NULL, compr tag vals
c = doCompare(pTagIdxKey1->data, pTagIdxKey2->data, pTagIdxKey1->type, 0);
__compar_fn_t func = getComparFunc(pTagIdxKey1->type, 0);
c = func(pTagIdxKey1->data, pTagIdxKey2->data);
if (c) return c;
}
@ -377,3 +387,16 @@ static int smaIdxKeyCmpr(const void *pKey1, int kLen1, const void *pKey2, int kL
return 0;
}
static int taskIdxKeyCmpr(const void *pKey1, int kLen1, const void *pKey2, int kLen2) {
int32_t uid1 = *(int32_t *)pKey1;
int32_t uid2 = *(int32_t *)pKey2;
if (uid1 > uid2) {
return 1;
} else if (uid1 < uid2) {
return -1;
}
return 0;
}

Some files were not shown because too many files have changed in this diff Show More